About measuring rpm with using ir sensor

I need some help.
I followed all the process that who made before.
My LCD monitor works great i guess. It shows "TACHOMETER" , "0 RPM" as the codes mentioned.
But the problem is the monitor always shows 0 rpm.
I found the sensor works properly with light blinked when I did some movements in front of the sensor.

I'll show the code what I used.
Thanks for reading my questions and always welcome with your help

//DIY Tachometer to Measure Accurate RPM using Arduino
//DIY Tachometer to Measure Accurate RPM using Arduino
//This code is published by https://www.circuitschools.com
//Attribution required to republish.

#include <LiquidCrystal_I2C.h>
// Create the lcd object address 0x27(get it from i2cscanner) and 16 columns x 2 rows
LiquidCrystal_I2C lcd (0x27, 16,2); //

float value=0;
float rev=0;

int rpm;
int oldtime=0;
int newtime;

void isr() //interrupt service routine




void setup()


lcd.init (); //initialize LCD

// Turn on the backlight on LCD.

lcd. backlight ();

attachInterrupt(digitalPinToInterrupt(2),isr,RISING); //attaching the interrupt


void loop()



detachInterrupt(0); //detaches the interrupt

newtime=millis()-oldtime; //finds the time

int wings= 3; // no of wings of rotating object, for disc object use 1 with white tape on one side
int RPMnew = rev/wings; //here we used fan which has 3 wings

rpm=(RPMnew/newtime)*60000; //calculates rpm

oldtime=millis(); //saves the current time




lcd.print( rpm);
lcd.print(" RPM");
lcd.print(" ");



I brought this code from "DIY Tachometer to Measure Accurate RPM using Arduino ESP8266 ESP32 – Circuit Schools"

rev should be an integer

use noInterrupts() and interrupts() to dis/enable interrupts just around the code needed

    noInterrupts ();
    int RPMnew = rev / wings;
    interrupts ();

if rev is captured over a period of 1 second (i.e. delay(1000)), shouldn't the value be multiplied by 60? (is there a need for newtime)?

1 Like

From attachInterrupt() - Arduino Reference

"Typically global variables are used to pass data between an ISR and the main program. To make sure variables shared between an ISR and the main program are updated correctly, declare them as volatile".


rev should be of "volatile int" type.

We could use a little help, post the schematic, not a frizzy picture. Also follow the instructions and post the code properly. You are doing this with an interrupt, how many interrupts per revolution and what is the min and max RPMs.