Rpm counter IR tachometer - Help needed

Im trying to build rpm counter using IR leds and arduino uno. The output im receiving in the serial monitor is totally a glitch.
the output is random numbers though the motor fan is not placed b/w IR leds(instead of 0).Even if i place motor b/w IR leds there is no changes in the output, it is keep on giving random numbers.kindly help( whether the bug is in program or circuit)

led (status) ---- pin 12 (connected via 200 ohm resistor)
IR transmitter --- pin 13 (connected via 200 ohm resistor)
IR receiver ---- pin 2 (connected via 10k resistor)
IR leds are fixied facing eachother.

int ledPin = 13;                // IR LED connected to digital pin 13
int statusPin = 12;             // LED connected to digital pin 12

volatile byte rpmcount;
volatile int status;

unsigned int rpm;

unsigned long timeold;

 void rpm_fun()
 {
   //Each rotation, this interrupt function is run twice, so take that into consideration for 
   //calculating RPM
   //Update count
      rpmcount++;
      
   //Toggle status LED   
   if (status == LOW) {
     status = HIGH;
   } else {
     status = LOW;
   }
   digitalWrite(statusPin, status);
 }

void setup()
 {
   Serial.begin(9600);
   //Interrupt 0 is digital pin 2, so that is where the IR detector is connected
   //Triggers on FALLING (change from HIGH to LOW)
   attachInterrupt(0, rpm_fun, FALLING);
   
   //Turn on IR LED
   pinMode(ledPin, OUTPUT); 
   digitalWrite(ledPin, HIGH);
   
   //Use statusPin to flash along with interrupts
   pinMode(statusPin, OUTPUT);

   rpmcount = 0;
   rpm = 0;
   timeold = 0;
   status = LOW;
 }

 void loop()
 {
   //Update RPM every second
   delay(1000);
   //Don't process interrupts during calculations
   detachInterrupt(0);
   //Note that this would be 60*1000/(millis() - timeold)*rpmcount if the interrupt
   //happened once per revolution instead of twice. Other multiples could be used
   //for multi-bladed propellers or fans
   rpm = 30*1000/(millis() - timeold)*rpmcount;
   timeold = millis();
   rpmcount = 0;
   
   //Write it out to serial port
   Serial.println(rpm,DEC);
   
   //Restart the interrupt processing
   attachInterrupt(0, rpm_fun, FALLING);

  }

I have attached circuit diagram and output screenshot

Hi,
(1)if I remember correctly, the attach Interrupt with FALLING Didn't work for me at all. I used CHANGE(?) and then explicitly read the current digital pin value.
(2) did u check the electrical signal from the IR gate? For a digital input you need a digital signal, Ie the signal should be a square wave with steep slopes. In my case I needed a dumb amplifier using a single transistor to get such a clear signal.
HTH, Robert

A few comments....

  1. it looks like this is posted twice....the moderators will not be happy with double posting :cold_sweat:
  2. Its not clear the magnitude of RPM you are measuring.
  3. Is it worth using microseconds vs millis for better accuracy
  4. It may be worth disabling interrupts for longer, in case you are getting multiple interrupts at the same time (de-bounce)
  5. you are likely to get some interference from ambient light if the sensor is not physically shielded
  6. probab;y a good idea to mention the model numbers of the LEDs
  7. It appears your input is analog and you are feeding this into a digital interrupt pin....not surprising you would get varying results?

etc.....

Hello,

From this code posted above for the rpm sensor can anyone explain the line : rpm = 30*1000/(millis() - timeold)*rpmcount;

From what I have gathered 'rpmcount' will be the number of interrupts, '(millis() - timeold)' the time duration between the rpm value updating and '30*1000' derived from having two two interrupts per revolution. Correct ?

Either way I dont understand how that calculation gives rpm

Sorry im somewhat new to this.

Thanks

Revs per minute = #revs  * ( 1/(time interval, in minutes) )

Which translates to the following based on the example provided by the OP.

rpm = rpmcount * ( 1/( (millis()-timeold)/1000/60 )

(note rpmcount is a bad choice as its really a timeinterval count not an rpm count)

...the time interval is in milliseconds, so we have to divide it by 1000 to get to seconds and then 60 to get to minutes). This example assumes one interrupt per revolution.

When there are 2 interrupts per revolution( ie 2 blades rotating) then the rpmcount value should be divided by 2.

So the above can then be re-written as:

rpm = rpmcount/2 * ( 1/( (millis()-timeold)/1000/60 )

which is the same as

rpm = rpmcount * ( 1/( (millis()-timeold)/1000/30 )

which is the same as

rpm = rpmcount * 30 *1000/(millis()-timeold)

Hope that helps?

I see, Thank you for the reply its a big help.

All the best