ESP32@arduino ideとmicrobitのBLE通信

esp32(arduino ide)とmiciro:BitでBLE通信する

# esp32 ble ライブラリの修正

## 前提
Arduino ideとbleライブラリの導入する。
参考：[Arduino IDEでESP32 BLEライブラリを導入 \- Qiita](https://qiita.com/tomorrow56/items/afa06e206eec9fafcc7a)

ESP32のBLEライブラリの指定アドレスタイプとMicro:bitのアドレスタイプが一致しないのでこのままでは繋がりません。

## 手順
{Arduinoホームフォルダ}/hardware/espressif/esp32/libraries/BLE/src/BLEClient.cpp
を開き、114行目の
**BLE_ADDR_TYPE_PUBLIC**を**BLE_ADDR_TYPE_RANDOM**に書き換える。

```cpp:BLEClient.cpp書き換え後
	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/
にて、
1. 高度なブロックからパッケージの追加、Bluetoothを追加
2. プロジェクトの設定でBluetoothのペアリング方法を「No Pairing Required」にする(*1)
3. お好きなプログラムを作って、microbitに書き込む

## 作例
基本サービスを使ったプログラム：https://makecode.microbit.org/_DV07965eR8sV

Aボタンを押してる間だけ加速度の値を送るプログラム：https://makecode.microbit.org/27602-21517-86728-91519


## 参考
[micro:bitとWebBluetoothで通信してみました \- Qiita](https://qiita.com/yokmama/items/5522fabfb5b9623278e2)

---
以上で完了です。あとはお好きなプログラムを作って下さい。繋がるはずです。

# サンプルプログラム

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 のアプリ](https://play.google.com/store/apps/details?id=no.nordicsemi.android.mcp&hl=ja)など)

Miro:bit->ESP32の順で起動すると繋がり、シリアルモニタにMicrobitから受信した値が表示されるはずです。*2

```cpp
#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ライブラリの下記サンプルを使う場合ちょっと注意です。

https://github.com/nkolban/ESP32_BLE_Arduino/blob/master/examples/BLE_client/BLE_client.ino

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](https://lancaster-university.github.io/microbit-docs/resources/bluetooth/bluetooth_profile.html)

---

*1:もしかしたらこれが原因でMicro:bit側のアドレスタイプがランダムになっているかもしれません。
*2:継ぎ接ぎの末、コンパイルだけ通したコードなので動かないかも・・・。