Wio LTE 体験会にいってきました

Wio LTE 体験会にいってきました

f:id:ueponx:20171105122920j:plain

先日、連休中に行われたWio LTE 体験会にいってきました。

seeed.connpass.com

ここ最近Seeedさんによく行っているような気がします。

Wio LTEについては

soracom.jp github.com

このあたりをみていただくとして、LTEの通信とGroveのセンサーが使えてArduino IDEでプロトタイピングできるIOボードって感じでしょうか。(間違っていたらごめんなさい)

最近は、Arduino IDEの環境で開発するボードが増えてきているので、比較的とっつきやすいかなと思います。

環境設定

まずはパッケージを開けてアンテナコネクタにケーブルを接続し、続いてSIMカードを指します。SIMコネクタの部分に関しては2階建て構造になっているので下側(基板側)にコネクタ面を基板側の向きで差込ます。

このあたりはSORACOMの松下さんのブログが詳しく書いてあります。

blog.soracom.jp

接続が終わると以下のような感じになります。

f:id:ueponx:20171105122844j:plain

ここまでできたら後はソフトウエアの環境設定になりますが基本的にはこちらの情報を元に設定していけばLチカまではいけるかなと思います。

github.com

自分はArduino IDEは既にインストールしていたので以下の手順を踏んでいきました。

  • Wio Tracker LTEボードの追加
  • Wio LTEライブラリの追加
  • DFUモード起動時のWinUSBデバイスドライバーに切り替え
  • 通常モード起動時のVirtual COM Portデバイスドライバーのインストール*1

    この4つを行いました。

    自分は通常モード起動時のドライバーの認識では手順にはない認識状態になりました。とりあえずそのまま作業を行い初回の書き込みまではうまく行ったのですが、その後シリアルモニタが開けなかったので、この状態でもVirtual COM Portデバイスドライバーのインストールを行った方がいいかと思います。

    USBシリアルデバイスとして認識されている f:id:ueponx:20171105115958j:plain

    初回の書き込み後、シリアルデバイスの認識が以下に変化しました。 f:id:ueponx:20171105120016j:plain

    インストール後は【STMicroelectronics Virtual COM Port】に変化してシリアルモニタで確認できるようになります。

    f:id:ueponx:20171105122824j:plain

    SampleのフルカラーLEDのLチカも動作しました。

    Groveセンサーの接続(温湿度センサー)

    続いてはGrove接続のセンサーである温湿度センサーを接続してみます。

    Grove - Temperature&Humidity Sensor - Seeed Wiki

    多分これだと思います。

    こちらサンプル例のスケッチから

    f:id:ueponx:20171105124703j:plain

    上記のように操作してgrove-temperature-and-humidity-sensorを選択します。

    センサーはソースにも書いてある様に【D38】に接続をします。

    【抜粋】

    #include <WioLTEforArduino.h>
    
    #define SENSOR_PIN    (WIOLTE_D38)
    
    void setup()
    {
      TemperatureAndHumidityBegin(SENSOR_PIN);
    }
    …(以下略)…
    

    続いて書き込みになります。書き込み時にはボードをDFUモードにするのを忘れないでください。DFUモードと通常モードの違いはデバイスマネージャを確認するか、Arduino IDEで【ツール】→【シリアルポート】の部分がグレーアウトしているかを見てもわかるかなと思います。(…後者は多分)

    書き込みは問題ないと思いますので、正常に終了したらリセットボタンを押して通常モードで起動します。そして、シリアルモニターを起動すると以下のような画面になると思います。

    f:id:ueponx:20171105120051j:plain

    これで温度と湿度が取得できました。

    LTEで通信(IFTTTで通知する)

    先程まででセンサーの値が取得できたので、次はLTEを使った通信になります。 IFTTTのWebhooksを使用してデータを送信し、送信後PushBulletを使ってプッシュ通知を行います。

    ifttt.com

    Pushbullet - Your devices working better together

    Pushbulletはスマートフォンのアプリでもありますが、Chrome拡張もあります。 f:id:ueponx:20171105131254p:plain

    ハードの接続はこれまでの手順で終わっていますので、特に作業はありません。

    こちらもサンプルを使用しますが、そのままではダメなのでベースにして作業を行います。

    IFTTTの設定

    IFTTTに登録する新しいアプリを作成します。(事前にPushBulletのサービスへログインしておいてください。

    f:id:ueponx:20171105132645j:plain

    IFTTTにログインして画面右上の下向き矢印をクリックし、【New Applet】を選択します。ここからアプリの設定が開始になります。

    f:id:ueponx:20171105132813p:plain

    画面の【[+]This】のボタンをクリックします。するとトリガーとなるサービスの選択画面に遷移します。

    f:id:ueponx:20171105133042p:plain

    今回は検索ボックスにWebhooks(旧MakerChannel)を入力します。

    f:id:ueponx:20171105133312p:plain

    すると、サービスが一つに絞られます。このWebhooksのアイコンをクリックします。

    f:id:ueponx:20171105133437p:plain

    つづいでトリガーの選択になりますが、ここは一つしかないので【Receive a web request】を選択します。

    f:id:ueponx:20171105134305p:plain

    トリガーに名前を付けます。これをプログラムでも使用するのでメモします。自分はwiolte_sampleと名前を付けました。名前が決まったら【Create trigger】のボタンをクリックします。

    f:id:ueponx:20171105140045p:plain

    次にトリガーに対する動作の設定になります。トリガーの設定同様に【[+]That】をクリックすると、サービス選択画面になります。

    f:id:ueponx:20171105140501p:plain

    検索ボックスにpushbulletを入力すると、サービスが絞り込まれますので、PushBulletのアイコンをクリックします。

    f:id:ueponx:20171105140710p:plain

    Pushbulletにはサービスが4つありますが、今回はPush a noteを使用します。アイコンというかボタンをクリックします。

    f:id:ueponx:20171105142719p:plain

    あとは細かい設定ですが、今回は通信ができたことが知りたいので、そのままにして【Create action】のボタンをクリックします。

    f:id:ueponx:20171105143633p:plain

    最後の確認画面になるので、【Finish】ボタンをクリックします。

    f:id:ueponx:20171105144141p:plain

    これで一応IFTTT側の設定はおわりなのですが、WebhooksのKeyも必要になるのでそれを取得しておきます。(自分はここで毎回悩みます) 画面内の左上のWebhooksの文字をクリックします。

    f:id:ueponx:20171105144555p:plain

    するとWebhooksのサービス画面になります。

    f:id:ueponx:20171105145116p:plain

    画面内の【Documentation】のボタンをクリックします。

    f:id:ueponx:20171105173715p:plain

    するとキーが表示されるのでこれもメモしておきます。

    コードの改良

    忘れずに冒頭のWEBHOOK_EVENTNAMEWEBHOOK_KEYを自分の作成したものに変更します。

    【ifttt-webhookのサンプル例-抜粋】

    #include <WioLTEforArduino.h>
    #include <stdio.h>
    
    #define APN               "soracom.io"
    #define USERNAME          "sora"
    #define PASSWORD          "sora"
    
    #define WEBHOOK_EVENTNAME "wiolte_sample" //メモしたものに変更
    #define WEBHOOK_KEY       "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" //メモしたものに変更
    #define WEBHOOK_URL       "https://maker.ifttt.com/trigger/"WEBHOOK_EVENTNAME"/with/key/"WEBHOOK_KEY
    
    …(以下略)…
    

    オリジナルのサンプルでは、起動してからの起動時間を表示するものなので、これをGroveセンサーで取得した温度と湿度に変更します。 先程のgrove-temperature-and-humidity-sensorサンプルとifttt-webhookサンプルをあわせたものになります。

    【ifttt-webhook-改】

    #include <WioLTEforArduino.h>
    #include <stdio.h>
    
    #define APN               "soracom.io"
    #define USERNAME          "sora"
    #define PASSWORD          "sora"
    
    #define WEBHOOK_EVENTNAME "wiolte_sample" //メモしたものに変更
    #define WEBHOOK_KEY       "XXXXXXXXXXXXXXXXXXXXXXXXXXXX" //メモしたものに変更
    #define WEBHOOK_URL       "https://maker.ifttt.com/trigger/"WEBHOOK_EVENTNAME"/with/key/"WEBHOOK_KEY
    
    #define INTERVAL          (60000)
    
    #define SENSOR_PIN    (WIOLTE_D38)
    
    WioLTE Wio;
    
    void setup() {
      delay(200);
    
      SerialUSB.println("");
      SerialUSB.println("--- START ---------------------------------------------------");
    
      SerialUSB.println("### I/O Initialize.");
      Wio.Init();
    
      SerialUSB.println("### Power supply ON.");
      Wio.PowerSupplyLTE(true);
      delay(5000);
    
      SerialUSB.println("### Turn on or reset.");
      if (!Wio.TurnOnOrReset()) {
        SerialUSB.println("### ERROR! ###");
        return;
      }
    
      SerialUSB.println("### Connecting to \""APN"\".");
      delay(5000);
      if (!Wio.Activate(APN, USERNAME, PASSWORD)) {
        SerialUSB.println("### ERROR! ###");
        return;
      }
      
      SerialUSB.println("### init Sensor.");  
      TemperatureAndHumidityBegin(SENSOR_PIN);
    }
    
    void loop() {
      char data[100];
      int status;
    
      float temp;
      float humi;
    
      if (!TemperatureAndHumidityRead(&temp, &humi)) {
        SerialUSB.println("ERROR!");
        goto err;
      }
      SerialUSB.print("Current humdity = ");
      SerialUSB.print(humi);
      SerialUSB.print("%  ");
      SerialUSB.print("temperature = ");
      SerialUSB.print(temp);
      SerialUSB.println("C");
    
      SerialUSB.println("### Post.");
      sprintf(data, "{\"value1\":\"temp %f\", \"value2\":\"humi %f\"}", temp, humi);
      SerialUSB.print("Post:");
      SerialUSB.print(data);
      SerialUSB.println("");
      if (!Wio.HttpPost(WEBHOOK_URL, data, &status)) {
        SerialUSB.println("### ERROR! ###");
        goto err;
      }
      SerialUSB.print("Status:");
      SerialUSB.println(status);
    
    err:
      SerialUSB.println("### Wait.");
      delay(INTERVAL);
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //
    
    int TemperatureAndHumidityPin;
    
    void TemperatureAndHumidityBegin(int pin)
    {
      TemperatureAndHumidityPin = pin;
      DHT11Init(TemperatureAndHumidityPin);
    }
    
    bool TemperatureAndHumidityRead(float* temperature, float* humidity)
    {
      byte data[5];
      
      DHT11Start(TemperatureAndHumidityPin);
      for (int i = 0; i < 5; i++) data[i] = DHT11ReadByte(TemperatureAndHumidityPin);
      DHT11Finish(TemperatureAndHumidityPin);
      
      if(!DHT11Check(data, sizeof (data))) return false;
      if (data[1] >= 10) return false;
      if (data[3] >= 10) return false;
    
      *humidity = (float)data[0] + (float)data[1] / 10.0f;
      *temperature = (float)data[2] + (float)data[3] / 10.0f;
    
      return true;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    //
    
    void DHT11Init(int pin)
    {
      digitalWrite(pin, HIGH);
      pinMode(pin, OUTPUT);
    }
    
    void DHT11Start(int pin)
    {
      // Host the start of signal
      digitalWrite(pin, LOW);
      delay(18);
      
      // Pulled up to wait for
      pinMode(pin, INPUT);
      while (!digitalRead(pin)) ;
      
      // Response signal
      while (digitalRead(pin)) ;
      
      // Pulled ready to output
      while (!digitalRead(pin)) ;
    }
    
    byte DHT11ReadByte(int pin)
    {
      byte data = 0;
      
      for (int i = 0; i < 8; i++) {
        while (digitalRead(pin)) ;
    
        while (!digitalRead(pin)) ;
        unsigned long start = micros();
    
        while (digitalRead(pin)) ;
        unsigned long finish = micros();
    
        if ((unsigned long)(finish - start) > 50) data |= 1 << (7 - i);
      }
      
      return data;
    }
    
    void DHT11Finish(int pin)
    {
      // Releases the bus
      while (!digitalRead(pin)) ;
      digitalWrite(pin, HIGH);
      pinMode(pin, OUTPUT);
    }
    
    bool DHT11Check(const byte* data, int dataSize)
    {
      if (dataSize != 5) return false;
    
      byte sum = 0;
      for (int i = 0; i < dataSize - 1; i++) {
        sum += data[i];
      }
    
      return data[dataSize - 1] == sum;
    }
    
    ////////////////////////////////////////////////////////////////////////////////////////
    

    編集が終了したら書き込みです。何回もいいますが、書き込み時にはボードをDFUモードにするのを忘れないでください。 書き込みが終わったらリセットして通常モードで起動します。

    f:id:ueponx:20171105150404j:plain

    動作させるとシリアルモニター側に接続の様子と温度湿度の様子が表示され、定期的にPushBulletから通知がトースト表示されるようになります。

    おわりに

    Wio LTEを使ってセンサー情報をつかったプッシュ通知ができました。ここまででだいたい2時間ぐらいかなと思います。 (IFTTTの設定で手こずらなければもっと早くできたかなと思いますが。)サンプルも充実し、使いやすいので かなり注目のデバイスです。 この後にはSORACOM Harvestにもアップロードする実験をしたのですが、それについては別エントリーで書こうかなと思います。こっちもサンプルのソースを改良するだけでうまく行きますよ。

    購入するのであれば、センサーセットが12月に発売されるのでそっちがいいかなと思います。

    soracom.jp

    Seeedの坪井さん、松岡さん、参加者のみなさん、どうもありがとうございました。

    次回も開催されるようなので興味のあるかたは参加してはどうでしょうか?

    seeed.connpass.com

    *1:ドライバーの取得は申請しないと行けないのでこの部分だけかなり時間がかかります。 公式のWikiが変更されましたので短縮されたと思います。 InstallVCOMDriver ja · SeeedJP/WioLTEforArduino Wiki · GitHub