Skip to content

Feet wet with the Arduino: Debouncing

January 3, 2011

My lovely family got me for Xmas this year an Arduino Uno, and some associated bits like a breadboard.  I’ve always been interested in how things work, but intimidated by component-level electronics, so I figured this would be a good place to get over it and learn something at the same time.

I’d already done a bunch of reading, including the Getting Started guide (thanks, Douggie, Hannah!), so next came a quick trip to RadioShack, where I rifled through their parts bins looking for anything interesting to hook up.  Maybe not the cheapest solution, but it was a neat experience to be able to dig through and find stuff that might be fun to hook up, but not be sure what it’s useful for yet.  In a world where everything you buy has an exact purpose, and generally only one way of hooking it up, it was an eyeopener!

Button and two LEDs

Small beginnings

Among other things I ended up with a couple of plain old green LEDs, and a momentary switch (275-646).  I had to crimp the switch’s legs with a pair of pliers to get them to fit into my breadboard, since in my RadioShack fugue I wasn’t savvy enough to imagine this might be something I’d want to do.

I’ve done some programming, and am comfortable digging and researching until I understand something, so I was happy enough with the coding side of it – which in fact is very similar to c#, given its c / c++ heritage.  Something that fascinates me is that in coding, everything is very deterministic most of the time, but in hardware, there was a whole side I’d never guessed at; contacts can ‘bounce‘, or a potentiometer can flick back and forth between two values, or any number of other mysterious and distressing behaviours can manifest.  I decided to combine the LEDs and a button, and explore the whole thing to get a better handle on it.

Every Arduino LED tutorial starts off with a LED (or two), and indicates you needed a resistor in line with each LED.  A bit of digging turned up the underlying reason: the LEDs just don’t handle the current that results from a 5V source. That’s probably not exactly worded correctly, and of course there’s more to it than that, but the end result is that I needed 100 ohm resistors in series with each LED.  The resistance calculation was pretty straightforward using a handy online calculator; doing it manually is a bit more work, but definitely useful.  It took me a while to find a site that actually explains the calculation, which works out as follows:

The Arduino’s digital pins provide 5V, and my LEDs have a forward voltage (voltage level needed to make them light) of 2.1 volts.  So we need to reduce the 5V DOWN to 2.1V, i.e. reduce it by 2.9V – this is the amount the resistor has to drop the voltage by.  The LEDs have a forward current (how much current we want to drive through the LED) of 30 mA.

So for the resistor, since V=IR, i.e. 2.9 = (0.030 * R), then R = 2.9 ÷ 0.030 = 96.6667.  The next ‘size up’ for resistors is 100Ω, so we select that. Whew!

The only other thing that I found non-intuitive is that I needed a resistor between the switch and ground.  After some research to understand it, I found it helps to think of it this way: When the switch is open, the digital pin ‘sees’ the ground normally, through the resistor.  In this case, the resistor is redundant; there’s only one path, so the digital pin is ‘low’.  When the switch is closed, however, the pin can see two paths; one to ground, and one to the 5V source.  The fact that one path (the ground path) has a resistor causes the pin to have a ‘preferred path’ the other way, through to the 5V source – i.e. the resistor on the ‘ground path’ makes it a less ‘desirable’ path.  I’m sure that’s not technically accurate, but it makes it easier for me to remember!

So, the circuit looks like this in Fritzing:

 

The tidy version - thanks Fritzing!

The tidy version - thanks Fritzing!

And less attractive, but keepin’ it real:

The Board

All good!

The Arduino code to control all this is as follows:

const int led0Pin = 11;            // LED1 is connected to pin 11
const int led1Pin = 12;            // LED2 is connected to pin 12
const int btnPin = 2;              // Momentary button is connected to pin 2
const int minTime = 30;            // The minimum time the button must be pressed (in ms) before we consider it a valid press
int lastReadBtnState;              // Used to store the last state that we read from the button (this could flop all over the place)
int acceptedBtnState;              // Used to store the last ACCEPTED state that we read from the button (this should be very stable)
int ledLit = 0;                    // Which LED is lit; 0 = led0, 1 = led1
unsigned long lastChangeTime;      // Used to store the last time that we observed a change in the button's state
boolean inTransition = false;      // If this is true, we've observed a button change, and are waiting to see if it is stable

void setup()
{
Serial.begin(9600);                      // Initialise the serial output so that we can write out debug messages
pinMode(led0Pin, OUTPUT);                // Set the LED0 pin as output
pinMode(led1Pin, OUTPUT);                // Set the LED1 pin as output
pinMode(btnPin, INPUT);                  // Set the button pin as input
acceptedBtnState = digitalRead(btnPin);  // Initialise the stable button state to whatever state it actually is
lastReadBtnState = acceptedBtnState;     // Indicate that we're in a stable state
}

void loop()
{
lastReadBtnState = digitalRead(btnPin);
if (!inTransition && (lastReadBtnState != acceptedBtnState))
// Bam, we registered a button state change
{
lastChangeTime = millis();  // Mark the time we observed the change
inTransition = true;        // Note that we're now in a transition state
Serial.println("Button state changed from " + StateToStr(acceptedBtnState) + " to " + StateToStr(lastReadBtnState) + ".  Going into transition");
}
else if (inTransition && ((millis() - lastChangeTime) > minTime))
// The button state hasn't changed for at least minTime milliseconds, so assume we're stable now
{
Serial.println("Met minimum time requirement: going from " + StateToStr(acceptedBtnState) + " to " + StateToStr(lastReadBtnState));
if (lastReadBtnState == LOW)
// Only toggle the LED if the button is in a LOW state
{
Serial.println("New state is LOW; toggling LED");
ledLit = 1 - ledLit;
}
// Move the last-read value into the accepted state variable
acceptedBtnState = lastReadBtnState;
// Note that we're no longer in transition
inTransition = false;
}

// Turn on the appropriate LED
if (ledLit == 0)
{
digitalWrite(led0Pin, HIGH);
digitalWrite(led1Pin, LOW);
}
else
{
digitalWrite(led0Pin, LOW);
digitalWrite(led1Pin, HIGH);
}
}

String StateToStr(int AState)
// Given a pin state variable, returns a text equivalent of its value
{
return (AState == HIGH ? "HIGH" : "LOW");
}

The LEDs alternate smoothly when the button is pressed, so mission accomplished.  Back to the sack of goodies to see what’s next!

Advertisement

From → arduino

Leave a Comment

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.