Intern

M5StackとCatM+GNSSモジュールで取得した位置情報をMQTTでNode-REDに送る

はじめに

 今回は「M5Stack Basic V2.7」と「CatM + GNSS」を使用して取得したGPS(位置情報)をMQTTでNode-REDに送る方法を紹介する

 ・M5StackをArduino IDEで動かす方法については過去の記事を参照

M5Stackとは何か、何ができるか 目次 ・M5Stackとは? ・M5Stackの中身 ・使用方法 ・活用例 M5Stackと...
M5StackをArduino IDEで動かす 目次 ・はじめに ・使用デバイス ・Arduino IDEのインストール ・BOARDS MANAGERの設定 ...

 ・M5Stack内部から取得した加速度データをMQTTでNode-REDに送る方法については過去の記事を参照

M5Stackの中の加速度センサーの情報をMqttでNode-REDに送ってみよう はじめに 今回は前回セットアップしたM5Stackの中にある加速度センサの情報をMQTTでNode-RED(Windows)にデ...

使用デバイス

 M5Stack Basic V2.7

 ・M5Stackの2.7バージョン、CatM+GNSSモジュールとの通信を管理し、取得したGPSデータを処理・表示する中心的な役割を担う。

 CatM + GNSSモジュール

 ・CatM+GNSSモジュールは、LTE Cat-M1通信とGNSS(GPS)機能を統合したモジュールであり、低消費電力で広域通信が可能なため、IoTデバイスに最適なモジュールとなっている。今回はGPS衛星から位置情報を取得し、そのデータをM5Stackに送信する役割を担う。

接続方法

 全体構成

 ハードウェア接続

 1. PCとM5StackをTypeC-USBで接続

 2. GROVEオス-メスケーブルを使用してM5StackとCatM+GNSSを接続

 3. CatM+GNSSに9~24Vの電源・GPSアンテナ・LTEアンテナを繋げる

 ライブラリマネジャーの設定

 ・ライブラリマネージャーで「PubSubClient」を検索&インストール

 コード概要

#include <M5Stack.h>
#include <WiFi.h>
#include <PubSubClient.h>

// WiFi設定
const char* ssid = "****";  // WiFiのSSID
const char* password = "****";  // WiFiのパスワード

// MQTTブローカーの設定
const char* mqtt_server = "****";  // ホストマシンのIPアドレス
const char* mqtt_topic = "/m5stack/gps";  // MQTTトピック

WiFiClient espClient;
PubSubClient client(espClient);

// GPSモジュールとのシリアル接続を定義
#define SerialGPS Serial2

void setup_wifi() {
  delay(10);
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(ssid);

  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.println("WiFi connected");
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
}

void reconnect() {
  // 再接続ループ
  while (!client.connected()) {
    Serial.print("Attempting MQTT connection...");
    // 接続を試みる
    if (client.connect("M5StackClient")) {
      Serial.println("connected");
    } else {
      Serial.print("failed, rc=");
      Serial.print(client.state());
      Serial.println(" try again in 5 seconds");
      // 再試行まで5秒待機
      delay(5000);
    }
  }
}

void setup() {
  M5.begin();
  Serial.begin(115200); // デバッグ用シリアル通信
  SerialGPS.begin(9600, SERIAL_8N1, 16, 17); // GPSモジュールとのシリアル接続設定

  Serial.println("Initializing GPS module...");

  // GPSモジュールの初期化
  SerialGPS.println("AT+CGNSPWR=1"); // GNSS電源をオンにする
  delay(1000);
  while (SerialGPS.available()) {
    char c = SerialGPS.read();
    Serial.print(c);
  }
  Serial.println();

  SerialGPS.println("AT+CGNSSEQ=\"RMC\""); // GNSS出力シーケンスを設定
  delay(1000);
  while (SerialGPS.available()) {
    char c = SerialGPS.read();
    Serial.print(c);
  }
  Serial.println();

  Serial.println("GPS initialized");

  setup_wifi();
  client.setServer(mqtt_server, 1883);
}

