#やること
前回の続きで、ESP32DevKitCとArduinoIDEを使って、ESP32でマルチコア・マルチスレッドを使っていきます。
複数のプロセスを並行処理するマルチスレッドでは、プロセス間でデータの受け渡しをする際にルールを決めておかないと、同じデータを同時に上書きするなどの問題が生じます。
そこで今回はキューによるデータの受け渡しを試してみます。
#そもそもキューとは
キュー(Queue)とは列のことです。
スレッド間で順次データを送信していくわけですが、キューの仕組みを使えば、もし受け取り先でデータの処理が遅れていた場合に、データを列に並べて待機させることができます。
処理が空き次第、待ち列の先頭からデータを相手にコピーで渡していきます。コピーが済んだ先頭のデータは消去され、次のデータが先頭に押し出されます。
#準備
- Arduino IDEの入ったPC
- Arduino IDEでESP32が使えるようにしてある
- ESP32DevKitC
Arduino IDEで試す
ではさっそくキューを試してみましょう
TaskHandle_t thp[2];//マルチスレッドのタスクハンドル格納用
QueueHandle_t xQueue_1;//Queueを使う準備 [キューハンドル名]
void setup() {
Serial.begin(115200);
xQueue_1 = xQueueCreate( 10, 16 );
//xQueueCreate( [待ち行列の席数], [一席あたりのバイト数] );
//スレッドの準備
xTaskCreatePinnedToCore(Core0a, "Core0a", 4096, NULL, 2, &thp[0], 0);
xTaskCreatePinnedToCore(Core1a, "Core1a", 4096, NULL, 1, &thp[1], 1);
//xTaskCreatePinnedToCore(
// [タスク名], "[タスク名]",
// [スタックメモリサイズ(4096or8192)], [NULL],
// [タスク優先順位(1-24)] 大きいほど優先順位が高い,
// [宣言したタスクハンドルのポインタ(&thp[0])], [CoreID(0or1)]);
}
void loop() {//メインループ
Serial.println("[ main ] loop");
delay(100);
}
void Core1a(void *args) {//スレッド ①
int a = 0;//送信データの変数
while (1) {
xQueueSend( xQueue_1, &a, 0 );
//xQueueSend([キューハンドル名], [送る値], [待ち行列の席が空くまで待つ時間]);
a++;
delay(1000);
}
}
void Core0a(void *args) {//スレッド ②
int b = 0;//データ受信用の変数
while (1) {
/* メッセージ受信待ち */
xQueueReceive( xQueue_1, &b, portMAX_DELAY );
//xQueueSend([キューハンドル名], [データを受信するアドレス], [キュー空きを待つ最大時間。portMAX_DELAYで永久待ち])
Serial.print("[Core0a] xQueueReceive:");
Serial.println(b);
delay(1);
}
}
実行結果
Core0aはdelay(1)間隔の高速ループでキューからの受信を待ち受けています。 一方で、Core1aはdelay(1000)のゆっくりとした間隔でキューを発信しています。 また、メインループはdelay(100)の間隔で更新されています。 このため、メインループ10回の表示につき、Core0aが受け取ったキューを1回表示するという実行結果になります。ポイント
・キュー先頭のデータは一度取得されると消えます。
たとえばキューのデータが1つしかない場合に、2つのプロセスからキューのデータを取得しようとすると、最初にキューにアクセスしたプロセスだけがデータを取得できます。
・キューの繰り出しはOSが自動的に行ってくれます。
・キュー空きを待つ最大時間は、portMAX_DELAYで永久待ちとなります。
・送受信用の変数はスレッドの内部に持つようにします。(ローカルスコープ)
#参考URL
FreeRTOSでマルチタスク (on ESP32)
Arduino – ESP32 のマルチタスク ( Dual Core ) を試す
[[M5Stack] マルチスレッドで並列処理を行う]
(https://qiita.com/kotai2003/items/6a4d620a51ca0f1535dc)
ESP32のマルチタスクとCPU利用率を調べる
ESP32のFreeRTOS入門 その2 タスクの作成
xQueueReceive
が大変参考になりました。ありがとうございました。
次回
次はセマフォの使い方を試してみます。
次回記事:
前回記事: