IoT何をいまさら(75) ありがちなM5StickCからNode-REDに温度報告

Joseph Halfmoon

前回、M5StickCからラズパイ上のNode-REDにHelloしてみましたが、micro:bit用のダッシュボードを「成りすまし」使用でした。今回はちゃんとM5StickC用のダッシュボードを作った上でJSON化したデータを送信して表示させたいと思います。題材はありがちな温度と湿度、センサはこれまた定番DHT11であります。

まずはM5StickCに温湿度センサDHT11を取り付けるところから。使用したDHT11はSeeed社製のGroveモジュール化されたものです。M5StickCにもGroveコネクタが搭載されているのですが、

Groveコネクタ同士で配線するのはチト躊躇われました

M5StickC、M5Stack共通の仕様なのですが、Groveコネクタに出ている電源は5V、しかし入出力信号はESP32のIO電圧3.3Vなのです。そのまま直結してしまうと、3.3Vの端子に5Vにプルアップした信号が接続されてしまいます。M5Stackと別なGroveモジュール使ってこれでも一応動作することは確認済ですが、凄く気持ちが悪いです。そこでM5StickCの上部のHAT接続用拡張端子(3.3V電源出ている)側に接続することにいたしました。回路はこんな感じ。

M5StickC_DHT11_schematic

M5StickC上で動作させるコード(Arduino環境)は末尾に記録しておきます。MQTTブローカへのPublishに使わせていただいたライブラリについては既に前回説明したので、今回はDHT11センサの測定に使わせていただいたライブラリとJSON化のライブラリのみ説明いたします。

DHT11温湿度センサは人気のセンサなのでArduino環境ではライブラリが大量に見つかります(RISC-Vマイコン用に自力で書いてみたこともありましたがそれほど複雑ではないです。)今回使用させていただいたのは Adafruit社の

DHT sensor library

であります。DHT11だけでなくDHT22にも対応するもの。M5StickC上でもちゃんと動作いたしました。

もう一つ、測定したデータをWiFi経由してMQTTブローカに送るにあたり今回は「ちゃんと」JSON化して送り出すために使わせていただいたのが、

ArduinoJson

であります。Benoit BLANCHON様のMITライセンスの一品。これとよく似たお名前でご本家Arduino様がArduino_Jsonという別なライブラリを出しておられることにも気付いたのですが、ベータ版と書いてあったので見送りました(例によって保守的。)

この2つがあれば、DHT11で温度と湿度を測ってJSON化することは容易にできます。既にMQTTブローカ宛てにPublishするところは前回やっているのでガチャンコするだけ。なお、温度と湿度まとめて1回の送信でも良いのですが、後でいろいろやることを考えて測定項目とそのデータという組で1回送信ということにいたしました。

一応、温湿度測りながら動作しているところはこちら。

M5StickC and DHT11Node-RED側のフローとダッシュボード

問題は前回 micro:bit用のフローとダッシュボードを流用していたNode-RED側です。M5StickCからJSONでシリアライズして送信した筈、といっても実際にちゃんと届いているのか?ちょっと迷って Node-RED User Group Japan様のサイトを読んでいたら金言?が 「メッセージを利用する」より一文引用させていただきます。

メッセージの構造を理解する最も簡単な方法は、 Debugノードにメッセージを渡し、デバッグサイドバーでそれを確認することです。

ああ、そういうことで良いのね。しかし、MQTT-inで入って来た文字列をJSONのパーサとかに入れないとオブジェクトにならないの?ユーザー会様はそんな疑問もオミトオシだ。「パースされたJSONメッセージを受信」から一文引用させていただきます。

新しいバージョンのMQTT node(Node-REDバージョン0.19以降)は、 出力オプションが必須指定で存在するため、JSONノードは必須ではありません。

実際MQTT-inノードのプロパティの下の方にプルダウンメニューあり、そこで指定するだけで文字列はオブジェクト化されてしまうようでした。やってみました。最初のフローがこちら。

debugFlow

そしてデバッグサイドバーはこちら。

JSON_DEBUGなんだ簡単じゃん、ということで温度、湿度にゲージをとりつけたフローがこちら。

M5StickC_flowこれをデプロイ(忘れずに)して、M5StickC側を起動してみるとアイキャッチ画像のようにゲージにデータが表示されてまいります。

次はデータを蓄積して何かテキトーな処理してみるかね。

IoT何をいまさら(74) MtStickC/M5StackからNode-REDにHello へ戻る

IoT何をいまさら(76) また、ありがちなNode-REDからSQLite へ進む

今回使用したM5StickC上のソースコードはこちら
// M5StickC MQTT publish: DHT11 sensor
#include <WiFi.h>
#include <PubSubClient.h>
#include <M5StickC.h>
#include <ArduinoJson.h>
#include "DHT.h"

#define DHTPIN 0
#define DHTTYPE DHT11
DHT dht(DHTPIN, DHTTYPE);

char *ssid = "Your SSID";
char *password = "Your PASSWORD";
const char *brokerAdr = "Your Broker IP address";
const int  brokerPort = 1883;

WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

char buf[100];
char tempS[5];
char humiS[5];
StaticJsonDocument<200> doc;

void reconnect() {
  while(!mqttClient.connected()) {
    if (!mqttClient.connect("M5StickC")) {
      delay(5000);
    }
  }
}

void sendTEMP() {
  doc["mesType"] = "TEMP";
  doc["data"] = tempS;
  serializeJson(doc, buf, 99);
  mqttClient.publish("M5StickC/Measurements", buf);
}

void sendHUMI() {
  doc["mesType"] = "HUMI";
  doc["data"] = humiS;
  serializeJson(doc, buf, 100);
  mqttClient.publish("M5StickC/Measurements", buf);
}

void readDHT() {
  float humi = dht.readHumidity();
  float temp = dht.readTemperature();
  M5.Lcd.setCursor(0, 20);
  if (isnan(humi) || isnan(temp)) {
    M5.Lcd.printf("ERROR: DHT11 sensing.");
  } else {
    sprintf(tempS, "%4.1f", temp);
    sprintf(humiS, "%4.1f", humi);
    M5.Lcd.printf("Temp: %s Humi: %s", tempS, humiS);
    reconnect();
    sendTEMP();
    sendHUMI();
  }
}

void setup() {
  M5.begin();
  M5.Lcd.setRotation(3);
  
  dht.begin();
  
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    M5.Lcd.setCursor(0,0,2);
    M5.Lcd.print("Waiting WiFi");
    delay(500);
  }
  M5.Lcd.setCursor(0,0,2);
  M5.Lcd.print("Start WiFi and Publish");
  mqttClient.setServer(brokerAdr, brokerPort);
  reconnect();
  mqttClient.publish("M5StickC/Status", "Running");
}

void loop() {
  readDHT();
  delay(6000);
}