You should do as little as possible in an interrupt. Here is what I was talking about in (untested) code:
volatile unsigned long pulses = 0;
void setup()
{
Serial.begin(9600);
pinMode(2,INPUT);
attachInterrupt(0,"pulseCounter",RISING);
}
void pulseCounter()
{
pulses++;
}
void loop()
{
static unsigned long tick = 0;
unsigned long mil = millis();
float pps;
float interval;
if(tick <= mil)
{
interval = (mil-tick) / 1000;
tick = mil + 1000;
pps = interval / (float)pulses;
pulses = 0;
Serial.print("Pulses per second: ");
Serial.println(pps,4);
}
}
The interrupt purely counts the pulses, and nothing else. No calculating, no timing, nothing - just count the pulses.
The main loop deals with the timing, and the calculation of the number of pulses per second.
You could do the interrupt/pulse counting using pure hardware if you wanted more accuracy and lower latency, by feeding the pulses in to the input pin of a timer, then using that to count the pulses - the rest is the same, except you're reading and resetting a timer's count value instead of a pulses variable.