Help us understand the problem. What is going on with this article?

IoT ハッカソン Wio LTE デバイス環境 設定手順

More than 1 year has passed since last update.

はじめに

本コンテンツは、IoT ハッカソンで使用する技術ハンズオンの資料です。
環境は参加者が自由選択できますので、参考としてご活用ください。

概要

SORACOM Air サービスを使用して、センサーから取得して、クラウドにデータを転送するまでの手順を説明します。

目次

準備

Wio LTE for Arduino 公式の Wiki ページ、SORACOM の WioLTE ハンズオンページを参考にインストールを進めて行きます。

WioLTE ハンズオンページ

以下のページより、"開発環境の準備" 〜 "ステップ 3: 温湿度センサーのデータを SORACOM Harvest で可視化"までの手順を実施してください。

https://github.com/soracom/handson/wiki/Wio-LTE-%E3%83%8F%E3%83%B3%E3%82%BA%E3%82%AA%E3%83%B3

公式の Wiki

デバイスのハード仕様、"Wio LTE for Arduino"ライブラリに関する情報を参照する場合は、以下の Seeed の Wiki ページを参照してください。

https://seeedjp.github.io/Wiki/Wio_LTE_for_Arduino/Home-ja.html

外部ライブラリ導入

温度センサーを取得するために、Arduino IDE に Seeed 社(Grove センサ製造元)が公開しているライブラリを導入します。

プログラム

クラウドにセンシングした値を送信するためのスケッチ(コード)を書いていきます。

temperature.ino
#include <WioLTEforArduino.h>
#include <DHT.h>            // https://github.com/Seeed-Studio/Grove_Temperature_And_Humidity_Sensor
#include <stdio.h>

// データ送信先選択
#define TARGET_SORACOM_BEAM       0
#define TARGET_SORACOM_FUNNEL     1
#define TARGET_SORACOM_HARVEST    2
#define USE_TARGET                TARGET_SORACOM_FUNNEL

#if USE_TARGET == TARGET_SORACOM_BEAM
  // Beam(UDP)を使う場合
  constexpr char *TARGET_HOST = "beam.soracom.io";
  constexpr uint16_t TARGET_PORT = 23080;
#elif USE_TARGET == TARGET_SORACOM_FUNNEL
  // Funnelを使う場合
  constexpr char *TARGET_HOST = "funnel.soracom.io";
  constexpr uint16_t TARGET_PORT = 23080;
#elif USE_TARGET == TARGET_SORACOM_HARVEST
  constexpr char *TARGET_HOST = "harvest.soracom.io";
  constexpr uint16_t TARGET_PORT = 8514;
#else
# error "not selected use protocol."
#endif

//
// 送信データ定義
//
struct SendPacket
{
  float temp;

  // 送信データをJSON文字列へ変換
  String JsonStringify() const
  {
    String result("");
    char buf[32];

    sprintf(buf, "%d", static_cast<int>(this->temp));
    result += "{\"tmpr_c\":";
    result += buf;
    result += "}";

    return result;
  }
};

//
// グローバル変数
//
WioLTE g_wio;
DHT g_temp_hum(WIOLTE_D38, DHT11);

//
// 初期化処理
//
void setup()
{
  delay(200);

  SerialUSB.println("start: I/O Initialize.");
  g_wio.Init();

  SerialUSB.println("start: Power ON.");
  g_wio.PowerSupplyLTE(true);

  SerialUSB.println("start: Module Initialize.");
  if(!g_wio.TurnOnOrReset()){
    SerialUSB.println("error:  Module init failed.");
    return;
  }

  SerialUSB.println("start: APN activate.");
  if(!g_wio.Activate("soracom.io", "sora", "sora", 3000)){
    SerialUSB.println("error: APN activate failed.");
  }

  g_wio.PowerSupplyGrove(true);
  delay(500);
  g_temp_hum.begin();

  SerialUSB.println("setup OK.");

  SerialUSB.print("target host: ");
  SerialUSB.println(TARGET_HOST);
}

//
// 定期処理
//
void loop()
{
  SendPacket data;

  data.temp = g_temp_hum.readTemperature(); // 温度データ取得
  SerialUSB.print("temp:"); SerialUSB.println(data.temp);

  sendData(data);

  delay(5000);
}

