Bouncing Inputs

Bumbles aren't the only thing that bounce. So do push buttons. When you press your basic, normally open, momentary style button, it closes its little internal switch connection. In an ideal world we could hook that up to our Circuit Playground, like we have the alligator clips, and get an input signal that would look like this:

That's the way a button should work and how most people think they work. However, in reality it looks more like this:

It goes up and down several times before finally stabilizing. Take a button apart and check out its guts and see how it works. Inside you'll find some form of mechanism that brings two contacts together - much like we are doing with the alligator clips. However, the contact doesn't happen instantly. It bounces around a bit, going closed, open, closed, open, closed, etc. This is purely a mechanical phenomenon, kind of like dropping a ball - it bounces before finally sitting still on the ground.

It does this over the period of time = t. While this period of time is very fast, and seems almost instantaneous to you and me, to the Circuit Playground, it's a huge period of time. The Circuit Playground can execute many many instructions in that period of time.

We can use our alligator clip setup to gain an appreciation for this. We will use the "pull down" setup from the previous section, so make sure you've got the alligator clips hooked up that way.

Now run the following sketch.

Download: file
///////////////////////////////////////////////////////////////////////////////
// Circuit Playground Digital In - Bounce Demo
//
// Author: Carter Nelson
// MIT License (https://opensource.org/licenses/MIT)

#include <Adafruit_CircuitPlayground.h>

int currentState;
int previousState;
uint32_t count;

///////////////////////////////////////////////////////////////////////////////
void setup() {
  Serial.begin(9600);
  
  CircuitPlayground.begin();
  
  pinMode(3, INPUT);

  count = 0;
  
  currentState = digitalRead(3);
  previousState = currentState;
}

///////////////////////////////////////////////////////////////////////////////
void loop() {
  currentState = digitalRead(3);
  if (currentState != previousState) {
    count = count + 1;
    Serial.print("State changed from ");
    Serial.print(previousState);
    Serial.print(" to ");
    Serial.print(currentState);
    Serial.print(". count = ");
    Serial.println(count);
    previousState = currentState;

    //delay(100);
  }
}

With this sketch loaded and running on the Circuit Playground, open the Serial Monitor.

Tools -> Serial Monitor

Now play around with touching the alligator clips together.

Touch the RED to the BLUE alligator clip.

Did you get more than one print out when you made the connection? Try touching the clips several times and watch the behavior of the messages in the Serial Monitor. If you do it just right, you can get only one message to print. However, more often you get multiple lines. Same when the connection is removed - the bounce happens in both directions.

Touching the alligator clips together like this is a very bouncy operation. The Circuit Playground is fast enough to see all those bounces and prints out a message each time.

Here's what I get trying this after a fair amount of coffee to add some extra bounce.

So how do we fix this? There are many ways, both hardware based and software based. So many in fact that a discussion of debouncing techniques is worthy of its own guide (or more).

However, we will demonstrate one very simple software approach. The trick is to just add a delay after the initial detection. This forces the Circuit Playground to go to sleep during the bouncing and not pay any attention to it.

To test this, simply uncomment (remove the //) the following line in the previous sketch. (it's near the bottom)

Download: file
  delay(100);

Run this new code and play around again with touching the alligator clips together. Now you should get a single print out when touched and separated as shown below.

The main drawback to this technique is that the Circuit Playground can not do anything else during the delay() period. For more complicated programs the processor is always doing something and you try to avoid forcing is to go to sleep using something like delay().

However, for simple programs, this technique works just fine. In fact, you'll see it used quite often. It's simple and works. Ever seen anything like this at the top of a sketch?

Download: file
#define DEBOUNCE    100

Look elsewhere in the code and you'll likely find:

Download: file
delay(DEBOUNCE)

It's using the same technique and simply defining the delay period globally.

This guide was first published on Feb 26, 2017. It was last updated on Feb 26, 2017. This page (Bouncing Inputs) was last updated on Sep 20, 2019.