1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【FreeRTOS × ESP32】タスクでLチカして“並行処理”を体感する入門記事

Posted at

目次

  1. FreeRTOSのタスクとは?
  2. ブレッドボードの部品配置
  3. 【実装】delay() で普通にLチカしてみる
  4. 【実装】FreeRTOSのタスクを使用し、Lチカしてみる
  5. タスクを使用する上での注意点
  6. まとめ

1. FreeRTOSのタスクとは?

FreeRTOSにおける「タスク」は、
“自分の仕事を延々と繰り返す、小さなプログラム単位”
です。
Arduino の loop() が 1つしかないのに対し、
FreeRTOS では loop() を複数に分割して独立して動かせる というイメージです。

例:タスクで分割できる処理
・LEDを点滅させるタスク
・0.2秒ごとにシリアル出力するタスク
・センサー値を取得するタスク
・Wi-Fi通信を行うタスク

これらを同時進行で動かせるのがタスクの考え方です。
3章で、loop()単体の挙動との違いを比較します。

2. ブレッドボードの部品配置

ESP32 の実物が少し雑で申し訳ありませんが、
LEDの配線図は以下を参考にしてください。
LED_ブレッドボード.png
GPIO 16 → LED → 抵抗 → GND
の構成です。

3. 【実装】delay() で普通にLチカしてみる

最初に「Arduino標準のLチカ」を実装して、
delay() がどのように動作を止めてしまうか 確認します。

今回の仕様
・LEDを1秒間隔で点滅
・LEDのON/OFFをシリアル出力
上記の2つのをdelayを使用して実現します。

#include <Arduino.h>

void setup() {
  Serial.begin(115200);
  //GPIOの16ピンをOUTPUTに設定
  pinMode(16, OUTPUT);
}

void loop() {
  //LEDをON
  digitalWrite(16, HIGH);
  delay(1000);
  Serial.println("LED is ON");
  //LEDをOFF
  digitalWrite(16, LOW);
  delay(1000);
  Serial.println("LED is OFF");
}

▼ 処理の流れ
LED ON→1s待機→"LED is ON表示"→
LED OFF→1s待機→"LED is OFF表示" 
(以後ループ)

delay(1000) の間は CPU が完全に停止します。
他の処理は一切動きません。
これがタスクとの大きな違いになります。
それでは次にタスクを使用した場合を確認しましょう。

4. 【実装】FreeRTOSのタスクを使用し、Lチカしてみる

続いて、LED点滅とシリアル出力を 別々のタスク として動かします。
今回の仕様
・LEDを1秒間隔で点滅(タスクA)
・LED状態を0.2秒間隔でシリアル出力(タスクB)

#include <Arduino.h>

bool led_flag = false;

void LedTask(void *pvParameters) {
  //GPIOの16ピンをOUTPUTに設定
  pinMode(16, OUTPUT);
  while (1) {
    //LEDをON
    digitalWrite(16, HIGH);
    led_flag = true;
    //1秒待機
    vTaskDelay(1000 / portTICK_PERIOD_MS);
    //LEDをOFF
    digitalWrite(16, LOW);
    led_flag = false;
    //1秒待機
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void SerialTask(void *pvParameters) {
  while (1) {
    if(led_flag) {
      Serial.println("LED is ON");
    } else {
      Serial.println("LED is OFF");
    }
    //0.2秒待機
    vTaskDelay(200 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(115200);
  //2つのタスクを開始
  xTaskCreate(LedTask, "LedTask", 2048, NULL, 1, NULL);
  xTaskCreate(SerialTask, "SerialTask", 2048, NULL, 1, NULL);
}

void loop() {}

▼ 処理の流れ
タスクA(LED)
LED ON → 1秒休憩 → LED OFF → 1秒休憩
(以後ループ)

タスクB(シリアル)
LEDの状態を出力 → 0.2秒休憩
(以後ループ)

ターミナル上では、
LEDが1秒周期で変化する間にログが5回出ているのが確認できます。
image.png

▼ ポイント
・2つの処理が“独立して”動いている
・vTaskDelay() 中は他タスクが動く

5. タスクを使用する上での注意点

FreeRTOSには便利な機能が多い反面、
タスクを扱ううえで押さえるべきポイントがあります。

① タスクを増やしすぎない
タスクが多い=良い ではないです。
推奨:
2〜5個程度
タスク間通信は Queue / Semaphore で整理
※Queue/Semaphoreは別記事で解説予定です。

② スタックサイズは適量に
ESP32はWi-FiやBluetoothで多くのRAMを使用します。
一般的には 2048〜4096 がバランス良いです。

③ 優先度は基本「1」で揃える
初心者ほど“優先度で制御しようとする”傾向がありますが、
実務では優先度1を複数並べた構成の方が安定します。

④ delay() を併用しない
FreeRTOS内で delay() を使うと、
スケジューラが止まりタスク制御が不安定になります。
→ vTaskDelay() を統一的に使うことが大切。

6. まとめ

今回は delay() と vTaskDelay() を比較しながら、
FreeRTOSの「タスク」がどう動くのかを実例で紹介しました。

タスクの本質
・タスクは「独立した仕事単位」
・vTaskDelay は「他タスクへCPUを渡す」ための命令
・delay は「CPUを止める」ため、同時処理には不向き

FreeRTOSでは他にも
Queue・Semaphore・タイマー・イベントグループなど便利な仕組みがあり、
次回以降の記事で比較しながら触れていく予定です。

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?