Arduino ESP32は、Bluetoothシリアル(SPP)のスレーブデバイスになるサンプルは付属しており、PCからはBluetoothシリアルで容易に接続することができました。
(例えば arduino-esp32/SerialToSerialBT.ino at master · espressif/arduino-esp32 · GitHub など。)
少し前に、Bluetoothシリアルのマスター側になり、他のデバイスに接続するためのライブラリやサンプルも用意されたようです。
arduino-esp32/SerialToSerialBTM.ino at master · espressif/arduino-esp32 · GitHub
これを使って、ESP32からBluetooth対応のUSB電圧/電流センサーに接続して情報を取得してみました。使ったUSBセンサーはこれ。
UM25C
arduino-esp32 は、Arduino IDEのボードマネージャから1.0.4にアップデートしたものを使っています。
まずは、setupでデバイスに接続を行ってみます。
接続は、Bluetoothデバイスの名前、もしくはアドレスを直接指定して行います。
アドレスの方が高速に接続できるようです。
#include "BluetoothSerial.h"
BluetoothSerial SerialBT;
String name = "UM25C";
uint8_t address[6] = {0x00, 0x11, 0x55, 0x33, 0x22, 0x77};
char *pin = "1234";
void setup() {
Serial.begin(115200);
SerialBT.begin("ESP32test", true);
Serial.println(String("Connecting to ") + name + " ...");
bool connected = SerialBT.connect(name);
if (connected) {
Serial.println("Connected Succesfully!");
} else {
while (!SerialBT.connected(10000)) {
Serial.println("Failed to connect. retry ...");
}
}
}
このUSBセンサーは、0xf0 という 1 byte のコマンドを送ると、130バイトほどのバイナリデータを返してくるようになっています。
1秒に1回 ESP32 からコマンドを送り、受け取ったデータをシリアルでPCに返してみます。
byte buffer[130];
int pos = 0;
void loop() {
static unsigned long last_wr = 0;
if (millis() - last_wr > 1000) {
SerialBT.write(0xf0);
last_wr = millis();
}
while (SerialBT.available()) {
buffer[pos++] = SerialBT.read();
if (pos >= sizeof(buffer)) {
handle_data();
pos = 0;
}
}
delay(20);
}
void handle_data() {
String data =
String("{\"V\":") + String((buffer[2] * 256 + buffer[3]) / 1000.0, 3) +
",\"A\":" + String((buffer[4] * 256 + buffer[5]) / 10000.0, 4) +
",\"W\":" + String((buffer[8] * 256 + buffer[9]) / 1000.0, 3) +
",\"C\":" + String(buffer[10] * 256 + buffer[11]) +
",\"mAh\":" + String(buffer[16] * 65536L + buffer[17] * 4096L + buffer[18] * 256 + buffer[19]) +
",\"mWh\":" + String(buffer[20] * 65536L + buffer[21] * 4096L + buffer[22] * 256 + buffer[23]) +
",\"ohm\":" + String((buffer[124] * 256 + buffer[125]) / 10.0, 1) +
"}\n";
Serial.print(data);
}
これで、シリアルモニターにUSBセンサーの値がJSONっぽい形式で返ってきました。
{"V":4.697,"A":1.2048,"W":5.658,"C":19,"mAh":646,"mWh":3049,"ohm":3.8}
{"V":4.700,"A":1.3035,"W":6.126,"C":19,"mAh":647,"mWh":3051,"ohm":3.6}
現状の問題点
どういうわけか、デバイスと接続できなくても20〜30秒程度経過すると connected = true が返ってきてしまいました。
また、途中でデバイス側のリセットなどで切断された場合、仮に SerialBT.disconnect(); SerialBT.connect(); を実行し直しても再接続がうまくいきません。
仕方なく、一定時間応答がない場合、 ESP.restart() でESP32全体を再起動するという処理を入れると、うまく再接続されています。