初めてのM5GO(M5Stack)メモ

【2020/08/15更新】
最近、M5Stack 関連はしばらくお休みしている間に新製品がたくさん出てきて、開発環境関連もいろいろ更新されているようですね。古い情報がそのままになっていることも多く、辿り着いたサイトが最新の情報かどうかは要確認です。オフィシャルな情報としては以下が最新でしょうか。以前も書いているように、オフィシャルなドキュメントもファームウェアの更新に追いついていないこともよくありますが。

- M5Stack メインサイト https://m5stack.com
- UIFlow Tutorial https://docs.m5stack.com/#/en/uiflow/uiflow_home_page
- Arduino Tutorial https://docs.m5stack.com/#/en/arduino/arduino_home_page


【2019/04/29更新】
ここの内容は古くなってしまっていて、多少参考になるのは「Adafruit MicroPython Tool (ampy)」の部分ぐらいでしょう。最新のドキュメントは以下になると思いますが、Firmware や UIFlow の更新が頻繁に行われているため、内容が実態に追いついていないようです。
https://m5stack.github.io/UIFlow_doc/ja/index.html

# 概要
５月末にM5GOを入手し、それ以来１ヶ月、あれこれ試行錯誤したメモです。Arduino IDEを試したりもしていますが、主にMicroPythonを使っています。

- M5GO Cloud
- M5GOへのシリアル接続
- M5GO Cloud からプログラムを動かした場合の Stack Size
- Firmware更新
- Adafruit MicroPython Tool (ampy)
- rtc.ntp_syncのバグ(M5GO firmware v0.11)

##ホスト環境
iMac (macOS High Sierra) 

##M5GO Cloud
M5GO Cloud へはすんなり接続し、サンプルプログラムも動いたけど、やはり自分でプログラムを書いて動かしたい。M5GO Cloud 上でサンプルプログラムを参考に書いてみるけど、Cloud上ではエラーがあると単に動かないだけでどこが悪いのかが全くわからない。

##M5GOへのシリアル接続
M5GO Cloud での操作時にscreenコマンドを使ってシリアル接続しておき、メッセージを確認。
シリアル接続するために /dev/tty.SLAB_USBtoUART というデバイスが存在しない場合は以下のドライバをインストール。

CP210x USB to UART Bridge VCP Drivers
https://www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers

screenはmacOSに標準で含まれているのでそれを使用。

```
$ screen -v
Screen version 4.00.03 (FAU) 23-Oct-06
$ screen /dev/tty.SLAB_USBtoUART 115200
```

デフォルトではスクロールバックできなかったり、終了するとscreenの表示が消えてしまうので、以下の設定でスクルールバックおよび終了時にも表示を残すようにした。

```
$ cat ~/.screenrc 
termcapinfo xterm* ti@:te@
```

##M5GO Cloud からプログラムを動かした場合の Stack Size
M5GO Cloudでプログラムを作って試した時に、stack overflowが発生することがあった。

```
***ERROR*** A stack overflow in task m5go_run has been detected.
```

以下のテストプログラムで試したところ、MainThreadのStack Sizeが20480なのに対してM5GO Cloudから動かした場合のスレッド「m5go_run」は4096。

```python:
import _thread
import micropython

print('thread name: ', _thread.getSelfName())
print('_thread.list()')
print(_thread.list())
print('micropython.mem_info()')
print(micropython.mem_info())
```

出力結果

```
thread name:  m5go_run
_thread.list()
ID=1073626460, Name: m5go_run, State: running, Stack=4096, MaxUsed=2436, Type: PYTHON
ID=1073428404, Name: MainThread, State: running, Stack=20480, MaxUsed=5844, Type: MAIN
None
micropython.mem_info()
stack: 1156 out of 4096
GC: total: 80000, used: 34144, free: 45856
 No. of 1-blocks: 414, 2-blocks: 103, max blk sz: 450, max free sz: 2051
None
```

以下のようにTimerを使うとMain Threadで動かせることを確認したけど、M5GO Cloudから繰り返し実行しようとすると「```Timer already in use.```」のエラーになってしまうので、そこまでしてM5GO Cloudで動かすのではなく、最初からMain Threadで動かすようにした方がよさそう。

```python:
import machine

def func():
    :    :   :

t0 = machine.Timer(0)
t0.init(period=0, mode=t0.ONE_SHOT, callback=func)
```

##Firmware更新

M5GOはIoT Starter Kitということで、すぐに使えるセンサーがセットになっていて便利なのですが、とりあえずM5GO Cloudを試した後は、Firmwareを余計なもののないM5Cloudのものに入れ替え。
手順は以下のサイトを参考。
https://github.com/m5stack/M5Cloud
使用しているFirmwareは以下のもので

