Problems on optical tachometer

I’ve played around with this code a bit to see what works best, and I think I have a problem with my variables that I can’t pinpoint. I’ve got an IR emitter/detector counting interrupts from four reflectors on the inside of the wheel and calculating RPM. Here’s my code and some of the output. The output is what’s causing some confusion as I’m getting some “ovf” readings for RPM. The first number is RPM the second number is the count within the 1 second that it’s counting the interrupts.

Thanks in advance for the help!

const int irDet = 3;       // Detector connected to pin 3
const int irInt = 1;       // Detector connected to interrupt 0 (int.0)
const int irEmit = 13;     // Emitter output from pin 13

int count =0L;              // Count interrupts
double rpm;    // Wheel RPM

unsigned long timeold;

void setup() {
  pinMode(irDet, INPUT_PULLUP);
  pinMode(irEmit, OUTPUT);
  Serial.begin(9600);
  digitalWrite(irEmit, HIGH);             // Emitter turned on
}

void loop() {
  count = 0;
  attachInterrupt(irInt, irISR, RISING);
  delay(1000);                            // Measure for 5 seconds
  detachInterrupt(irInt);
  
  rpm = 30*count/((millis() - timeold)/1000);
  Serial.print("RPM:\t"); Serial.print(rpm); Serial.print("\t"); Serial.println(count);
  timeold = millis();
}
     
void irISR() {
  count++;  
}
RPM:	990.00	33	
RPM:	1110.00	37	
RPM:	ovf	 37	
RPM:	1110.00	37	
RPM:	1110.00	37	
RPM:	1110.00	37	
RPM:	1080.00	36	
RPM:	1110.00	 37	
RPM:	1230.00	41	
RPM:	ovf	64	
RPM:	2160.00	72	
RPM:	2280.00	76	
RPM:	2130.00	71	
RPM:	1980.00	66	
RPM:	1860.00	62	
RPM:	ovf	 60	
RPM:	1770.00	59	
RPM:	1590.00	53	
RPM:	1140.00	38	
RPM:	210.00	7	
RPM:	0.00	0	
RPM:	ovf	 0
RPM:	0.00	0	
RPM:	0.00	0	
RPM:	0.00	0
  attachInterrupt(irInt, irISR, RISING);
  delay(1000);                            // Measure for 5 seconds
  detachInterrupt(irInt);

This is a pretty lousy way to use an interrupt. 5 seconds, huh?

  rpm = 30*count/((millis() - timeold)/1000);

Perform integer arithmetic. Then, store the result in a float. How is that useful?

You know how long you counted pulses for. Why is there any reason to involve time in this equation?

Just noticed the comment, I didn't realize it said 5. The interrupt was 1 second.

The reason I was using time was just on a whim. I saw another code for an optical tach that used it and thought it was worth a try (the time was between 1.000 - 1.002 but doesn't really make a difference anyhow). I removed the time and it works fine now, thanks! I wanted to use the float because I have 16 reflectors that trigger the count and wanted the current rpm to come out more accurate, but wasn't paying much attention to the whole mix of things (whoops :blush:).

My take on this is that you are using interrupts where they are quite inappropriate, and (as a consequence in part) you have no debounce code. I am not surprised it is unreliable or am surprised that the results you get are as good as they are!

Whilst an enclosed optical encoder or even a vane slot sensor may be relatively reliable, a reflective sensor on a moving part (which may be dirty) is unlikely to be. You need a debounce function for starters, and a PLL would be better.