Unit E - College Practice

28. External Interrupts

React instantly to a pin edge, then finish the work in loop().

Estimated time 3 hours

Learning outcomes

  • Identify Uno hardware interrupt pins
  • Use attachInterrupt with a volatile flag
  • Keep an ISR short and safe
  • Handle the event in loop with non-blocking outputs

Parts and preparation

Uno, push-button, LED with 330 ohm resistor and a passive buzzer.

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

External Interrupts instructional connection diagram
Open the diagram for a larger view. Trace every connection before building.

What an interrupt does

An interrupt can pause the main program when a pin edge occurs, run an ISR, then return. It is useful for rare, time-critical events such as a limit switch or encoder tick.

Uno pins

On the classic Uno, external interrupt INT0 is D2 and INT1 is D3. Many other pins need pin-change interrupts, which are more advanced.

ISR rules

Keep the ISR extremely short. Set a volatile flag or count, then return. Avoid delay, Serial printing, floating-point work and long library calls inside the ISR.

Shared data

Variables written in an ISR and read in loop must be volatile. For multi-byte values that must stay consistent, briefly disable interrupts while copying them in loop.

Wiring and safe build sequence

  1. Button from D2 to GND with INPUT_PULLUP
  2. D8 -> 330 ohm -> LED -> GND
  3. Passive buzzer signal -> D7; buzzer GND -> GND
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;
const byte ledPin = 8;
const byte buzzerPin = 7;

volatile bool eventPending = false;
volatile unsigned int eventCount = 0;

unsigned long beepUntil = 0;
bool ledOn = false;

void onButtonEdge() {
  eventPending = true;
  eventCount++;
}

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(ledPin, OUTPUT);
  pinMode(buzzerPin, OUTPUT);
  Serial.begin(9600);
  attachInterrupt(digitalPinToInterrupt(buttonPin), onButtonEdge, FALLING);
}

void loop() {
  if (eventPending) {
    noInterrupts();
    eventPending = false;
    unsigned int countCopy = eventCount;
    interrupts();

    ledOn = !ledOn;
    digitalWrite(ledPin, ledOn);
    tone(buzzerPin, 1200);
    beepUntil = millis() + 80;
    Serial.print("Events: ");
    Serial.println(countCopy);
  }

  if (beepUntil != 0 && millis() >= beepUntil) {
    noTone(buzzerPin);
    beepUntil = 0;
  }
}

How the code works

  1. FALLING matches an INPUT_PULLUP button that goes LOW when pressed.
  2. digitalPinToInterrupt(2) maps D2 to interrupt 0 on Uno.
  3. The beep duration is finished in loop with millis, not delay inside the ISR.

Test and record evidence

Expected result: Each clean button edge toggles the LED, chirps briefly and prints an increasing count.

Practical evidence checklist

Common faults and checks
  • Multiple counts per press: add software debounce in loop or a short ignore window after an event.
  • No response: confirm the button is on D2 and uses INPUT_PULLUP to GND.
Extension challenge: Ignore further interrupts for 200 ms after each accepted event to debounce in software.

Check your understanding

Q1. Which Uno pins have external interrupts?

Show answer

D2 (INT0) and D3 (INT1).

Q2. What should an ISR usually do?

Show answer

Only set a flag or update a simple count, then return quickly.