* m5cloud-20180516-v0.4.0.bin

M5Cloud には繋がないので boot.py の最後の「import m5cloud」を削除。

```python:
# This file is executed on every boot (including wake-boot from deepsleep)
import sys
sys.path[1] = '/flash/lib'
from m5stack import lcd, speaker, buttonA, buttonB, buttonC

# ---------- M5Cloud ------------
if True:
    if buttonB.isPressed():
        lcd.println('On: OFF-LINE Mode', color=lcd.ORANGE)
    else:
        import wifisetup
        #import m5cloud
```

M5GOのFirmwareを入れる場合は以下からダウンロード。最新版は v0.15
https://github.com/m5stack/M5GO/tree/master/firmware

##Adafruit MicroPython Tool (ampy)

M5GO上のファイルを入れ替えたり、簡単に動作確認するために、ファイル確認・転送・実行用のツール ampy をインストール
https://github.com/adafruit/ampy

```
pip install adafruit-ampy
```

```
$ ampy --help
Usage: ampy [OPTIONS] COMMAND [ARGS]...

  ampy - Adafruit MicroPython Tool

  Ampy is a tool to control MicroPython boards over a serial connection.
  Using ampy you can manipulate files on the board's internal filesystem and
  even run scripts.

Options:
  -p, --port PORT    Name of serial port for connected board.  Can optionally
                     specify with AMPY_PORT environemnt variable.  [required]
  -b, --baud BAUD    Baud rate for the serial connection (default 115200).
                     Can optionally specify with AMPY_BAUD environment
                     variable.
  -d, --delay DELAY  Delay in seconds before entering RAW MODE (default 0).
                     Can optionally specify with AMPY_DELAY environment
                     variable.
  --version          Show the version and exit.
  --help             Show this message and exit.

Commands:
  get    Retrieve a file from the board.
  ls     List contents of a directory on the board.
  mkdir  Create a directory on the board.
  put    Put a file or folder and its contents on the...
  reset  Perform soft reset/reboot of the board.
  rm     Remove a file from the board.
  rmdir  Forcefully remove a folder and all its...
  run    Run a script and print its output.
```

以下は M5GOのfirmware v0.15を入れた状態でのリスト

```
$ export AMPY_PORT=/dev/tty.SLAB_USBtoUART
$ ampy ls /flash
utils.mpy
wificonfig.mpy
res
boot.py
m5stack.mpy
img
examples
M5GO.mpy
lib
wifisetup.mpy
main.py
fonts
```

ampyを使用してプログラムを実行

```
$ cat hello_world.py 
print('Hello, World!')
$ ampy run hello_world.py 
Hello, World!
```

##rtc.ntp_syncのバグ(M5GO firmware v0.11)

M5GOのfirmware v0.11のMicroPythonでは rtc.ntp_sync でTimeZoneを指定するとエラーになるという問題があり、プログラムで時刻を表示しようとしてしばらく悩みました。

```python:
import machine
import time

print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))

rtc = machine.RTC()
rtc.ntp_sync('ntp.nict.jp', tz='JST-9')
for i in range(100):
    if rtc.synced():
        print('synced.')
        break
    print(i, end=' ')
    time.sleep_ms(10)

print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
```

実行結果

```
1970-01-01 00:01:51
Unhandled exception in thread started by <function m5go_run at 0x3ffcb6c0>
Traceback (most recent call last):
  File "m5go_cloud.py", line 7, in m5go_run
  File "<string>", line 7, in <module>
ValueError: tz string length must be 3 - 64
```

以下にTimeZoneをsys.tzで指定するという回避策がありました。
https://github.com/loboris/MicroPython_ESP32_psRAM_LoBo/issues/130

```python:
import machine
import time
import sys

print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))

rtc = machine.RTC()
rtc.ntp_sync('ntp.nict.jp')
sys.tz('JST-9')
for i in range(100):
    if rtc.synced():
        print('synced.')
        break
    print(i, end=' ')
    time.sleep_ms(10)

print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()))
```

実行結果

```
1970-01-01 00:05:24
0 1 2 3 4 5 6 7 8 9 synced.
2018-07-09 21:39:07
```

この問題はM5GOのfirmware v0.15で対応されており、M5CloudのFirmwareでも問題ありません。

##参考
* [M5Stackであそぼう](http://mag.switch-science.com/2018/02/28/getting-started-with-m5stack/)
* [M5GOのfirmwareをM5Stack用に書き換える（＋戻し方）](http://littlewing.hatenablog.com/entry/2018/05/21/153646)
* [ampy: MicroPythonマイコンとPCとのファイル転送ツール](https://ambidata.io/blog/2018/03/15/ampy/)