実施したこと
- ATOM S3とOMRON製非接触温度センサ(D6T-44L-06)をつなげてみた
- ATOM S3とShifr.ioを連携してMQTT通信を試してみた
- shiftr.ioからenebularへデータを流した
使ったもの
主要なコンポーネントだけ軽く説明します。
ちなみに今回は下記のような簡単なデータの流れを組みます。
ATOM S3
- M5Stackが出しているケース付きの小さなESP32-Sボード
- カラー液晶がついていたり、加速度センサがついていたりする。
- Switch scienceだと一個3000円ぐらいで買える。
D6T-44L-06
- OMRONが提供している非接触温度センサ
- 4x4のグリッドで温度を取得してくれる
- I2Cでデータ取得可能
- 9000円あれば買える
Shiftr.io
- 多分一番平易に使えるMQTTブローカー
- パブリックインスタンスを使えばログイン無しで使える
- データ量などの制限はあるが、クローズドなMQTTブローカーを無料で作れる
今回はパブリックインスタンスのmqtt://public:public@public.cloud.shiftr.io
を使用する。ちなみにやり取りされているノード情報はリアルタイムに見ることができる。
なので、絶対に個人情報を入力・設定しないようにしてください。下記リンクから分かる通り、すべての人に丸見えになります。
enebular
- 多分一番手早くNode-REDできるプラットフォーム
- クラウド環境を使っている場合は一定時間で接続が切れますが、更新かければそのまま利用可能
- enebular editorを使えば作成してきたフローをローカルで動かせる。当然ながら接続が切れることもなくなる
M5ATOMとD6T-44L-06の接続方法について
ATOM S3と温度センサを連携する仕組みはこちら。
一応i2cでデータを取得するようにしている。
node-red側について
enebularだとデフォルトでMQTT用ノードが用意されている。
とりあえずデバッグノードでデータだけ取得する。
mqttサーバー設定
サーバーとしてmqtt://public:public@public.cloud.shiftr.io
を設定する。
これが使用するパブリックインスタンスのMQTTブローカーとなる。
mqtt in側設定
トピック
にsub/M5Stack
のみ設定。
フロー全文はこちら。
[{"id":"72a21c6a252776c8","type":"mqtt in","z":"157d2eb59ec0c836","name":"","topic":"pub/M5Stack","qos":"2","datatype":"auto","broker":"2101c8387dd7f0c1","nl":false,"rap":true,"rh":0,"inputs":0,"x":230,"y":100,"wires":[["141691691fb17918"]]},{"id":"141691691fb17918","type":"debug","z":"157d2eb59ec0c836","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":490,"y":80,"wires":[]},{"id":"2101c8387dd7f0c1","type":"mqtt-broker","name":"Shifter","broker":"mqtt://public:public@public.cloud.shiftr.io","port":"1883","clientid":"","autoConnect":true,"usetls":false,"protocolVersion":"4","keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","birthMsg":{},"closeTopic":"","closeQos":"0","closePayload":"","closeMsg":{},"willTopic":"","willQos":"0","willPayload":"","willMsg":{},"sessionExpiry":""}]
ATOM S3に書き込むプログラム
何度も言いますが、shftr.ioはパブリックインスタンスを使用しているため、個人情報などは流さないように。
なお、画面描写はlovyanGFX(Version 1.1.2)を使用していて、チラツキ防止にスプライト表示をしています。
#include <Arduino.h>
#define LGFX_AUTODETECT
#include <LovyanGFX.hpp>
#include <LGFX_AUTODETECT.hpp>
#include <WiFi.h>
#include <MQTT.h>
#include <ArduinoJson.h>
#include <M5AtomS3.h>
#include "OmronD6T.h"
#include <math.h>
#define WIDTH (128 / 4)
#define HEIGHT (128 / 4)
static LGFX lcd;
static LGFX_Sprite sprite(&lcd);
unsigned long lastMillis = 0;
// Wi-FiのSSID
char *ssid = "xxxxxxx";
// Wi-Fiのパスワード
char *pass = "xxxxxxxx";
WiFiClient httpsClient;
MQTTClient client;
OmronD6T sensor;
float gain = 10.0;
float offset_x = 0.2;
float offset_green = 0.6;
float sigmoid(float x, float g, float o) {
return (tanh((x + o) * g / 2) + 1) / 2;
}
uint16_t heat(float x) {
x = x * 2 - 1;
float r = sigmoid(x, gain, -1 * offset_x);
float b = 1.0 - sigmoid(x, gain, offset_x);
float g = sigmoid(x, gain, offset_green) + (1.0 - sigmoid(x, gain, -1 * offset_green)) - 1;
return (((int)(r * 255) >> 3) << 11) | (((int)(g * 255) >> 2) << 5) | ((int)(b * 255) >> 3);
}
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("M5Stack", "public", "public")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("hello");
}
void messageReceived(String &topic, String &payload) {
Serial.println(topic + ": " + payload);
}
void setup() {
Serial.begin(115200);
M5.begin();
lcd.init();
lcd.clear();
sprite.createSprite(128, 128);
sprite.fillRect(0,0,128,128,TFT_BLACK);
sprite.pushSprite(0,0);
// Start WiFi
Serial.println("Connecting to ");
Serial.print(ssid);
// start wifi and mqtt
WiFi.begin(ssid, pass);
client.begin("public.cloud.shiftr.io", httpsClient);
client.onMessage(messageReceived);
connect();
}
void loop() {
StaticJsonDocument<192> doc;
JsonArray temps = doc.createNestedArray("temps");
client.loop();
delay(10);
if (!client.connected()) {
connect();
}
sensor.scanTemp();
sprite.createSprite(128, 128);
sprite.fillRect(0,0,128,128,TFT_BLACK);
int x, y;
for (y = 0; y < 4; y++) {
for (x = 0; x < 4; x++) {
float temp = sensor.temp[x][y];
if (temp > 100.0) {
return;
}
float t = map(constrain((int)temp, 0, 60), 0, 60, 0, 100);
uint16_t color = heat(t / 100.0);
sprite.fillRect(y * WIDTH, x * HEIGHT, WIDTH, HEIGHT, color);
sprite.setCursor(y * WIDTH + WIDTH / 2, x * HEIGHT + HEIGHT / 2);
sprite.setTextColor(BLACK, color);
sprite.printf("%.1f", temp);
temps.add((int)floor(temp*10));
}
}
sprite.pushSprite(0,0);
String output;
serializeJson(doc, output);
client.publish("/pub/M5Stack", output.c_str());
delay(500);
}
結果
おわりに
- ATOM S3でも普通にMQTT通信できた。今までのATOM liteやM5Stack Grayと同じ手順でも大丈夫っぽい。
- Shiftr.ioやenebularのおかげもあって、速攻でIoTできた。
- パブリックインスタンスむっちゃ便利。
- 4x4のセンサ値がせっかく取れているし、フロント側でいい感じに見える化したらカッコよさそう?