Electronic – arduino – Question about debouncing – delay of state change

arduinobuttondebounce

I have a very simple project where I needed to debounce a button (in software). Logically, my thought process is:

  • If the state's been stable for a while, and it changes, then immediately signal an event.

  • Ensure that the next state is stable before allowing another state change.

So if a button isn't pressed and has been that way for a while, but all of the sudden I read a changed input, I don't think I should need to wait to confirm that the changed input has been stable (I know that there has been an actual physical change to the button state). I can simply signal an event, but disallow new events for some set period of time to prevent false button bounces from signaling events.

Here's arduino code for a function getAction() done this way:

static int buttonBounceState = BUTTON_STATE_UP; // "Bouncing" state
static int buttonState = BUTTON_STATE_UP; // Debounced state
static unsigned long lastChangeMillis = 0; // Time of last state transition
unsigned long currentMillis;

buttonBounceState = digitalRead(BUTTON_PIN);

if (buttonBounceState != buttonState) {
   // Only allow state change if it's been 20 millis since last
   currentMillis = millis()
   if (currentMillis >= lastChangeMillis + 20) {
       buttonState = buttonBounceState; // Change state
       lastChangeMillis = currentMillis; // Only update timings at state transition
       // Button state has changed, so return an action
       if (buttonState == BUTTON_STATE_DOWN) return ACT_PRESS;
       else return ACT_RELEASE;
   }
}
// No button state change. Return no action.
return ACT_NONE;

However, it seems that everywhere I look, the way debouncing is done is that the initial state transition needs to become stable before actually performing a software state change/event signaling. For example, the bottom picture here: https://www.baldengineer.com/arduino-de-bounce-a-button-with-micros.html

My question: is it better to do debouncing this way? Is there something about my method that might fail that I'm not thinking about – i.e., some sort of noise while button is stable-open or stable-closed? If not, it seems that my method would give more accurate timings; and I don't miss very quick button taps (but delay until stable would). Also, how do these two software methods relate to hardware debouncing. How would a hardware debouncer be implemented that can time things similar to my method?

Best Answer

If you debounce by reacting immediately and blanking the button (ignoring subesquent stage changes for a pre-specified time), the benefit is low latency. The drawback is vulnerability to induced noise which can make or break some systems.

People don't react fast enough to notice a 10ms latency so I think it's usually best to debounce by checking that a change-of-state is stable for a few ms before reacting. That way you can prevent unexpected noise issues.

The main reason I sometimes debounce with "react immediately then blank" is when I am writing something quick and dirty test code which will ultimately be removed. I find it's usually simpler and less invasive to code the debounce this way so its faster to write and easier to remove from the final code.

Some hardware debouncers like the MAX6816 use hard-wired timers and counters. The MAX6816, in particular, waits for the state to be stable for a certain amount of time before passing it through.

On an FPGA it is also hard-wired in the sense timers, counters, and sampling register are used. You can have it react immediately then blank, or wait until the switch as stabilized before passing the signal through.

JK-flip flop debouncers change state immediately then "blank". I put blank in quotes because they do not use a time interval to ignore subsequent changes. Rather, it relies on something more akin to mechanical hysteresis. It immediately change state if and only if positive contact electrical is made. It does not react if contact is merely lost. Therefore, if contact is lost inside the switch (like due to a bounce) but no new positive contact is made, they do not change state. The switch should never be able to bounce so hard that flies far enough in the opposite direction to hit the other contact. This is similar to conservation of energy where a dropped ball should never bounce back up to the height from which it was dropped.

There are other methods of debouncing too like using low-pass filters and comparators which sort of relies on the switch to be stable for long enough, but can also be falsely triggered if the switch bounces too many times and the time constant is chosen to be too short since the capacitor will continue to charge or discharge as the switch makes contact with each bounce.