PR

【プログラミング入門】M5Stackで、シリアル通信メッセージをJSON形式に変換してWi-Fi(MQTT)でラズパイに送る方法

JSON
スポンサーリンク

今回は、ArduinoIDEのシリアルモニタで、シリアル通信メッセージを送って、これを受信したM5StackがJSON形式に変換して、Wi-Fi(MQTT)で、ラズパイに送る方法を紹介します。

想定ケースは、車両のECUからの車両情報を、M5Stack経由で、AWSなどのクラウドへアップロードするケースです。シリアル通信部分を、CANやLIN、SPI等の通信に差し替えることで、様々な用途があると思っています。

前提

・M5Stack
・Raspberry Pi4

 ラズパイには、MQTTブローカであるmosquitto、MQTTクライアントのmosquitto-clientsがインストールされていることが前提です。

M5StackとRaspberry Piは、同じWi-Fiを使います。

M5StackとラズパイをWi-Fi(MQTT)で繋ぎ、JSONデータを通信する方法

構成

ArduinoIDEに、必要なライブラリをインストールする

ライブラリは、以下をインストールします。

・PubSubClient
・ArduinoJSON

ArduinoIDEの「スケッチ」-「ライブラリをインクルード」-「ライブラリを管理」を選択する

ライブラリマネージャでは、「PubSubClient」と入力すると、PubSubClientを見つけられます。インストールボタンがありますので、これを押してインストールします。

「ArdunioJSON」ライブラリも、同様にインストールします。

サンプルコード(M5Stack)

ArduinoIDEを起動して、以下のサンプルコードをコピーしてください。


#define M5STACK_MPU6886

#include <WiFi.h>
#include <PubSubClient.h>
#include <M5Stack.h>
#include <stdio.h>
#include <string.h>
#include <ArduinoJson.h>

////////////////////////////////////////////////////////////////////////////////

// Wi-FiのSSID
char *ssid = "**********";

// Wi-Fiのパスワード
char *password = "************";

// MQTTの接続先(ラズパイ)のIP
const char *endpoint = "***.***.***.***";

// MQTTのポート
const int port = 1883;

// デバイスID デバイスIDは機器ごとにユニークにします
char *deviceID = "M5Stack";

// メッセージを知らせるトピック
char *pubTopic = "/pub/M5Stack";

// メッセージを待つトピック
char *subTopic = "/sub/M5Stack";

////////////////////////////////////////////////////////////////////////////////

WiFiClient httpsClient;
PubSubClient mqttClient(httpsClient);

// シリアル通信の初期化
void setup_serial(){
  Serial.begin(115200);
  while (!Serial) continue;
}

// Wi-Fiモジュールの初期化と開始
void setup_wifi(){
  
  Serial.println("Connecting to ");
  Serial.print(ssid);

  // WiFi接続性改善のため、いったん切断
  WiFi.disconnect( true, true ); //WiFi OFF, eraseAP=true
  delay(500);

  // WiFi開始
  WiFi.begin(ssid, password);
 
  // Wi-Fi接続待ち
  while (WiFi.status() != WL_CONNECTED){
    delay(500);
    M5.Lcd.print(".");
  }

  // WiFi接続成功メッセージの表示
  Serial.println("\nWiFi Connected.");
  M5.Lcd.setCursor(10, 40);
  M5.Lcd.setTextSize(2);
  M5.Lcd.println("WiFi Connected.");

  // M5StackのIPアドレスを表示
  M5.Lcd.print("IP address: ");
  M5.Lcd.println(WiFi.localIP());
  
}

void setup(){

  // M5Stack objectの初期化
  M5.begin();
  M5.Power.begin();
  M5.IMU.Init();

  setup_serial();

  // 画面初期設定
  M5.Lcd.fillScreen(TFT_NAVY);
  M5.Lcd.setCursor(10, 10);
  M5.Lcd.setTextSize(3);
  M5.Lcd.printf("START");

  // Wi-Fi処理の開始
  setup_wifi();

  // MQTTクライアントの初期化
  mqttClient.setServer(endpoint, port);

  // MQTT接続開始
  connectMQTT();

}

