M5-StickC(ESP32)をBLE MIDI Centralにして電子ピアノと繋ぐ

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(&amp;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の変換器を作るところまではがんばろう。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です