esp32(arduino ide)とmiciro:BitでBLE通信する
esp32 ble ライブラリの修正
前提
Arduino ideとbleライブラリの導入する。
参考:Arduino IDEでESP32 BLEライブラリを導入 - Qiita
ESP32のBLEライブラリの指定アドレスタイプとMicro:bitのアドレスタイプが一致しないのでこのままでは繋がりません。
手順
{Arduinoホームフォルダ}/hardware/espressif/esp32/libraries/BLE/src/BLEClient.cpp
を開き、114行目の
BLE_ADDR_TYPE_PUBLICをBLE_ADDR_TYPE_RANDOMに書き換える。
errRc = ::esp_ble_gattc_open(
getGattcIf(),
*getPeerAddress().getNative(), // address
BLE_ADDR_TYPE_RANDOM, // Note: This was added on 2018-04-03 when the latest ESP-IDF was detected to have changed the signature.
1 // direct connection
);
(現時点ではアドレスタイプが直書きになっていて変更できないので、Micro:bitのアドレスタイプに合わせて強制的に書き換えてやります。引数とかで指定できるようになるとこの作業は不要になり、この記事も無意味になります。)
microbit側
特殊なことはないです。Bluetoothパッケージを使ってプログラムを作ります。
手順
https://makecode.microbit.org/
にて、
- 高度なブロックからパッケージの追加、Bluetoothを追加
- プロジェクトの設定でBluetoothのペアリング方法を「No Pairing Required」にする(*1)
- お好きなプログラムを作って、microbitに書き込む
作例
基本サービスを使ったプログラム:https://makecode.microbit.org/_DV07965eR8sV
Aボタンを押してる間だけ加速度の値を送るプログラム:https://makecode.microbit.org/27602-21517-86728-91519
参考
micro:bitとWebBluetoothで通信してみました - Qiita
以上で完了です。あとはお好きなプログラムを作って下さい。繋がるはずです。
サンプルプログラム
BLEライブラリの修正で繋がるようになってますが、サンプルプログラムは以下のような感じです。
Micro:bit側
基本サービスを使ったプログラムを書き込んでおきます
https://makecode.microbit.org/_DV07965eR8sV
ESP32側
下記プログラムをArduinoIDEにコピペし、4行目のMACアドレスを自分のMicor:bitのBLEのMACアドレスに書き換えて書き込んでください。
(MACアドレスはスマホのBluetoothデバッグアプリで確認しましょう。AndroidであればnRF Connect for Mobile - Google Play のアプリなど)
Miro:bit->ESP32の順で起動すると繋がり、シリアルモニタにMicrobitから受信した値が表示されるはずです。*2
#include "BLEDevice.h"
static BLEUUID ubit_serviceUUID("E95D0753-251D-470A-A062-FA1922DFA9A8");
static BLEUUID ubit_accUUID("E95DCA4B-251D-470A-A062-FA1922DFA9A8");
static BLEAddress *pServerAddress = new BLEAddress("e0:73:d3:8f:72:29");
static BLERemoteCharacteristic *pRemoteCharacteristic;
static void Callback(
BLERemoteCharacteristic *pBLERemoteCharacteristic,
uint8_t *pData,
size_t length,
bool isNotify)
{
Serial.print("Notify/Indicate Callback for characteristic: ");
Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
Serial.print(" data length ");
Serial.print(length);
Serial.print(" data: ");
for(int i = 0;i < length ;i++)
{
Serial.print((char)pData[i]);
}
Serial.print("\n");
}
void setup()
{
BLEDevice::init("");
Serial.print("Forming a connection to ");
Serial.println((*pServerAddress).toString().c_str());
BLEClient *pClient = BLEDevice::createClient();
Serial.println(" - Created client");
// Connect to the BLE Server.
pClient->connect(*pServerAddress);
Serial.println(" - Connected to server");
// Obtain a reference to the service we are after in the remote BLE server.
BLERemoteService *pRemoteService = pClient->getService(ubit_serviceUUID);
if (pRemoteService == nullptr)
{
Serial.print("Failed to find our service UUID: ");
Serial.println(ubit_serviceUUID.toString().c_str());
return;
}
Serial.println(" - Found our service");
// Obtain a reference to the characteristic in the service of the remote BLE server.
pRemoteCharacteristic = pRemoteService->getCharacteristic(ubit_accUUID);
if (pRemoteCharacteristic == nullptr)
{
Serial.print("Failed to find our characteristic UUID: ");
Serial.println(ubit_accUUID.toString().c_str());
return;
}
Serial.println(" - Found our characteristic");
//enable Notify/Indicate
BLERemoteDescriptor *pRD = pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902));
if (pRD == nullptr)
{
Serial.print("Failed to find our descriptor UUID: ");
Serial.println(BLEUUID((uint16_t)0x2902).toString().c_str());
return;
}
uint8_t data[2] = {0x01, 0x00}; //Notify
//uint8_t data[2] = {0x02, 0x00}; //Indicate
pRD->writeValue(data, 2, false);
pRemoteCharacteristic->registerForNotify(Callback);
}
void loop()
{
}
サンプル(BLE_client.ino)を使う場合
ESP32 BLEライブラリの下記サンプルを使う場合ちょっと注意です。
notifyCallbackという関数がありますが、NotifyのCCCDを有効化していないので動きません。
上記コードのように有効化してあげましょう。
microbitのサービスUUID,キャラクタリスティックUUID一覧
サービス | キャラクタリスティック | UUID | タイプ | メモ |
---|---|---|---|---|
ボタン | E95D9882-251D-470A-A062-FA1922DFA9A8 | |||
ボタンA | E95DDA90-251D-470A-A062-FA1922DFA9A8 | R/N | 0 =押されてない、1 =押された、2 =長押し | |
ボタンB | E95DDA91-251D-470A-A062-FA1922DFA9A8 | R/N | 同上 | |
加速度 | E95D0753-251D-470A-A062-FA1922DFA9A8 | |||
データ | E95DCA4B-251D-470A-A062-FA1922DFA9A8 | R/N | XYZの順に各sint16、リトルエンディアンで格納 1000で割ると単位Gになる | |
周期 | E95DFB24-251D-470A-A062-FA1922DFA9A8 | R/W | 1, 2, 5, 10, 20, 80, 160, 640(ms)を指定(初期値20ms) | |
IO | E95D127B-251D-470A-A062-FA1922DFA9A8 | |||
データ | E95D8D00-251D-470A-A062-FA1922DFA9A8 | R/W/N | 最大19個のピンの値を取得・指定 uint8配列 | |
AD コンフィグ | E95D5899-251D-470A-A062-FA1922DFA9A8 | R/W | ADモード取得・指定 ビットnがピンnに対応 0でデジタル、1でアナログ | |
IO コンフィグ | E95DB9FE-251D-470A-A062-FA1922DFA9A8 | R/W | IOモード取得・指定 ビットnがピンnに対応 0で出力、1で入力 | |
PWM | E95DD822-251D-470A-A062-FA1922DFA9A8 | W | 構造体PwmControlData型(詳細は下記URL)でPWM指令 | |
LED | E95Dd91D-251D-470A-A062-FA1922DFA9A8 | |||
状態 | E95D7b77-251D-470A-A062-FA1922DFA9A8 | R/W | 5x5のLEDの全状態を取得・指定できる | |
テキスト | E95D93EE-251D-470A-A062-FA1922DFA9A8 | W | 表示したいテキストを書き込み utf8s | |
スクロール遅延 | E95D0d2d-251D-470A-A062-FA1922DFA9A8 | R/W | 文字を表示するまでの待機時間(ms) | |
磁気 | E95DF2D8-251D-470A-A062-FA1922DFA9A8 | |||
データ | E95Dfb11-251D-470A-A062-FA1922DFA9A8 | R/N | XYZの順に各sint16、リトルエンディアンで格納 | |
周期 | E95D386C-251D-470A-A062-FA1922DFA9A8 | R/W | 1, 2, 5, 10, 20, 80, 160, 640(ms)を指定(初期値20ms) | |
方位 | E95D9715-251D-470A-A062-FA1922DFA9A8 | R/N | 北からの度数 | |
温度 | E95D6100-251D-470A-A062-FA1922DFA9A8 | |||
温度 | E95D9250-251D-470A-A062-FA1922DFA9A8 | R/N | 摂氏 | |
UART | 6E400001-B5A3-F393-E0A9-E50E24DCCA9E | |||
TX | 6E400002-B5A3-F393-E0A9-E50E24DCCA9E | I | マイクロビットから送信、uint8配列 | |
RX | 6E400003-B5A3-F393-E0A9-E50E24DCCA9E | W | マイクロビットが受信、uint8配列 |
R:READ, W:Write, N:Notify, I:Indicate
イベントサービスは省略。詳細は下記サイトに。
参考:Bluetooth Developer Studio - Profile Report
*1:もしかしたらこれが原因でMicro:bit側のアドレスタイプがランダムになっているかもしれません。
*2:継ぎ接ぎの末、コンパイルだけ通したコードなので動かないかも・・・。