Skip to content

Supplementary: Timer, PWM and Interrupt

Objectives

At the end of this self-learning lab, you should be able to:

  • Use External Interrupt
  • Use Timer Interrupt

Info

This lab is optional. It lets you learn more intermediate but useful programming techniques in Arduino. If you find it difficult, feel free to skip this lab.

Things you need

  • Solderless breadboard
  • LED
  • A resistor, anything between a few hundred to a few thousand ohms is OK. Check the resistance with a multimeter or by reading the color code on it.
  • Momentary button
  • Hookup wire (or Dubon wires as we like to call them)

External Interrupt

You may have heard of interrupt service routine (ISR), which is a piece of code triggered by a interrupt signal.

On Arduino Uno, one pin 2 and pin 3 support interrupt. Connect a button to pin 2 like this.

Schematic for button

Run the following code:

const int BTN_PIN = 2;

bool g_state = false;

void handler(void);

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(BTN_PIN, INPUT_PULLDOWN);

  attachInterrupt(BTN_PIN, handler, RISING);
}

void loop() {
}

void handler(){
  g_state = !g_state;
  digitalWrite(LED_BUILTIN, g_state);
}

Here handler() is called once the button is pressed.

Try it yourself

Control a breathing light

Make a breathing light that turns on only when the button is pressed. Make use of external interrupt.

Timer Interrupt

Arduino has hardware timers, each consist of a counter and several registers to control the behaviour of the counter. The counter increments from 0 to its maximum, and then back to 0 again. (In upcounting mode. There are also downcounting mode, which behave similarly)

It is possible to generate interrupt signals using a timer. The function can be executed at a regular time intervals. This is especially useful in real-time control.

Here we will be using the PC13 LED as an example:

const int LED_PIN = LED_BUILTIN;
const int LED_RATE = 500000;  // in microseconds; therefore the interrupt handler will be called every 0.5s

void handler_led(void);

int g_state = 0;

void setup()
{
  pinMode(LED_PIN, OUTPUT);

  // Setup LED Timer
  // In output compare mode, timer counts from 0 to its reload value repeatedly; every time the counter value reaches one of the channel compare values, the corresponding interrupt is fired.
  Timer1.setMode(TIMER_CH1, TIMER_OUTPUTCOMPARE);
  Timer1.setPeriod(LED_RATE); // in microseconds
  Timer1.attachInterrupt(TIMER_CH1, handler_led); // handler_led() is the interrupt handler
}

void loop() {
}

void handler_led() {
    g_state = !g_state;
    digitalWrite(LED_PIN, g_state);
}

Here handler_led() is called every 0.5s. The LED should be blinking at 1 Hz.

Further Readings

Try it yourself

Control a breathing light Mk-II

Make a breathing light that can be toggled by a button or a command from serial input. Use timer interrupt to adjust the brightness of the LED, and use external interrupt read the state of the button.

You may check the maple documentation and see how to use pause() and resume().

Reference

External Interrupt

Timer Interrupt

Further Reading