M5Stack+GPSユニット+通信ユニット+IoT回線でGPSロガーを作る

木曜日 , 26, 5月 2022 2 Comments

M5StackとGPSユニット、通信ユニットを組み合わせてGPSロガーを作成してみました。(『M5Stack/ATOMとGPSユニットを使って位置情報をクラウドに保存する / M5シリーズUIFlowからKintoneに直接データをアップロードする』の続きになります。)
前回の記事ではWi-Fi環境を使いkintoneへアップロードしていましたが、今回はIoT回線(SORACOM)を使ってアップロードしています。

IMG_8973

SORACOM以外のIoT回線でもCAT-Mユニットが対応するSIMと通信方式であれば接続できます。
今回のサンプルプログラムではkintoneのAPI呼び出しを簡略化するためにSORACOM独自のゲートウェイサービスを使用しているので、SORACOM以外のIoT回線に転用する際は適宜環境に合わせてアレンジが必要です。

必要なもの

使い方

  • kintone上にアプリ(データベース)を作成し、外部からアクセスするためのAPIトークンを発行、および適切なアクセス権限を設定します。
    サンプルプログラムでは、「gps」というアプリを作成し、「gps_id」「gps_datetime」「latitude」「longitude」「altitude」「accx」「accy」「accz」というフィールドを文字列(1行)で定義しています。

    2022-05-26 (1)

    ※APIからアップロードする際に使用するのは、kintone上の「フィールド名」(設定画面一番上の項目)ではなく「フィールドコード」(設定画面一番下の項目)である点に注意が必要です。
    ※M5Stackに内蔵されたセンサーを使い加速度情報を取得、その値を「accx」「accy」「accz」に格納する予定でしたが加速度を取得するとデータ通信が接続断となってしまうため使用していません。

2022-05-26 (2)

  • PlatformIO上でソースコードをビルドしM5Stackに転送します。
  • 転送後M5Stackの電源を投入するとモデムの初期化とデータ通信の接続を行い、接続が完了するとGPS計測・表示、kintone上へのアップロードを繰り返します。
    kintone上にアップロードされるデータは以下のようになります。
    「gps_datetime」に設定される値はGMTです。

    2022-05-07 (1)

ソースコード

//
//  M5Stack Grayに接続したGPSユニットとCAT-Mユニットを使い計測したGPS位置情
//  報をSORACOMを経由してkintoneにアップロードするプログラム
//
//    PORT A: CAT-Mユニット
//    PORT B: GPSユニット
//    PORT C: 未使用
//
//  《事前準備》
//    1)kintone上には以下のフィールドを持つアプリを定義する
//      gps_id: GPS計測機器ID
//      gps_datetime: 日時
//      latitude: 緯度
//      longitude: 経度
//      altitude: 高度
//      accx: X方向加速度
//      accy: Y方向加速度
//      accz: Z方向加速度
//
//    2)SORACOM Beamからkintone上のアプリへアクセスできるように設定する
//      https://soracom.jp/services/beam/
//
// This software is distributed under the license of NYSL.
// http://www.kmonos.net/nysl/
//

#define TINY_GSM_MODEM_SIM7080
#define M5STACK_MPU6886 

#include <M5Stack.h>
#include <TinyGsmClient.h>
#include <TinyGPS++.h>

// SORACOMのAPN
const char GSM_APN[] = "soracom.io";
// SORACOM接続時のユーザ名
const char GSM_USERNAME[] = "sora";
// SORACOM接続時のパスワード
const char GSM_PASSWORD[] = "sora";

// SORACOM Beam サーバ
const char API_SERVER[] = "beam.soracom.io";
// SORACOM Beam URL
const char API_RESORCE[] = "/k/v1/record.json";
// SORACOM Beam ポート
const uint16_t API_PORT = 8888;

// kintoneアプリのアプリID(kintone環境に合わせて修正)
const char APP_ID[] = "1";

// GPSを計測機器のID
const char GPS_ID[] = "M5_001";

TinyGsm       modem(Serial1);
TinyGsmClient client(modem);
TinyGPSPlus   gps;

// kintoneのアップロードデータ編集用
char kintone_payload[512];

float accx0, accy0, accz0;
float accxT, accyT, acczT;
float accx, accy, accz;

void setup() {

  M5.begin(true, false, true, true);
  M5.Power.begin();

  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setTextSize(2);

  Serial.begin(115200);

  M5.Lcd.println("Initializing...");

  // M5センサ初期化
  M5.IMU.Init();

  // シリアル初期化
  Serial1.begin(9600, SERIAL_8N1, 22, 21);  // Modem: M5Stack Gray
  Serial2.begin(9600, SERIAL_8N1, 36, 26);  // GPS:   M5Stack Gray

  delay(100);

  // モデム初期化
  M5.Lcd.println("Restart modem");
  modem.restart();

  // modem.gprsConnect(GSM_APN, GSM_USERNAME, GSM_PASSWORD);
  // ネットワーク登録待ち
  M5.Lcd.print("Wait for network");
  while (!modem.waitForNetwork()) {
    M5.Lcd.print(".");
  }
  M5.Lcd.println("");

  // 接続
  modem.gprsConnect(GSM_APN, GSM_USERNAME, GSM_PASSWORD);

  // データ通信接続待ち
  M5.Lcd.print("Wait for connection");
  while (!modem.isNetworkConnected()) {
    M5.Lcd.print(".");
  }
  M5.Lcd.println("");

  // // 起動時点の加速度を取得
  // // ここで加速度を読み取ろうとするとネットワーク接続断
  // M5.IMU.getAccelData(&accx0, &accy0, &accz0);
}

