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
Open the diagram for a larger view. Trace every connection before building.

Floating inputs

An unconnected high-impedance input can randomly read HIGH or LOW. A pull-up or pull-down resistor establishes a default level.

INPUT_PULLUP

The Uno has internal pull-up resistors. Wire the button from the pin to GND: open reads HIGH and pressed reads LOW.

Contact bounce

Mechanical contacts make and break several times during a few milliseconds. Debouncing accepts a state only after it remains stable.

Edge detection

An event occurs when a state changes, such as HIGH to LOW. Edge detection counts one press instead of repeatedly acting while held.

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.