Using IR sensor and IR receiver to measure the speed of the shaft

Hi,
my code is

float value=0;
float rev=0;   
int rpm;
int oldtime=0;
int time;

#include<SD.h>

void isr() //interrupt service routine
{
rev++; //Each rotation, this interrupt function is run twice, so 
//take this into consideration 
//when calculating ROC Disk Speed
//update count
}
void setup()
{
SD.begin(); //initialise the SD
Serial.begin(9600); //initialise the serial communication
attachInterrupt(0,isr,FALLING);  //attaching the interrupt
//Interrupt 0 is digital pin 2, so that is where the IR detector is connected
//Triggers on FALLING (change from HIGH to LOW)
}

void loop()
{
  delay (1000);                 //Do not process interruptions during calculations

detachInterrupt(0);           //detaches the interrupt
millis();
time=millis()-oldtime;        //finds the time 
rpm=(rev/time)*60000;      //calculates rpm
oldtime=millis();             //saves the current time
rev=0;                        //reset the revolutions counted
Serial.print("ROC BD    " ); 
Serial.print(rpm);
Serial.println(" RPM");
attachInterrupt(0,isr,FALLING); //restart the interrupt processing
}

The circuit diagram is attached. Two variations from the attached circuit are:
(a) Instead of using the OLED screen, I am trying to log the data in the SD card.
(b) I have no switch on my circuit.

I am only getting values around 3000rpm even for a speed that should be for less than 100rpm.

Please advice, I am a novice in this area. I need the tachometer for my postgraduate project.

Thanks.

circuit diagram for making measuring RPM with IR LED and IR receiver.pdf (82.6 KB)

Please do an autoformat before posting, makes your code a lot more readable. Formatting is a mess.

You don't need to detach and then attach the interrupt. That's very bad practice. The normal way is to disable interrupts, copy the value to another variable, and re-enable interrupts:

noInterrupts();
int revCount = rev;
rev = 0;
interrupts();

Then the rpm calculation is probably going wrong as you're using 16-bit integers, and 60,000 is awfully close to the 65,535 limit of an unsigned int. As you're doing a division you probably best make the whole thing floating point:

rpm=(rev/time)*60000.0;      //calculates rpm

Otherwise, making that 60,000 an unsigned long should also do the job forcing the compiler to use a big enough variable:

rpm=(rev/time)*60000ul;      //calculates rpm

Oh, and rev of course has to be declared volatile. Forgot that one. That may be another source of problems.

Thank you for the response. I will incorporate your comments in my code and see what happens.