void loop() {

  // // ここで加速度を読み取ろうとするとネットワーク接続断またはプログラムが落ちる
  // M5.IMU.getAccelData(&accxT, &accyT, &acczT);
  // accx = accxT - accx0;
  // accy = accyT - accy0;
  // accz = acczT - accz0;

  // 稼働時間を見るためにローカル時間を取得
  struct tm tm;
  getLocalTime(&tm);

  // GPS計測
  while (Serial2.available() > 0) {
    gps.encode(Serial2.read());
  }

  // 計測値を表示
  M5.Lcd.fillScreen(BLACK);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE);
  M5.Lcd.setCursor(0, 0);

  M5.Lcd.printf("LOCAL=%04d/%02d/%02d %02d:%02d:%02d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
  M5.Lcd.printf("  GPS=%04d/%02d/%02d %02d:%02d:%02d\n", gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second());
  M5.Lcd.printf("\n\n");
  M5.Lcd.printf("  LAT=%.6f\n", gps.location.lat());
  M5.Lcd.printf("  LNG=%.6f\n", gps.location.lng());
  M5.Lcd.printf("  ALT=%.2f\n", gps.altitude.meters());
  M5.Lcd.printf("\n\n");

  M5.Lcd.printf("ACC-X=%f\n", accx);
  M5.Lcd.printf("ACC-Y=%f\n", accy);
  M5.Lcd.printf("ACC-Z=%f\n", accz);

  // データ通信接続ができていない場合、接続を試みる
  if(!modem.isGprsConnected()) {
    M5.Lcd.print("\nReconnecting");
    modem.gprsConnect(GSM_APN, GSM_USERNAME, GSM_PASSWORD);
    while (!modem.isNetworkConnected()) {
      M5.Lcd.print(".");
    }    
  }

  // SORACOM Beam経由でkintoneにデータをアップロードする
  sprintf(kintone_payload, 
    "{\"app\":\"%s\", \"record\":{\"gps_id\":{\"value\":\"%s\"},\"gps_datetime\":{\"value\":\"%04d/%02d/%02d %02d:%02d:%02d\"},\"latitude\":{\"value\":\"%3.6f\"},\"longitude\":{\"value\":\"%3.6f\"},\"altitude\":{\"value\":\"%.2f\"},\"accx\":{\"value\":\"%.4f\"},\"accy\":{\"value\":\"%.4f\"},\"accz\":{\"value\":\"%.4f\"}}}", 
    APP_ID, 
    GPS_ID,
    gps.date.year(), gps.date.month(), gps.date.day(), gps.time.hour(), gps.time.minute(), gps.time.second(),
    gps.location.lat(), gps.location.lng(), gps.altitude.meters(),
    accx, accy, accz);

  client.connect(API_SERVER, API_PORT);
  client.printf("POST %s HTTP/1.1\r\n", API_RESORCE);
  client.printf("Host: %s\r\n", API_SERVER);
  client.printf("Content-Length: %lu\r\n", strlen(kintone_payload));
  client.printf("Connection: close\r\n\r\n");
  client.println(kintone_payload);

  while (client.connected()) {
    String line = client.readStringUntil('\n');
    if (line == "\r") {
      break;
    }
  }

  client.stop();

  delay(500);
}


まとめ

できあがったGPSロガーを持ち歩き市街地~山間部、一般道・高速道をドライブしてみました。

人家もまばらな峠付近で5分程度通信が行えない状況がありましたが、その他の地域では非常に良好な通信状態が維持できていることを確認しました。(SORACOMはpaln-Dを契約)
参考までに通信が途切れた地域を掲載します。

2 thoughts on “ : M5Stack+GPSユニット+通信ユニット+IoT回線でGPSロガーを作る”
  • […] 通信ユニットとIoT回線を使いスタンドアロンでも動きGPSロガーを「M5Stack+GPSユニット+通信ユニット+IoT回線でGPSロガーを作る」 で公開しました。 […]

  • pizzaman より:

    興味深い情報をありがとうございます。
    SIMCOMのSIM7080GはGNSSとLTEを同時に使うことができないようですね。
    GNSSの機能を使うと通信が切れるのは謎だったのですが、ここで同じ経験をしている人がいらっしゃいました。
    https://stackoverflow.com/questions/61857667/sim7080g-module-cant-send-data-over-tcp-while-using-gnss/61884727#61884727

    チップのドキュメントに書いていないのは反則かと笑

  • pizzaman へ返信する コメントをキャンセル

    メールアドレスが公開されることはありません。 が付いている欄は必須項目です

    このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください