自律移動ロボットやSLAM(Simultaneous Localization and Mapping)の実装において、ホイールエンコーダから正確な速度情報を取得することは非常に重要です。ここでは、ESP32のPCNT(Pulse Counter)モジュールを利用して、モーターが最大出力時にどの程度の速度(m/s)に達するかを計測する方法を解説します。
プロジェクト構成とライブラリの導入
PlatformIO環境を使用する場合、platformio.iniにESP32用のエンコーダライブラリを追加します。これにより、ハードウェアタイマーを利用した高精度なパルスカウントが可能になります。
[env:featheresp32]
platform = espressif32
board = featheresp32
framework = arduino
lib_deps =
https://github.com/fishros/Esp32PcntEncoder.git
速度計測の実装
以下のコードは、2つのエンコーダからパルスを読み取り、一定周期ごとに移動距離を計算して速度を算出するものです。計算式内の係数(ここでは 0.1051566)は、タイヤの直径や減速比、エンコーダの分解能に基づいて算出された、1パルスあたりの移動量(mm/tickまたはm/tick)を表します。
#include <Arduino.h>
#include <Esp32PcntEncoder.h>
// エンコーダオブジェクトの配列(左右2輪分)
Esp32PcntEncoder rotaryEncoders[2];
// 速度計算用の変数
int64_t previousTicks[2] = {0, 0};
uint64_t lastTimestamp = 0;
float currentSpeeds[2] = {0.0f, 0.0f};
// モーター制御用ピン(検証用に最大出力に設定)
const int MOTOR_PWM_PIN = 23;
void setup() {
Serial.begin(115200);
// エンコーダの初期化 (チャンネル, GPIO_A, GPIO_B)
rotaryEncoders[0].init(0, 32, 33);
rotaryEncoders[1].init(1, 26, 25);
// 計測対象のモーターをフルスピードで回転させる
pinMode(MOTOR_PWM_PIN, OUTPUT);
digitalWrite(MOTOR_PWM_PIN, HIGH);
lastTimestamp = millis();
}
void loop() {
// 10ms間隔で計測を実行
delay(10);
uint64_t currentMillis = millis();
uint64_t timeDelta = currentMillis - lastTimestamp;
if (timeDelta == 0) return;
for (int i = 0; i < 2; i++) {
int64_t currentTicks = rotaryEncoders[i].getTicks();
int32_t deltaTicks = currentTicks - previousTicks[i];
// 速度計算: (パルス変化量 * 1パルスあたりの距離係数) / 時間変化量
// 結果はメートル毎秒 (m/s) を想定
currentSpeeds[i] = (float)(deltaTicks * 0.1051566) / timeDelta;
// 次回計算用の更新
previousTicks[i] = currentTicks;
}
lastTimestamp = currentMillis;
// シリアルモニタへの出力
Serial.printf("Ticks: L=%lld, R=%lld | Speed: L=%.4f m/s, R=%.4f m/s\n",
rotaryEncoders[0].getTicks(), rotaryEncoders[1].getTicks(),
currentSpeeds[0], currentSpeeds[1]);
}
計測のポイント
プログラムを実行すると、シリアルモニタに現在のパルス累積値と計算された速度が表示されます。モーターを最大出力で回転させた際の速度が、その駆動系における理論的な最大速度となります。
速度計算において dt(時間変化量)を使用することで、処理遅延が発生しても正確な速度を維持できるようにしています。この計測結果から得られた最大速度は、後のステップでPID制御のパラメータ調整や、ROS2のオドメディ計算の基礎データとして利用されます。