ESP32のマルチスレッドで複数のサーボモータを同時に動かす方法
ESP32で複数のサーボモーターを同時に動かす方法をご紹介します。
ゴール
RTOSのタスクを使って、動画のように2つのサーボーモータを独立して動かします。
なんの工夫もなしに delay 関数を使ってサーボモータを動かそうとすると、ひとつのサーボモータの処理が終わるまで待たなければならず、同時に動かすことが難しいです。非ブロッキングなポーリング処理(コルーチン)で動かすやり方も考えられますが、コーディングが複雑になり管理が難しいです。ESP32ならばFree RTOSのタスク機能(マルチスレッド)が使えますので、簡単に複数のサーボモータを動かすことが可能です。
ESP32のマルチスレッドで複数サーボを同時に動かす
ソースコード
次のコードは、FreeRTOSのタスク利用してマルチスレッドで複数サーボモータを制御する例です:
cpp
#include <Arduino.h>
#include <ESP32Servo.h>
#define SERVO_A_PIN 32
#define SERVO_B_PIN 33
Servo servoA, servoB;
const int pulse_min = 544; // default 544us
const int pulse_max = 2400; // default 2400us
// プロトタイプ宣言
void taskServoA(void * parameter);
void taskServoB(void * parameter);
void setup() {
Serial.begin(115200);
servoA.attach(SERVO_A_PIN, pulse_min, pulse_max);
servoB.attach(SERVO_B_PIN, pulse_min, pulse_max);
servoA.write(5); // リセット
servoB.write(5); // リセット
delay(2000);
// FreeRTOSを使用してタスクを作成
xTaskCreate(taskServoA, "TaskServoA", 10000, NULL, 1, NULL);
xTaskCreate(taskServoB, "TaskServoB", 10000, NULL, 1, NULL);
}
void loop() {
}
void taskServoA(void * parameter) {
for (;;) {
for (int pos = 5; pos <= 180; pos += 1) {
servoA.write(pos);
vTaskDelay(2 / portTICK_PERIOD_MS);
}
vTaskDelay(700 / portTICK_PERIOD_MS);
for (int pos = 180; pos >= 5; pos -= 1) {
servoA.write(pos);
vTaskDelay(2 / portTICK_PERIOD_MS);
}
vTaskDelay(700 / portTICK_PERIOD_MS);
}
}
void taskServoB(void * parameter) {
for (;;) {
for (int pos = 5; pos <= 180; pos += 1) {
servoB.write(pos);
vTaskDelay(6 / portTICK_PERIOD_MS);
}
vTaskDelay(300 / portTICK_PERIOD_MS);
for (int pos = 180; pos >= 5; pos -= 1) {
servoB.write(pos);
vTaskDelay(6 / portTICK_PERIOD_MS);
}
vTaskDelay(300 / portTICK_PERIOD_MS);
}
}
解説
サーボモータを、0度から180度へ行き来させるプログラミングです。サーボモータの制御は、ESP32Servo ライブラリを使用しました。
本来は pos = 0 とすべきですが、サーボモータが震えてしまうため、5度までを下限として pos = 5 のように宣言してます。
xTaskCreate で、タスク(スレッド)を作成します。一時停止を行いたい場合は delay 関数を使わずに、 vTaskDelay で処理します。vTaskDelay は、タスクを指定した時間だけブロック(一時停止)できます。