Hardware

GPIO debounce in C++

Level Intermediate
By admin 2 min read 1 reader
GPIO debounce in C++

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.

TEXT
Time ──────────────────────────────►
Signal:  ▁▁▁▔▁▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
              ↑ bounce

Strategy: time-based debounce

We consider a transition valid only if the state stays stable for 20 ms.

CPP
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

CPP
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

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.

Next steps

Comments

Comments (0)

Demo resets in 00:39:46