//
// データ送信処理
//
void sendData(const SendPacket &packet)
{
  int connectId;
  connectId = g_wio.SocketOpen(TARGET_HOST, TARGET_PORT, WIOLTE_UDP);
  if (connectId < 0) {
    SerialUSB.println("error: cannot connect.");
    return;
  }

  String data = packet.JsonStringify();
  SerialUSB.print("Send:");
  SerialUSB.print(data);
  SerialUSB.println("");
  if (!g_wio.SocketSend(connectId, data.c_str())) {
    SerialUSB.println("error: cannot send data.");
  }

  if (!g_wio.SocketClose(connectId)) {
    SerialUSB.println("error: cannot close socket.");
  }
}

解説

プログラムは大きく分けて 4 つに別れています。

  • 初期化(setup) : LTE 回線への接続、Grove センサの初期化
  • 定期処理(loop) : 温度線センサーから温度値を読み出し、送信処理(sendData)を呼び出す
  • 送信処理(sendData) : SORACOM へ接続し、温度データを文字列に変換(JsonStringify)して、SORACOM との接続を切断
  • 文字列へ変換(JsonStringify) : float 型からクラウドでデータ処理しやすい JSON 形式の文字列へ変換

初期化(setup)

WioLTE 本体の処理を呼び出すための変数をグローバル変数で準備します。

WioLTE g_wio;

温度センサーを使用するために、D38 ポートへ接続する定義と、センサーの種類(今回資料する温度センサーは DHT11 という型)を割り当てをしています。

DHT g_temp_hum(WIOLTE_D38, DHT11);

上記の割り当てた内容をsetup関数内で初期化します。

  1. はじめに、Initを呼び出して WioLTE 全体の初期化を行います。

    g_wio.Init();
    
  2. 次に LTE の機能を使用するための、PowerSupplyLTEで電源供給を ON し、LTE モジュールの起動操作TurnOnOrResetを呼び出します。
    PowerSupplyLTETurnOnOrReset順番で呼び出さないと正しく初期化できないので注意してください。

    g_wio.PowerSupplyLTE(true);
    
    SerialUSB.println("start: Module Initialize.");
    if(!g_wio.TurnOnOrReset()){
      SerialUSB.println("error:  Module init failed.");
      return;
    }
    
  3. データ通信を有効にするためActivateでアクティベーションします。
    SIM カードが刺さっていなかったり、圏外などで接続できない場合が 3 秒(3000 ミリ秒)で処理を中断するようにしています。
    (何も指定しない場合、120 秒間(2 分)のタイムアウト時間となります)

    SerialUSB.println("start: APN activate.");
      if(!g_wio.Activate("soracom.io", "sora", "sora", 3000)){
      SerialUSB.println("error: APN activate failed.");
    }
    
  4. Grove センサーへの電源供給を ON(g_wio.PowerSupplyGrove) して、g_temp_hum.begin()で温度センサーの初期化処理をしています。

      g_wio.PowerSupplyGrove(true);
      delay(500);
      g_temp_hum.begin();
    

定期処理(loop)

定期処理では、読み出しと送信処理を呼び出しています。

  1. readTemperatureで温度センサーから値を読み出し、data.tempに値を格納します。

    data.temp = g_temp_hum.readTemperature();
    
  2. sendDataでスケッチ(コード)で準備した送信用の関数呼び出しをします。

    sendData(data);
    
  3. 最後に 5000 ミリ秒(5 秒)待機して終了します。
    なお、時間を短くすることは可能ですが、
    温度センサーの DHT11 のサンプリング間隔が 2 秒以上の仕様のため、正しい値が取得できなくなってしまいます。

    delay(5000);
    

送信処理(sendData)

送信処理では、接続 → データ変換 → 送信 → 切断の順番で処理をします。

  1. 接続のためにSocketOpenを呼び出しをしています。
    接続先のホスト名、ポート番号はそれぞれTARGET_HOSTTARGET_PORTで定義しており、
    Beam/Funnel/Harvest を以下の定義を変更することで、切り替えができるようにしています。

    // SORACOM Beamに対して接続する場合
    #define USE_TARGET              SORACOM_PROTOCOL_BEAM
    
    // SORACOM Funnelに対してへ接続する場合
    #define USE_TARGET              TARGET_SORACOM_FUNNEL
    
    // SORACOM Harvestに対してへ接続する場合
    #define USE_TARGET              TARGET_SORACOM_HARVEST
    
  2. データ変換では、JsonStringifyを呼び出して、文字列へ変換しています。

  3. 送信データでは、送信先で SocketOpen で取得した"connectId"指定と、
    c_str()で String 型から char *型のデータを取得して送信します。

    if (!g_wio.SocketSend(connectId, data.c_str())) {
      SerialUSB.println("error: cannot send data.");
    }
    
  4. 最後に送信が終わったらSocketCloseで切断します。

