CircuitPythonをnRF52840で試す

#０）更新(2020年3月7日)
CircuitPython 5.0.0が2020年3月に正式リリースされたので、内容を更新しました。
従来使用していた4.1.0と比較するとBLE制御関連で色々と変更する必要がありましたので、プログラム更新ついでにサンプルプログラム情報も追加しました。
#１）使用するボード
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/abff7449-d081-4037-2be2-eff06babf774.png)
ボードは、Adafruit Feather nRF52840 Expressを使用します。購入は、下記で可能です。
**スイッチサイエンス**(コード番号 ADA-4062)
　https://www.switch-science.com/catalog/5400/
**MOUSER**(Mouser 番号 485-4062)
　https://www.mouser.jp/ProductDetail/Adafruit/4062?qs=3HJ2avRr9PJNiFE32RzJVw%3D%3D
**Digikey**(Digi-Key品番 1528-2828-ND)
　https://www.digikey.jp/products/ja?keywords=1528-2828-ND

ボードに関する基本情報は、下記を参照してください。
**包括的な説明**
　https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather
**CircuitPython関連**
　https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/circuitpython
**回路図**
　https://learn.adafruit.com/assets/68545
###何故、Adafruit Feather nRF52840 Expressなのか？
1) BLE機能が使えること　→　ワイヤレスでのデータ通信やBeacon機能が使える
2) nRF52840チップのUSB機能のみで、ホストとファイル交換やUART通信が可能
3) 2MBのファイルサイズがCircutPythonで利用できる　→　QSPIタイプのFlash搭載
4) 低消費電流でかつパワフル(Cortex-M4,64MHz,FPU,58μA/MHz)
5) Mbedで使い慣れている(nRF52840-DKとして認識させて使用可能)

次のボード候補は、下記です(現時点(3月7日)では売り切れ)。
Adafruit Feather nRF52840 Sense
https://www.adafruit.com/product/4516
多分、このボードを意識していると思われます（どちらが先かは知りません）。
https://store.arduino.cc/usa/nano-33-ble-sense
ここもご覧ください。
https://os.mbed.com/users/kenjiArai/notebook/mbed-os5-runs-on-arduino-nano-33-ble-sense-board/

#２）準備
ボードを購入しても、そのままではCircuitPythonは動作しません。
ボードへのプログラム書き込みとPCへの必要なプログラムのインストール、そしてBLE機能を試すためにiPhoneへのインストールを実施します。
最終的には、ボードと接続するセンサやアクチュエータを準備しますが、今回はハードウェアの追加作業が不要な範囲での説明に留めます。

＜動作を確認した開発環境＞
Windows10 Pro　　バージョン：1909　OSビルト：18363.657
iPhone7	　　　　　システムバージョン：13.3.1
###Bootloaderのチェックとアップデート
詳しい情報はここに説明があります。
　https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/update-bootloader
購入直後にPC(Win10)のUSB端子に接続してもシリアル(COM port)の認識だけで、ドライブとしては認識されません(USB CDC機能のみ、MSC機能なし)。
そこで、RESETスイッチをダブルクリックしてbootloaderモードにすると、ドライブと認識されます。ボードには、二つのスイッチがあり、USBコネクタに近い側がRESETスイッチ、BLEモジュールに近い側がUSERスイッチです。
ドライブを開くと下記のようなファイルが確認できますので、INFO_UF.txtの内容を確認します。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/eaf199ee-ddaa-7f40-edc9-13157475188f.png)

