ZombieMutex

30 results · ↑ ↓ navigate · Enter open · Esc close

All maker projects

Arduino / Embedded programming / Robotics

Arduino button debounce with millis()

Educational reference / No physical hardware testing claimed

A pushbutton produces short, noisy electrical transitions when it changes state. A naive handler may count one physical press several times. This sample accepts a press only after the input remains unchanged for 35 ms. The loop never calls delay().

The matching debounce state machine has automated host-side tests, including timer rollover. The Arduino sketch is a reference only: no physical board build, wiring or compilation is claimed.

By Jeffrey Monica

How the example works

  1. 01Use a pull-up input

    On Arduino boards supporting INPUT_PULLUP, connect the normally open pushbutton between digital pin 2 and GND. Pressed is LOW. Confirm your board's pinout before wiring.

  2. 02Track the most recent transition

    Every time the raw input changes, reset changedAt to the current millis(). This ensures bouncing delays the decision.

  3. 03Count only a stable press

    After the reading holds for 35 ms, update stablePressed. Toggle the LED on entering pressed state, not on release.

  4. 04Inspect edge cases

    Test a press with short bounce, a held press, release bounce, a second press, and millis() rollover. Change the interval based on actual switch measurements.

Reference code

Arduino C++. Read the limitations below before using this code with real hardware or network services.

Arduino C++
// Reference sketch: button on pin 2 to GND.
const uint8_t buttonPin = 2;
const uint8_t ledPin = LED_BUILTIN;
const unsigned long debounceMs = 35;
bool lastRaw = false;
bool stablePressed = false;
unsigned long changedAt = 0;
bool ledOn = false;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
}

void loop() {
  const unsigned long now = millis();
  const bool rawPressed = digitalRead(buttonPin) == LOW;
  if (rawPressed != lastRaw) changedAt = now;
  if ((unsigned long)(now - changedAt) >= debounceMs &&
      rawPressed != stablePressed) {
    stablePressed = rawPressed;
    if (stablePressed) {
      ledOn = !ledOn;
      digitalWrite(ledPin, ledOn ? HIGH : LOW);
    }
  }
  lastRaw = rawPressed;
}

Test cases to check

  • A burst of alternating raw samples shorter than 35 ms produces zero accepted presses.
  • One sustained press produces one accepted event, even if it is held for a long time.
  • Release bounce does not create another event; the next stable press counts once.
  • The unsigned time subtraction handles the normal millis() wraparound pattern.

Limits & safety

  • Host-side tests validate the state transitions only; this is not a claim of compilation or a completed hardware test.
  • Voltage and pin mapping vary by Arduino board; check its electrical specifications.
  • 35 ms is a demonstration interval, not an empirically verified value for every switch.

Official references

Public conversation / GitHub Discussions

Discuss this article

Public comments are being set up. There is no live comment feed yet, and this page will not load a third-party widget until the discussion repository is configured.

Send a private correction or question →