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センサーはこれ。
arduino-esp32 は、Arduino IDEのボードマネージャから1.0.4にアップデートしたものを使っています。
ESP32からデバイスにBluetooth SPPで接続する
まずは、setupでデバイスに接続を行ってみます。
接続は、Bluetoothデバイスの名前、もしくはアドレスを直接指定して行います。
アドレスの方が高速に接続できるようです。
#include "BluetoothSerial.h" BluetoothSerial SerialBT; String name = "UM25C"; uint8_t address[6] = {0x00, 0x11, 0x55, 0x33, 0x22, 0x77}; // アドレス直接指定も可能 char *pin = "1234"; //<- 接続用PIN。標準以外の場合は指定が必要 void setup() { Serial.begin(115200); // 初期化。名前とtrueを引数として渡すとマスターになる SerialBT.begin("ESP32test", true); Serial.println(String("Connecting to ") + name + " ..."); // 標準以外のPINが必要な場合はここで指定する // SerialBT.setPin(pin); // 名前を指定して接続する場合。スキャンのためか、10〜15秒程度かかる bool connected = SerialBT.connect(name); // アドレスを指定して接続する場合。こちらは2〜3秒で高速に接続できる //bool connected = SerialBT.connect(address); if (connected) { Serial.println("Connected Succesfully!"); } else { while (!SerialBT.connected(10000)) { Serial.println("Failed to connect. retry ..."); } } }
Bluetooth SPPデバイスと通信する
この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}