ESP32でMQTT通信(XIAO ESP32S3、Node-RED、HIDキーボード)
はじめに
今回はXIAO ESP32S3でMQTT通信を使ってみました。Node-RED MCUでMQTT通信を使ったことはあるのですが、今回はArduino IDEでプログラムを書き込んでいます。
Node-RED MCUを使わなかったのは、ESP32のHIDキーボード機能も使いたかったからです。ハードウェア的にはできたので、ノードを作成したいですね。
▼マイコンはこちら。小型のブレッドボードとの相性がいいですね。
▼SWITCH SCIENCEの販売ページはこちら。
▼Amazonの販売ページはこちら。
▼以前の記事はこちら
MQTT通信を試してみる
▼WiFiとの接続については、Seeed Studioのページに詳しく書かれています。
https://wiki.seeedstudio.com/xiao_esp32s3_wifi_usage/
MQTT通信のブローカーはShiftr.ioを使いました。
▼Shiftr.ioのパブリックなMQTTブローカーのページはこちら。下の方にサンプルプログラムもあります。
※なおパブリックなブローカーなので、送受信するデータが第三者にも見られてしまいます。データの扱いにはご注意ください。
サンプルプログラムを使ってみる
Shiftr.ioのサンプルプログラムを試してみました。MQTTライブラリが使われています。
▼MQTTライブラリの、GitHubのリポジトリはこちら
https://github.com/256dpi/arduino-mqtt/tree/master
▼プログラムはこちら。WiFiのSSIDとパスワードを設定してください。
//https://www.shiftr.io/try?lang=arduino
#include <WiFi.h>
#include <MQTT.h>
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
unsigned long lastMillis = 0;
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "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);
// start wifi and mqtt
WiFi.begin(ssid, pass);
client.begin("public.cloud.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
client.loop();
delay(10);
// check if connected
if (!client.connected()) {
connect();
}
// publish a message roughly every second.
if (millis() - lastMillis > 1000) {
lastMillis = millis();
client.publish("/hello", "world");
}
}
リポジトリを参照しながら、少しプログラムを見てみましょう。
- MQTTClientクラスのclientオブジェクトが生成されています。
- client.beginでポートについて指定されていませんが、デフォルトでは1883です。
- client.onMessage:メッセージを受信したときに呼び出す関数(Callback)を指定します。
- 受信したメッセージはCallback関数内でpayloadとして扱えます。
publishとsubscribeのトピック名を揃えておくと、送受信できます。
- client.publish:引数にトピック名、送信するメッセージを渡します。
- client.subscribe:指定したトピック名のメッセージを受信します。
Node-REDとMQTT通信を行う
Node-REDとESP32の間でMQTT通信を行ってみました。
▼私はパソコンにインストールしたNode-REDを使っていますが、インストールされていない場合はクラウド環境で実行できるenebularがおすすめです。
フローを用意する
mqtt in/outノードでMQTT通信を行います。先程のサンプルプログラムと合わせて、トピック名は/helloとします。
▼フローはこちら。injectノードのボタンを押すとメッセージを送信できます。
▼mqtt inノードの設定はこちら。mqtt outノードも同様です。サーバーのアドレスと、トピック名を指定します。
実行してみる
▼シリアルモニタに受信したメッセージが表示されました。Node-REDのinjectノードのボタンを押したときのメッセージも受信しています。
▼Node-REDのデバッグ画面にも表示されています。
応用例:MQTTキーボードにしてみる
MQTT通信とHIDキーボード機能を組み合わせてみました。BLEキーボードに擬えて、言うなればMQTTキーボードです。
プログラムを書き込むときは、BOOTボタンを押しながら電源を入れるようにしてください。書き込みモードになります。そうしないと、キーボード入力が奪われてパソコンを操作できなくなってしまう場合があります。
▼ちなみに、かなり前にArduino DueのHID機能を使ったことがあります。Dueの場合は、プログラムを書き込むためのUSBポートが分かれているので、入力が奪われずに済みました。
MQTT通信で受信した文字を、Callback関数内でキーボードに出力しています。実際に試してみると全然関係ない文字列も入力されたので、バックスラッシュを受信するまでの文字列をパソコンに入力するようにしました。
#include <WiFi.h>
#include <MQTT.h>
#include "USB.h"
#include "USBHIDKeyboard.h"
const char ssid[] = "ssid";
const char pass[] = "pass";
WiFiClient net;
MQTTClient client;
USBHIDKeyboard Keyboard;
const int buttonPin = 2;
int previousButtonState = HIGH;
int counter = 0;
char command[] = { 'h', 'e', 'l', 'l', 'o' };
void connect() {
Serial.print("checking wifi...");
while (WiFi.status() != WL_CONNECTED) {
Serial.print(".");
delay(1000);
}
Serial.print("\nconnecting...");
while (!client.connect("arduino", "public", "public")) {
Serial.print(".");
delay(1000);
}
Serial.println("\nconnected!");
client.subscribe("hello");
}
void messageReceived(String& topic, String& payload) {
Serial.println(topic + ": " + payload);
char command[100];
payload.toCharArray(command, 100);
for (int i = 0; i < sizeof(command); i++) {
if (command[i] == '\\') {
break;
}
Keyboard.write(command[i]);
Serial.print(command[i]);
}
Serial.println();
}
void setup() {
Serial.begin(115200);
pinMode(buttonPin, INPUT_PULLUP);
Keyboard.begin();
USB.begin();
WiFi.begin(ssid, pass);
client.begin("public.cloud.shiftr.io", net);
client.onMessage(messageReceived);
connect();
}
void loop() {
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW) {
for (int i = 0; i < sizeof(command); i++) {
Keyboard.write(command[i]);
delay(10);
}
delay(500);
}
client.loop();
if (!client.connected()) {
connect();
}
}
▼実際に試しているときの動画はこちら。Node-REDからは「Hi!」という文字列が2秒おきに送信されています。ボタンを押すと「hello」と入力されます。
最後に
ESP32とNode-REDでMQTT通信を行うことができました。MQTT通信のトピック名やSubscribe、Publishについて知っておかないとコードが分かりにくいかもしれませんが、Node-REDで使っていたので何となく分かりました。
先日行われた大阪公立大学の「データ利活用やってみよう!ハッカソン2023」では、さらにNode-REDとGoogle Spread Sheetsに連携させることもできました。とりあえずNode-REDと連携させておくと、いろんなことに使えそうですね。
▼ハッカソンでの発表動画はこちら。