user85294: Background although likely not needed: I am recieving a frequency on the destination side of a opto isolater.  A fan trips a hall effect sensor, and grounds a circuit which lights the opto.  On the recieving end I have a fully isolated arduino circuit that accurately reads this 550Hz (peak) signal.  However, my Uno stopped reading this value correctly.  So I debounced the circuit which did not fix the issue.  I now brought in a new (and isolated) Uno that has nothing else going on but reading this signal and its Interrupt is also sporatic after several seconds.
I believe it is operating OK until the signal gets to about 420Hz (which is nothing..).  PulseIn also returns many "0" durations with the "900ns" good durations.  So it seems the high/low trigger is flipping too often, which was not fixed with debounce. I can see using the oscilloscope that the signal is good at 550Hz
21:34:12.750 -> Htz: 0
21:34:14.575 -> L: 44
21:34:14.575 -> Htz: 88
21:34:15.265 -> L: 70
21:34:15.265 -> Htz: 140
21:34:15.479 -> L: 89
21:34:15.479 -> Htz: 178
21:34:15.913 -> L: 109
21:34:15.913 -> Htz: 218
21:34:16.452 -> L: 117
21:34:16.577 -> Htz: 234
21:34:16.986 -> L: 134
21:34:16.986 -> Htz: 268
21:34:17.511 -> L: 186
21:34:17.511 -> Htz: 372
21:34:18.036 -> L: 213
21:34:18.036 -> Htz: 426
21:34:18.567 -> L: 702
21:34:18.567 -> Htz: 1404
21:34:19.195 -> L: 1913
21:34:19.196 -> Htz: 3826
21:34:19.838 -> L: 3508
21:34:19.838 -> Htz: 7016

code
unsigned long timestamp;
int lsensorpin = 2;
int PWMpin = 3;
String printout;
unsigned int reading;
unsigned long L;
unsigned int lRPM;
unsigned int Htz;

void setup() {
  pinMode(lsensorpin, INPUT);//_PULLUP); //2
  pinMode(PWMpin, OUTPUT);
  analogWrite(PWMpin, 100);
  Serial.begin(9600);
  Serial.println("FInish Setup");
}

void loop() {

  //printout=" High:";
  //reading= pulseIn(lsensorpin, HIGH);
  //printout=printout + reading + " Low:";
  //reading= pulseIn(lsensorpin, LOW);
  //printout= printout + reading;
  //Serial.println(printout + reading);
  
  L=0;
  attachl();
  delay(500);
  detachl();
  Htz=L*2;
  lRPM= L*60;
  Serial.print("L: ");
  Serial.println(L);
  //Serial.print("Htz: ");
  //Serial.println(Htz);
  
  //Serial.print("RPM: ");
  //Serial.println(lRPM);
}

void tickL() {
L=L+1;
}

void attachl(){
    attachInterrupt(digitalPinToInterrupt(lsensorpin), tickL, RISING);
}

void detachl(){
    detachInterrupt(digitalPinToInterrupt(lsensorpin));
}



user10794: From my post about interrupts:

I have seen example code suggesting you count things for a second by turning interrupts off for a second and then on again. I don't recommend this, because for one thing, you can't do serial prints if interrupts are off.
Example (not recommended):
volatile unsigned long events;
const unsigned long INTERVAL = 1000;  // 1 second

void eventISR ()     
  { 
  events++;  
  }   // end of eventISR

void setup () 
  { 
  Serial.begin(115200); 
  attachInterrupt (digitalPinToInterrupt (2), eventISR, FALLING); 
  }   // end of setup

void loop ()    
  {
  events = 0;       // reset counter
  interrupts ();    // allow interrupts    
  delay (INTERVAL); // wait desired time
  noInterrupts();   // stop interrupts

  Serial.print ("I counted ");
  Serial.println (events);
  }  // end of loop

That may work for simple situations, but turning interrupts off means that the Serial prints won't work until they are turned on again (which they may not be in a more complex sketch).
It is better to use the millis() result and just detect when the time limit is up.
Improved sketch:
volatile bool counting;
volatile unsigned long events;

