ESP32をMicroPythonで動かしてみる(Mac)

前回の記事でESP32の公式Get Startedをなぞりました。 ndanah.hatenablog.com

公式のGet Startedは以下の文で締めくくられています。

That’s all what you need to get started with ESP32!
Now you are ready to try some other examples, or go right to developing your own applications.

「これでESP32の入門が終わりました!ここからは他のサンプルコードを動かしてみたり、自分のアプリを開発してみたりしてね!」

おい、コード触んねぇのかよ

仕方がないので$IDF_PATH/examples/を眺めると、とんでもなく充実したサンプルコードが置いてあります。なるほど、ネイティブはC言語で、API参照して書けばいいのね。と思いきや、検索してみると

誰もC言語で書いてなかった

選べるESP32の使い方

どうやら以下の4つのスタイルが選べそうです。
これ公式のどこかに書いてあるんだろうか?

当然、ネイティブのC言語で書く方法が最も制約もなくオーバーヘッドも少ないのだろうと思いますが…
今回は短時間でちゃちゃっと動かしてみたかったので、MicroPythonを使ってみることにしました。

MicroPythonのFWを書き込む

まずはesptoolを持ってきます。私の環境ではPython2系と3系が混在していて、pipを素で叩くと2系が起動してしまいます。前回、alias python=python3を通してあるので、python -mオプションでpython3系を指定してpipなどモジュールを呼び出します。この辺そろそろ何とかしないと…。

$ python -m pip install --user esptool
Collecting esptool
...

pipが頑張っている間に、MicroPython用のFWを落としてきます。

micropython.org

面倒くさいのでDownloadsに落ちてきたのをそのまま読ませます。適宜読み替えて下さい。

$ python -m esptool --chip esp32 --port /dev/cu.SLAB_USBtoUART write_flash -z 0x1000 ~/Downloads/esp32-xxxxxxxxxxxxxxxxxxxxxx.bin
esptool.py v2.6
...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...

無事書き込めたようです。

REPLでWiFiに繋げる

ここでESP32に接続すると、REPL(Read-Eval-Print Loop)、つまりPythonインタープリタとして見えます。

$ screen /dev/tty.SLAB_USBtoUART 115200

接続できたら、help()に倣ってコマンドを打ち込みます。WLANクラスを使います。

>>> import network
>>> wlan = network.WLAN(network.STA_IF)
I (66902) wifi: wifi driver task: ...

>>> wlan.status() # STAT_IDLE = 1000
1000

>>> wlan.active(True)
I (102812) phy: phy_version: ...
True

>>> wlan.isconnected()
False

>>> wlan.scan() # 802.11 b/g/nに対応。aは見えないので注意。
I (132822) network: ...

>>> wlan.connect('<SSID>', '<PASSWORD>')
I (176702) wifi: ...
I (179142) event: sta ip: 192.168.1.4, mask: 255.255.255.0, gw: 192.168.1.1
I (179142) network: GOT_IP

>>> wlan.status() # GOT_IP = 1010
1010

>>> wlan.isconnected()
True

この例ではESP32に192.168.1.4が割り当てられたようです。いったんESP32のセッションから抜けます。screenでのセッション終了はControl+a k。セッションが終了してもREPLの実行結果は保持されます。
なお、デタッチControl+a dした場合、セッションはバックグラウンドで続いているため、終了した気になってもう一度繋ごうとするとcould not find a ptyなどと言われて入れなくなります。screenコマンドについては以下を参照。
qiita.com

ターミナルに戻ったら、ESP32にpingを送ってみます。気が済んだらControl+Cで抜けます。

$ ping 192.168.1.4
PING 192.168.1.4 (192.168.1.4): 56 data bytes
64 bytes from 192.168.1.4: icmp_seq=0 ttl=255 time=96.846 ms
64 bytes from 192.168.1.4: icmp_seq=1 ttl=255 time=18.740 ms
64 bytes from 192.168.1.4: icmp_seq=2 ttl=255 time=42.254 ms
...
--- 192.168.1.4 ping statistics ---
23 packets transmitted, 23 packets received, 0.0% packet loss
round-trip min/avg/max/stddev = 18.740/68.027/130.109/31.132 ms

ネットワーク上の別のマシンから見えていることが確認できました。

今後のためのメモ

MicroPythonでは起動時に実行されるboot.pyとループ実行されるmain.pyを、それぞれampyを使って転送することでアプリケーションコードをデプロイできるらしい。
micropythonをはじめよう(ESP32編) - 寝台急行はまなす

依存モジュールも同様にampyで置いて参照するみたいです。
micropythonでmqtt - 寝台急行はまなす

でも、みんなが使ってるArduino coreの方が良さそう…なのかな?