Basic IO: Button Debounce
In this article we will take a look at how a button debouncer can effectively created using a PIC. So what is button debouncing?
The Button Debounce Problem
Thinking of using contact switches on your next project? Well better be prepared! It might not be as easy as you think. Contact switches have tiny little springs on them that pop them up when you release the button. This is great for popping the button, but terrible as a digital input. This is because the springs, when releases, bounces around and creates instability for a short duration. Observe the following typical circuit. Keep in mind that you cannot feed an open circuit to a microcontroller. A digital input to a microcontroller must always be a guaranteed 1 or a 0, otherwise the behavior of the chip is unpredictable (hence, you need a pull-up resistor).

When the switch is open, the pull-up resistor raises the voltage at Probe to Vcc. When the switch is closed, the voltage at Probe is shorted to ground. I’ve captured a scope trace of the contact switch with a pull-up resister shown below.

Notice the region where the signal goes up and down. This duration of the instability is on the order of several milliseconds, usually no more than 10ms. In human terms, this is not such a big deal, but to a microcontroller processing at 20 MIPS, this can be disastrous. To a microcontroller, it would read the input as multiple button presses instead of just one. This means that for any circuit involving a contact switch, a debouncer should be used. A debouncer is a device that filters out the messy outputs of a contact switch, and gives you clean edge transition. Dirty inputs = bad, clean inputs = good. There are several ways to achieve this. In geek speak, we want to build a sampling filter. Because different applications have different requirements, Engscope is proud to present 3 different ways to solve the button debounce problem.
External Filter Method – When you have the money
Obviously this input problem has been around for a few decades. As advanced as we are in technology there are simple laws of physics that you just can’t get around. Every day items from microwave and mouse buttons to keyboard keys all has to have mechanisms built in to recognize a false edge from a real one. Imagine your computer mouse not having a debouncer. You’ll be doubling clicking on everything because nearly all your single clicks will actually be read by the computer as several clicks within a very short amount of time. If the keyboards didn’t have a debouncing mechanism, this page would probably lllloooooookkk liikkkeeee ttttthhiiisss…..
Several companies make devices that solves this problem. Maxim has a line of debouncers that I use very often. The 681x series are excellent IC’s that get the job done. They are also very easy to use with flexible input voltages and requiring maybe one external bypass capacitor. Since they are specifically designed for debouncing switches, the delay associated with the IC’s are about 20-40ms. This means that the edge transition on the output of the debouncer arrives at the microcontroller about 40ms later than when the contact switch is pressed. This is usually acceptable when humans are doing the button pushing. I don’t know about you, but can’t time my button pressing to the 10ms scale. A 50ms delay is usually not noticeable. If you don’t have debouncers but have some voltage supervisors around, they will work as well, although the delay associated with them are about 200ms (a lot of voltage supervisors have 100ms or 200ms delays). This is usually way too much, and the buttons will have a “lag” feel to it. If you have a 50ms voltage supervisor lying around, they are much better for this purpose.
The advantages to using an external filter are many. For one, you are freeing up computation time. If you know for sure that your input are clean, you do not need anything on the software end when doing the sampling. Less computation requirements, your microcontroller is free to do more stuff. This also means less code to write, making the overall program easier to compose and revise. There are disadvantages as well. Extra IC’s cost a lot of money, and they take up real estate on PCB’s. They also suck down power and create heat (albeit very little). These are things to be concerned about especially in mobile applications.
The following circuit shows how to hook up the MAX6818. This is the set up I use when I don’t have power/heat/PCB real estate restrictions. You can can then attached the input pin to any of the allowed digital inputs on a PIC. You can find the PIC circuit here.

There’s no need for a pull-up resistor because it is included in the MAX6818. Sampling the input before and after the debouncer IC shows the delay and the clean output. Note the delay is about 50ms, as depicted in the datasheet.

Undersampling: sampling based filter – When you are lazy
If you don’t want complicated code, or are out of room on your PCB, it is still possible to debounce your inputs. One way to do this would be to significantly undersample the incoming signal. If you look at the output of a button, there is a period of uncertainty. As we mentioned, this period of uncertainty is usually about 10 to 20 ms. Look what happens if we sample more than once within the uncertainty period.

The resulting string of sampled data becomes …1, 1, 1/0, 1/0, 0, 0…. This is a problem because we have two uncertain samplings. If by coincidence the microcontroller reads the uncertain data as …1, 1, 0, 1, 0, 0… then we have a problem, because the microcontroller has detected two negative edge transitions from 1 to zero, and will assume that the button has been pressed twice.
We can get around this problem by sampling with the exact period of the length of the uncertainly. Consider the following sampling scenario:

The resulting string of sampled data is …1, 1, 1/0, 0, 0…. Even though we sampled during the uncertainty period, we only sampled once. We can get away from with this because the microcontroller can either read the input as …1, 1, 1, 0, 0… or …1, 1, 0, 0, 0…. Either way we have only one negative edge transition.
Now suppose we really really undersample, then the following will occur:

Well, if we don’t even sample in the debounced uncertain duration, we can be sure that our inputs are correct and does not include double button presses due to debouncing. We can write a simple program to detected input using timers. This sample program debounces the inputs by undersampling. Here’s a typical program that samples at period of 20ms.
Engscope Debounce Undersample Project
Please read the disclaimer before downloading.
Oversampling: software based filter – When you are being a smart ass
Another way to debounce through software is by oversampling the input. Obviously, to “oversample” means to sample very quickly (usually a lot higher than the Nyquist frequency). In this case though, it just means that compared to the oscillation of the debounce, the sampling frequency is very fast. So how does it work?
Consider the following graph. Let’s say we sample the input very quickly and add the results up. Then we set up the software to take a look at the last 100 samples. Suppose that we define the software to compute a running sum of the last 100 samples in the following manner: if the sample is a 0, subtract 1 (if the sum is already 0, don’t subtract); if the sample is a 1, add 1 (if the sum is already 100, don’t add). Let’s use this algorithm to analyze the scope trace.

At the beginning of the trace, all the values are 0, so our running sum must be a zero. During debounce period the running sum is between 0 and 100, so we are not sure if an button has been pressed. However, after the debounce period, the running sum starts to add up very quickly, and eventually increases to 100. By using if statements, we can easily put together a program that can filter out the debounce using the running sum principle. You can download a sample project with this running sum algorithm integrated.
PIC Button Debounce Oversample Project
Please read the disclaimer before downloading.
Please leave a comment if you got questions!

Entries (RSS)
Another idea would be to hook an interrupt on the input. When the button is pushed, the interrupt is called and the routine does its work. But it also flags that input as disabled for the next 20ms and sets itself to be recalled after 20ms to reset everything to be ready for another button press.
Makes sense?
Would work however, interrupts, especially external interrupts are hot commodities. You would want to reserve them for input captures of digital signals, not waste them on buttons. The lower model PICs has 3 external interrupts, and some only have 1 I believe. The software oversampling filter really is the most elegant solution because you can use any old input pin and save your interrupt resources.
-J