先日、
SWITCHSCIENCE で
M5Stack Core2 for AWS – ESP32 IoT 開発キットを購入しました。
この M5Stack Core2 for AWS で
Amazon FreeRTOS を動かしたいと思い、インターネットで検索しながら試していたのですが、初心者用のまとまっている情報がなくて少し苦労したので、備忘録として方法をメモします。
環境は macOS 12.4 です。Python については、pipenv や virtualenv を使っているとエラーになってうまくできなかったので、それらは使っていません。
ESP-IDF のインストール
まずは、ESP32 の開発フレームワークである ESP-IDF をインストールします。
基本的に
公式ドキュメントのとおりにコマンドを実行しました。
mkdir esp && cd esp
git clone -b release/v4.2 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32
Amazon FreeRTOS の設定
FreeRTOS を GitHub から以下のコマンドでダウンロードします。
git clone https://github.com/aws/amazon-freertos --recursive
AWS CLI をインストールしていない場合は、インストールしておきます。
インストール方法は
公式ドキュメントを参照してください。
インストール後に、以下のコマンドで AWS CLI に認証情報の設定をします。私は
公式ドキュメントにならって、AmazonFreeRTOSFullAccess と AWSIoTFullAccess ポリシーをアタッチした IAM ユーザーを新規作成して、その認証情報を使用しました。
必要な Python ライブラリをインストールします。
pip install tornado nose
pip install boto3
次に FreeRTOS のリポジトリにある SetupAWS.py スクリプトを実行します。
まず、amazon-freertos/tools/aws_config_quick_start/configure.json に WI-FI の接続情報等を入力します。
{
"afr_source_dir":"../..",
"thing_name":"M5 Stack の AWS IoT に設定するモノの名前",
"wifi_ssid":"WI-FI の SSID",
"wifi_password":"WI-FI のパスワード",
"wifi_security":"WI-FI のセキュリティタイプ"
}
wifi_security に設定できる値は、FreeRTOS の
GitHub リポジトリの README を確認してください。
SetupAWS.py スクリプトを実行します。
cd tools/aws_config_quick_start/
python SetupAWS.py
この段階で AWS IoT コンソールにモノが作成されます。
デモのビルドと書き込み
FreeRTOS のリポジトリに含まれている
coreMQTT Mutual Authentication デモをビルド・書き込みをして M5Stack Core2 for AWS で動かしてみます。
まず、ESP-IDF のツールチェーンをインストールします。
cd /path/to/amazon-freertos
vendors/espressif/esp-idf/install.sh
source vendors/espressif/esp-idf/export.sh
デモをビルドして M5Stack Core2 for AWS に書き込みます。M5Stack Core2 for AWS を USB で接続してから実行します。
idf.py -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 build
idf.py erase_flash
idf.py flash
idf.py monitor
「Ctrl+]」キーで monitor から抜けることができました。Ctrl+c や Ctrl+z で抜けられないので注意してください。
monitor で以下のように MQTT トピック (<モノの名前>/example/topic) にメッセージ (Hello World!) が送信されます。AWS IoT コンソールの MQTT テストクライアントでトピックをサブスクライブすると、メッセージが受信できます。
(略)
223 6712 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=42.
224 6712 [iot_thread] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
225 6712 [iot_thread] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPubAckSend.
226 6712 [iot_thread] [mqtt_demo_mutual_auth.c:1116] [INFO] [MQTT_MutualAuth_Demo] Incoming QoS : 1
227 6712 [iot_thread] [mqtt_demo_mutual_auth.c:1127] [INFO] [MQTT_MutualAuth_Demo] Incoming Publish Topic Name: m5stackcore2/example/topic matches subscribed topic.Incoming Publish Message : 228 6814 [iot_thread] [mqtt_demo_mutual_auth.c:572] [INFO] [MQTT_MutualAuth_Demo] Keeping Connection Idle...
229 7014 [iot_thread] [mqtt_demo_mutual_auth.c:552] [INFO] [MQTT_MutualAuth_Demo] Publish to the MQTT topic m5stackcore2/example/topic.
230 7014 [iot_thread] [mqtt_demo_mutual_auth.c:562] [INFO] [MQTT_MutualAuth_Demo] Attempt to receive publish message from broker.
231 7020 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
232 7020 [iot_thread] [core_mqtt.c:1162] [INFO] [MQTT] Ack packet deserialized with result: MQTTSuccess.
233 7020 [iot_thread] [core_mqtt.c:1175] [INFO] [MQTT] State record updated. New state=MQTTPublishDone.
234 7022 [iot_thread] [mqtt_demo_mutual_auth.c:1054] [INFO] [MQTT_MutualAuth_Demo] PUBACK received for packet Id 6.
235 7025 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=42.
236 7025 [iot_thread] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
237 7025 [iot_thread] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPubAckSend.
238 7025 [iot_thread] [mqtt_demo_mutual_auth.c:1116] [INFO] [MQTT_MutualAuth_Demo] Incoming QoS : 1
239 7025 [iot_thread] [mqtt_demo_mutual_auth.c:1127] [INFO] [MQTT_MutualAuth_Demo] Incoming Publish Topic Name: m5stackcore2/example/topic matches subscribed topic.Incoming Publish Message : 240 7125 [iot_thread] [mqtt_demo_mutual_auth.c:572] [INFO] [MQTT_MutualAuth_Demo] Keeping Connection Idle...
241 7325 [iot_thread] [mqtt_demo_mutual_auth.c:580] [INFO] [MQTT_MutualAuth_Demo] Unsubscribe from the MQTT topic m5stackcore2/example/topic.
242 7331 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
243 7331 [iot_thread] [mqtt_demo_mutual_auth.c:1085] [INFO] [MQTT_MutualAuth_Demo] Unsubscribed from the topic m5stackcore2/example/topic.
244 7431 [iot_thread] [mqtt_demo_mutual_auth.c:602] [INFO] [MQTT_MutualAuth_Demo] Disconnecting the MQTT connection with xxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com.
245 7431 [iot_thread] [core_mqtt.c:2149] [INFO] [MQTT] Disconnected from the broker.
(略)
238 6956 [iot_thread] [mqtt_demo_mutual_auth.c:1116] [INFO] [MQTT_MutualAuth_Demo] Incoming QoS : 1
239 6956 [iot_thread] [mqtt_demo_mutual_auth.c:1127] [INFO] [MQTT_MutualAuth_Demo] Incoming Publish Topic Name: m5stackcore2/example/topic matches subscribed topic.Incoming Publish Message : 240 7056 [iot_thread] [mqtt_demo_mutual_auth.c:572] [INFO] [MQTT_MutualAuth_Demo] Keeping Connection Idle...
241 7256 [iot_thread] [mqtt_demo_mutual_auth.c:580] [INFO] [MQTT_MutualAuth_Demo] Unsubscribe from the MQTT topic m5stackcore2/example/topic.
242 7262 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
243 7262 [iot_thread] [mqtt_demo_mutual_auth.c:1085] [INFO] [MQTT_MutualAuth_Demo] Unsubscribed from the topic m5stackcore2/example/topic.
244 7362 [iot_thread] [mqtt_demo_mutual_auth.c:602] [INFO] [MQTT_MutualAuth_Demo] Disconnecting the MQTT connection with xxxxxxxxxxxxxxx.iot.ap-northeast-1.amazonaws.com.
245 7362 [iot_thread] [core_mqtt.c:2149] [INFO] [MQTT] Disconnected from the broker.
246 7363 [iot_thread] [mqtt_demo_mutual_auth.c:631] [INFO] [MQTT_MutualAuth_Demo] Demo completed an iteration successfully.
247 7364 [iot_thread] [mqtt_demo_mutual_auth.c:632] [INFO] [MQTT_MutualAuth_Demo] Demo iteration 3 completed successfully.
248 7364 [iot_thread] [mqtt_demo_mutual_auth.c:644] [INFO] [MQTT_MutualAuth_Demo] Short delay before starting the next iteration....
249 7864 [iot_thread] [mqtt_demo_mutual_auth.c:655] [INFO] [MQTT_MutualAuth_Demo] Demo run is successful with 3 successful loops out of total 3 loops.
250 7864 [iot_thread] [INFO ][DEMO][78640] memory_metrics::freertos_heap::before::bytes::223740
251 7864 [iot_thread] [INFO ][DEMO][78640] memory_metrics::freertos_heap::after::bytes::127640
252 7864 [iot_thread] [INFO ][DEMO][78640] memory_metrics::demo_task_stack::before::bytes::5848
253 7864 [iot_thread] [INFO ][DEMO][78640] memory_metrics::demo_task_stack::after::bytes::2584
I (80335) wifi:state: run -> init (0)
I (80335) wifi:pm stop, total sleep time: 64309502 us / 77261588 us
I (80335) wifi:new:<2,0>, old:<2,0>, ap:<255,255>, sta:<2,0>, prof:1
I (80335) WIFI: WIFI_EVENT_STA_DISCONNECTED: 63
254 7964 [iot_thread] [INFO ][DEMO][79640] Demo completed successfully.
E (80345) wifi_init: Wi-Fi not stop
I (80355) WIFI: WIFI_EVENT_STA_STOP
I (80365) wifi:flush txq
I (80365) wifi:stop sw txq
I (80365) wifi:lmac stop hw txq
I (80365) wifi:Deinit lldesc rx mblock:10
255 7968 [iot_thread] [INFO ][INIT][79680] SDK cleanup done.
256 7968 [iot_thread] [INFO ][DEMO][79680] -------DEMO FINISHED-------
別のデモをビルドして実行してみる
今度は別のデモ (
AWS IoT Device Shadow デモアプリケーション) に切り替えて、ビルドして実行してみます。
デモの切り替えは vendors/espressif/boards/
esp32/aws_demos/config_files/aws_demo_config.h の 53 行目の #define を変更するだけで可能です。
#define CONFIG_DEVICE_SHADOW_DEMO_ENABLED
あとは最初のデモと同様に、M5Stack Core2 for AWS を接続して、以下のコマンドでビルドと書き込みを行うだけです。
idf.py -DVENDOR=espressif -DBOARD=esp32_wrover_kit -DCOMPILER=xtensa-esp32 build
idf.py erase_flash
idf.py flash
idf.py monitor
monitor では以下のようなログが確認できます。
2 7 [iot_thread] [INFO ][DEMO][70] ---------STARTING DEMO---------
I (752) BTDM_INIT: BT controller compile version [bfbbe1e]
3 7 [iot_thread] [INFO ][INIT][70] SDK successfully initialized.
(略)
93 1253 [iot_thread] [mqtt_demo_helpers.c:685] [INFO] [MQTT] Cleaned up outgoing publish packet with packet id 10.
94 1264 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=206.
95 1264 [iot_thread] [core_mqtt.c:1045] [INFO] [MQTT] De-serialized incoming PUBLISH packet: DeserializerResult=MQTTSuccess.
96 1264 [iot_thread] [core_mqtt.c:1058] [INFO] [MQTT] State record updated. New state=MQTTPubAckSend.
97 1264 [iot_thread] [shadow_demo_main.c:695] [INFO] [ShadowDemo] pPublishInfo->pTopicName:$aws/things/m5stackcore2/shadow/update/accepted.
98 1264 [iot_thread] [shadow_demo_main.c:590] [INFO] [ShadowDemo] /update/accepted json payload:{"state":{"reported":{"powerOn":1}},"metadata":{"reported":{"powerOn":{"timestamp":1656813737}}99 1264 [iot_thread] [shadow_demo_main.c:637] [INFO] [ShadowDemo] clientToken: 001246
100 1264 [iot_thread] [shadow_demo_main.c:642] [INFO] [ShadowDemo] receivedToken:1246, clientToken:1246
101 1264 [iot_thread] [shadow_demo_main.c:650] [INFO] [ShadowDemo] Received response from the device shadow. Previously published update with clientToken=1246 has been accepted.
102 1305 [iot_thread] [shadow_demo_main.c:984] [INFO] [ShadowDemo] Start to unsubscribe shadow topics and disconnect from MQTT.
103 1305 [iot_thread] [mqtt_demo_helpers.c:1028] [INFO] [MQTT] UNSUBSCRIBE sent topic $aws/things/m5stackcore2/shadow/update/delta to broker.
104 1311 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
105 1311 [iot_thread] [mqtt_demo_helpers.c:733] [INFO] [MQTT] MQTT_PACKET_TYPE_UNSUBACK.
106 1371 [iot_thread] [mqtt_demo_helpers.c:1028] [INFO] [MQTT] UNSUBSCRIBE sent topic $aws/things/m5stackcore2/shadow/update/accepted to broker.
107 1377 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
108 1377 [iot_thread] [mqtt_demo_helpers.c:733] [INFO] [MQTT] MQTT_PACKET_TYPE_UNSUBACK.
109 1437 [iot_thread] [mqtt_demo_helpers.c:1028] [INFO] [MQTT] UNSUBSCRIBE sent topic $aws/things/m5stackcore2/shadow/update/rejected to broker.
110 1444 [iot_thread] [core_mqtt.c:886] [INFO] [MQTT] Packet received. ReceivedBytes=2.
111 1444 [iot_thread] [mqtt_demo_helpers.c:733] [INFO] [MQTT] MQTT_PACKET_TYPE_UNSUBACK.
112 1504 [iot_thread] [core_mqtt.c:2149] [INFO] [MQTT] Disconnected from the broker.
113 1504 [iot_thread] [shadow_demo_main.c:1041] [INFO] [ShadowDemo] Demo iteration 1 is successful.
114 1504 [iot_thread] [INFO ][DEMO][15040] memory_metrics::freertos_heap::before::bytes::223324
115 1504 [iot_thread] [INFO ][DEMO][15040] memory_metrics::freertos_heap::after::bytes::122928
116 1506 [iot_thread] [INFO ][DEMO][15060] memory_metrics::demo_task_stack::before::bytes::5848
117 1506 [iot_thread] [INFO ][DEMO][15060] memory_metrics::demo_task_stack::after::bytes::2952
I (16742) wifi:state: run -> init (0)
I (16742) wifi:pm stop, total sleep time: 8346384 us / 13687395 us
I (16742) wifi:new:<2,0>, old:<2,0>, ap:<255,255>, sta:<2,0>, prof:1
I (16742) WIFI: WIFI_EVENT_STA_DISCONNECTED: 63
E (16752) wifi_init: Wi-Fi not stop
I (16752) WIFI: WIFI_EVENT_STA_STOP
118 1606 [iot_thread] [INFO ][DEMO][16060] Demo completed successfully.
I (16772) wifi:flush txq
I (16772) wifi:stop sw txq
I (16772) wifi:lmac stop hw txq
I (16772) wifi:Deinit lldesc rx mblock:10
119 1610 [iot_thread] [INFO ][INIT][16100] SDK cleanup done.
120 1610 [iot_thread] [INFO ][DEMO][16100] -------DEMO FINISHED-------
AWS IoT コンソールをのモノの Device Shadow を確認すると、作成されていて状態も設定されているのが確認できます。
Core2FactoryTest に設定する
購入直後の状態ではないですが、デモの実行ができたので、元にもどす代わりに Core2FactoryTest というアプリケーションを書き込んでおきます。
M5Burner というアプリケーションを利用するので、インストールします。
このサイトからダウンロードできます。
インストール後 M5Burner を起動する際に、私の環境ではターミナルから、以下のコマンドで動かす必要がありました。(この
サイトを参考にしました。上記のサイトを見ると v3 になっていたので、現在は起動コマンドが少し違うかもしれません。)
/Applications/M5Burner.app/Contents/MacOS/electron-m5burner-v2-eletron
起動後、画面上部にて COM ポートを選択し、Core2FactoryTest を検索して、Burn ボタンを押下することで Core2FactoryTest を書き込むことができます。
Burn ボタンを押下後少し待つと、M5Stack Core2 for AWS から音がするので、画面をタップすると以下のようになります。
参考資料
上記で紹介したサイトやドキュメントの他に、以下のブログ記事も参考にしました。
FreeRTOS については Interface 2021 年 4 月号の特集が勉強になりました。