【ESP32プログラム】DCモータを動かしてみよう
サーボモータはロボットアームなどに使われるモータですが、車両のタイヤなどを動かす場合にはDCモータを使います。今回はDCモータのESP32での制御について紹介したいと思います。
結線図
図1に結線図を示します。
今回は2つのDCモータを制御することにします。車輪を2つ動かして電子工作カーを作ることを前提にするためです。タミヤのダブルギヤボックスを使います。また、DCモータを制御するのにDRV8833というドライバを使います。
DCモータの操作量を決める入力装置として以前の記事で紹介した操作装置を使います。この操作装置の左右のジョイスティックのx操作(90度回転して木片に付けているので上下操作に対応します)を使って、右のジョイスティックを上に操作すると右側のモータが前進回転、下に操作すると後進回転することにします。同じく左側のジョイスティックを操作すると左側のモータが同様に動くようにします。
モータはDCモータドライバを介してコントロールしますので、ESP32とは直接の結線はありません。VMはモータを動かすための電力で、3〜5Vくらいを入力します。今回は電池ボックスから3Vを入力しています。
DCモータドライバとESP32との結線は5つです。DCモータドライバを作動させるための電源であるSTBYを3.3Vに接続します。ESP32からの指令はPWMで指令しますが、それぞれ以下のように決戦します。
・AIN1をGPIO26
・AIN2をGPIO25
・BIN1をGPIO14
・BIN2をGPIO12
なお、ジョイスティックの結線はこちらの記事を参照してください。
これで結線は完了です。次にプログラムを見ていきましょう。
プログラム
操作系の記事で書いたように無操作時の電圧は個体差がありますのでプログラムでその差を吸収しなければなりません。
NEUTRAL_X1とNEUTRAL_X2に中立時のおおよその値を設定しておきます。ノイズでこの値は変動しますし、他方のジョイスティックの操作によっても微妙に変化してしまうので、本当はノイズの電気的な処理やフィルタ処理をすべきですが、今回は不感帯を200ほど設けて「#define DEADZONE 200」、中立時に動かないようにだけしておきます。
あとはジョイスティックの値に応じてESP32に標準であるPWM指令関数「analogWrite」でそれぞれ該当するGPIO(左右及び前後進)へPWM指令を出すだけです。
#define MOTOR_A_IN1 25
#define MOTOR_A_IN2 26
#define MOTOR_B_IN1 14
#define MOTOR_B_IN2 12
#define PIN_X1 32
#define PIN_X2 34
#define NEUTRAL_X1 1850
#define NEUTRAL_X2 1940
#define DEADZONE 200
void setup() {
// モータAとモータBのピンを出力モードに設定
pinMode(MOTOR_A_IN1, OUTPUT);
pinMode(MOTOR_A_IN2, OUTPUT);
pinMode(MOTOR_B_IN1, OUTPUT);
pinMode(MOTOR_B_IN2, OUTPUT);
}
void loop() {
int x1 = analogRead(PIN_X1);
int x2 = analogRead(PIN_X2);
int pwmA = 0;
int pwmB = 0;
// モータAの回転方向とスピード設定
if (x1 < NEUTRAL_X1 - DEADZONE) {
// 逆回転
pwmA = map(x1, 0, NEUTRAL_X1 - DEADZONE, 255, 0);
analogWrite(MOTOR_A_IN1, LOW); // IN1をLOWにして逆回転
analogWrite(MOTOR_A_IN2, pwmA); // IN2にPWM信号
} else if (x1 > NEUTRAL_X1 + DEADZONE) {
// 正回転
pwmA = map(x1, NEUTRAL_X1 + DEADZONE, 4095, 0, 255);
analogWrite(MOTOR_A_IN1, pwmA); // IN1にPWM信号
analogWrite(MOTOR_A_IN2, LOW); // IN2をLOWにして正回転
} else {
// 停止
pwmA = 0;
analogWrite(MOTOR_A_IN1, LOW);
analogWrite(MOTOR_A_IN2, LOW);
}
// モータBの回転方向とスピード設定
if (x2 < NEUTRAL_X2 - DEADZONE) {
// 逆回転
pwmB = map(x2, 0, NEUTRAL_X2 - DEADZONE, 255, 0);
analogWrite(MOTOR_B_IN1, LOW); // IN1をLOWにして逆回転
analogWrite(MOTOR_B_IN2, pwmB); // IN2にPWM信号
} else if (x2 > NEUTRAL_X2 + DEADZONE) {
// 正回転
pwmB = map(x2, NEUTRAL_X2 + DEADZONE, 4095, 0, 255);
analogWrite(MOTOR_B_IN1, pwmB); // IN1にPWM信号
analogWrite(MOTOR_B_IN2, LOW); // IN2をLOWにして正回転
} else {
// 停止
pwmB = 0;
analogWrite(MOTOR_B_IN1, LOW);
analogWrite(MOTOR_B_IN2, LOW);
}
delay(100); // 更新タイミング 100ms更新
}