```INFO_UF.txt
UF2 Bootloader 0.2.9 lib/nrfx (v1.1.0-1-g096e770) lib/tinyusb (legacy-755-g55874813) s140 6.1.1
Model: Adafruit Feather nRF52840 Express
Board-ID: NRF52-Bluefruit-v0
Bootloader: s140 6.1.1
Date: Feb 22 2019
```
INFO_UF.txtの記述がVer0.2.9以上であれば、作業は必要ありません。
0.2.8かそれ以前の場合には、Bootloaderのアップデートを行う必要があります(上記リンク先に詳細説明あり）。ZIPファイルをダウンロードし、adafruit-nrfutil.exeを実行し、シリアルポートを介してZIPファイルを流し込むようです。この場合も、ボードはRESETボタンをダブルクリックしてbootloaderモードにして置くことを忘れないで実行します。
今回、上記リンク先を覗いたところ、Bootloaderも更新され、Ver0.3.1となっていたので、更新してみました。
更新時の注意として、adafruit-nrfutil.exe実行時にCOMライン指定をしなければなりませんが、PCが認識するCOM番号が通常モード(CIRCUTPYのドライブ名の時)とBOOTモード(FTHR840BOOT)で異なります。必ずBOOTモードにしてから認識されるCOM番号を調べ、コマンドラインのスクリプトへ反映してください。

###CircuitPythonの実行ファイルの書き込み
CircuitPythonの最新版5.0.0を、
　https://circuitpython.org/board/feather_nrf52840_express/
から入手します。
２０２０年３月７日時点でのファイル名は、
　adafruit-circuitpython-feather_nrf52840_express-en_US-5.0.0.uf2
です。
このファイルを書き込むために、再びbootloaderモードにします。RESETスイッチをダブルクリックして、ドライブがFTHR840BOOTの名前で認識されることを確認します。
Copy & pasteでUF2ファイルをファルダに入れると、Circuitpythonの実行ファイルが最新のbootloaderで書き込まれます。書き込みが正常終了すると、CIRCUITPYのドライブとして認識されます。
###CircuitPythonの環境確認
ボードの環境設定が正しく行われたかを確認します。USBケーブルを抜き差しして、電源ONからやり直して、PCにドライブとして認識されているか確認します(USB MSC機能)。
CIRCUTPYのドライブが確認できればOKです。プロパティでドライブ内容を確認してみてください。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/b8aa363a-7322-d417-fff8-4a87c35bb24d.png)
私はnRF52840用CircuitPythonとして、SparkFun Pro nRF52840 Mini
　https://www.sparkfun.com/products/15025
も同時に使用していますが、ドライブ領域は236kBです。
それに対して、Adafruit Feather nRF52840 Expressでは、2MBの作業領域を持っています。
仮想ドライブ用として、2MBのFLASH(QSPI)を搭載しているからです。作業領域の広さがこのボードの強みです。RESETのダブルクリックでbootloaderモードも、再度確認してください。
今回新規ではなく5.0.0へのアップデートをした方は、仮想ドライブを初期化することをお勧めします(必ずバックアップを忘れずに！！)。
アップデートに伴いライブラリなど多くのファイルを書き換えたのですが、途中で削除できないファイルが出たり、ファイル構造が破壊されたような痕跡が確認されました。
仮想ドライブの初期化方法は、下記に情報があります。
https://learn.adafruit.com/welcome-to-circuitpython/troubleshooting#easiest-way-use-storage-dot-erase-filesystem-20-24
REPLモードで2行を順次打ち込み実行します
###PC(win10)側の準備
先ずは、USB経由でシリアル通信できることを確認します。私は、Tera Termを使用しています。
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/6e7c2a0b-2bb1-9f68-062e-1ce8a415584f.png)
CircuitPythonを接続してからTera Termを立ち上げると、COMxxにてシリアルデバイスが見つかりますので、接続します。シリアルのボーレートが、9600bpsであることを確認し、Cntrl-Dにてsoft rebootすれば、画面表示が始まります。
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/c8971e31-be87-7db9-cabc-9a8e42776407.png)
USBのCDC+MSC機能により、PC(Win10)に①仮想COMと②ストレージデバイスとして認識されれば完了です。
CircuitPythonを動作させるには、以上の準備が確認できれば充分ですが、
**Mu**
　https://codewith.mu/
を使うと、pyファイル編集とシリアル通信のモニターができるので便利です。
詳細は割愛しますが、興味があれば下記などを参照してインストールしてください。
「日本語化してみたMuエディタ」　https://qiita.com/inachi/items/8f61586cd2482987b8d0
後半にAdafruit CircuitPythonモードの説明などがあります。尚、@inachi氏のおかげで正式リリース版は既に日本語化が完了しているので、そのままダウンロードすれば使用できます。
###iPhone側の準備
nRF52840をCircuitPythonで動作させれば、BLE機能も制御できます。
CircuitPythonボード同士でも出来ますが、iPhoneとBLEで通信させると様々な動作を確認できます。先ずは、下記ソフトをiPhoneにインストールします。
Adafruit Bluefruit LE Connect 
https://apps.apple.com/app/adafruit-bluefruit-le-connect/id830125974#?platform=iphone
Android用もありますが、動作確認していません。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/3680e350-803b-03f6-abed-2ff64ab3c2fd.png)
#３） ピン配置と名称
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/3657da99-d4a5-00b0-e107-0bcc15ab220f.png)
#４） REPL(Read Eval Print Loop)モード
###REPLの起動
TeraTermを起動して、Ctrl+Dでsoft rebootし、EnterキーでREPLモードを立ち上げる。TeraTermのは、9600bps設定を確認してください。
**＜注意点＞**
CIRCUITPYのディスクドライブ内にcode.pyが既に存在し、電源投入後にエラーなしで実行されている場合には、 Ctrl+Dを押してもREPLモードに移行しません。
その場合には、Ctrl+CにてKeyboardInterruptを発生させてREPLモードに移行します。REPLモードからcode.pyに戻るには、 Ctrl+Dを押します。
RESETスイッチの操作でもcode.pyの実行が可能ですが、その場合にはUSB経由のCDC＋MSC機能が一度停止し、シリアル通信とドライブの認識が中断します。
Muを使用している場合には、作業継続できなくなる場合があるので、ソースコード編集中ではRESETスイッチ操作は極力やめましょう。
###ポート名称の確認
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/972b3a54-4a2a-d4cd-cd8e-81f0e088f555.png)
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/6f9bdc60-4da4-275e-adf6-b03d5109a34a.png)
上記名称をPythonのプログラム中に使用しますので、重要です。exampleの中から使えそうなプログラムを持ち込んだ場合には、ボード特有の名称でエラーが発生することがありますので、注意が必要です。
###組込みモジュールの確認
下記画面は、4.1.0の古いものです。同じコマンドで追加内容を確認ください。
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/398d0745-afdd-05cc-8b12-0e39b62109a2.png)
###プログラム実行
**１）LEDの点灯**
複数行で少し長いですが、一行ずつ入力します。エラーとなる場合には、スペル間違いが考えれれますので、入力し直します。

