Electronic – arduino – Wheel encoder using an IR sensor


I made a rotary encoder using a IR sensor and a wheel with printed black and white spokes. Everything seems to work but I'm wondering if there is a better way to code this. The IR signal looks ideally like a square wave and I have it looking for the rising edge of each wave. Then calculate the time between rising edges to calculate the wheel's RPM.

int wheelPin = 11; // I/O pin for encoder
int count = 0; // number of encoder ticks 
bool rising = false; // bool for rising edge of encoder signal
double dt; // time between rising edges
long dtStore[2]; // FIFO array holding current and previous rising edge times
float rpm;

void setup(){

void loop() {
  int wheelVal = analogRead(wheelPin); // get encoder val

/* check to see if we are at a low spot in the wave.  Set rising (bool) so we know to expect a rising edge */

if (wheelVal < 200) {
  rising = true;

/* Check for a rising edge.  Rising is true and a wheelVal above 200 (determined experimentally)*/

if (rising && wheelVal > 200) {
   dtStore[0]=dtStore[1]; // move the current time to the previous time spot
   dtStore[1] = millis(); // record the current time of the rising edge
   dt = dtStore[1]-dtStore[0]; // calculate dt between the last and current rising edge time
   rpm = (0.0625)/dt*1000*60; // RPM calculation
   rising = false; // reset flag

Best Answer

There are two things you should do.

Firstly, implement a little bit of hysterisis. Currently, it look like you're using 200 as the threshold in both the rising and falling direction. What you'll always get with analogue sensors is a bit of noise. This means that, even during a rising edge, you might actually see a tiny falling edge sometimes. You might even see it cross your threshold up, then down, then up again!

Encoder Hysterisis

  • The green line shows what you hope your sensor is producing.
  • The red line shows what it's probably producing. Actually, it's probably much worse than this.
  • The purple line is what you want
  • The black line is what you could be getting

So, when the signal is rising, use 200 as your threshold. And when the signal is falling, use something like 150 as a threshold.

Secondly, you could use both the rising and falling edges to calculate your speed. That way you can have twice the update rate.