本来の目的が何なのか分からなくなっているが、道楽だからいいだろうということで、、nRF52840のボードを買った。外観は以下
目の前の目的はBLEでiOSと接続できるKeyboard風SWを実現するため。CircuitPythonを焼いて、modulesで使えるモジュールを表示させた。どうもBLEのライブラリが無いようなのだが。。なぜか!?
Adafruit CircuitPython 7.0.0 on 2021-09-20; Adafruit Feather nRF52840 Express with nRF52840 >>> help('modules') __main__ bitmaptools math sharpdisplay _bleio board microcontroller storage adafruit_bus_device builtins micropython struct adafruit_pixelbuf busio msgpack supervisor aesio collections neopixel_write synthio alarm countio onewireio sys analogio digitalio os terminalio array displayio pulseio time atexit errno pwmio touchio audiobusio fontio rainbowio traceback audiocore framebufferio random ulab audiomixer gc re usb_cdc audiomp3 getpass rgbmatrix usb_hid audiopwmio io rotaryio usb_midi binascii json rtc vectorio bitbangio keypad sdcardio watchdog Plus any modules on the filesystem
BLEは組み込まれておらず、外部モジュールとして手動で加えるようであった。。
https://github.com/adafruit/Adafruit_CircuitPython_BLE
adafruitのbundleを落としてきて、ZIPを解凍して、BLEライブラリをCopy&Pasteするようであった。
iOSと接続している実装例がAdafruit社から出ていて、コードの冒頭は以下である。これらのライブラリを入手してセットアップする必要がある。(
https://learn.adafruit.com/ble-hid-keyboard-buttons-with-circuitpython/ble-keyboard-buttons-libraries-and-code
)
import adafruit_ble from adafruit_ble.advertising import Advertisement from adafruit_ble.advertising.standard import ProvideServicesAdvertisement from adafruit_ble.services.standard.hid import HIDService from adafruit_ble.services.standard.device_info import DeviceInfoService from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS from adafruit_hid.keycode import Keycode
V7のbundleを展開して、adafruit_ble , adafruit_hidを nRF52840にコピーした。これにより上記のライブラリ importはエラーなく実行できたが、ソースコード本体の実行でエラーが出た。特に、、
adafruit_bleモジュール内に BLERadioクラスがある前提で書かれているが、このクラスがどこか別のモジュールに移っているようである。あるいは、、使い方が変わったのか??
ble = adafruit_ble.BLERadio()
# PyLint can't find BLERadio for some reason so special case it here. ble = adafruit_ble.BLERadio() # pylint: disable=no-member
再起動してdir()関数で確認するとBLERadioが存在した。先ほどエラーになったのは、adafruit_bleを何かで上書きしてしまったせいだろうか。
Adafruit CircuitPython 7.0.0 on 2021-09-20; Adafruit Feather nRF52840 Express with nRF52840 >>> import adafruit_ble >>> dir(adafruit_ble) ['__class__', '__name__', '__file__', '__path__', '__version__', 'Service', '_bleio', 'advertising', 'characteristics', 'sys', 'services', 'Advertisement', '__repo__', 'BLEConnection', 'BLERadio', 'attributes']
Git上にあったBLE_HIDサンプルを動かしてみた。
https://github.com/adafruit/Adafruit_CircuitPython_BLE/blob/main/examples/ble_hid_periph.py
エラーなく動作して、iOSではペアリングまで行えた。以下はCircutPython側のログ表示
advertising Start typing: a1 i1 u1 e1 o1
Basicで言うところのinkey$関数のような動作をしているので、nRF52840と接続しているシリアルコンソール(REPL画面)からaiueoと打ち込んだ。以下はiOSの画面。BLEキーボードからキー入力されたと認識され、「あいうえお」と表示された。
まとめ
MicroPython版のESP32用BLEライブラリではiOSと接続できてもペアリングまで進められなかった。CircuitPythonの場合、ペアリングも可能でキーボード入力まで行えた。なお、、MicroPython版のSTM32用BLEライブラリだと、NimBLEが使われており、ペアリングも可能かもしれない。が、、適当なSTM32ボードが見つけられなかった(たしか。なぜCircuitPythonに切り替えたのだったか、少し忘れかけているが。) 自分に実力があったらESP32 + MicroPythonでBLEライブラリをデバッグしてなんとかペアリングも実装してしまえるのだろうけど、、そんな余力も時間も知力もない。ということで、、今後BLEのアプリを作る場合は、動作が安定しているCircuitPythonを使うことにする。夜の8時過ぎにボードが届いて、CiruitPythonのファームをボードに焼いて、適当に調べながら2時間ぐらいでBLE Keyboardの試作が動いた。CircuitPythonのBLEは作りこまれているなーと感心いたします。
■追記
adafruit_bleのソースを読んでみたが、ハードレイヤーを制御するコードが全くなかった。よく見ると、import _bleioを実行しており、そっちに任せているようであった。改めて組み込みモジュールを再確認すると、、_bleioが存在していた。(見落としていた)
>>> import _bleio >>> dir(_bleio) ['__class__', '__init__', '__name__', 'Adapter', 'Address', 'Attribute', 'BluetoothError', 'Characteristic', 'CharacteristicBuffer', 'Connection', 'Descriptor', 'PacketBuffer', 'RoleError', 'ScanEntry', 'ScanResults', 'SecurityError', 'Service', 'UUID', 'adapter', 'set_adapter']
_bleioのソースは確認していないけど、BLEコントローラを制御していると思われる。(といっても、ミドルウエアを介してハードを制御しているのだろうと推測しますが)
ご参考
最新版のBundle
https://github.com/adafruit/Adafruit_CircuitPython_Bundle/releases/download/20211207/adafruit-circuitpython-bundle-7.x-mpy-20211207.zip