Generating PDF...

Preparing...
Back

External Interrupts in Practice

Build a digital inverter with a signal generator, oscilloscope, and Arduino API

DE6417 Microcontrollers 2 - Week 2 Practical Session

Today you will make the microcontroller react to edges

Understand

Explain how an external event can interrupt the normal program flow.

Configure

Use attachInterrupt() on pin 2 or pin 3 at Arduino API level.

Measure

Use the oscilloscope to prove that the output is the inverse of the input.

The practical outcome: a square wave enters the Arduino, and the Arduino output changes to the opposite logic level whenever the input changes.

Part 1: Why Interrupts?

Polling can miss events. Interrupts respond when the event happens.

Polling only sees the signal when the loop checks

check 1 check 2 check 3 edge edge
Input Square wave
Loop checks Only at blue lines
Problem Edges happen between checks

A polling loop samples the pin at particular moments. A fast input can change between those moments, so the program reacts late or not at all.

Click the button to connect the picture to the code.

An interrupt responds at the edge, not at the next poll

1

Main loop

The program can do other work. It does not need to keep checking pin 2.

2

Input changes

The signal generator creates an edge on pin 2.

3

Callback runs

The callback reads pin 2 and writes the opposite value to pin 8.

digitalWrite(8, !digitalRead(2));
4

Output is inverted

On the scope, CH2 should be opposite to CH1.

The important idea: the input edge calls a short callback immediately.

Only two Arduino pins matter today

  • Pin 2 can be used with digitalPinToInterrupt(2)
  • Pin 3 can be used with digitalPinToInterrupt(3)
  • We will use the Arduino API only.
  • Our practical will use CHANGE, because an inverter must respond to both rising and falling transitions.
const byte INPUT_PIN = 2;

attachInterrupt(
  digitalPinToInterrupt(INPUT_PIN),
  inputChanged,
  CHANGE
);

Quick quiz: choose the trigger mode

The input is a square wave. The output must update on both high-to-low and low-to-high changes. Which mode fits best?

Pick one.

Part 2: Build the Inverter

The oscilloscope is the proof, not decoration.

The practical circuit has one input and one output

Input side

  • Signal generator output to Arduino pin 2
  • Signal generator ground to Arduino GND
  • Oscilloscope CH1 on pin 2

Output side

  • Arduino pin 8 is the inverted output
  • Oscilloscope CH2 on pin 8
  • Scope ground shares Arduino ground
Do not connect a negative signal to the Arduino input. Use 0 V to 5 V logic levels, or the TTL output if your signal generator has one.

Signal generator setup

  • Waveform: square wave
  • Low level: 0 V
  • High level: 5 V
  • Start frequency: 10 Hz or 100 Hz
  • Duty cycle: 50%
  • Connect all grounds together before measuring
Many generators display amplitude assuming a 50 ohm load. If connected to a high-impedance Arduino input, the measured voltage may be different. Always verify CH1 on the scope before connecting to the Arduino pin.

Predict the oscilloscope result

CH1 input on pin 2
CH2 output on pin 8
The two waveforms should be opposite. When CH1 is high, CH2 should be low. When CH1 is low, CH2 should be high.

Interactive inverter simulator

Input pin 2

0
->

Output pin 8

1
Input LOW means output HIGH.

Starter code: the callback does one small job

  • loop() is intentionally empty.
  • The callback runs when pin 2 changes.
  • Do not print from the callback.
  • Use the oscilloscope to observe the result.
const byte INPUT_PIN = 2;
const byte OUTPUT_PIN = 8;

void inputChanged() {
  int inputState = digitalRead(INPUT_PIN);
  digitalWrite(OUTPUT_PIN, !inputState);
}

void setup() {
  pinMode(INPUT_PIN, INPUT);
  pinMode(OUTPUT_PIN, OUTPUT);
  int startState = digitalRead(INPUT_PIN);
  digitalWrite(OUTPUT_PIN, !startState);
  attachInterrupt(
    digitalPinToInterrupt(INPUT_PIN),
    inputChanged,
    CHANGE
  );
}

void loop() {
  // The signal is handled by the callback.
}

Practical task: build and verify

Build

  1. Connect generator output to pin 2.
  2. Connect Arduino pin 8 to scope CH2.
  3. Upload the inverter code.
  4. Start with 10 Hz, then try 100 Hz.

Verify

  1. CH1 shows the input square wave.
  2. CH2 changes at the same edges.
  3. CH2 is opposite to CH1.
  4. loop() is not reading the signal.
Write down: frequency tested, CH1 voltage range, CH2 voltage range, and whether the output is inverted.

Quick quiz: why is loop empty?

Which explanation is best?

Select an answer.

Troubleshooting map

If CH1 is missing

  • Check generator output is enabled.
  • Check scope probe and ground clip.
  • Check voltage range is 0 V to 5 V.

If CH2 is not inverted

  • Check pin 8 is the output pin in code.
  • Check CHANGE is used.
  • Check the uploaded sketch is the latest one.

If the Arduino behaves strangely

  • Disconnect the signal and check voltage settings.
  • Confirm common ground.
  • Confirm the input never goes below 0 V.

If output timing looks delayed

  • Lower the frequency.
  • Remember the callback uses software instructions.
  • This is not a replacement for a high-speed logic gate.

Frequency challenge: find the practical limit

Once the inverter works at low frequency, increase the signal generator gradually.

  • Start at 10 Hz.
  • Try 100 Hz, then 1 kHz.
  • Observe edge timing and waveform quality.
  • Stop if the output no longer follows cleanly.
Discussion point: interrupts are excellent for event response, but a microcontroller running software is not the same as a dedicated hardware inverter.

Exit quiz

QuestionYour answer
Which Arduino Uno pins can use attachInterrupt() today?
Why did we use CHANGE?
What should CH2 show when CH1 is HIGH?
Answer the three questions.

Optional reveal: complete sketch

Use this only after attempting the practical.

const byte INPUT_PIN = 2;
const byte OUTPUT_PIN = 8;

void inputChanged() {
  int inputState = digitalRead(INPUT_PIN);
  digitalWrite(OUTPUT_PIN, !inputState);
}

void setup() {
  pinMode(INPUT_PIN, INPUT);
  pinMode(OUTPUT_PIN, OUTPUT);
  int startState = digitalRead(INPUT_PIN);
  digitalWrite(OUTPUT_PIN, !startState);
  attachInterrupt(
    digitalPinToInterrupt(INPUT_PIN),
    inputChanged,
    CHANGE
  );
}

void loop() {
}

What you should remember

Events

Interrupts let code react when an input changes, instead of constantly checking it.

CHANGE

An inverter must update on both edges, so CHANGE is the right trigger mode.

Limits

This is a learning inverter. For high-speed inversion, use hardware logic.