こんにちは。
他人のコードをコピーして、コマンドとかよくわからないまま、物を作っている私のような人に、
ちょっとでも役に立つのならと思い、自分が回避できた問題を記載していきたいと思う。
arduinoに関するトラブルは、ちょっとググれば同じような問題に直面している人が数多くいて
そうした問題の回避方法はかなりヒットするのだが、
今回の問題は、英語サイトも含めてほとんどヒットせず
自力でやれる事をやってみたので、記録として残します。
ESP32-BLE-Keyboardをつかってiphoneに接続すると、文字入力が出来なくなる。(画面のキーボードが表示されなくなる)
これは、既知の仕様(問題)です。
なので、ESP32とのコネクションを一時的に切るなどをしたいが、そこで嵌った
https://github.com/T-vK/ESP32-BLE-Keyboard
ESP32-BLE-Keyboardで、bluetoothをスタートさせるには、サンプルにもあるとおり
bleKeyboard.begin();でスタートさせるが、 これに対して
bleKeyboard.end();という関数もあるが、まったくこれが機能しない。
それもそのはず、BleKeyboard.cppの中をみてみると
void BleKeyboard::end(void)
{
}
となっていて、何も入っていない。
うーむ。 これは困った。
ということでいろいろと、どうすればいいのか、調べてみた。
まず、ESP32を使うようになって、aruduinoからとの大きな違いにマルチタスクという言葉が出てくる。Bluetoothやwifiなどは、
マルチタスクで動いているので、メインの関数とは別のところで動いている
それを管理しているのが、FreeRTOS というものらしい
なので、bleKeyboard.begin();で起動させたタスクを、止めればいいという事になる。
FreeRTOS によると、起動したタスクは、vTaskDelete(NULL);というコマンドで止めれるらしい
なので、
void BleKeyboard::end(void)
{
vTaskDelete(NULL);
}
としてみたが、ダメだった。 これを呼ぶと、無応答になってしまう。
なぜ、無応答なのか調べていったら、
bleKeyboard.begin()という関数は、BleKeyboard::taskServerを呼んでいる
この関数の一番最後に、vTaskDelay(portMAX_DELAY); //delay(portMAX_DELAY);
というのがある。portMAX_DELAYが何を意味しているのか、ググってみたけど、全くヒット
しなかった。通常は、時間を入れるようなので、1000を入れたところ、1秒でこの関数は終了したが
リセットを繰り返すようになってしまった。
起動したタスクが正常に終了していないのが原因と思い先ほどの
vTaskDelete(NULL);
を入れたところ、リセットされず、プログラムは終了した。
しかし、まだ問題があった。
タスクを終了しても、iphoneは、まだ bleKeyboardとつながったままだった。
BleKeyboard::taskServerの前半を見てみると
BLEDevice::init(bleKeyboardInstance->deviceName);
という関数があったので
BLEDevice::deinit();
対になるように、この関数を入れたところ、
無事iphoneから、ESP32を切り離す事ができた
bluetoothを無事停止する方法はわかったので、
こちらの意図したタイミングで、bluetoothが切れるように
vTaskDelay(portMAX_DELAY);があったところを
//vTaskDelay(portMAX_DELAY); //delay(portMAX_DELAY);
while(digitalRead(2)){
vTaskDelay(1000);
}
BLEDevice::deinit();
vTaskDelete(NULL);
とした。
適当に空いているI/Oを使って、タスクに指示を送る方法にした。
これで、メインループでI/O 2番をHIGHにしておけば、
bluetoothはつながったままになり、
好きなタイミングで、2番をLOWにすれば、
マルチタスクは終了できるようになった
再びつなぎたくなったら、bleKeyboard.begin()を走らせればOK
ここにたどりつくのに丸3日かかった
なお、BleKeyboard.cpp内でdigitalReadを有効にするために、
Arduino.h>を include する事
以上