LoginSignup
11
9

More than 3 years have passed since last update.

M5Stackでマルチタスク

Posted at

概要

以前、M5Stackを搭載し、スマホから操作できるラジコンを作りました
モーターを動作させる処理とLCD更新処理が同じループにいるため、操作遅延等を引き起こす可能性があったり、LEDをほわほわ光らせる制御を同時に行いたいとき等にかなり処理が煩雑になってしまいます。

M5StackはESP32が入っており、ESP32はデュアルコアかつFreeRTOSで動いているとのことなのでマルチタスクを実装してみようと思います。

参考記事

環境

  • OS: MacOS Mojave
  • エディタ:Visual Studio Code
  • IDE: PlatformIO (VSCodeの拡張機能)
  • マイコン: M5Stack GRAY

マルチタスクとは

複数のタスクを並行して処理すること。

複数のコアが乗っている場合、それぞれのコアで処理を並行して行うことができる。

1つのコアでマルチタスクをする場合はスレッドに分け、一つのタスクを一定時間処理し、次のタスクを一定時間処理し...みたいにすることで並列処理を行う。

タスク生成関数

参考記事にわかりやすく書かれていますが、xTaskCreatePinnedToCoreでマルチタスクを生成できる。
また、こちらに詳細に書かれています。


BaseType_t xTaskCreatePinnedToCore(
    TaskFunction_t pvTaskCode,
    const char *constpcName,
    const uint32_t usStackDepth, 
    void *constpvParameters,
    UBaseType_t uxPriority, 
    TaskHandle_t *constpvCreatedTask,
    const BaseType_t xCoreID)

pvTaskCode

関数ポインタ

*constpcName

タスク名

usStackDepth

スタックサイズ(Byte)

*constpvParameters

タスクへ渡すパラメータ

uxPriority

タスクの優先度
数字が大きいほど優先度が高い

*constpvCreatedTask

タスクを参照するためのハンドラー

xCoreID

タスクを実行するコア(tskNO_AFFINITY or 0 or 1)
値がtskNO_AFFINITYの場合、タスクはスケジューラーが勝手にコアを決めてくれる。
コア0はWiFiやBluetooth通信機能で使用されるので、機能を使用する場合は避けたほうがいいかも。
コア1はloop関数が実行されるコア

マルチタスクを実装

注意する点は

  • 実行するタスク(関数)は終了してはいけない。無限ループを実装しましょう。これを見つけるまでに時間がかかりました...
  • タスクにはdelay関数をいれる。入れないと待ち時間がなくタスクが切り替わりません。

このソースコードではコア1を指定しているのでコア1でスレッドを生成してマルチタスクが実行されているということになります。
loop関数は呼び出し元で無限ループとなっているので終了しません。

main.cpp
#define M5STACK_MPU6886    // IMUの種類を指定

#include <Arduino.h>
#include <M5Stack.h>
#include "utility/MPU9250.h"

TaskHandle_t lcdTaskHandle = NULL;

float accX = 0.0F;
float accY = 0.0F;
float accZ = 0.0F;

float gyroX = 0.0F;
float gyroY = 0.0F;
float gyroZ = 0.0F;

float pitch = 0.0F;
float roll = 0.0F;
float yaw = 0.0F;

float temp = 0.0F;

// Task function
void lcdUpdateTask(void *args)
{
  while (1) // マルチタスクの処理は終了してはいけない
  {
    M5.Lcd.setCursor(0, 60);
    M5.Lcd.printf(" %5.2f   %5.2f   %5.2f   ", pitch, roll, yaw);
    M5.Lcd.setCursor(220, 82);
    M5.Lcd.print(" degree");
    M5.Lcd.setCursor(0, 120);
    M5.Lcd.printf("Temperature : %.2f C", temp);
    delay(10);
  }
}

void setup()
{
  // LCD設定
  M5.begin();
  M5.Lcd.setBrightness(100);
  M5.Lcd.setTextSize(2);
  M5.Lcd.setTextColor(WHITE, BLACK);

  // IMU設定
  M5.IMU.Init();

  // マルチタスク処理実行
  xTaskCreatePinnedToCore(lcdUpdateTask, "lcdTask", 4096, NULL, 1, &lcdTaskHandle, 1);
}

void loop()
{
  // IMUのデータを取得
  M5.IMU.getAhrsData(&pitch, &roll, &yaw);
  M5.IMU.getTempData(&temp);

  delay(1);
}

11
9
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
11
9