Alternate aproach to interupt debounce

I am using an interupt that I am currently debouncing as follows:

void dbInterupt() 
{
  rsInteruptTime = millis();
  if (rsInteruptTime - lastRsInteruptTime >= 500)
  {
    // do stuff

    lastRsInteruptTime = rsInteruptTime;
  }
}

It's not working satisfactorily.

If I understand it, this will start the debounce time from the first instant the interupt goes HIGH, and not from the start of a period which is consistently high.
So if you get two bursts of noise Tdb apart, they will be treated as a valid HIGH (first in diagram), whereas a valid trigger has to be contantly HIGH for at least Tdb (second in diagram).

debounce.jpg

I think the debounce code examples I've found for standard digital inputs can typically cope with this, but I don't think they work for interupts, and all the interupt debounce code seems to be of the above format.

Does this make sense, and can anyone suggest a solution (cos I'm damned if I can figure it out!)?

debounce.jpg

What are you using for the input to trigger the interrupt? It would not be likely that a switch would produce several "noise" bursts unrelated to a switch closure, so that doesn't appear to fit your situation.

For a switch input, I would trigger the interrupt on a change of the input state (both rising and falling edge), read the input inside the ISR to get the current state, then save the time the interrupt occurred so that any additional interrupts during the debounce time could be ignored. That would not work for your situation because of the random "noise" spikes unrelated to the switch.

I'm not sure you can implement an ISR that will handle the input you have shown, you could record the time of the rising and falling edge interrupts, and recognize the input if the time interval between rising and falling edges exceeded a minimum amount, but that would only recognize a valid input at the falling edge of the input, not at the time of rising edge + debounce time.

debouncing a noisy input typically requires seeing a consistent value (no change) for some minimum period of time. this is why simply polling and resetting a timer whenever there is a change in state and checking for some minimum period when there isn't a change is a conventional approach

i can see using an interrupt to look for a high state and ignoring any subsequent interrupts within some period of time after the first edge. You can't use an interrupt to recognize a consistent state because there is no edge to trigger on. this would recognize a button press, for example on the first edge. A subsequent button press would only be recognized only after some period of time.

Debouncing is different from noise-suppression. Debouncing is to prevent multiple triggering when the
switch bounces, you want (I think) to stop noise pulses from being registered, which means you have to
distinguish short noise pulses as being different from genuine switch pulses.

Conventional debouncing methods expect the switch pin is not subject to any interference.

Can you explain a bit about what your application is? What does the button control? Why an interrupt vs polling? Why does it need to be debounced?

Thanks all.

david_2018:
What are you using for the input to trigger the interrupt? It would not be likely that a switch would produce several "noise" bursts unrelated to a switch closure, so that doesn't appear to fit your situation.

It's not a switch in the conventional sense, but rather an electrical contact which pulls the interupt pin low. The contact needs to be changed periodically, and unplugging it is triggering the ISR.

MarkT:
Debouncing is different from noise-suppression ... you want (I think) to stop noise pulses from being registered, which means you have to
distinguish short noise pulses as being different from genuine switch pulses.

Correct, that's what I'm trying to do.
So debounce is the wrong term. Is there a way to code to ignore noise pulses on an interupt?

steve20016:
Can you explain a bit about what your application is? What does the button control? Why an interrupt vs polling? Why does it need to be debounced?

The interupt toggles between standby/output-data and returning to the main funcitons, and needs to toggle to standby/output-data from anyhere within the main code. When in standby, the contact connected to the interupt needs to be unplugged and replaced.

I could use polling, but that would mean calling the standby/output function an increasing nummber of times within a single loop function.

It needs bebouncing because no debounce = no certainty of standby/output.

I think it would help if you describe the sorts of signals that you want to capture and, separately, the sorts of signals that you want to avoid.

My sense from reading the Thread so far is that there is nothing obvious to distinguish them.

And can you explain this further

The interupt toggles between standby/output-data and returning to the main funcitons, and needs to toggle to standby/output-data from anyhere within the main code.

It sounds to me like it may be an inappropriate use of interrupts.

Suppose that the ISR sets a flag when it is triggered and authorised to set the flag by the main code and the main code regularly checks for the flag - then the control can shift to the main code and leave the ISR code very simple. Something like

void dbInterrupt() {
   if (flagSet == false) {
      flagSet = true;
   }
}

and

void loop() {
   if (flagSet == true) {
       // do stuff
       flagSet = false;
   }
   // other code
}

...R

I think you can just move the update of lastRsInteruptTime outside the If statement. Then you would get a full Tdb period with no interrupt before you recognize the next interrupt as valid. In other words, if you get an interrupt, and the period hasn't expired, you not only don't recognize it as valid, but you also start over counting again.

void dbInterupt()
{
  rsInteruptTime = millis();
  if (rsInteruptTime - lastRsInteruptTime >= 500)
  {
    // do stuff

  }

  lastRsInteruptTime = rsInteruptTime;

}

Edit: Actually, for my solution your drawing isn't quite right. If the interrupt occurs on the rising edge, then the Tbd period will begin on the most recent "noise" rising edge, and will not have expired when the valid interrupt occurs. So there will be no interrupts recognized as valid in the picture, except possibly the very first one. See attached revised picture.

The situation depicted in your original picture would require that the determination of whether an interrupt is valid would be made later - long after the interrupt has been serviced. So that would involve following up in the main loop, and it might actually be easier to switch to polling for the whole thing. It's just not clear to me what kinds of patterns you need to distinguish between.

debounce-revised.jpg