文字列へ変換(JsonStringify)

取得するデータは単精度浮動小数点(float 型)ですが、DHT11 のセンサー精度は分解能 1℃ で小数点以下を取れないため、
sprintf整数(int 型)に変換した上で、文字列に変換しています。

また、最終的に JSON 形式に変換する必要があるため、"{<key>:<value>}"の形式にしていきます。
以下に 25℃ が取れた場合の変換過程を右側にコメントをつけて説明します。

    sprintf(buf, "%d", static_cast<int>(this->temp));   // 25.0 → "25"    浮動小数点から整数へ変換しbufへ格納
    result += "{\"tmpr_c\":";                           // {"tmpr_c":     resultに「{」括弧開きとキー「tmpr_c」を追加
    result += buf;                                      // {"tmpr_c":25   resultに「25」の文字列を追加
    result += "}";                                      // {"tmpr_c":25}  resultに「}」括弧閉じを追加

クラウド環境の準備

WioLTEへスケッチを書き込んだら、クラウド環境の設定を行なっていきます。
クラウドの環境はIoT ハッカソン クラウド環境 設定手順を参照してください。

トラブルシュート

D38 ポート以外がうまく機能しない

起動直後は、D38 以外は OFF になるため、有効にする必要があります。
PowerSupplyGroveを setup()関数内で呼び出すことで解決します。

WioLTE wio;

void setup()
{
  wio.Init();                 // Wio LTEを初期化
  wio.PowerSupplyGrove(true); // Groveコネクタの電源供給ON
}

参考

公式 Wiki

デバイスのハード仕様、"Wio LTE for Arduino"ライブラリに関する情報を参照する場合は、以下の Seeed の Wiki ページを参照してください。

https://seeedjp.github.io/Wiki/Wio_LTE_for_Arduino/Home-ja.html

各種センサの値取得方法

各センサの値の取得方法はスケッチ(IDE)のスケッチ例のそれぞれ下記を参照してください。

ファイルスケッチ例スケッチ例Wio LTE for Arduino

センサ/アクチュエータ スケッチ名
プッシュボタン grove-button
磁気センサ grove-magnetic-switch
ブザー grove-buzzer
温度・湿度センサ grove-temperature-and-humidity-sencor
超音波センサ grove-ultrasonic-ranger
3 軸加速度センサ grove-accelerometer
GPS センサ grove-gps

追加センサーの使い方

センサー/アクチュエータ リンク
水センサー http://wiki.seeedstudio.com/Grove-Water_Sensor/
水分センサー http://wiki.seeedstudio.com/Grove-Moisture_Sensor/
衝突センサー http://wiki.seeedstudio.com/Grove-Collision_Sensor/
傾きセンサー http://wiki.seeedstudio.com/Grove-Tilt_Switch/
ラインセンサー http://wiki.seeedstudio.com/Grove-Line_Finder/
心拍センサー http://wiki.seeedstudio.com/Grove-Ear-clip_Heart_Rate_Sensor/
PIRモーションセンサー http://wiki.seeedstudio.com/Grove-PIR_Motion_Sensor/
RGB LED http://wiki.seeedstudio.com/Grove-Chainable_RGB_LED/
磁気スイッチ http://wiki.seeedstudio.com/Grove-Magnetic_Switch/
uhuru
株式会社ウフルはインターネットによる革新的なサービスがお客様企業の価値向上につながる事を目指し「テクノロジーと自由な発想で未来を創る」を企業理念に掲げています。エッジとクラウドを “つなぐ” IoTオーケストレーションサービス「enebular®」をベースにIoTやデジタルマーケティングの領域で顧客のビジネスに変革をもたらし続けております。
https://uhuru.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした