この記事はPythonその2 Advent Calendar 2019の2日目です。1日目は@ssh-22さんのre.subを使った高度な文字列置換でした。
Arduino, Raspberry Pi の誕生によって急速にエコシステムが整ってきているIoT界隈ですが、Raspberry Pi は Python で実装していけるもののちょっとした電子制御には Arduino の方が圧倒的に手軽に利用できます。
とはいえ Arduino 言語(C/C++もどき)ではなく、使い慣れた Python で書きたいという方もいらっしゃるのではないでしょうか。本記事では組み込み用 Python である MicroPython を利用した開発を金銭的な意味でも手軽に始める手引を書いていきたいと思います。
用意するもの
- Arduino ……ではなく ESP32開発ボード
- サンハヤト社 ニューブレッドボード SAD-101
作業環境はmacOS + Python3です。
ESP32開発ボード
最近のArduino界隈ではArduinoと同じ開発環境が使えて、Wifi/Bluetoothが使えるESP32が主流になっています(正確にはArduinoではないけど大体同じように使える)。
定番のArduion UNOよりも概ね高機能なのに安いESP32-DevKitCおよび互換品がよく使われています。
急ぐなら1,480円の秋月電子 ESP32-DevKitCとか、2,200円のスイッチサイエンスESPr Developer 32なりを調達しましょう。
ただ個人的にはaliexpressなどの海外通販をおすすめします。今回は436円のこちらを調達しました。お値段1/3です。ただし届くまで3週間位かかりました。
1,500円程度で買えるなら国内で購入してもいいのですが、電子工作は部品を壊したり、なにか作るのに使ったら使い回すのが面倒だったりするので、急がなければ1/3の値段で3つ買っておく方がおすすめです。
海外通販でクレジットカード決済をしたくない方にはpaypalが使えるbanggoodなどのほかサイトも有るのですが、国内購入と価格差が少ないので国内で買ってしまったほうがいいかもしれません。それでもRaspberry Piに比べれば半額以下です。
(追記)と思ったらAmazonで安く売ってますね。2個でも2,000円以下なのでもうこのへんでいいんじゃないかな。
サンハヤト社 ニューブレッドボード SAD-101
ESP32-DevKitCはピン列の間の幅が少し広く、安く売っている両サイド5穴ずつのブレッドボードだと差し込み穴がたりません。
ニューブレッドボードシリーズであれば両サイド6穴ずつなので使いやすいです。今回は一番シンプルな SAD-101 を用意しました。
ちょっと高級なブレッドボードなのでAmazonで518円です。
MicroPythonのインストール
あとは日本語訳されているドキュメントに従ってESP32にMicroPythonをセットアップしていきましょう。
通常ESP32-DevKitC購入時にはArduino CoreというArduino互換ファームウェアが書き込み済みです。
このままではArduino言語でしか実装できないのでMicroPythonのファームウェアを書き込み直します。
ファームウェアのダウンロード
ESP32用のMicroPythonでは「Wifiが使えるがBluetoothが使えないファーム」「Bluetoothは使えるがWifiが使えないファーム」のどちらかを選択しなければなりません。
今回は「Wifiが使えるファーム」の安定ビルドを選んでみます。
ドライバのインストール
ESP32-DevKitCにUSB接続するためにSilicon Labsのドライバをインストールします。
CP210x USB - UART ブリッジ VCP ドライバ
今回はmacOS用ドライバをインストールしました。ESP32をUSBで接続すると、おそらく/dev/cu.SLAB_USBtoUART
にESP32が認識されるはずです。
書き込み済みファームウェアの初期化
$ pip install esptool
$ esptool.py --port /dev/cu.SLAB_USBtoUART erase_flash
実行するとこんな結果が出ると思います。
$ esptool.py --port /dev/cu.SLAB_USBtoUART erase_flash
esptool.py v2.8
Serial port /dev/cu.SLAB_USBtoUART
Connecting........_
Detecting chip type... ESP32
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: XX:XX:XX:XX:XX:XX
Uploading stub...
Running stub...
Stub running...
Erasing flash (this may take a while)...
Chip erase completed successfully in 8.4s
Hard resetting via RTS pin...
ファームウェアの書き込み
$ esptool.py --chip esp32 --port /dev/cu.SLAB_USBtoUART write_flash -z 0x1000 esp32-idf3-20190529-v1.11.bin
実行するとこんな結果が出ると思います。
$ esptool.py --chip esp32 --port /dev/cu.SLAB_USBtoUART write_flash -z 0x1000 esp32-idf3-20190529-v1.11.bin
esptool.py v2.8
Serial port /dev/cu.SLAB_USBtoUART
Connecting........____
Chip is ESP32D0WDQ6 (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: XX:XX:XX:XX:XX:XX
Uploading stub...
Running stub...
Stub running...
Configuring flash size...
Auto-detected Flash size: 4MB
Compressed 1146864 bytes to 717504...
Wrote 1146864 bytes (717504 compressed) at 0x00001000 in 63.5 seconds (effective 144.4 kbit/s)...
Hash of data verified.
Leaving...
Hard resetting via RTS pin...
これで MicroPython のセットアップができました。
早速Pythonで動かしていってみようと思います。
Pythonの実行
MicroPython REPLの利用
まずはREPLプロンプトにアクセスしてみます。
$ screen /dev/tty.SLAB_USBtoUART 115200
おもむろにhelp() [enter]
と入力して以下のように出力されれば成功です。
Welcome to MicroPython on the ESP32!
For generic online docs please visit http://docs.micropython.org/
For access to the hardware use the 'machine' module:
import machine
pin12 = machine.Pin(12, machine.Pin.OUT)
pin12.value(1)
pin13 = machine.Pin(13, machine.Pin.IN, machine.Pin.PULL_UP)
print(pin13.value())
i2c = machine.I2C(scl=machine.Pin(21), sda=machine.Pin(22))
i2c.scan()
i2c.writeto(addr, b'1234')
i2c.readfrom(addr, 4)
Basic WiFi configuration:
import network
sta_if = network.WLAN(network.STA_IF); sta_if.active(True)
sta_if.scan() # Scan for available access points
sta_if.connect("<AP_name>", "<password>") # Connect to an AP
sta_if.isconnected() # Check for successful connection
Control commands:
CTRL-A -- on a blank line, enter raw REPL mode
CTRL-B -- on a blank line, enter normal REPL mode
CTRL-C -- interrupt a running program
CTRL-D -- on a blank line, do a soft reset of the board
CTRL-E -- on a blank line, enter paste mode
For further help on a specific object, type help(obj)
For a list of available modules, type help('modules')
>>>
print()
も返ってきます。
>>> print("hello")
hello
screen
コマンドはctrl + a
+ k
で終了確認のプロンプトが出るのでy
で終了します。
ソースコードの転送
REPLでコードを書いていくのは辛いのでソースコードファイルを転送できるようにします。
まずはツールのインストール。
$ pip install adafruit-ampy
転送済みのファイルを確認します。
$ ampy -p /dev/tty.SLAB_USBtoUART ls
/boot.py
boot.py
だけが転送されている事がわかります。
内容も確認してみます。
$ $ ampy -p /dev/tty.SLAB_USBtoUART get /boot.py
# This file is executed on every boot (including wake-boot from deepsleep)
#import esp
#esp.osdebug(None)
#import webrepl
#webrepl.start()
全行コメントアウトされている事と、boot.py
に書かれた内容はボードがリセットされたときの最初の1度だけ実行されることがわかります。
boot.py
実行後に(存在すれば)メイン処理としてmain.py
が実行されます。以下のようなコードをmain.py
として転送してLチカしてみます。
import machine
import time
pin13 = machine.Pin(13, machine.Pin.OUT)
while True:
pin13.on()
time.sleep_ms(500)
pin13.off()
time.sleep_ms(500)
転送は以下のコマンドで行います。
$ ampy -p /dev/tty.SLAB_USBtoUART put main.py
これで500ms間隔でD13ピンに接続されたLEDが点灯すれば成功です。
まとめ
MicroPythonを知った当初はファームウェアの書き換えが必要など、敷居が高いように思えましたが実際にやってみると慣れないツールを使う局面はあるもののそれほど難しいこともなくPythonコードの転送と実行まで実現できました。今回の手順は1度やってしまえばあとはソースコードを転送するだけなのでPythonに慣れた方はESP32をMicroPythonで使うというのもかなりアリな選択肢ではないでしょうか。
今回は行っていませんが、ESP32の通信機能を利用してWifi APへの接続も以下のような感じで簡単に出来るようなので夢が広がります。
import network
sta_if = network.WLAN(network.STA_IF); sta_if.active(True)
sta_if.scan() # Scan for available access points
sta_if.connect("<AP_name>", "<password>") # Connect to an AP
sta_if.isconnected() # Check for successful connection
そしてなにか面白いものを作ったらぜひIoTLTで発表すると良いと思います。
ちなみに冒頭でも書きましたが届くまで待つことが出来るなら436円でこれだけ遊べるのです。控えめに言って最高じゃないですか?