M5Stack をシリアル接続してデバッグする(MicroPython)

 最近は M5Stack を主に m5cloud を使って MicroPython で色々と試しています。 m5cloud での開発は、 M5Stack が Wi-Fi に繋がっていればPCと直接接続しなくても良いというのもメリットの一つだと思うのですが、その分デバッグはしづらいところがあります。ちょっとした確認であれば lcd.print() 等で画面に出力して確認することもできるのですが、 SyntaxError などでそもそもちゃんと動かない時には起動時に下記のような画面で止まってしまい、原因が何なのかがわかりません。

f:id:akanuma-hiroaki:20181103120541j:plain

 なのでやはりデバッグするにはシリアルケーブルで接続して、出力を確認しながらするのが効率的です。

シリアル接続

 私の Mac 環境では M5Stack を USB ケーブルで接続すると、下記のようなデバイスとして認識されます。

$ ls -l /dev/tty.SLAB_USBtoUART 
crw-rw-rw-  1 root  wheel   21,  24 Nov  2 08:27 /dev/tty.SLAB_USBtoUART

 screen コマンドでデバイスに接続します。ボーレートは 115,200 を指定します。

$ screen /dev/tty.SLAB_USBtoUART 115200

シリアル出力確認

 シリアル接続した状態で M5Stack を再起動すると、下記のようにシリアルコンソールに情報が出力されます。

[M5Cloud] Downloading:/flash/main.py  ......
[M5Cloud] Downloading:/flash/README.md  .
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:4636
load:0x40078000,len:0
load:0x40078000,len:12948
entry 0x4007852c

Internal FS (SPIFFS): Mounted on partition 'internalfs' [size: 2424832; Flash address: 0x1B0000]
----------------
Filesystem size: 2221568 B
           Used: 56320 B
           Free: 2165248 B
----------------

Device ID:807d3ac471bc
Connect WiFi: SSID:XXXXXXXXXXXXXXXX PASSWD:XXXXXXXX network...
....
Connected. Network config: ('172.20.10.12', '255.255.255.240', '172.20.10.1', '172.20.10.1')
[M5-807d3ac471bc] M5Cloud connected.

FreeRTOS running on BOTH CORES, MicroPython task started on App Core (1).

 Reset reason: Soft CPU reset
    uPY stack: 19456 bytes
     uPY heap: 80000/19280/60720 bytes

MicroPython ESP32_LoBo_v3.2.16 - 2018-05-15 on M5Stack with ESP32
Type "help()" for more information.
>>>

 上記の例はエラーなく正常に起動できたケースですが、例えば SyntaxError があると上記の出力の途中に下記のようにエラーメッセージが出力されます。これでエラーの原因や場所が特定できます。

Traceback (most recent call last):
  File "main.py", line 11
SyntaxError: invalid syntax

 また、print デバッグを行いたいときは、 print() を使用すればその引数がシリアルコンソールに出力されます。例えば下記のように API のレスポンスの内容を print() で出力するようにしてみます。

response      = urequests.get(self.base_url.format(prefecture, self.api_key))
json          = response.json()
main          = json['main']
print(main)

 これを実行すると下記のように API のレスポンスがシリアルコンソールに出力されて行きます。

{'pressure': 1025, 'humidity': 54, 'temp_min': 283.15, 'temp_max': 287.15, 'temp': 284.75}
{'pressure': 1027, 'humidity': 74, 'temp_min': 283.15, 'temp_max': 287.15, 'temp': 284.81}
{'pressure': 1025, 'humidity': 54, 'temp_min': 288.15, 'temp_max': 288.15, 'temp': 288.15}
{'pressure': 1025, 'humidity': 54, 'temp_min': 283.15, 'temp_max': 287.15, 'temp': 284.75}
{'pressure': 1027, 'humidity': 74, 'temp_min': 283.15, 'temp_max': 287.15, 'temp': 284.81}

MicroPython のインタラクティブ実行

 正しく起動していれば、起動時の出力が終わると下記のように MicroPython のインタラクティブシェルが起動しますので、ここでインタラクティブの MicroPython を実行して動作を確認することができます。

MicroPython ESP32_LoBo_v3.2.16 - 2018-05-15 on M5Stack with ESP32
Type "help()" for more information.
>>> import time
>>> time.gmtime()
(1970, 1, 1, 0, 22, 50, 5, 1)
>>> 

 Python にはあっても MicroPython にはないクラスやメソッドもありますので、インタラクティブシェルで実際のボード上での挙動が確認できるのは便利ですね。

まとめ

 直接ケーブルで Mac と接続する必要はあるものの、上記のような情報なしで開発していくのは非効率なので、開発中はシリアルコンソールの利用が必須かと思います。今のところは m5cloud で開発をしていますが、バージョン管理等ができない不便さはあるので、開発もローカルで行ってシリアル接続で転送するやり方も検討してみようかと思います。