MaixduinoのESP32のファームウェアインストールとアナログ入力（Maixpy）

#1.はじめに
SIPEEDのMaixduinoについては、以前、以下の記事を書きましたが、今回はESP32のファームウェアを書き込んでMaixduinoからPythonコードを書くことでアナログ入力の値を取得してみるところまでやってみたいと思います。

https://qiita.com/ykoji/items/1624ee88e1796d0e8c90

Maixduinoのセットアップに関する情報は、日本語のものはそこまで多くなく、英語または中国語で書かれたものしかないので、もしセットアップで苦戦されている方のお役に立てれば、と思います。なお、以下の内容の利用は、正誤の問題を含め、自己責任でお願いいたします。

#2.読んでおくと良いもの（参考）
英語の情報にはなりますが、以下が参考になりました。英語が読める方はざっと目を通されるとイメージがわくと思います。

https://github.com/micropython/micropython/blob/master/docs/esp32/tutorial/intro.rst

https://www.espressif.com/sites/default/files/documentation/esp32_datasheet_en.pdf

https://github.com/sipeed/Maixduino_esp32_fimware/releases/tag/v1.4.1

#3.Maixduino全体を制御するための基本的事項
Maixduinoの中核部分は、
①Sipeed M1 AIモジュール（K210を含む）と、
②ESP32
の２つから構成されています。
①のファームウェアについては、<a href ="https://qiita.com/ykoji/items/1624ee88e1796d0e8c90">前回の記事</a>でPort0からインストールをしたものです。統合開発環境のMaixPyを使って顔認識などのAIを使ったり、前回の記事のLチカのようにデジタル出力をするだけならこれだけで十分なのですが、それだけだとMaixduinoの半分の機能しか使っていないと言って良いでしょう。
②のESP32は、センサーなどからの値を入力するために不可欠なアナログ入力端子やWifi通信・ブルートゥース通信などの機能を持っており、これらの機能を使おうとすると、別途、ESP32のファームウェアを別の方法でインストールする必要があります。
なお、SipeedM1モジュールは、ファームウェアを入れることでESP32とコミュニケーションができるようになっています。このため、ESP32の機能は、MaixpyでPythonのプログラムを書くことで制御できる、すなわち、Maixduinoのすべての機能（①と②）は１つのpythonプログラムで全体制御ができるようになっているのです。

#4.全体手順と準備
Sipeed M1 AIモジュールのファームウェアはKFlashというSipeed公式のソフトウェアを使い、ファームウェアをインストールするだけの簡単なものでした。一方で、ESP32のファームウェアは、ちょっとしたコツが必要になります。（WINDOWSだとKFLASHのようなソフトウェアが使えるようですが）

まず最初に、ESP32のファームウェアを<a href = "https://github.com/sipeed/Maixduino_esp32_fimware/releases/tag/v1.4.1">ここ</a>からダウンロードしておきます。

また、ファームウェアの書き込みには、esptools.pyというプログラムを使います。ターミナルから以下を入力してインストールしておきます。

```terminal
% pip install esptool
```

#5.ファームウェアの書き込み
まず、PCのどのポートにボードが接続されているのかを調べます。Macのターミナルで、lsコマンドを使いますが、ls -lだけだと大量に出てくるので、以下のように実行します。

```terminal
% ls -l /dev/tty.*

crw-rw-rw-  1 root  wheel   18,   0  6  5 08:38 /dev/tty.Bluetooth-Incoming-Port
crw-rw-rw-  1 root  wheel   18,   4  6  5 08:49 /dev/tty.usbserial-xel_sipeed0
crw-rw-rw-  1 root  wheel   18,   2  6  5 09:03 /dev/tty.usbserial-xel_sipeed1
```
３つ出てきましたね。このうち、①tty.usbserial-xel_sipeed0は、Sipeed M1モジュールで、既にKFLASHを使ってファームウェアをインストールしたものです。ここでは、②tty.usbserial-xel_sipeed1に先ほどダウンロードしたファームウェアをインストールすることになります。私の環境の場合には、/dev/tty.usbserial-xel_sipeed1 がMSP32にアクセスするポートのパスになります（これは、ファームウェアの書き込みをするときのコマンドで使うことになります。）。

ファームウェアのインストール（フラッシュ）には、pipコマンドでインストールしたesptoolを使います。まっさらな状態にインストールすべきなので、インストール前にeraseをします。次を実行してみてください。

```terminal
% esptool.py --chip esp32 --port /dev/tty.usbserial-xel_sipeed1 erase_flash

esptool.py v3.1
Serial port /dev/tty.usbserial-xel_sipeed1
Connecting...
Failed to get PID of a device on /dev/tty.usbserial-xel_sipeed1, using standard reset sequence.
.....___
Chip is ESP32-D0WDQ6 (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 9.1s
Hard resetting via RTS pin...
```

うまく行けたでしょうか？たまに、esptool.FatalError: Timed out waiting for packet header とエラーが出てしまうケースがあるとの報告があるようです。私も一度出たことがありますが、USBとの接続を抜いて挿し直すとうまくいきました。Maixduino以外では、ブートボタンとリセットボタンを同時に押して、リセットボタンを話す技や、コンデンサを使う技があるようです。

