Arduinoで何らかの速度を計測しようとしたときに、対象に取り付けた物体の通過する回数をカウントし、その回数が1分間に何回かを計測してRPMを算出することがよくある。
一般的には非接触で光の反射回数を捉えるもの、磁気の強弱を計測するもの、スリットを使い、光の透過を計測する方法などがある。
今回は、最も単純な磁気を計測するホール素子を扱う場合の方法について記載する。
回転体のどこか一か所に磁石などを取り付け、それを固定されたホール素子によって通過する回数を計測するというのが最も単純な方法である。ただし、この一定の時間範囲内で通過する回数を計測するという単純な方法をArduino上でプログラムにすると以下のような問題が起きる。
カウント数が少ない場合は演算して算出される計測誤差が非常に大きくなる。
例えば、約60[rpm]の場合、1秒間計測して得られる回数は0,1,2のどれかである。これを60秒間繰り返したと想定して計算すると0~120[rpm]という推定になってしまう。求めたい回転数とはかけ離れた誤差を含むことになる。
精度を上げようと思うと計測時間が長くなり、更新間隔が長くなる。
上記誤差を吸収するためには計測間隔を長めにとって、時間範囲によって切り取られる誤差を吸収する必要がある。時間を長くとれば長くとるほど精度は向上していくが、逆に回転数が得られる間隔が伸びてしまう。
Arduino上のプログラムを書く際、単純に時間間隔で切り取るという方法を使った時点で誤差は生じてしまうため、入力される信号を使って割り込みをかける必要がある。また、その割込みに対しても精度の良いタイマーを使うことによってパルスの間隔そのものを精度よく算出することでRPMをリアルタイムに出力できるようにする。
#include <Arduino.h>
unsigned long rpm_time;
float rpm;
bool tooslow = 1;
void setup() {
Serial.begin(9600);
TCCR1A = 0;
TCCR1B = 0;
TCCR1B |= (1 << CS12); //Prescaler 256
TIMSK1 |= (1 << TOIE1); //enable timer overflow
pinMode(2, INPUT);
attachInterrupt(0, RPM, FALLING);
}
ISR(TIMER1_OVF_vect) {
tooslow = 1;
}
void loop() {
delay(1000);
if (tooslow == 1) {
}
else {
rpm = 120 / (rpm/ 31250.00);
Serial.println(round(rpm));
}
}
void RPM () {
rpm = TCNT1;
TCNT1 = 0;
tooslow = 0;
}