Working in the area of the Internet of Things (IoT) quickly led me to realize that I could no longer rely solely on my understanding of software engineering, ignorant of all things hardware related and hoping that it would be taken care of by a clever hardware engineer. Clearly, there was going to be a lot about hardware that I would have to learn – but that’s ok I actually quite like learning new things. This weekend’s learning revolved around debouncing switches using RC circuits. And I thought I’d share some of the details for all the other software engineers out who are trying to catch up on hardware just like me 🙂


Ok this isn’t the switch I wired into the debouncing circuit but everyone loves a big red button 🙂

Down to the real work. Let’s start by discussing exactly what hardware button debouncing is. Imagine we have the simple circuit below.


When we close the circuit the voltage at the pin should transition from a high value to low value and of course it will. However, from the point of view of a micro controller attached to the pin (PIN) it might not be the clean high to low transition we expect. The reason for this is the pin is measuring a digital signal but the switch is controlling an analog voltage. The analog voltage is interpreted as a high or low digital value based on two threshold voltages. Voltage input high (VIH) refers to the minimum voltage that can be consider a digital high. Voltage input low (VIL) refers to the maximum voltage that can be considered a digital low. When the switch is closed the rapidly changing flow of current may lead the voltage at the pin to transition through VIH and VIL several times before finally being driven to GND. Equivalently when the switch is opened a similar set of transitions may occur before the voltage felt at the pin is VDC. As a result a single state transition (open/closed) at the switch may lead to multiple state transitions (high/low) at the digital pin. This is what is referred to as bounce and it can cause problems if a developer or engineer hasn’t taken account of it.

Debouncing the button refers to removing these additional state transitions at the digital pin. This can be achieved with hardware or software. For the purposes of this tutorial we will debounce the button by using an RC (resistor capacitor) circuit. By carefully selecting the correct values for resistors and capacitors in our circuit we can smooth the transition of voltage at the digital pin. Let’s take a look at the RC circuit we will use.


The top of the circuit is connected to 3.3V and the bottom of the circuit is connected to ground. The resistors R1 and R2 will control the charging and discharging of the capacitor C. And the circuit element labeled PIN is connected to a digital input pin on a Raspberry Pi – note the applied voltage is 3.3V as the Raspberry Pi uses 3.3V logic levels. The circuit is relatively easy to build but we will still need to calculate the values of R1, R2 and C to use. Before we get down to the equations (I love equations) let’s take a second to see how this circuit behaves with the switch open and closed.

When the switch is open there is a potential difference across the capacitor. This difference allows the capacitor to charge at a rate determined by R1, R2 and C. When charged the pin should read a value of 3.3V.

When the switch is closed the accumulated charge on the capacitor can drain away – as there is no longer a potential difference across the capacitor. The rate at which the charge drains will be determined by the value of R2 and C.

We will start by choosing a value of C. A capacitor with a capacitance of 1µF is a commonly available and suitable component. With C set we can calculate the value of R2. With the switch open the capacitor C will be charged. When the switch is closed the capacitor will discharge through R2. The equation describing that discharge is given by:


where Vcap(t) is the voltage across the capacitor at time t, R is the resistance of the circuit and C is the capacitance of the circuit. Rearranging this equation we have:


The last thing we need to do to calculate the value of R is to select a value for t. The value we choose for t should be large enough that all of the bouncing occurs before that time. Choosing this value can be tricky if you don’t have access to an oscilloscope – a scope will give you a really clear view of the voltage signals and timings. I didn’t have access to a scope so I took to the internet and found an article by someone who did. The Ganssle Group article suggested 20ms as a reasonable time for all bounce to have occurred for a range of common pins they tested.

With values for t (20ms), C (1µF), Vcap – which for discharging is VIL – (1.8V) and V0 (3.3V) we can calculate R – or more specifically R2 in our circuit above – as (approx.) 21.5k?. I rounded this to 22k? as I had one on hand.

To calculate the value of R1 we look at the equation required to charge the capacitor. That is when the switch opens. The equation that describes the charge in the capacitor is:


Where Vcap is the voltage across the capacitor, V0 is the voltage the capacitor will finally rise to, C is the capacitance, t is the time and R is the resistance – in this instance R1+R2. Rearranging we have:


Substituting in the values t (20ms), C (1µF), Vcap – which for charging is VIH – (1.8V) and V0 (3.3V) we can calculate R – or more specifically R1+R2 – as (approx.) 73k?. Which meant R1 must be 51k?. I had a 47k? and a 3,900? resistor to hand so wired these in series to create an R1 of 50,900? resistance.

With the values of R1, R2 and C established I built the circuit. I then hooked it up to an Arduino Due (which has the same logic levels and very similar threshold voltages to a Raspberry Pi) for testing and wrote a short Sketch to detect rising and falling voltages using hardware interrupts.


As expected (or at least hoped) I got clean transitions as the button was pushed. Now all that’s left is to have a peek at the code and look at the results with the resistor only and the resistor-capacitor circuits. Enjoy!

volatile int rises = 0;
volatile int falls = 0;

int prev_rises = rises;
int prev_falls = falls;

void rise(void)

void fall(void)

void setup() {
  // put your setup code here, to run once:

void loop() {
  // put your main code here, to run repeatedly:
  int i;
  Serial.println("**** Begin loop ****");
        Serial.println("A rise");
  prev_rises = rises;
        Serial.println("A fall");
  prev_falls = falls;
  Serial.println("**** End loop ****");

With output:


The image on the left is the output for the resistor only circuit and the image on the right is the output for the resistor-capacitor circuit. Both images correspond to a single button click.

ShareShare on Facebook0Share on Google+1Tweet about this on TwitterShare on LinkedIn0
Back to Articles

Leave a Reply