1年ぐらい前に次のような記事を書いたのですが、Blynkで新規アカウント登録ができなくなってしまったため、BalaCもMQTTで動かせるようにしてみました。
と、いっても、このBalaCも製造停止になってしまい、在庫でしか入手できなくなっているんですけどね。
動作ビデオ
とりあえず、どんな感じか動作ビデオを見てみてください。
Blynkとそんなに変わらないんじゃないかと思います。
MQTT Joystickコントローラー
Blynkの代わりとなるMQTT対応のJoystickコントローラーアプリを色々と探してみましたが、Androidにしか対応してないこのアプリしか見つけることができませんでした。
なので、iOSユーザーの方は今回は使うことができません。
まぁ、以前紹介したAndroidアプリプレーヤー(エミュレーター)のBlueStacksを使えば、PCで使うことはできます。(マウスだと操作が難しいです。)
アプリはすごくシンプルで、設定画面などはなく、この画面の赤枠左側にブローカーアドレス、右側にパブリッシュするトピックを指定するだけで使えます。

例えばトピックに
hiro/BalacMQTT/Joystick
と指定した場合、左のJoystickを動かすと
hiro/BalacMQTT/Joystick/left
というトピックでパブリッシュされ、右のJoystickを動かすと
hiro/BalacMQTT/Joystick/right
というトピックでパブリッシュされます。
値は「<角度> <速度>」というフォーマットで文字列で送られます。
角度は真右が0度となり、時計と逆周りの順で360度まで(0度)です。
速度は真ん中が0で、一番端が100です。
このMQTT Joystickコントローラーの注意点は「手を離したときの値が送られていないことがある」ということで、手を話すと真ん中に戻るのですが、その値(0 0)が送られないことがあります。なので、なるべる指を付けたままで操作することをお勧めします。
サンプルコードの改造
サンプルコードは次のURLからダウンロードできます。
12行目に次のコードを追加
#include <wifi.h> // WiFiライブラリ #include <pubsubclient.h> // MQTTライブラリ #define WIFI_SSID "この文字列をWiFiのSSIDで置き換えます" #define WIFI_PASS "この文字列をWiFiのパスワードで置き換えます" // MQTT設定 #define MQTT_TOPIC_ID "xxxxxx" // トピック識別用ID #define MQTT_DEVICE_ID MQTT_TOPIC_ID "-1" // デバイスID(ユニークなID) #define MQTT_BROKER_ADDR "broker.hivemq.com" // MQTTブローカーのアドレス #define MQTT_TOPIC_RIGHT MQTT_TOPIC_ID "/BalacMQTT/Joystick/right" // 右のトピック #define MQTT_TOPIC_LEFT MQTT_TOPIC_ID "/BalacMQTT/Joystick/left" // 左のトピック // グローバル変数/オブジェクト WiFiClient wclient; // WiFi接続用オブジェクト PubSubClient client(MQTT_BROKER_ADDR, 1883, wclient); // MQTT接続用オブジェクト

83行目に次のコードを追加
client.setCallback(callback); // データを受信した時に呼び出される関数

92行目に次のコードを追加
connectMQTT(); // MQTT接続/接続確認

133行目に次のコードを追加
// 購読しているトピックを受信した時に呼び出される関数
void callback(char* topic, byte* payload, unsigned int length) {
// 受信データ取得
int angle = 0; // Joystickの角度
int speed = 0; // Joystickのスピード
bool findSpace = false;
for (int i=0; i<length; i++) {
if ((char)payload[i] == 0x20) {
findSpace = true;
} else {
if (!findSpace) {
angle = angle * 10;
angle += ((char)payload[i] - 0x30);
} else {
speed = speed * 10;
speed += ((char)payload[i] - 0x30);
}
}
}
//Serial.printf("angel:%d speed:%d\n", angle, speed);
// モーター制御
moveRate = 0.0;
spinContinuous = false;
spinStep = 0.0;
if (speed > 40) {
if (90-20<angle && angle<90+20) // 前
moveRate = -2.0;
else if (270-20<angle && angle<270+20) // 後
moveRate = 2.0;
else if (360-20<angle || angle<0+20) { // 右
moveRate = -2.0;
spinContinuous = true;
spinStep = -40.0*clk;
} else if (180-20<angle && angle<180+20) { // 左
moveRate = -2.0;
spinContinuous = true;
spinStep = 40.0*clk;
}
}
}
// WiFiに接続
void connectWiFi() {
if (WiFi.status() != WL_CONNECTED) { // WiFiが繋がっていなかったら
Serial.print("\nConnecting to " WIFI_SSID); // ログにWiFiのSSIDを表示
WiFi.begin(WIFI_SSID, WIFI_PASS); // WiFiに接続
while (WiFi.status() != WL_CONNECTED) { // WiFiが繋がるまでループ
delay(1000); // 1秒待つ
Serial.print("."); // ログに「.」を表示
}
Serial.println("connected"); // ログに「WiFi connected」を表示
}
}
// MQTT接続/接続確認
void connectMQTT() {
connectWiFi(); // WiFiに接続/接続確認
while (!client.connected()) { // MQTTブローカーの接続確認
Serial.print("Attempting MQTT connection...");
if (client.connect(MQTT_DEVICE_ID)) { // MQTT接続ブローカーに接続
Serial.println("connected");
} else {
Serial.print("Retying in 5 seconds - failed, rc=");
Serial.println(client.state());
delay(5000);
}
client.subscribe(MQTT_TOPIC_RIGHT); // 指定トピックを購読
client.subscribe(MQTT_TOPIC_LEFT); // 指定トピックを購読
}
client.loop(); // 接続維持用
}


開発環境
最後に開発環境について書いておきます。
- Arduino IDE 1.8.16
-
Arduino core for the ESP32 1.0.6 - ボード

- M5StickC 0.2.5 - ライブラリ

- PubSubClient 2.8.0 - ライブラリ
