Unit B - Inputs & Outputs

08. Digital Inputs, Pull-Ups & Debouncing

Read stable button and switch signals.

Estimated time 3 hours

Learning outcomes

  • Explain floating inputs
  • Wire an internal pull-up input
  • Detect a press edge
  • Debounce a mechanical button without blocking

Parts and preparation

Uno, push button, jumper wires and onboard LED.

Before power: inspect wiring, confirm supply voltage and ensure all connected circuits share GND.

Digital Inputs, Pull-Ups & Debouncing instructional connection diagram

Floating inputs

An unconnected high-impedance input can randomly read HIGH or LOW. A pull-up or pull-down resistor establishes a default level so the pin is defined when the button is open.

INPUT_PULLUP

The Uno has internal pull-up resistors. Wire the button from the pin to GND: open reads HIGH and pressed reads LOW. That active-low wiring is the usual course pattern for push buttons.

Contact bounce

A mechanical button does not snap cleanly between open and closed. As the contacts meet, they bounce for a few milliseconds and the pin voltage chatters between HIGH and LOW.

If your sketch reacts to every raw edge, one physical press can look like many presses. That is why counts race, LEDs flicker, and menus jump.

Ideal clean HIGH to LOW press edge compared with a real bouncing button waveform that chatters for several milliseconds
Ideal: one clean edge. Real button: several false edges during bounce, then a stable LOW.

Software debounce

Debouncing accepts a new state only after the raw reading stays unchanged for a short time (debounceMs, often about 20-50 ms).

In this lesson's sketch, every change to the raw reading restarts a millis() timer. When the timer reaches debounceMs and the reading still differs from stableState, the sketch updates stableState. Bounce edges never last long enough to be accepted.

Three-step diagram: bouncing raw reading, short debounce windows that restart on each change, then one clean stableState edge after 30 ms of stability
Restart the timer on every raw change. Only a full stable window updates stableState.

Edge detection

Acting while the button is held (level detection) fires again every loop pass. An event should happen when the stable state changes - for an INPUT_PULLUP button, that is usually the falling edge HIGH to LOW.

This sketch toggles the LED only when stableState becomes LOW, so one press equals one toggle.

Side-by-side comparison of level detection causing many actions while held versus edge detection causing one action on the falling edge
Level: many actions while held. Edge: one action when stableState becomes LOW.

Wiring and safe build sequence

Breadboard wiring for lesson 08: Digital Inputs, Pull-Ups & Debouncing
Breadboard layout for this lesson. Match colours and pins before powering the circuit. Click the image for a larger view.
  1. One button side -> D2
  2. Opposite button side -> GND
  3. Configure D2 as INPUT_PULLUP
Power rule: switch off before moving wires. Arduino I/O pins are control signals; high-current loads require a driver and suitable external supply.
const byte buttonPin = 2;
bool stableState = HIGH;
bool lastReading = HIGH;
unsigned long changedAt = 0;
const unsigned long debounceMs = 30;

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

void loop() {
  bool reading = digitalRead(buttonPin);
  if (reading != lastReading) {
    changedAt = millis();
    lastReading = reading;
  }
  if (millis() - changedAt >= debounceMs && reading != stableState) {
    stableState = reading;
    if (stableState == LOW) {
      digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
    }
  }
}

How the code works

  1. The timer restarts whenever the raw reading changes.
  2. Unsigned subtraction remains safe when millis rolls over.
  3. The LED toggles only on the stable pressed edge.

Test and record evidence

Expected result: Each physical press toggles the onboard LED exactly once.

Practical evidence checklist

Common faults and checks
  • Four-leg buttons connect pairs of legs internally; rotate the button if it always reads pressed.
  • Print reading and stableState for diagnosis.
Extension challenge: Count stable button presses and print the count over Serial.

Check your understanding

Q1. Why must an input not float?

Show answer

Its logic level would be undefined and noise-sensitive.

Q2. What is button bounce?

Show answer

Rapid unintended transitions as mechanical contacts settle.