unsigned long startTime;
const unsigned long INTERVAL = 1000;  // 1 second

void eventISR ()
  {
  if (counting)
    events++;    
  }  // end of eventISR
  
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  attachInterrupt (digitalPinToInterrupt (2), eventISR, FALLING);
  }  // end of setup

void showResults ()
  {
  Serial.print ("I counted ");
  Serial.println (events);
  }  // end of showResults
  
void loop ()
  {
  if (counting)
    {
    // is time up?
    if (millis () - startTime < INTERVAL)
      return;  
    counting = false;
    showResults ();
    }  // end of if
    
  noInterrupts ();
  events = 0;
  startTime = millis ();
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  counting = true;
  interrupts ();
  }  // end of loop

In loop() here we wait for the interval (1 second in this case) to be up, otherwise we return, effectively doing nothing. You could of course do other things instead of just returning.
If the time is up we display the count.
If counting is not currently active (and presuming we want it to be active) we remember the start time, reset the counter to zero, and let it start counting up.
That code seemed to work OK up to 100 kHz, although the counts were getting a bit inaccurate. You can do more precise timings by using the hardware counters / timers. Details here:
http://www.gammon.com.au/timers

Also you should declare the variable L to be volatile.

85294: <p>Background although likely not needed: I am recieving a frequency on the destination side of a opto isolater.  A fan trips a hall effect sensor, and grounds a circuit which lights the opto.  On the recieving end I have a fully isolated arduino circuit that accurately reads this 550Hz (peak) signal.  However, my Uno stopped reading this value correctly.  So I debounced the circuit which did not fix the issue.  I now brought in a new (and isolated) Uno that has nothing else going on but reading this signal and its Interrupt is also sporatic after several seconds.</p>
<p>I believe it is operating OK until the signal gets to about 420Hz (which is nothing..).  PulseIn also returns many &quot;0&quot; durations with the &quot;900ns&quot; good durations.  So it seems the high/low trigger is flipping too often, which was not fixed with debounce. I can see using the oscilloscope that the signal is good at 550Hz</p>
<pre><code>21:34:12.750 -&gt; Htz: 0
21:34:14.575 -&gt; L: 44
21:34:14.575 -&gt; Htz: 88
21:34:15.265 -&gt; L: 70
21:34:15.265 -&gt; Htz: 140
21:34:15.479 -&gt; L: 89
21:34:15.479 -&gt; Htz: 178
21:34:15.913 -&gt; L: 109
21:34:15.913 -&gt; Htz: 218
21:34:16.452 -&gt; L: 117
21:34:16.577 -&gt; Htz: 234
21:34:16.986 -&gt; L: 134
21:34:16.986 -&gt; Htz: 268
21:34:17.511 -&gt; L: 186
21:34:17.511 -&gt; Htz: 372
21:34:18.036 -&gt; L: 213
21:34:18.036 -&gt; Htz: 426
21:34:18.567 -&gt; L: 702
21:34:18.567 -&gt; Htz: 1404
21:34:19.195 -&gt; L: 1913
21:34:19.196 -&gt; Htz: 3826
21:34:19.838 -&gt; L: 3508
21:34:19.838 -&gt; Htz: 7016
</code></pre>
<p>code</p>
<pre><code>unsigned long timestamp;
int lsensorpin = 2;
int PWMpin = 3;
String printout;
unsigned int reading;
unsigned long L;
unsigned int lRPM;
unsigned int Htz;

void setup() {
  pinMode(lsensorpin, INPUT);//_PULLUP); //2
  pinMode(PWMpin, OUTPUT);
  analogWrite(PWMpin, 100);
  Serial.begin(9600);
  Serial.println(&quot;FInish Setup&quot;);
}

