Question 11.5: Debouncing a Button Press Sometimes when you press the butto......

Debouncing a Button Press

Sometimes when you press the button on a switch, the expected action happens more than once, because the switch contacts bounce. In that case, you want to write code to de-bounce the switch.

Step-by-Step
The 'Blue Check Mark' means that this solution was answered by an expert.
Learn more on how do we answer questions.

There are a number of solutions to this problem. To explore them, build the breadboard setup from Recipe 11.2.

The original code for this example, without any attempt at debouncing, looks like this:

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
switch_pin = 18
led_pin = 23
GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(led_pin, GPIO.OUT)
led_state = False
old_input_state = True # pulled-up
while True:
new_input_state = GPIO.input(switch_pin)
if new_input_state == False and old_input_state == True:
led_state = not led_state

old_input_state = new_input_state
GPIO.output(led_pin, led_state)

The problem is that if the switch contacts bounce, it is just as if the switch were pressed more than once in very rapid succession. If they bounce an odd number of times, then things will seem to be OK. But if they bounce an even number of times, the two events will toggle the LED on and then straight back off again.

You need to ignore any changes after the switch is pressed for a short amount of time, while the switch finishes bouncing.

The quick and easy way to do this is to introduce a short sleep after the button press is detected by adding a time.sleep command of, say, 0.2 seconds. This delay is probably much higher than necessary, strictly speaking. You may find that you can reduce this considerably.

import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
switch_pin = 18
led_pin = 23
GPIO.setup(switch_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(led_pin, GPIO.OUT)
led_state = False
old_input_state = True # pulled-up
while True:
new_input_state = GPIO.input(switch_pin)
if new_input_state == False and old_input_state == True:
led_state = not led_state
time.sleep(0.2)
old_input_state = new_input_state
GPIO.output(led_pin, led_state)

Discussion

This solution is OK in most situations, but you might also consider using the switch pin with an interrupt (Recipe 9.12).

Switch bouncing occurs on most switches and can be quite severe on some switches, as the oscilloscope trace in Figure 11-7 shows.

You can see that there is contact bounce both as the switch closes and when it is released. Most switches are not as bad as this one.

See Also

For the basics of connecting a button, see Recipe 11.1.

11.7

Related Answered Questions

Question: 11.13

Verified Answer:

Use an RTC (real-time clock) module. A very common...
Question: 11.8

Verified Answer:

Keypads are arranged in rows and columns, with a p...
Question: 11.2

Verified Answer:

Record the last state of the button and invert tha...
Question: 11.1

Verified Answer:

Connect a switch to a GPIO pin and use the RPi.GPI...
Question: 11.7

Verified Answer:

Use a rotary (quadrature encoder) connected to two...
Question: 11.9

Verified Answer:

Use a PIR (passive infrared) motion detector modul...
Question: 11.12

Verified Answer:

The solution to this is very similar to that of us...
Question: 11.11

Verified Answer:

There are at least two ways to solve this problem....