```
import board
from digitalio import DigitalInOut, Direction、Pull
led = DigitalInOut(board.BLUE_LED)
led.direction = Direction.OUTPUT
led.value = True
led.value = False
```

REPLモードでは、キーボード入力の履歴を覚えています(８行分)ので、>>>部分でUPキー(△)を押して、led.value = Trueの行とled.value = Falseの行を相互に押せば、青色LEDの点灯、消灯が確認出来ます。led = DigitalInOut(board.BLUE_LED)の行に戻り、 RED_LEDに修正後に、その後の行を同様に履歴を辿って実行すれば、キー操作を最少にしながら赤色LED点灯も確認できます。

**２）SWITCHの確認**
これにはwhile分が入っているのでCircuitPython側で自動インデントが起こります。
最後の行でDELキー操作すると、行実行(この場合複数行)が起こります。


```
 import board
 from digitalio import DigitalInOut, Direction、Pull
 import time
 sw = DigitalInOut(board.SWITCH)
 sw.direction = Direction.INPUT
 sw.pull = Pull.UP
 while True:
        print(sw.value)
        time.sleep(1)
 (DELキーで戻してEnter)
```

Trueが一秒毎に表示され、SWITCHを押すとFalseが表示されます。
終了するには、Ctrl+Cを押します。
**＜注意点＞**
SWITCHは、P1_03とGND間に接続されていて、外部にはプルアップ用の抵抗がありません。sw.pull = Pull.UPを実行しないと判定結果が不安定となります。
押されていない場合には、端子が3.3V付近の為に、True=1=Hと認識されて、押された時にFalse=0=Lとなります。

#５）プログラムファイルの実行
###Tera Term + エクスプローラー＋エディタ
下記をエディタにて編集し、code.pyの名称でファイル保存します。
Tera Termの画面上で、REPLモードであることを確認してから、保存したファイルをエクプローラーで、CIRCUITPYとして認識されたフォルダ内にcopy&pasteすれば、準備は完了です。
Tera Termの画面で、Ctrl+Dを押せばプログラムの実行が始まります。
画面上にエラーが表示されれば、その行のスペルチェックをして再度ファイルを上書きすれば、LEDの点滅が開始されます。

```code.py
import time
import board
from digitalio import DigitalInOut, Direction, Pull
led = DigitalInOut(board.BLUE_LED)
led.direction = Direction.OUTPUT
n = 0
while True:
    led.value = True
    time.sleep(1.0)
    led.value = False
    time.sleep(1.0)
    print(n)
    n += 1
```
###Muのみで
Muを使用するとシリアル通信とプロッター機能が使用できるので、操作インターフェイスがMuだけで構築できます。

```code.py
import time
import board
from digitalio import DigitalInOut, Direction, Pull
led = DigitalInOut(board.BLUE_LED)
led.direction = Direction.OUTPUT
n = 0
while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)
    print((n % 20,))
    n += 1
```
動作させた時のMu画面です。
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/22cc1232-1d53-09e9-01f1-2db164242d89.png)
Muの操作手順(初めての場合)
1) ボードをPCのUSBに挿入します(Mu立上げ前)
2) Muを立上げます
3) (A)新規をクリックして、新しファイルを「無題」で開きます
4) (B)部分に上記code.pyの13行を打ち込みます
5) (C)保存で、CIRCUITPYのフォルダ開き、code.pyの名称にて保存します
6) (D)シリアルと(E)プロッターをそれぞれ開き、進捗を確認できます
7) 入力ミスの場合には、問題の行がシリアルのウインドウに表示されますので、修正します
8) 修正後に(C)保存で上書きすれば、再度実行が始まります
9) エラーが発生する場合には、(F)チェックで問題点を把握することも出来ます
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/7a86a848-e953-91ac-6c8e-10c6f94b1fec.png)
ボードにcode.pyが書き込まれた状態で、Muを立上げるとCIRCUITPYドライブを探しに行き、code.pyが開かれた状態で再開されます。

