encoder RPM count / speedometer accuracy

Hi guys,

i want to use an optical encoder as a speedometer / rpm counter.

i am using the following code, which seems to work, but i can hardly test it for accuracy.
what do you guys think, is it accurate to calculate the rpm like this?

thanks for any feedback!

#include <SimpleTimer.h>
#include <Encoder.h>

Encoder myEnc(2,3);
SimpleTimer timer;
long oldPos = 0;

void repeatMe() {
    long newPos = myEnc.read();
    long rpm = ((newPos) - (oldPos)) * .75;
    Serial.println(rpm);
    oldPos = newPos;

}

void setup() {
    Serial.begin(9600);
    timer.setInterval(100, repeatMe);
}

void loop() {
    timer.run();
}

It will register 3 rpm for each 40 counts/second from the encoder - that's appropriate for an 800 count-per-revolution encoder (200 pulse-per-revolution).

You would do better not to throw away accuracy by truncating to integer, use float:

const int timer_delay = 100 ;
const int counts_per_rev = 800 ;
float factor = 60000.0 / delay / counts_per_rev ;

void repeatMe() {
    long newPos = myEnc.read();
    float rpm = (newPos - oldPos) * factor;
    Serial.println(rpm);
    oldPos = newPos;
}

repeatMe() is an interrupt service routine (ISR). While it is running, interrupts are disabled. Doing things that require interrupts, such as Serial.print(), in an ISR is a really bad idea. Don't come here complaining that your Arduino locks up when the rpm picks up. You've been warned.

Even if you'd handle the interrupts correctly, the calculation would be inaccurate.

Let's calculate: - Interrupt every 100ms. - Rotation speed provides one pulse every 200ms (as an example)

This will happen then with your calculation:

0 pulse after 100 ms, so you calculate: float rpm = (newPos - oldPos) * factor; = 0

1 pulse after 200 ms, so you calculate: float rpm = (newPos - oldPos) * factor; = factor

So even if the rotating speed is all the same for all the time, you will calculate different rpm by 'factor', which is 0.75 rpm in your case.

If it's not a problem for you, that all the same rpm speeds lead to showing speed differences of 'factor' (0.75), then maybe it's OK for you. But normally I'd expect, that the LCD displays always the same rpm if the rpm is actually the same, and not the last digit (and all digits after the decimal point) changing all the time.

You could either: Measure and calculate correctly.

Or: Push your calculated values through something like a "low-pass" filtering and do not show the value of each calculation as it hops up and down, but the smoothened value by time only.

thanks guys! thats what I thought :(

is there any sample which does that correctly?

I would recommend that you stop using the libraries, and gain a better understanding of your code.

Read the encoder counts. There are endless examples of how to do this. To determine a rotation speed you will either count for a fixed period of time, or determine the time period for a fixed number of counts. It's all fairly simple, and you can optimize your code for your rotational speed and the encoder you are using.

Check out the example for "smoothing" in section 03 analog examples of the IDE for running average code.