// MQTT接続処理
void connectMQTT(){

  // MQTT接続待ち
  while (!mqttClient.connected()){
    if (mqttClient.connect(deviceID)){
      // 所定のデバイスと接続した
      Serial.println("Connected.");
      int qos = 0;
      mqttClient.subscribe(subTopic, qos);
      Serial.println("Subscribed.");
    }else{
      // 所定のデバイスと接続失敗 ⇒ 再トライする
      Serial.print("Failed. Error state=");
      Serial.print(mqttClient.state());
      // Wait 5 seconds before retrying
      delay(5000);
    }
  }
}

// MQTT接続管理
void mqttLoop(){
  // MQTT接続状態を監視し、切断されていたら、再接続を試みる
  if (!mqttClient.connected()){
    connectMQTT();
  }
  // MQTTクライアント側の定期処理の実行
  mqttClient.loop();
}

// 文字列 = split(元の文字列,分割文字列,分割した後何番目の文字列か)
String split(String data, char separator, int index){
    int found = 0;
    int strIndex[] = {0, -1};
    int maxIndex = data.length();
    int endcheck = false;

    for(int i=0; i < maxIndex; i++){
        if( data.charAt(i) == separator ){
            found++;
            if ( found == index ){ strIndex[0] = i+1; }
            if ( found == index+1 ){ strIndex[1] = i; endcheck=true; }
            if(endcheck){ break; }
        }
    }
    return (strIndex[1]==-1) ? data.substring(strIndex[0]) : data.substring(strIndex[0], strIndex[1]);
}
//分割文字の数
int Keywordcounter(String Original,char Keyword){
    int Keywordcount = 0;
    for (int i = 0; i < Original.length(); i++){
        if (Original.charAt(i) == Keyword) { 
          Keywordcount++; 
        }
    }
    return Keywordcount;
}

void loop(){

  StaticJsonDocument<500> doc;
  char pubMessage[256];

  // MQTT接続監視
  mqttLoop();

  // シリアル通信受信時にメッセージを送信する
  int recieved_byte_size = Serial.available();
  if (recieved_byte_size){
    String recieveData = Serial.readStringUntil('\n');

    //描画!
    M5.Lcd.fillScreen(TFT_DARKGREEN);
    M5.Lcd.setTextSize(2);
    M5.Lcd.setCursor(0,10);
    M5.Lcd.println(recieveData);      
          
    Serial.println("シリアル通信データ:" + String(recieveData));

    //分割文字の数
    int count = Keywordcounter(recieveData, ',');
    String part[count+1];

    // シリアルデータの分割
    for (int i = 0; i < count+1; i++){
        part[i] = split(recieveData,',',i);
    }

    // JSONメッセージの作成
    JsonArray idValues = doc.createNestedArray("ID");
    idValues.add(part[0]);

    JsonArray dataValues = doc.createNestedArray("data");
    dataValues.add(part[1]);

    serializeJson(doc, pubMessage);

    // メッセージの画面表示
    Serial.print("topic= ");
    Serial.println(pubTopic);
    Serial.print("Message= ");
    Serial.println(pubMessage);
    M5.Lcd.print(pubMessage);  

    // メッセージのPublish
    mqttClient.publish(pubTopic, pubMessage);
    Serial.println("Published.");
    Serial.println("");
    
  }else{
  }

}

M5Stackへの書き込みが完了し起動をすると、M5Stackは、Wi-Fiルータと接続  → MQTTの接続を行い、PCからのシリアル通信を待ち受けます。

JSONデータを作成するのに、ArduinoJSONというライブラリを使いました。とても簡単に、JSONデータを扱うことができ、とても便利です。

ラズパイ側のmosquittoを起動する

ラズパイのコンソールを起動して、mosquittoを動作させます。

> mosquitto_sub -d -t /pub/M5Stack

PCのArduinoIDEのシリアルモニターからメッセージを送信する

ArduinoIDEのシリアルモニターを起動させます。