void loop() {
  if (!client.connected()) {
    reconnect();
  }
  client.loop();

  SerialGPS.println("AT+CGNSINF"); // GNSS情報を照会
  delay(1000);

  String gpsData = "";
  while (SerialGPS.available()) {
    char c = SerialGPS.read();
    gpsData += c;
  }

  if (gpsData.length() > 0) {
    Serial.println("Data received:");
    Serial.println(gpsData);

    // 受信データの解析
    if (gpsData.startsWith("AT+CGNSINF")) {
      int index = gpsData.indexOf(":");
      if (index != -1) {
        String gpsInfo = gpsData.substring(index + 1);
        String jsonPayload = parseGPSData(gpsInfo);

        // MQTTメッセージの送信
        client.publish(mqtt_topic, jsonPayload.c_str());

        // デバッグ用にシリアル出力
        Serial.println("Published GPS data:");
        Serial.println(jsonPayload);
      }
    } else {
      Serial.println("No valid GPS data");
    }
  }
  delay(5000); // 5秒待機後、再度照会
}

String parseGPSData(String gpsInfo) {
  gpsInfo.trim();
  String data[20];
  int index = 0;

  while (gpsInfo.length() > 0 && index < 20) {
    int commaIndex = gpsInfo.indexOf(",");
    if (commaIndex == -1) {
      data[index++] = gpsInfo;
      break;
    } else {
      data[index++] = gpsInfo.substring(0, commaIndex);
      gpsInfo = gpsInfo.substring(commaIndex + 1);
    }
  }

  String jsonPayload = "{";
  jsonPayload += "\"latitude\": " + data + ",";
  jsonPayload += "\"longitude\": " + data + ",";
  jsonPayload += "\"altitude\": " + data[5] + ",";
  jsonPayload += "\"speed\": " + data[6];
  jsonPayload += "}";

  return jsonPayload;
}

 コードの説明

 ① WifiとMQTTブローカーの接続(以下の内容をコードに記入):
  ・WifiのSSID → 右下のインターネットアクセスで確認
  ・Wifiのパスワード
  ・ホストマシンのIPアドレス → CMDで”ipconfig”するなどして確認

 ➁ 初期設定
  ・M5.begin()でM5Stackを初期化。
  ・Serial.begin(115200) データ転送速度
  ・SerialGPS.begin(9600, SERIAL_8N1, 16, 17) UART通信で実装するため、16/17Pinに設定する

 ➂ MQTTメッセージの送信
  ・client.publish(mqtt_topic, jsonPayload.c_str())
  ・PubSubClientライブラリを使用してMQTTメッセージを特定のTOPICに公開する

 ➃ データ取得ループ
  ・SerialGPS.println("AT+CGNSINF")でGNSS情報を要求
  ・取得したデータを解析し、緯度、経度、高度、速度などの情報を表示

 ポートが開いているか確認

 ① 管理者権限でCMDを立ち上げ、mosquittoを起動する

net start mosquitto

 ➁ 1883ポートが開いているか(LISTENINGされているか確認)

netstat -an | find "1883"

→ 開いていない、MQTT接続ができない場合
 ・Windowsのファイアウォールで1883ポートを開ける

 ・mosquitto.confファイルに以下のコードを挿入する
  →メモ帳アプリ等を管理者権限で開き、ファイルを開くを押す
   C:\Program Files\mosquittoで全てのファイルを表示し、
   mosquitto.confファイルを開く

listener 1883
allow_anonymous true

Node-REDのフロー

全体像

MQTT INノードの設定

 ・画像の通り設定

実行結果

Arduino IDEの画面

-> Data received:
  GPSモジュールからデータが受信されたことを示している

-> AT+CGNSINF
  M5StackがGPSモジュールに送信したATコマンド

-> +CGNSINF:1,1,20240724030344.000,~
  GPSモジュールから返ってきたデータ

-> OK
  GPSモジュールからの応答

-> Published GPS data:
  GPSデータがMQTTトピックに公開されたことを示す

-> {“latitude”: 35.678178,”longitude”: 139.687137,”altitude”: 51.589,”speed”: 0.00}
  MQTTメッセージとして公開されたGPSデータ

緯度(Latitude):35.678227
経度(Longitude):139.687100
高度(Altitude):42.436
速度(Speed):0.00

→ 取得したGPS(位置)データをNode-RED上で確認することができた