#MonthOfCode - Day 5: bounce

My entry for the 5th day of the month of code. The theme for today is: bounce.

Today, we go in the hardware world. Let’s talk about buttons and the bouncing problem.

When you push a button or toggle a switch, you move a metallic part which makes contact with the rest of the circuit. The contact is never perfect at the beginning and it looks like the button is pressed and released multiple times before stopping on the correct position.

If you use this simple Arduino code with a button between ground and pin 12, you’ll easily reproduce the problem:

bounce.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void setup() {
pinMode(12, INPUT_PULLUP); // PULLUP is here to read HIGH when the pin is floating
Serial.begin(9600);
Serial.println("hello");
}

void loop() {
static bool oldState = HIGH;
bool state = digitalRead(12);

if (state != oldState) {
Serial.println(state);
oldState = state;
}
}

Instead of seeing one 0 and one 1 when you press and release the button, you will probably see bouncing.

1
2
3
4
5
6
7
8
9
10
11
12
// press
0
1
0
// release
1
// press
0
1
0
1
0

Today’s code is a function that debounces the signal so that it correctly reads the button state.

debounce.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*
* Note: this code only works with one pin
*/

bool debounceRead(int pin, long debounceDelay) {
static bool lastButtonState = HIGH;
static bool buttonState;
static long lastDebounceTime = 0;

bool reading = digitalRead(pin);

if (reading != lastButtonState) {
lastDebounceTime = millis();
}

if ((millis() - lastDebounceTime) > debounceDelay) {
if (reading != buttonState) {
buttonState = reading;
}
}
lastButtonState = reading;

return buttonState;
}

Usage:

usage.cppview raw
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void setup() {
pinMode(12, INPUT_PULLUP);
Serial.begin(9600);
Serial.println("hello");
}

void loop() {
static bool oldState = HIGH;
//bool state = digitalRead(12);
bool state = debounceRead(12, 5); // ignore bouncing for 5 ms

if (state != oldState) {
Serial.println(state);
oldState = state;
}
}

And now you’ll see:

1
2
3
4
5
6
7
8
// press
0
// release
1
// press
0
// release
1