**＜注意点＞**
□　ボードをPCのUSBに接続してからMuを立上げないと、シリアルが認識されません
□　ファイル名がcode.pyしか許されませんし(main.pyも可)、CIRCUTPY上で作業が行われるので、ファイルのバックアップや、機能を変化させた時の管理が難しい
　→　変更履歴管理や機能別ファイル管理をしっかりしないと上書きなどで大切なファイルを失うリスクがあります
□　シリアルの画面を、後から開くと何も表示されないことがあります
　→　Ctrl+CやCtrl+Dを活用しましょう
□　プロッターを利用する場合には、シリアル出力(print文)に工夫が入ります
　→　(1,2,3)のようなタプルの形式にします
　　　詳しくは、下記に情報があります
　　　　　https://codewith.mu/en/tutorials/1.0/plotter

#６）Libの活用
###最新libの入手
最新のライブラリは下記で入手できます。
　https://circuitpython.org/libraries
ライブラリにはexampleもありますので、参考にしましょう。
###libの利用方法
ライブラリをCIRCUITPYのlibフォルダー内に格納します。
ライブラリの選択は、アプリケーションに依って変わりますが、２MBのフォルダサイズがあるので、順次コピーして当面は大丈夫でしょう。
各フォルダ内には、mpyファイル群が入っています。
![15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/59a04ac7-fc56-a1fc-57d8-117df18f8a27.png)
#７）サンプルプログラム
追加のハードウェア接続なしで確認出来るプログラムを紹介します。おまけ部分のリンク先にZIPファイルで格納しました。
ここで紹介するのは、iPhone上のAdafruit Bluefruit LE Connectのアプリを使用し、BLE通信でボード上のNeoPixelの色調と照度を制御するものです。
ZIPファイル内、\copy_CIRCUITPY\application\Color_Picker内のcode.pyを実行します。
iPhone操作は、Adafruit Bluefruit LE Connecを立ち上げて、下記の順で画面を開きます。
![IMG_0498.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/e2540b60-8789-a017-864f-e0e057375002.jpeg)
![IMG_0499.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/4f9300de-fc92-3807-b2b7-a393fd71e0f0.jpeg)
![IMG_0500.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/433774/aff60a7e-3004-d049-cf01-2102c0a2de60.jpeg)
操作は下記が参考になるでしょう。
https://www.adafruit.com/product/3406
接続時のNeoPixelの輝度は、すごく高いのでスライドで調整しないと目にきついです。
輝度スライドを左端にすれば、消灯します。
他のプログラムも、ボードだけで動作します。
仮想ドライブの領域が大きいので、ZIP解凍後にCIRCUITPYドライブのlib内に解凍後のlib内のすべてのディレクトリとmpyファイルをコピーします。更にルートディレクトリにapplicationディレクトリをすべてコピーしてみてください。余計なファイルを入れても、ドライブには充分な余裕があります。application内の各機能別にcode.pyが入っていますので、トライする機能のcode.pyをルートディレクトリのcode.pyに上書きすれば動作確認出来ます。
こうすれば、PC側のバックアップを毎回操作しなくてもCIRCUITPY内のCopy&Pasteで確認が簡単に出来ます。
サンプル内\copy_CIRCUITPY\application\BAT_Voltを実行すると、電源電圧がUSBの+5VやCPUのVDDの3.3V付近ではない値を示します。
これは、まさしくバッテリ電圧で、リチウムポリマ電池を接続する端子の電圧ですので、気を付けてください。
#８）CircuitPythonの参考リンク
CircuitPython　GitHub
　https://github.com/adafruit/circuitpython
CircuitPython　5.0.xバージョン仕様
　https://circuitpython.readthedocs.io/en/5.0.x/shared-bindings/index.html
Adafruit Feather nRF52840 Express
　https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather
　https://learn.adafruit.com/introducing-the-adafruit-nrf52840-feather/circuitpython
nRF52840 BLE
　https://github.com/adafruit/Adafruit_CircuitPython_BLE
nRF52840　サンプル
　https://learn.adafruit.com/circuitpython-nrf52840
　https://learn.adafruit.com/bluetooth-light-switch-with-crickit-and-nrf52840
　https://learn.adafruit.com/circuitpython-ble-crickit-rover
#９）おまけ
CircuitPythonで呼び出すボードのピン名をまとめたPDFファイル(３）ピン配置と名称に類似)
　https://onedrive.live.com/?id=E726C1E354E854B2%211040037&cid=E726C1E354E854B2
サンプルプログラムも入れて置きました。