Motor in use
今回は、以下のモータを使用します。RobotShop というオンラインショップにお世話になりました。
36mm 12V 170RPM ブラシ付き DCギアモータ (エンコーダ付き) (1:51)
概要 36mm 12V 170RPM ブラシ付き DCギアモータ エンコーダ付き (1:51) ギア比: 1:51 回転数: 170 トルク: 11.5kg・cm 電圧: 12V エンコーダ付き 36mm 12V 170RPM ブラシ付き DCギアモータ (1:51) には、エンコーダが付属してています。無負荷時速度 ...
Board connection
4.8V の電源をモータの電源ケーブルに印加し、センサ用の電源は esp32 から取っています。このサイトと同様に output の A を PIN 32 に、B を PIN 33 に接続します。
RPM calculation
Velocity
rpm の値は以下で計算できるみたいです。
Output RPM = ((Pulses Recieved in 1 sec * 60) / PPR) / Gear Ratio
https://control.com/forums/threads/encoder-to-rpm-calculation.4792/
データシートを見ると、今回使用するモータは PPR が 12、ギア比が 1:51 です。
Rotational direction
また、回転方向についても考えます。参考にしたのは、以下の二つの動画と
maxon のサイトです。
PIN A の立ち上がり時に注目すると、PIN B も HIGH のときは反時計回り、PIN B が LOW のときは時計回りとなります。
Source code
こちらのソースコードをベースにしました。
以下が、今回モータの rpm を計測するのに使用した esp32 のコードです。
#define ENCODER_A_PIN 32
#define ENCODER_B_PIN 33
volatile long encoderValue = 0;
long previousMillis = 0;
void encoder_func() {
// A_val and B_val are HIGH / LOW
int A_state = digitalRead(ENCODER_A_PIN);
int B_state = digitalRead(ENCODER_B_PIN);
if (A_state == B_state) {
encoderValue++; // counter clockwise
} else {
encoderValue--; // clockwise
}
}
void setup() {
Serial.begin(115200);
pinMode(ENCODER_A_PIN, INPUT_PULLUP);
pinMode(ENCODER_B_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_A_PIN), encoder_func, RISING);
}
void loop() {
int interval = 1000;
int currentMillis = millis();
if (currentMillis - previousMillis > interval) {
previousMillis = currentMillis;
int ppr_val = 12;
int gear_ratio = 51;
int rpm_val = (float)(encoderValue * 60 / ppr_val / gear_ratio);
Serial.print(rpm_val);
Serial.println(" rpm");
encoderValue = 0;
}
}
- attachInterrupt() という関数を使い、ENCODER_A_PIN が LOW から HIGH になった瞬間に、回転方向に応じて encoderValue をインクリメント(デクリメント)する
- 1 秒ごとに、エンコーダ値から rpm (revolutions per minute) を計算して出力する
Experiment
以下の写真のように、モータを固定して esp32、PC、電池をつなぎます。
出力結果は 67 rpm となっていました。実際に一分間のモータの回転数を目視で計測してみると 68 回だったので、計測結果とエンコーダの読み取り値から計算した rpm は、ほぼ相違なしと言えそうです。
コメント