M5 Stick-CとRoland HP603をBLE MIDIで接続してデータ送受信するまで
経緯
Grove端子でつなげるMIDIシールド(necobit電子)を買ってみた。これで家の電子ピアノと繋いで子供に自慢しようとしたところ、どうやら有線のMIDI端子はないことに気づいた。とりあえずBluetooth MIDIとしては使えるようだ。マニュアル見るとAppleのみ接続を保証とかいてあるが、そんなことはないはず?
Arduinoのライブラリとかは一通りそろっていそうなので、簡単に接続できると思ったのだけど、そうでもなかったので記録しておく。
設定~接続まで
ここは特にサンプルコードどおりに勧めて苦労せず。スキャンしてMIDIのサービス持っているデバイスを探して接続して……
送信
その後、Note Onとか送ってみたら全然認識しない。色々調べたらとりあえず暗号化しないとダメとの事。以下を適切に追加すればOKだった。
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
M5-StickCのボタン押せば音が鳴るところまではできた。
受信
これがどうもうまくいかない。よく追加されている以下のコードを追加したけどだめ。
const uint8_t notifyOn[] = {0x1, 0x0}; pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902))->writeValue((uint8_t*)notifyOn, 2, true);
比較のためにnRF connect をAndroid端末に入れてみる。
connectして、MIDI serviceのIDをひらいてNotificationをenable. ちゃんと鍵盤ひいたらNotification経由でMIDIメッセージが読み込めている。
ここでようやく、電子ピアノ側の表示が、自分のM5 StickCで接続したときと違っていることに気づく。うまく拾えているnRF connectで接続したときは、こう。
M5Stickで接続しているときはこう。
と、M5 Stickの時には液晶のbluetoothマークの横にP+MIDIが出ていない。
差分がないかと、bluetooth snifferを作ってしらべようとSeeed Studio XIAO nRF52840 を買ってきた。いろいろ苦労はしたが、無事sniffer化できたので比較。比較前にM5 StickCのほうは暗号化を一時停止。
M5 StickC(自前)とnRF connectとの違いは、下の赤枠部分の有無。nRF connectで接続したあとは、IntervalのネゴシエーションがMasterとSlaveとの間でやりとりされている。
どうやったらこのシーケンスが走るかよくわからなかったが、ライブラリの中に、esp_err_t
esp_ble_gap_update_conn_params(
esp_ble_conn_update_params_t
*params)
というのを見つけた。
パラメータを見ると、
/// Connection update parameters typedef struct { esp_bd_addr_t bda; /*!< Bluetooth device address */ uint16_t min_int; /*!< Min connection interval */ uint16_t max_int; /*!< Max connection interval */ uint16_t latency; /*!< Slave latency for the connection in number of connection events. Range: 0x0000 to 0x01F3 */ uint16_t timeout; /*!< Supervision timeout for the LE Link. Range: 0x000A to 0x0C80. Mandatory Range: 0x000A to 0x0C80 Time = N * 10 msec Time Range: 100 msec to 32 seconds */ } esp_ble_conn_update_params_t;
となっており、ここのmin/max intervalを設定して呼び出せば何かやってくれそう。適当に、以下のコードをconnect処理の後、notify handlerを登録した後辺りに追加。
esp_ble_conn_update_params_t conn_params; memcpy(conn_params.bda, (device->getAddress()).getNative(), sizeof(esp_bd_addr_t)); conn_params.timeout = 400; conn_params.latency = 0; conn_params.min_int = 30; conn_params.max_int = 36; Serial.println("try to update param"); if(::esp_ble_gap_update_conn_params(&conn_params)==ESP_OK){ Serial.println("update param completed"); }
今度は無事 nRFの時と同じように液晶にp+MIDIの表示が出るようになり、NotificationをがHP603から出て、M5 Stickで読み出せるようになった。snifferで見てみても、
と、なんとなくinrtervalをネゴって決めるような動作が見られた。
まとめ
- 送信は暗号化
- 受信はInterval parameterの更新
をそれぞれ追加すれば送受信は大丈夫そう。とりあえずGrove MIDIシールド+M5 stickCで有線MIDIとBLE MIDIの変換器を作るところまではがんばろう。