void loop() {

  //printout=&quot; High:&quot;;
  //reading= pulseIn(lsensorpin, HIGH);
  //printout=printout + reading + &quot; Low:&quot;;
  //reading= pulseIn(lsensorpin, LOW);
  //printout= printout + reading;
  //Serial.println(printout + reading);
  
  L=0;
  attachl();
  delay(500);
  detachl();
  Htz=L*2;
  lRPM= L*60;
  Serial.print(&quot;L: &quot;);
  Serial.println(L);
  //Serial.print(&quot;Htz: &quot;);
  //Serial.println(Htz);
  
  //Serial.print(&quot;RPM: &quot;);
  //Serial.println(lRPM);
}

void tickL() {
L=L+1;
}

void attachl(){
    attachInterrupt(digitalPinToInterrupt(lsensorpin), tickL, RISING);
}

void detachl(){
    detachInterrupt(digitalPinToInterrupt(lsensorpin));
}
</code></pre>
<p><a href="https://i.stack.imgur.com/MQ1lJ.jpg" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/MQ1lJ.jpg" alt="Debounced Signal" /></a></p>
 10794: <p>From my <a href="http://gammon.com.au/forum/?id=11488&amp;reply=10#reply10" rel="nofollow noreferrer">post about interrupts</a>:</p>
<hr />
<p>I have seen example code suggesting you count things for a second by turning interrupts off for a second and then on again. I don't recommend this, because for one thing, you can't do serial prints if interrupts are off.</p>
<h2>Example (not recommended):</h2>
<pre><code>volatile unsigned long events;
const unsigned long INTERVAL = 1000;  // 1 second

void eventISR ()     
  { 
  events++;  
  }   // end of eventISR

void setup () 
  { 
  Serial.begin(115200); 
  attachInterrupt (digitalPinToInterrupt (2), eventISR, FALLING); 
  }   // end of setup

void loop ()    
  {
  events = 0;       // reset counter
  interrupts ();    // allow interrupts    
  delay (INTERVAL); // wait desired time
  noInterrupts();   // stop interrupts

  Serial.print (&quot;I counted &quot;);
  Serial.println (events);
  }  // end of loop
</code></pre>
<p>That may work for simple situations, but turning interrupts off means that the Serial prints won't work until they are turned on again (which they may not be in a more complex sketch).</p>
<p>It is better to use the millis() result and just detect when the time limit is up.</p>
<h2>Improved sketch:</h2>
<pre><code>volatile bool counting;
volatile unsigned long events;

unsigned long startTime;
const unsigned long INTERVAL = 1000;  // 1 second

void eventISR ()
  {
  if (counting)
    events++;    
  }  // end of eventISR
  
void setup ()
  {
  Serial.begin (115200);
  Serial.println ();
  attachInterrupt (digitalPinToInterrupt (2), eventISR, FALLING);
  }  // end of setup

void showResults ()
  {
  Serial.print (&quot;I counted &quot;);
  Serial.println (events);
  }  // end of showResults
  
void loop ()
  {
  if (counting)
    {
    // is time up?
    if (millis () - startTime &lt; INTERVAL)
      return;  
    counting = false;
    showResults ();
    }  // end of if
    
  noInterrupts ();
  events = 0;
  startTime = millis ();
  EIFR = bit (INTF0);  // clear flag for interrupt 0
  counting = true;
  interrupts ();
  }  // end of loop
</code></pre>
<p>In loop() here we wait for the interval (1 second in this case) to be up, otherwise we return, effectively doing nothing. You could of course do other things instead of just returning.</p>
<p>If the time is up we display the count.</p>
<p>If counting is not currently active (and presuming we want it to be active) we remember the start time, reset the counter to zero, and let it start counting up.</p>
<p>That code seemed to work OK up to 100 kHz, although the counts were getting a bit inaccurate. You can do more precise timings by using the hardware counters / timers. Details here:</p>
<p><a href="http://www.gammon.com.au/timers" rel="nofollow noreferrer">http://www.gammon.com.au/timers</a></p>
<hr />
<p>Also you should declare the variable <strong>L</strong> to be volatile.</p>
