Is this code still the current state of play for debouncing:
// The interrupt routine - runs each time a falling edge of a pulse is detected
void onPulse()                  
{  
  if ( (millis() - pulsetime) > min_pulsewidth) {
    pulseCount++;					//calculate wh elapsed from time between pulses 
  }
 pulsetime=millis(); 	
}
The problem with that approach is that it de-bounces, but it doesn’t de-glitch. I can’t recall how fast AVR’s edge detectors are but they’ll be very fast. The stm32 edge detector promises to latch pulses as brief as 10 nsecs. That’s handy when you need to capture genuine short pulses from another IC on the board, but not so useful when you’ve got 10m of cable driving the pin and large electric motors inducing glitches. A 10 nsec (or even 10 usec) pulse is not a genuine pulse in this context but will be counted by that code above. That code will ensure you only count one of them but that’s one too many.
The approach I take is: after things kick off, wait for the dust to settle (no transitions for 40 msecs) then look at the pin state. If it’s the same as it was before anything happened then declare it a glitch and ignore it all, otherwise declare it as an edge. So the 40 msecs not only dictates how frequently pulses can arrive, but also how prolonged they have to be before being counted.
I’ve coded that on the stm32 so the code isn’t directly relevant to the Arduino context but it’s pretty easy to describe in pseudo code. It does require you to enable interrupts on both falling and rising edges - you can do that in AVR land with the PinChange interrupt.
either_edge_isr()
  current_state = read_pin();
  if (current_state == output_state)
    last_edge = 0;                                          // stop the timer
  else
    last_edge = millis();                                 // start the timer
  pulse_input = current_state;
main loop:
  if (last_edge  &&  millis() - last_edge > 40)    //  has timer expired?
    last_edge = 0;                                               // stop timer
    output_state = pulse_input;                          // promote out filtered output state
    if (output_state == 0)                                    // count falling edges of filtered output
      pulse_count++;
I’ve left out details about capturing the volatile ISR state in a consistent fashion, but normal rules apply there. This code also relies on a low latency main loop. If you main loop latency is in the tens of msecs, then the 40 msecs becomes 50 or 60 which is probably still ok. But if your main loop can stall for seconds then your debounce period becomes seconds and you’re sure to lose pulses. I run a tight main loop, with a tight h/w watchdog set to police it, but my plan B if ever I had to surrender that would be to use a h/w countdown timer instead of a s/w timer. Then 40 msecs after the last edge, the timer ISR will run and do what I do above in the main loop code.
output_state above is just a s/w concept, it’s the filtered output of the pulse input, but if you have a spare IO pin then it’s easy enough to output it so you can view the filter in action. In these two pics, Green is the noisy unfiltered pulse input, and Yellow is s/w derived output_state - and it’s’ the Yellow falling edges that get counted:
Given those either-edge ISRs can arrive as frequently as every 10 nsecs (or whatever speed your edge-detector promises) it’s also worth putting a real h/w LPF on the input to protect against a rogue input bringing the processor to its knees.
In the following pics, Green is the unfiltered input, Yellow is the input after the h/w LPF and Red is output_state (the s/w filtered output that drives the pulse counter). You can see in the second pic no pulse was counted at all because even though all that noise dragged on for ~40 msecs it was never quiet for 40 msecs so it was all deemed to be glitches and done away with.





