[ESP32]新しいタスクを追加する方法

ESP32

新しいタスクを追加する方法

プログラムを作成していくと、新たにタスクを追加したい時がくると思います。

例えば、以下のような処理をするプログラムを作成する場合は別々のタスクで実行した方が良いと思います。

  1. 赤外線センサーで人を検知するとLEDを光らせる。
  2. 外部サーバと通信接続して検知データを送信する。

このような場合、1.は周期的に動作して赤外線センサーからの情報を読み取っていますが、2.の処理に時間を要する場合、1.の処理が待たされて人がいるのにLEDがなかなか光ってくれないかもしれません。

サンプルコード(コピペで動作)

使用API:xTaskCreatePinnedToCore() / vTaskDelete()

TaskHandle_t thp[2];
ulong count = 0;

// the setup function runs once when you press reset or power the board
void setup() {
  
  // initialize serial communication at 115200 bits per second:
  Serial.begin(115200);
  
  // Now set up two tasks to run independently.
  xTaskCreatePinnedToCore( TaskA, "TaskA", 2048, NULL, 2, &thp[0], APP_CPU_NUM);
  xTaskCreatePinnedToCore( TaskB, "TaskB", 2048, NULL, 2, &thp[1], APP_CPU_NUM);

  delay(10000);
  vTaskDelete(thp[0]);
  Serial.println("TaskA End");
  vTaskDelete(thp[1]);
  Serial.println("TaskB End");

  Serial.printf("uxTaskPriorityGet : %d\n", uxTaskPriorityGet(NULL));
  Serial.printf("xPortGetCoreID : %d\n", xPortGetCoreID());
}

void loop()
{
  // Empty. Things are done in Tasks.
}

/*--------------------------------------------------*/
/*---------------------- Tasks ---------------------*/
/*--------------------------------------------------*/
void TaskA(void *pvParameters)  // This is a task.
{
  Serial.println("TaskA Start");
  while( 1 ) {
    delay(100);
    count++;
  }
  // ここにはこないが明示的にタスク終了を記載しておく。
  vTaskDelete(NULL);
}

void TaskB(void *pvParameters)  // This is a task.
{
  Serial.println("TaskB Start");
  while( 1 ) {
    Serial.printf("TaskB : %d\n", count);
    delay(1000);
  }
  // ここにはこないが明示的にタスク終了を記載しておく。
  vTaskDelete(NULL);
}

上記サンプルコードでは、メインタスクが11行目,12行目でTaskAとTaskBを生成し、10秒後に15行目,17行目でTaskAとTaskBを削除しています。

xTaskCreatePinnedToCore(引数)

pxTaskCodeタスクの関数ポインタ
pcNameタスク名称
(ユーザーのためのタスク名称)
usStackDepth スタックサイズ(bytes)
(1024,2048,4096などで指定)
pvParameters タスク生成時に渡すパラメータが格納されるポインタ
(渡すものがなければNULLでよい)
uxPriority タスク優先度(0~24)
(数字が大きくなるほど優先度高)
pvCreatedTask 生成したタスクハンドル
(必要なければNULLでもよい)
xCoreID コアID
(PRO_CPU_NUM (0) APP_CPU_NUM (1))

メインタスクのCPUとタスク優先度を調べるために、20行目,21行目にuxTaskPriorityGet()とxPortGetCoreID()を追加しておきました。

確認方法でもわかるようにCPUは1を使用しており、タスク優先度は1です。アプリタスクを追加する場合で、デュアルCPUの動作をする必要がない場合は、CPU1で追加するのが良いでしょう。

vTaskDelete(引数)

xTaskToDeleteタスクハンドル
(NULLの場合は自タスク)

自タスクが終了する場合は、必ずvTaskDelete(NULL)で終了しなければならないようです

vTaskDelete(NULL)を忘れるとシステムが止まります…。

確認方法

実行すると、以下のようにシリアルポートに出力されます。

TaskAがカウントアップした変数の値をTaskBが表示できています。

まとめ

ESP32でのタスクの動作を理解できれば、複数タスクによるシステムを作ることができますね。

今後タスク間通信や、セマフォなど紹介していきます。

コメント

タイトルとURLをコピーしました