Table of Contents
プログラム
Lチカのソースコードはこちらです。
※コードが更新されると困るので、本家のものからforkしています。
動作としてはIoT CoreのMQTTブローカーをSubscribeして、メッセージがPublichされたタイミングでLEDを点滅する、というものです。
もう一度メッセージをPublishすると、LEDの点滅が停止します。
プログラム構成
Lチカのプログラムは下図のような構成で動作しています。実際にはデバイス制御やWi-Fi、UI制御のプログラムも存在していますが、割愛しています。
ポイントはAWS IoT Coreとの通信を行っていることと、複数のタスクが強調動作しているという2点です。この点を踏まえて以下の解説を読んでください。
platformio.ini
このファイルが存在するということはこのディレクトリ自体がPlatformIOのプロジェクトであることを示しています。
framework
が espidf
となっていますね。M5Stackは Arduino
と espidf
が選択できるのですが、今回はより玄人向けの espidf
を使っていることがわかります。
[env:core2foraws]
platform = espressif32@3.2.1
framework = espidf
board = m5stack-core2
monitor_speed = 115200
upload_speed = 2000000
board_build.f_flash = 80000000L
board_build.flash_mode = qio
build_unflags = -mfix-esp32-psram-cache-issue
main.c - app_main()
espidf
を使う場合、 app_main()
がエントリポイントとなります。
- Core2ForAWS_Init()
- これはesp-idfのcomponentsである
core2forAWS
の初期化関数です - サポートするH/Wの初期化関数を順次実行します
- これはesp-idfのcomponentsである
- Core2ForAWS_Display_SetBrightness()
- 関数名の通り、ディスプレイの明るさを設定しています
- ui_init()
- 画面に表示するUIを初期化しています
- UI周りの処理は同じディレクトリにある
ui.c
に記述されていますね
- initialise_wifi()
- Wi-Fiの初期化関数です
- Wi-Fi周りの処理は同じディレクトリにある
wifi.c
に記述されていますね
- xTaskCreatePinnedToCore()
- リアルタイムOS(以下RTOS)上で動作する組込みプログラムを読み解く上で重要な関数です
- 詳細は後述します
補足: タスク起動
espidfにおけるタスク起動は xTaskCreatePinnedToCore を用います。
タスクとはRTOSにおける実行コンテキストのようなものです。Linuxにおけるプロセスまたはスレッドが概念としては近いです。(厳密にはいろいろ違いがあります)
ここでは2つのタスクを起動しています。
- aws_iot_task()
- AWS IoT Coreとの通信を行うタスクです。
- 詳細は後述します。
- blink_task()
- LEDを点滅させるタスクです。
- こちらも詳細は後述します。
また、タスク構成について特筆すべきポイントがいくつかあります。
- aws_iot_taskの方がスタックが多く割り当てられています。通信処理でそれなりにメモリを食うためと予想されます。
- 両方のタスクがコア1に割り当てられています。つまり、この2つのタスクは厳密に同時に処理されることは無いということです。
main.c - aws_iot_task()
AWS IoT CoreのMQTTブローカーに対してサブスクライブするタスクです。
- aws_iot_mqtt_init()
- MQTTクライアントを指定したパラメータで初期化しています。
- この時点ではまだAWS IoT Coreに接続していません
- xEventGroupWaitBits()
- これはFreeRTOSが提供するEventGroupsと呼ばれる仕組みを利用する関数です
- ここでは別タスクで行っているWi-Fiの接続を待っています
- aws_iot_mqtt_connect()
- AWS IoT CoreとMQTT接続しています
- aws_iot_mqtt_subscribe()
- AWS IoT CoreのMQTTブローカーに対してサブスクライブしています
- メッセージがPublishされた場合は
iot_subscribe_callback_handler()
をコールバックします
- メッセージがPublishされた場合は
- AWS IoT CoreのMQTTブローカーに対してサブスクライブしています
- aws_iot_mqtt_yield()
- AWS IoT CoreのMQTTクライアントのKeepAliveおよびメッセージの受信処理を行います。
- メッセージの受信頻度よりも高頻度で呼び出す必要があります
- この例だと3000msで呼び出し、100msでタイムアウト
blink.c - blink_task()
LEDの点滅(通称: Lチカ)を行うタスクです。
このタスクは起動直後にサスペンド(中断)しており、aws_iot_task()
にて適宜レジューム(再開)されます。
- vTaskSuspend()
- FreeRTOSが提供するタスクをサスペンドする関数です
- 引数がNULLの場合はこの関数を呼出したタスク自信をサスペンドします
- Core2ForAWS_Sk6812_Clear()
- LEDコントローラを初期化しています
- SK6812とはLEDのコントローラです(参考: データシート)
- Core2ForAWS_Sk6812_SetSideColor()
- フルカラーLEDの表示色をセットします
- 今回の場合は
0xffffff
(白色点灯) →0x000000
(消灯) を繰り返しています
- vTaskDelay()
- 引数で指定した期間、タスクをBlocked状態とします
- 要は指定した時間(tick)、タスクを待たせています
main.c - iot_subscribe_callback_handler()
AWS IoT Coreに対してSubscribeしているtopicに対して、Publishが発生したときのコールバック関数です。
blink_task()
の状態を取得して、サスペンドしている場合はレジューム、そうでなければサスペンドを実施しています。
感想
単純なLチカプログラムですが、じっくり読むと奥が深いですね。 今回はまだ浅い部分しかコードリーディングできていませんが、さらにコードを読み込んでいくことで学びがありそうです。