いよいよファームウェアの書き込みを行います。以下のコマンドを入力してください。通信速度（baud）のところはPCの環境にもよりますが、Githubなどで紹介されている速度1500000ではエラーが出て書き込めなかったので、115200にしています。また、先ほど取得したボードのポートまでのパスもここで指定します。


```terminal
% esptool.py --chip esp32 --port /dev/tty.usbserial-xel_sipeed1 --baud 115200 write_flash -z 0x0000 maixduino_esp32_firmware_v1.4.1_0x0.bin

esptool.py v3.1
Serial port /dev/tty.usbserial-xel_sipeed1
Connecting...
Failed to get PID of a device on /dev/tty.usbserial-xel_sipeed1, using standard reset sequence.
.....__
Chip is ESP32-D0WDQ6 (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...
Flash will be erased from 0x00000000 to 0x00118fff...
Compressed 1150976 bytes to 630987...
Wrote 1150976 bytes (630987 compressed) at 0x00000000 in 57.1 seconds (effective 161.3 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
```

これでボードのファームウェアの書き込みは終了しました。

#6 Maixpyでのコーディング

アナログ入力A0~A5とグラウンド（GND）の間にかかっている電圧を取得するプログラムをMaixPyで書いてみます。以下がコードになります。

```python
import network
import utime
from Maix import GPIO
from fpioa_manager import *

#MaixDuinoのアナログINのマッピング
fm.register(25,fm.fpioa.GPIOHS10)#cs
fm.register(8,fm.fpioa.GPIOHS11)#rst
fm.register(9,fm.fpioa.GPIOHS12)#rdy
fm.register(28,fm.fpioa.GPIOHS13)#mosi
fm.register(26,fm.fpioa.GPIOHS14)#miso
fm.register(27,fm.fpioa.GPIOHS15)#sclk

nic = network.ESP32_SPI(cs=fm.fpioa.GPIOHS10,rst=fm.fpioa.GPIOHS11,rdy=fm.fpioa.GPIOHS12,
mosi=fm.fpioa.GPIOHS13,miso=fm.fpioa.GPIOHS14,sclk=fm.fpioa.GPIOHS15)

# ANALOG INのA0~A5までの入力値の取得、表示
while True:
    try:
        adc = nic.adc()
    except Exception as e:
        print(e)
        continue
    for v in adc:
        print("%04d" %(v), end=" ")
    print()
    utime.sleep_ms(100)
```
#7. コードを走らせる前のボードの準備（とりあえず）
とりあえず、以下の写真のようにA3とグランドを接続し、A3から０が出るかどうかを試してみたいと思います。
本来であれば、可変抵抗とオシロスコープをつないで電圧値を変更させ、それに応じて読み取った値が変化するかどうかを確認すべきですが、今回はとりあえず簡単な動作確認にとどめたいと思います。

![IMG_1041.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280313/8e52372e-5c7f-4836-389e-cf7d0fb77b5d.jpeg)

#8. 実行後のターミナル上の出力
では、6.で書いたプログラムを実行するとどのようになるか、やってみましょう。MaixPyでプログラムを実行する時に接続先のボードを選択するよう求められますが、この時は、ESP32（USB1）ではなく、Sipeed M1 AIモジュール(USB0)になります。（前述の通り、MaixPy側からESP32とコミュニケーションを取るため。）

実行すると、以下のように表示されると思います。A3のところをグラウンドと接続してあるので、A3（左から３つ目の列）はすべてゼロであることが確認できますね。

```terminal
>>> [esp32_spi] use soft spi
0566 1315 0000 1195 0000 0000 
0000 0594 0000 0219 0000 0000 
0000 0285 0000 0000 0000 0000 
0329 0797 0000 0438 0306 0067 
0608 1291 0000 1205 0771 0066 
0315 1066 0000 0914 0391 0000 
0000 0409 0000 0000 0000 0000 
0089 0439 0000 0055 0038 0000 
0576 1150 0000 1007 0693 0167 
0560 1291 0000 1271 0729 0000 
0080 0767 0000 0528 0048 0000 
0000 0238 0000 0000 0000 0000 
0375 0822 0000 0539 0390 0131 
0577 1237 0000 1168 0734 0029 
0368 1115 0000 1049 0491 0000 
0000 0400 0000 0000 0000 0000 
0068 0405 0000 0031 0017 0000 
0575 1136 0000 0993 0680 0164 
0564 1303 0000 1278 0741 0000 
0107 0832 0000 0579 0095 0000 
0000 0259 0000 0000 0000 0000 

```

#9.最後に
いかがでしたでしょうか？アナログ端子が使えると、センサーの入力などもできるようになるのでボードの活躍の幅が広がってくると思います。
今後、センサーをつなげてみたり、センサーからとったデータをWifi経由でデータベースに飛ばしてみたりと工夫をしていきたいと思います。