GPIO debounce in C++
Log in to track your progress.
0 of 4 lessons completed · 0% complete
Mechanical buttons bounce: without debouncing you get ghost presses. We implement a robust filter in C++.
The bounce problem
A mechanical button does not switch instantly from LOW to HIGH: for a few milliseconds the contacts vibrate and the microcontroller reads spurious transitions.
Time ──────────────────────────────►
Signal: ▁▁▁▔▁▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
↑ bounce
Strategy: time-based debounce
We consider a transition valid only if the state stays stable for 20 ms.
class DebouncedButton {
public:
DebouncedButton(uint8_t pin, bool pullup = true)
: pin_(pin), stableState_(HIGH), lastRead_(HIGH) {
pinMode(pin_, pullup ? INPUT_PULLUP : INPUT);
}
bool pressedEdge() {
const bool reading = digitalRead(pin_);
const unsigned long now = millis();
if (reading != lastRead_) {
lastChangeMs_ = now;
lastRead_ = reading;
}
if ((now - lastChangeMs_) >= 20 && reading != stableState_) {
stableState_ = reading;
if (stableState_ == LOW) {
return true; // falling edge with pull-up
}
}
return false;
}
private:
uint8_t pin_;
bool stableState_;
bool lastRead_;
unsigned long lastChangeMs_ = 0;
};
Usage
DebouncedButton btn(2);
void loop() {
if (btn.pressedEdge()) {
Serial.println("Click!");
}
}
Approach comparison
| Approach | Pros | Cons |
|---|---|---|
delay() after read |
Simple | Blocks everything |
| Time debounce | Lightweight, non-blocking | Requires state |
| RC hardware filter | Less electrical noise | Extra parts/cost |
Recommended test
Connect a debug LED to pin 13 and increment a counter on each pressedEdge(). If the counter increases by more than one per press, increase the window to 30–40 ms or check ground and pull-up wiring.
Comments (0)