Switch bouncing is non-ideal behavior of the contacts that creates multiple electrical transitions for a single button push or release. Pretty much every switch or button that has a spring in it is subject to bounce.
One of the approaches to handle the switch bouncing is to check the button
state (on/off) every 10 to 20 ms and store the states in a byte variable.
That is,
b7b6b5b4b3b2b1b0
presents a history of 8 most recent checks.
The oldest button state is b0 and the most recent button state is
b7
(bi=1 is button is off and 0 otherwise).
This
variable is updated in a shift register after every button status check. The
old variable value is shifted right on 1 bit, and the
new bit is inserted as
bit7.
b7b6b5b4b3b2b1b0 ⇒ 0 b7b6b5b4b3b2b1 ⇒ newb7b6b5b4b3b2b1
We accept the button status as ON (pressed) if the button was detected to
be pressed at least for the last two checkings
(b7=b6=0).
In other terms, the variable value is of the form
00xxxxxx, where x are the remaining bits in the
shift register.
This way we introduce a constant press_threshold
= 00111111 = 0x3F.
Therefore, once the shift register value after the next check becomes less or
equal to press_threshold, we accept the new
button state as ON.
Similarly the debouncing can be performed when the button is released.
It turns out that tactile buttons bounce more when they are released compared
to pressing them.
We address this situation by waiting for the button to be OFF (released) at
least for the last 6 checkings, i.e. 111111xx.
That is, the value in the shift register
must be not less that release_threshold =
11111100 =
0xFC for the button state to change from ON to OFF.
Putting all together, for every button we allocate a 1-byte
variable shift_reg and a binary variable
state indicating its state (1 = OFF, 0 = ON).
The debouncing algorithm consists of periodic repetition of
steps 1 to 3 in the following pseudocode:
0. shift_reg = 0xFF; state = OFF // initialization 1. new = current button value // 1="OFF" 0="ON" 2. shift_reg = (shift_reg >> 1) + (new << 7) 3. if (state == OFF) // check old state { if (shift_reg <= press_threshold) { state = ON // new state perform needed tasks // button press is detected } } else // old state is ON { if (shift_reg >= release_threshold) { // button release is detected state = OFF // just update button state // usually do nothing else here } }