LoginSignup
32
19

More than 3 years have passed since last update.

[M5Stack] マルチスレッドで並列処理を行う

Posted at

1.はじめに

M5StackのMPUのESP32には、並列処理を行うために、マルチスレッドという仕組みが用意されています。
自分の勉強用のため、M5StackのExampleのコードを、その内容を噛み砕いて、整理していきます。

2.プログラムの構造

2.1. Arduinoのプログラムの基本構造

Arduinoのプログラムは、void setup()とvoid main()の二つの関数によるプログラム構造となっています。
まずvoid setup()で、初期化処理を行います。例えば、変数、定数の宣言、通信部分の設定などがこのvoid setup()関数によって行われます。
そして、実行したいメインのタスク内容は、void loop()の中に記述します。例えば、圧力センサーの値をモニターに表示するタスクを考えましょう。(1) 圧力センサーより測定データを取得する。(2)単位の変換などのデータ処理を行う。(3)LCDやSerialモニターへの出力する、(4)一定な時間間隔でこれらの処理を繰り返し実行します。などの一連の処理部分をこのvoid loop()に書いておきます。
image.png

2.2. マルチスレッド処理のプログラムの構造

マルチスレッドのプログラムは、上記のArduinoの基本プログラムと構造が少し異なります。
まず、void setup()に、xTaskCreatePinnedCore()を用いて、並列処理を行いたいタスクを宣言します。タスク数は単数、複数のどちらでもOKですが、並列処理が目的なので、基本的に複数のタスクを宣言することになります。

そして、void loop()にはマルチスレッド用の内容を記述しません。(マルチタスクではないタスクは記述しても構いません。)その代わりに、void task0(), void task1()のような並列処理するタスクを関数として記述し、各々の関数の中にはwhile文を利用したループ構造とします。そのループの中に並列処理されるタスクの処理内容を記述します。
image.png

マルチスレッドを利用する関数

マルチスレッドは、xTaskCreatePinnedToCore()を利用し、引数のルールは下記のようになります。
ESP32の場合、Core数が2なので、引数Core IDは0か1になります。

xTaskCreatePinnedToCore(タスクの関数名, "タスク名", スタックメモリサイズ, NULL, タスク優先順位, タスクハンドリングポインタ, Core ID)

例えば、二つのタスクを2番目のコア(Core ID=1)にマルチスレッドで並列処理を行いたい場合は、下記のようなコードになります。

xTaskCreatePinnedToCore(task0, "Task_0", 4096, NULL, 1, NULL, 1)
xTaskCreatePinnedToCore(task1, "Task_1", 4096, NULL, 2, NULL, 1)

プログラムコード

M5StackのExampleのMultithread例題のコードです。

// Copyright (c) 2020 aNoken

#include <M5Stack.h>

/* task0のループ関数 */
void task0(void* arg) {
  static int cnt = 0;
  //カウントアップしてシリアルとLCDに表示する
  while (1) {
    Serial.printf("task0 thread_cnt=%ld\n", cnt);
    M5.Lcd.printf("task0 thread_cnt=%ld\n", cnt);
    cnt++;
    vTaskDelay(1000);
  }
}

/* task1のループ関数 */
void task1(void* arg) {
  static int cnt = 0;
  //カウントアップしてシリアルとLCDに表示する
  while (1) {
    Serial.printf("task1 thread_cnt=%ld\n", cnt);
    M5.Lcd.printf("task1 thread_cnt=%ld\n", cnt);
    cnt++;
    vTaskDelay(1500);
  }
}

void setup() {
  M5.begin();                       //M5Stackを初期化
  M5.Power.begin();                 //M5Stackのバッテリ初期化
  M5.Lcd.clear(BLACK);
  M5.Lcd.setTextColor(YELLOW);
  M5.Lcd.setTextSize(3);
  M5.Lcd.setCursor(0, 0);

  //task0のループ関数を起動
  xTaskCreatePinnedToCore(task0, "Task0", 4096, NULL, 1, NULL, 1);

  //task1のループ関数を起動
  xTaskCreatePinnedToCore(task1, "Task1", 4096, NULL, 2, NULL, 1);
}

void loop() {  //Arduinoのメインのループ関数はここで実行
  static int cnt = 0;

  //カウントアップしてシリアルとLCDに表示する
  M5.Lcd.clear(BLACK);
  M5.Lcd.setCursor(0, 0);
  M5.Lcd.printf("Maintask thread_cnt=%ld\n", cnt);
  Serial.printf("Maintask thread_cnt=%ld\n", cnt);
  cnt++;
  vTaskDelay(1200);
}

まとめ

M5Stack(ESP32)のマルチスレッドで並列処理を行う方法を整理しました。

参考資料

  1. https://anoken.jimdofree.com/
  2. https://github.com/anoken/
  3. https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/freertos.html
32
19
0

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
32
19