Sunday, November 16, 2014

Debouncing GPIO Input

Reading the state of a GPIO pin is very simple.  There are several methods to do this.  But what if you need to detect a very short pulse on a GPIO line or you need to respond very quickly to a state change without using a lot of the CPU to poll the state of the pin? This is exactly what interrupts are designed for.  I will cover how to use interrupts in a future post.  This post will show you how to deal with a common problem that must be addressed before interrupts will work correctly.

When the contacts of a mechanical switch close, they will almost always bounce a little.  This causes multiple spikes up and down on the connected line until the contact is firmly made.  The result is a series of pulses when a single state change was expected. This is, for obvious reasons, called "bouncing" and must be corrected either with hardware or software.

If that wasn't clear enough, maybe a picture will help. Imagine a push-button connected to a GPIO line. When the button is not pressed, a pull-up resistor holds the GPIO at 3.3 volts so that it reads a value of 1.  When the button is pressed, the line is connected to ground and the GPIO will read 0.  But on closer inspection, something else really happens. As this graph shows, the bouncing of the voltage level causes spurious state changes to the GPIO input. If you use an interrupt to increment a counter when the state changes on the GPIO, then a single button press can result in the counter incrementing two, three, or more times when the programmer is expecting only a single increment.

This can be dealt with in software, but that method tends to be unreliable in many instances. It is much better to correct for the bouncing using a simple hardware circuit.  This is called debouncing and one simple solution is shown below.

By connecting a capacitor as shown here, the result is a "smoothing" of the voltage curve. Before the button is pressed, the capacitor is fully charged and the GPIO will read 1. When the button is pressed, the capacitor will start draining through R2 at a rate determined by the size of the C1 and the R2.  The voltage on the GPIO pin will smoothly curve down from 3.3V to 0V and the GPIO will sense a single state change.

The values for C1 and R2 will determine how quickly the state changes.  If they are too small, then there could still be some bouncing.  If they are too large, then the circuit may respond too slowly for the application needed.  This could result in state changes being missed. You may need to experiment to find the proper values for a specific application. The values shown in this circuit are a good place to start.

A digital circuit that is also commonly used for debouncing is called the set/reset latch and can be constructed from two nand gates. To learn more about this option and everything else you might want to know about debouncing, read this paper.   A Guide to Debouncing

Now that you input is properly debounced, you can go on to using it to reliably drive an interrupt.

1 comment:

  1. Thanks so much for explanation of the bouncing and the hardware solution coming along with it. Just what I needed and it works fine!
    regards Chris (the Netherlands)

    ReplyDelete