Handling Button Presses and Debounce Methods

Handling Button Presses and Debounce Methods

Monday June 15th, 2015 0 By Admin

Often, you want to control an Arduino using a button. Fortunately, connecting a button is straightforward, and the Arduino IDE even provides a pre-made sketch that you can find under

Examples -> 02.Digital -> Button.

Here is the source code:

[code]
/*
Button

Turns on and off a light emitting diode(LED) connected to digital
pin 13, when pressing a pushbutton attached to pin 2.

The circuit:
* LED attached from pin 13 to ground
* pushbutton attached to pin 2 from +5V
* 10K resistor attached to pin 2 from ground

* Note: on most Arduinos there is already an LED on the board
attached to pin 13.

created 2005
by DojoDave
modified 30 Aug 2011
by Tom Igoe

This example code is in the public domain.

http://www.arduino.cc/en/Tutorial/Button
*/

// constants won’t change. They’re used here to
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin

// variables will change:
int buttonState = 0; // variable for reading the pushbutton status

void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}

void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
}
else {
// turn LED off:
digitalWrite(ledPin, LOW);
}
}
[/code]

In addition to an Arduino, you’ll need a button and a resistor. The resistor connects pin 2 to ground, pulling the voltage at the pin to 0V. When you press the button, the pin is connected to the supply voltage (5V), and the voltage at the pin quickly rises to 5V. This voltage change is detected by the Arduino and can be read using the digitalRead function.

 

The sketch sets pin 2 to input mode and pin 13 to output mode. Pin 2 is where the button is connected, and on the Arduino, there’s already an LED built into pin 13. In the loop, it continuously checks the state of pin 2 using digitalRead. The variable buttonState is then set to 0 or 1, depending on the value digitalRead returns. If buttonState is set to 1, the LED is turned on; otherwise, it’s turned off..

Single Button Presses

However, this doesn’t allow toggling between on and off states with a single button press. To achieve this, you can use the following code:

[code]
/*
Button

Turns on and off a light emitting diode(LED) connected to digital
pin 13, when pressing a pushbutton attached to pin 2.

The circuit:
* LED attached from pin 13 to ground
* pushbutton attached to pin 2 from +5V
* 10K resistor attached to pin 2 from ground

* Note: on most Arduinos there is already an LED on the board
attached to pin 13.

*/

// constants won’t change. They’re used here to
// set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 13; // the number of the LED pin

// variables will change:
int buttonState = LOW; // variable for reading the pushbutton status
int buttonread = 0;

void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}

void loop() {
// read the state of the pushbutton value:
buttonread = digitalRead(buttonPin);

// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonread == HIGH) { //Check if Button was pressed before and being pressed now

if (buttonState == LOW)
{
// turn LED on:
digitalWrite(ledPin, HIGH);
buttonState = HIGH;
Serial.println("Button pressed");
}
}
else {
if (buttonState == HIGH) {
digitalWrite(ledPin, LOW);
buttonState = LOW;
}
}
}

[/code]

  1. At the beginning, buttonState is initialized to LOW. This variable keeps track of whether the button has been pressed before, and LOW indicates that it hasn’t been pressed yet.
  2. The code then uses digitalRead to check the button’s state. If buttonState is already in the LOW state, the LED is turned on, buttonState changes to HIGH, and we receive a message via the Serial Port using the Serial.println command. Even when releasing the button, the LED remains on.
  3.  If you press the button again, buttonState is already in the HIGH state, and the else if condition is met and executed. Within this condition, buttonState is set back to LOW, and the LED is turned off.

In essence, this works, but…

Frequently, multiple messages are sent via the serial interface even though the button was pressed only once. This shouldn’t happen in theory; even if you hold down the button, the code for buttonState == LOW should only execute once.

The image above, for example, is after a single button press. What happened?

 

Bouncing

When you press the button, you close the electrical circuit, but this doesn’t happen instantly. The mechanical components inside the button are not perfect, and it may take a little time for the circuit to fully close. This behavior is known as “bouncing.” As you can imagine, this is quite problematic. For instance, a keyboard might produce multiple characters in rapid succession with a single keypress. Correcting this behavior is called “debouncing,” and there are several approaches to achieve it, both through electrical and software means.

The simplest software solution involves waiting for a brief moment after reading the button. Then, if the button was in the HIGH state, read the button again. If the button is still in the HIGH state, the Arduino can be quite sure that it was indeed a genuine button press.

[code]
if (buttonread == HIGH) { //Check if Button was pressed before and being pressed now
delay(5);
if ((buttonState == LOW) && (digitalRead(buttonPin)) )
{
if (digitalRead(buttonPin)) {
// turn LED on:
digitalWrite(ledPin, HIGH);
buttonState = HIGH;
Serial.println("Button pressed");
}
}
}
[/code]

The exact duration of the wait depends on the specific situation and is not particularly critical. Typically, a delay of 5 to 50 milliseconds is sufficient.