sakura.io + Arduino + GROVE でGPSロガー (4)

さくらインターネットsakura.io を使って電子工作初心者がIoTなGPSロガーを作るメモ。その4
[その1] [その2] [その3] [その4] [その5] [その6]


プラットフォームへのデータ送信

まずsakura.ioのコントロールパネルからプロジェクトを追加。
モジュールを登録して連携サービスに「WebSocket」を追加しておく。

さくらインターネットのサンプルスケッチを読む。

/* /SakuraIO/examples/Standard.ino 前後省略しています */

  // Tx Queue
  uint8_t ret;

  ret = sakuraio.enqueueTx((uint8_t)0, (int32_t)counter);
  Serial.print("Enqueue ");
  Serial.println(ret);

  uint8_t avail;
  uint8_t queued;

  sakuraio.getTxQueueLength(&avail, &queued);

  Serial.print("Tx Available=");
  Serial.print(avail);
  Serial.print(" Queued=");
  Serial.println(queued);

  if(queued >= 30){

    ret = sakuraio.clearTx();
    Serial.print("Clear ");
    Serial.println(ret);

  }else if(queued >= 5){

    ret = sakuraio.send();
    Serial.print("Send ");
    Serial.println(ret);
  }

sakuraio.enqueueTxでキューに追加する。
sakuraio.getTxQueueLength でキューの状態を確認。

sakura.ioの基板上のキューは32 個まででキューが5個以上になればsakuraio.sendでまとめて送信。
キューが30個以上になればsakuraio.clearTxでキューの中身をクリアしているようだ。

チャンネルIDは0~127で1つのチャンネルに8 byteのデータが保存できる。
また一度に16 チャンネル分を送信できる。
IntやFloatなどの数値データを送受信するのに適しているようだ。

/* /SakuraIO/examples/Standard.ino 前後省略しています */

 // Unixtime
  uint32_t unixtime = (uint32_t)(sakuraio.getUnixtime()/1000UL);

  Serial.print("Unixtime ");
  Serial.println(unixtime);

sakuraio.getUnixtimeでUnixタイムスタンプを取得出来る便利な機能がある。


GPSの緯度・経度を送ってみる

sakura.ioは月に10,000回以内の通信であれば基本料金で利用できます。
24時間連続稼動する場合にはおよそ5分に1回通信が出来る計算となります。

今回は20秒間隔でGPSの「緯度・経度」2チャンネル分の情報をキューに追加して、キューが6個以上たまればプラットフォームに送信するようにしてみます。およそ1分間隔で通信する計算になります。

simple_gps_6.ino の内容

#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <SakuraIO.h>

SakuraIO_I2C sakuraio;
TinyGPSPlus gps;
SoftwareSerial ss(2, 3);

int led_sakuraio = 4;
int led_gps = 6;

//---GPSの更新間隔
const unsigned long GPS_UPDATE_TIME = 20000;

//---最後にキューに追加した時間
unsigned long queued_time = 0;

//---最後にGPSのLEDが光った時間
unsigned long led_gps_time = 0;

///=======================================================================
//   + setup()
///=======================================================================
void setup() {

    //---Serialポートを開く
    Serial.begin(9600);

    //---SoftwareSerialポートを開く
    ss.begin(9600);

    //---出力に設定
    pinMode(led_sakuraio, OUTPUT);
    pinMode(led_gps, OUTPUT);

    //---起動時LEDを点灯
    digitalWrite(led_sakuraio, HIGH);
    digitalWrite(led_gps, HIGH);

    delay(2000);

    //---2秒後にLEDを消灯
    digitalWrite(led_sakuraio, LOW);
    digitalWrite(led_gps, LOW);
}

///=======================================================================
//   + loop()
///=======================================================================
void loop() {

    //---------------------------------------------
    //   + sakura.ioがオンラインの時
    //---------------------------------------------

    if ((sakuraio.getConnectionStatus() & 0x80) == 0x80) {

        digitalWrite(led_sakuraio, LOW);

        //---------------------------------------------
        //   + sakura.ioがオフラインの時
        //---------------------------------------------

    } else{

        //---0.5秒間隔の点滅
        if(millis() % 1000 > 500) {

            digitalWrite(led_sakuraio, HIGH);

        } else{

            digitalWrite(led_sakuraio, LOW);
        }
    }

    //---GPS用LEDを1秒で消す
    if(led_gps_time && (millis() - led_gps_time) > 1000){

        //--GPS用のLEDを消す
        digitalWrite(led_gps, LOW);
    }

    //---------------------------------------------
    //   + GPS受信データの展開
    //---------------------------------------------

    while (ss.available() > 0) {

        //---GPSモジュールからの読み込み
        char c = ss.read();

        //---GPSからの生データ
        //-Serial.print(c);

        //---GPSの[NMEA]形式の変換
        gps.encode(c);

        //---------------------
        //   +GPS位置情報更新
        //---------------------

        if (gps.location.isUpdated()) {

            //---緯度
            float gps_lat = gps.location.lat();

            //---経度
            float gps_lng = gps.location.lng();

            //---シリアルモニタに表示する
            Serial.print(F(" LAT=")); Serial.print(gps_lat, 6);
            Serial.print(F(" LNG=")); Serial.println(gps_lng, 6);

            //---------------------
            //   +キューに追加
            //---------------------

            //---20秒間隔でGPS情報をキューに追加する
            if(!queued_time || (millis() - queued_time) > GPS_UPDATE_TIME){

                //---GPS用のLEDを点灯
                digitalWrite(led_gps, HIGH);

                //---GPSのLEDが光った時間
                led_gps_time = millis();

                //---Queueに追加する
                EnQueue(gps_lat, gps_lng);
            }
        }
    }
}

///=======================================================================
//   +Queueに追加する
///=======================================================================
void EnQueue(float p_gps_lat, float p_gps_lng) {

    uint8_t ret;

    //---LAT
    ret = sakuraio.enqueueTx((uint8_t)0, (float)p_gps_lat);
    Serial.print(F(" Enqueue_0 ")); Serial.print(ret);

    //---LNG
    ret = sakuraio.enqueueTx((uint8_t)1, (float)p_gps_lng);
    Serial.print(F(" Enqueue_1 ")); Serial.println(ret);

    //---キューに追加した時間
    queued_time = millis();

    //---------------------------------------------
    //   + sakura.ioに送信する
    //---------------------------------------------

    uint8_t avail;
    uint8_t queued;

    sakuraio.getTxQueueLength(&avail, &queued);

    Serial.print(" Tx Available="); Serial.print(avail);
    Serial.print(" Queued="); Serial.println(queued);

    //---30個以上でクリア
    if(queued >= 30){

        ret = sakuraio.clearTx();
        Serial.print(" Clear "); Serial.println(ret);

        //---6個以上で送信
    }else if(queued >= 6){

        ret = sakuraio.send();
        Serial.print(" Send "); Serial.println(ret);
    }
}

sakura.ioコントロールパネルの「WebSocket」の画面に送信結果が表示されています。


GPSの送信部分は完成!と思いきや。
実際に持ち出して動作テストしてみると何だこれ使えないとなります。

キューに保存出来るのは32個。20秒毎に2チャンネル分を消費するので5分間でキューが溢れます。
つまり5分以上sakura.ioがオフラインになると座標データが消失するのです。

また車載電源などを利用して自動車用のGPSとした場合、エンジンを切った時点でキューに残っている座標が消失します。

田舎の山道などをドライブするとごっそり位置情報が消えてるのがわかります…。

…その問題は後回しにして次回はプラットフォームからのデータの受取部分を書いてみます。