上部の欄に、以下を入力して、Enterを押します。

123,1122334455

ラズパイのコンソールに、以下のメッセージが表示され、シリアル通信メッセージが、ラズパイに伝わっていることがわかります。

Received message 'b'{"ID":["123"],"data":["1122334455"]}'' on topic '/pub/M5Stack' with QoS 0

まとめ

今回は、ArduinoIDEのシリアルモニタで、シリアル通信メッセージを送って、これを受信したM5StackがJSON形式に変換して、Wi-Fi(MQTT)で、ラズパイに送る方法を紹介します。

オススメ

M5Stackシリーズ ATOM S3

  • ESP32-S3FN8チップを搭載したAtomS3は、幅広いアプリケーションに対応する高性能と汎用性の高い機能を提供します。
  • 内蔵のWiFi機能により、AtomS3はIoTデバイスや接続されたプロジェクトに最適で、シームレスな通信を保証します。
  • わずか24x24x13mmの寸法で、AtomS3は小さなフォームファクターで強力なコンピューティングを提供し、組み込みシステムやスマートデバイスに最適です。
  • 0.85インチIPSスクリーンはクリアな視覚フィードバックを提供し、下のプログラム可能なボタンはユーザーコントロールを強化します。
  • 6軸ジャイロセンサー(MPU6886)を搭載し、AtomS3は正確なモーション検出と方向トラッキングを可能にし、プロジェクトにインタラクティブなレイヤーを追加します。
オススメ

デイトラは総受講者数30,000人超の、Webスキルを学べる国内最大規模のオンラインスクールです。

動画コンテンツを見ながら自習を行い、わからないところをチャットツールで質問を行うという形式で学習を行います。そのため、時間・場所を選ばず自分のペースで学習できます。

デイトラ最大の特徴はフリーランスや副業を意識したコースを中心としていることです。Web系フリーランスに必要なスキルを学べるコースを備えており、実際に多数の受講生がフリーランスとなっています。

<オススメポイント>

1. フリーランス/副業を意識したカリキュラム

デイトラは運営陣が全員元フリーランスで、フリーランス向けメディア「東京フリーランス」の運営も行っています。そのためフリーランスに求められるスキル感や現在の流行、そして案件獲得の方法にまで精通しており、カリキュラムにもそのノウハウを反映しています。

「何かを作れるようになる」といった漠然としたゴールではなく、「実際に仕事を受けられるレベルに達する」ことをゴールとしているため、カリキュラムは非常にハイレベルです。

■提供中のコース一覧
・Web制作コース
・Webアプリ開発コース
・Webデザインコース
・Shopifyコース
・動画制作コース
・Pythonコース
・Webマーケティングコース
・AIライティングコース
・Javaコース

2. 受講生による好意的な口コミ

デイトラはTwitter・ブログともに受講生による好意的な口コミが非常に多いです。

カリキュラムやウェビナーなどのサービスの質に満足する声や、実際に案件を獲得できた・転職に成功したなどの成果報告が多数見られます。実際に受講した方の満足する声が多いからこそ、それを見た人が安心して受講に踏み切られています。

デイトラが一年間で8000人以上から受講してもらえたのも、口コミで人が人を呼ぶ構造になっているのが最大の要因です。

3. 圧倒的なコストパフォーマンス

デイトラは一年間のサポート付きで99,800円と格安でサービスを提供しています(例:Web制作コース)。一般的なプログラミングスクールが数十万円の受講料でサポート期間も三ヵ月ほどであることが多いため、それらに比べて非常に安価な価格設定となっています。

さらに、卒業後はカリキュラムの閲覧が不可になるスクールも多い中、デイトラは一度受講したらその後もカリキュラムを見放題です。カリキュラムは随時アップデートされるため、「常に最新の情報を提供してくれる教材」として活用される方も多いです。

デイトラは完全オンラインで教室を持たないスクールで、受講生の口コミによる集客が中心となっています。そのため固定費・広告費を抑え、格安でサービス提供を行えています。

デイトラ

コメント

タイトルとURLをコピーしました