Bench NotesUno handbook

Hardware Interrupts

Catch button presses the instant they happen on pins 2 and 3, with safe ISR and shared-variable rules.

AdvancedPushbuttonSerial

Overview

An interrupt makes the processor pause the main program and run a short function (an interrupt service routine, ISR) the moment a pin changes. On the Uno, pins 2 and 3 support external interrupts. They suit events too short or too frequent to catch by polling: encoder pulses, fast sensors, wake-up signals.

You will need

  • Arduino Uno R3
  • Momentary pushbutton
  • Jumper wires

Wiring

Uno pinConnects toNotes
2Button, one sideINPUT_PULLUP, interrupt on FALLING edge
GNDButton, other side
Wiring for Hardware InterruptsArduino Uno D2 (INT0) to Pushbutton side A; Arduino Uno GND to Pushbutton side B.Connections (each line is one wire)Arduino UnoPushbuttonD2 (INT0)side AGNDside B
Original wiring diagram. Each line is one jumper wire; boxes on a line are series resistors.

Rules for ISRs

  • Keep them short: set a flag or update a counter and return.
  • Declare variables shared with the main program volatile.
  • When reading a shared value larger than one byte, briefly disable interrupts so it cannot change halfway.
  • Do not use delay() or Serial printing inside an ISR.

The sketch

interrupt_counter.ino
const int BUTTON_PIN = 2;   // pins 2 and 3 support interrupts on the Uno

volatile unsigned int pressCount = 0;
volatile unsigned long lastPressMs = 0;

void onButtonFalling() {
  unsigned long now = millis();      // millis() can be read, but does not advance, inside an ISR
  if (now - lastPressMs > 50) {      // ignore bounce
    pressCount++;
    lastPressMs = now;
  }
}

void setup() {
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), onButtonFalling, FALLING);
  Serial.begin(9600);
}

void loop() {
  static unsigned int lastReported = 0;

  noInterrupts();                    // copy multi-byte shared data safely
  unsigned int count = pressCount;
  interrupts();

  if (count != lastReported) {
    Serial.print("Presses: ");
    Serial.println(count);
    lastReported = count;
  }
  delay(200);                        // presses are still counted during this delay
}

How the code works

Even with the delay(200) in the loop, no press is lost, because the ISR runs the moment the pin falls. For ordinary buttons polling is usually simpler; interrupts earn their complexity when timing really matters.

What you should observe

  • Each press increases the count printed in the Serial Monitor by one.
  • Rapid presses during the delay are all counted.