Edited at

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


はじめに

本コンテンツは、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/