ESP32には、モーター制御に特化したハードウェア周辺回路であるMCPWM (Motor Control Pulse Width Modulator)が搭載されています。これを利用することで、CPUの負荷を抑えつつ、複数のモーターに対して精密なPWM信号を生成することが可能です。
MCPWMの概要
MCPWMは、単なるPWMジェネレーターではなく、電力電子機器の制御を目的とした多機能モジュールです。主に以下のような用途で活用されます。
- ブラシ付き/ブラシレスDCモーター、サーボモーターの制御
- デジタル電源変換(スイッチング電源)
- パワーDAC(デューティ比をアナログ値として利用)
- 外部パルス幅の計測(速度や距離の算出)
- ベクトル制御(FOC)のための空間ベクトルPWM (SVPWM) 生成
プロジェクトのセットアップ
ここでは、ESP32のMCPWMを簡単に扱うためのライブラリを利用して実装を行います。PlatformIO環境を使用する場合、platformio.iniに以下の依存関係を追加します。
[env:esp32dev]
platform = espressif32
board = esp32dev
framework = arduino
lib_deps =
https://github.com/fishros/Esp32McpwmMotor.git
このライブラリを使用することで、最大12チャンネルのPWM出力(DCモーター6台分)を効率的に管理できます。
モーター制御の実装
以下のサンプルコードは、2つのモーターを異なるピンに割り当て、周期的に正転・逆転を繰り返す制御ロジックです。コードの可読性を高めるため、ピン番号を定数として定義しています。
#include <Arduino.h>
#include <Esp32McpwmMotor.h>
// モーター制御用インスタンス
Esp32McpwmMotor motorHandler;
// ピンアサインの定義
const int LEFT_MOTOR_ID = 0;
const int RIGHT_MOTOR_ID = 1;
void setup() {
Serial.begin(115200);
// モーター0: GPIO 23 と 22 を使用
motorHandler.attachMotor(LEFT_MOTOR_ID, 23, 22);
// モーター1: GPIO 12 と 13 を使用
motorHandler.attachMotor(RIGHT_MOTOR_ID, 12, 13);
}
void loop() {
// パターン1: 左モーター後退、右モーター前進
Serial.println("Moving Pattern A...");
motorHandler.updateMotorSpeed(LEFT_MOTOR_ID, -65);
motorHandler.updateMotorSpeed(RIGHT_MOTOR_ID, 65);
delay(2500);
// パターン2: 左モーター前進、右モーター後退
Serial.println("Moving Pattern B...");
motorHandler.updateMotorSpeed(LEFT_MOTOR_ID, 65);
motorHandler.updateMotorSpeed(RIGHT_MOTOR_ID, -65);
delay(2500);
}
コードの解説
このプログラムでは、Esp32McpwmMotorクラスを使用してハードウェアの抽象化を行っています。
attachMotor(id, pin1, pin2): 指定したIDのモーターに対して、使用するGPIOピンを割り当てます。内部的にMCPWMのタイマーとオペレーターがセットアップされます。updateMotorSpeed(id, duty): 対象モーターの回転速度を制御します。引数には-100から100の値を指定し、正の値は正転、負の値は逆転、0は停止に対応します。
ハードウェアレベルでは、MCPWMユニットがデューティ比に応じたパルスを生成し、モータードライバー(L298NやTB6612FNGなど)を介してモーターの回転数と方向を物理的に制御します。この手法を用いることで、ROS 2などの上位レイヤーから送信される速度指令(cmd_vel)を、最終的に具体的なPWM信号へと変換する基盤が整います。