話題の CircuitPython を試してみる

(更新

Trying Adafruit CircuitPython in addition to MicroPython.

プログラミング日和のゴールディンウィーク 2日目ですが、皆様いかがお過ごしでしょうか。

Adafruit が最近熱心なのが、MicroPython をカスタマイズ(?)した CircuitPython です。もちろん同社の SAMD21 ボードで動作するのですが、Arduino Zero でも動作するようなので試してみました。流行りものに弱い性格です。 🙂

ところで、最近 Arduino Zero の入手性が悪いですね。本家 Arduino サイトでは扱ってますが、Adafruit でもスイッチサイエンスでも discontinued(製造中止)の文字が見られます。何か大人の事情でもあるのでしょうか。

最近は、安価な JTAG エミュレータが売られているので回避策はありますが、Arduino Zero(あるいは M0 PRO)は、このボードだけで JTAG(SWD)デバッグができる優れものの Arduino です。チャンスがあったら購入しておくことをお勧めします! (PRO でない M0 には EDBG が載っていませんので御注意。)

MicroPython と何が違うのか

閑話休題。こちらのサイトを見ると、おしゃれな GUI の画像がたくさんあって、ちょっと心惹かれます。本家 MicoPython は素晴らしいプロジェクトなのですが、どうしても荒削りな部分が目立ちます。私は ESP8266 でしか評価したことがないので偏見があるかも知れませんが、例を挙げてみると

  • リセットすると Flash ROM 上のプログラムが自動起動するのは良いのだが、バグのあるプログラムをうっかり Flash ROM に書いてしまうと、二度と REPL コンソールと対話できなくなることがある。(何かボタンを押しながら起動すると、自動起動せずに REPL と対話できると便利です。まあ、ユーザー側で工夫できないこともありませんが。)
  • REPL で対話的に書いたコードを、Flash ROM にセーブしたり、エディタで編集したりすることができない。あるいは難しい。これが解決すると、往年の BASIC マイコンみたいな環境が手に入るのですけどね。
  • 処理が終わったらスリープで消費電力をミニマムにして、時間がたったら起きてくる、というような設計をしづらい。ESP8266 版では、deep sleep しない限り Wi-Fi の電力を消費し続ける。deep sleep してしまうと、スリープから起きたときにパワーオンリセットと同じ動作になってしまう。
  • ESP8266 版特有かも知れないが、ファイルシステムが頑健でなく、ファイル書込中にリセットをかけてしまたりすると、MicroPython が立ち上がってこなくなることが、しばしば。

さて。CircuitPython はこのような問題に解決策を示しているのでしょうか?

CircuitPython の GitHub サイトを覗くと、「何が MicroPython と違うのか」という説明がありますが、基本的なポイントは以下のようです。

  • ファイルシステム上に置く *.py ファイルの名前を役割、またその振舞いを明確に定義する。具体的には、
    • boot.py は USB 初期化前に(USB の扱いについては後述)一度だけ実行する。その時点ではシリアルポート(?)が無効なので、結果を boot_out.txt というファイルに出力する。
    • その後、main.py あるいは code.py という名前のコードを実行する。コードの実行中にシリアルポートから interrupt されたり、プログラムが終了したりした時点で実行環境は失われる。(Python プロンプトに返ってこない。)
  • できるだけ USB マスストレージを活用する。USB ポートを持たない ESP8266 でも動作するが、オリジナルの MicroPython とあまり変わらない。

結局、上記の私の課題の中で、スリープ以外については解決できているようです。ポイントは、CircuitPython デバイスを USB で接続するとマスストレージ(USB メモリ)のように見えるので、何かおかしなことが起きたらファイルを書き換えれば良い、また、ファイルの編集はホストのパソコン上で編集する、ということのようです。

またマスストレージは DOS ファイルシステムとして見えているので、何かクラッシュしてもホスト OS からフォーマットし直せるかも知れません。

ただし、MicroPython での魅力の一つは REPL を通じて対話的に Python が利用できるということだったのですが、現状の Mu という環境(バージョン不明)では、REPL ボタンを押しても REPL でお話できませんでした。何か追加の設定が必要なのかも知れません。(USB CDC を通じてシリアル通信をすれば、REPL は使えました。)

Arduino M0 PRO で動かしてみた

さて。最後になりましたが、私の持っている Arduino M0 PRO(古いですね…)で動かしてみましたので、備忘録として手順をまとめておきます。

まず Arduino に CircuitPython を書き込まなくてはいけないのですが、Adafruit のボード以外では UF2 というブートローダーが動いていないので、BOSSA というアップローダーで CircuitPython イメージを書き込む必要があります。つまり、Arduino 用のブートローダーをそのまま使うことになる訳ですが、一つ注意点があります。Adafruit のサイトに説明があるのですが、どうも M0 PRO のブートローダーではダメで、Arduino Zero 用のブートローダーに変更する必要があるようです。M0 PRO と Zero の違いがいまひとつ分かっていないのですが、これら SAMD21 シリーズの Arduino には EDBG という JTAG(SWD)デバイスが載っているので、Arduino Sketch IDE でブートローダーを書き換えることができます。具体的手順は、こちらの Adafruit サイトを参考にしてください。

さて。Arduino Zero 用のブートローダーが動くようになったら BOSSA でイメージ(.bin ファイル)をアップロードします。今回は、CircuitPython 2.2.4 を評価してみました。

まず最初に、Arduino Zero(実は M0 PRO)の NATIVE USB ポートにパソコンを繋ぎます。ここで重要なポイントは、場合によっては BOSSA が Arduino とうまく通信できないことがあることです。これは Arduino Sketch IDE を使っている場合にも時々起きる現象なので、知っておいたほうが良いでしょう。

BOSSA(bossac コマンド)でファイルがアップロードできない、またはお話できない場合は、リセットボタンを 2回連続してタップします。そうすると、L と書かれた LED(GPIO #13 だそうです)が、ほわーんほわーん、と眠そうに明滅し始めます。こうすると、BOSSA とうまく通信できます。

BOSSA のコマンドも上記 Adafruit サイトにありますが、私がうまくいった例を示しておきます。私は Mac OS を使っているので、ポートの指定(-p)は適宜変更してください。なお、Adafruit のサイトでは BOSSA 1.8 を使うように指示がありますが、Arduino Sketch IDE に SAMD21 対応の(最新)ボードパッケージをインストールしてあれば、その中に BOSSA 1.7 が入っているので、それが使えます。今回もそれを使います。Mac OS であれば、

bash$ ~/Library/Arduino15/packages/arduino/tools/bossac/1.7.0/bossac \
      --port=/dev/tty.usbmodemなんとかかんとか -U true -i -e -w -v \
      adafruit-circuitpython-arduino_zero-2.2.4.bin -R

行が長すぎるのでバックスラッシュで区切っていますが、そのまま続けてタイプして大丈夫です。

うまく書き込めると、USB マスストレージ(USB メモリ)がパソコンから認識されます。あとは、このマスストレージに code.py というファイルを置けば、リセットボタンを押すことで、この code.py が実行される、という仕組です。つまり、Mu も PyCharm のいずれも必須の環境ではありません。

はい、今日はここまで。プログラミングもほどほどにして、ゴールデンウィークを楽しみましょう! 🙂