Processor Interrupts with Arduino

Pages
Contributors: JordanDee, Ell C
Favorited Favorite 10

Example: Interrupting an LED Sequence

Interrupts can also come in handy when dealing with long sequences of things. Let's look at another simple example with LEDs - let's say that we are going to use the built-in RGB LED on a LilyPad USB Plus to cycle through a sequence of colors, fading each color on and off. The fade cycle time for each color is 10 seconds and we have a number of these boards sewn into costumes on stage. What happens if one of these costumes gets out of sync?

Rather than having to wait for the cycle to end and trying to reset the board in sync with the other boards, we can add an interrupt to pin 10 (this is interrupt 0 on the LilyPad USB Plus board). When the button is pressed, the interrupt is triggered and we move on to the next color. This allows us to get the offending costume in sync faster and the show can go on.

Let's make this happen for ourselves. If you'd like to follow along, grab a LilyPad USB Plus. You'll need the buttons, jumpers, and power supply from the previous experiment. You will also need a few alligator clip to pigtail wires to connect to the LilyPad sew tabs.

Hook it all up as you see here:

Lilypad USB Plus Hookup Diagram

Select the board and COM port for the the LilyPad USB Plus. Then upload the code below.

/*
Example: Interrupting an LED sequence
SparkFun Electronics

Follow the tutorial at: 
https://learn.sparkfun.com/tutorials/processor-interrupts-with-arduino#example-interrupting-an-led-sequence

This code is released under the MIT License (http://opensource.org/licenses/MIT)

******************************************************************************/

// Cycling through a series of colors using the built-in LED on the LilyPad USBPlus. Using an interrupt to switch quickly between colors

// The built-in LED:

int RGB_red = 12;
int RGB_green = 13;
int RGB_blue = 14;

int x = 0;  // variable to be updated by the interrupt

//Fade variables
int ledMode = 0; //color mode to control LEDs
int colorSwitch = 0; //compare to current_FadeVal to know whether or not to switch colors yet
int prev_FadeVal = 0;
int current_FadeVal = 0;
boolean increasing = true;

//variables to keep track of the timing of recent interrupts
unsigned long button_time = 0;  
unsigned long last_button_time = 0; 


void setup() {

// Make all of our LED pins outputs:

  pinMode(RGB_red, OUTPUT);
  pinMode(RGB_green, OUTPUT);
  pinMode(RGB_blue, OUTPUT);
  attachInterrupt(0, increment, CHANGE);
  Serial.begin(9600);  //turn on serial communication

}

void loop()
{
  // In this code we'll step through seven rainbow colors (primary, secondary, tertiary).

  // Unlike digitalWrite, which can be only HIGH (on) or LOW (off),
  // analogWrite lets you smoothly change the brightness from 0 (off) to 255 (fully on).
  // When analogWrite is used with the RGB LED, you can create millions of colors!

  
  FadeColor();
}

// Interrupt service routine for interrupt 0
void increment() {

  button_time = millis();
  
  //check to see if increment() was called in the last 250 milliseconds
  if (button_time - last_button_time > 250)
  {
    //increment counter
    x++;

    //turn led off
    analogWrite(RGB_red,0);
    analogWrite(RGB_green,0); 
    analogWrite(RGB_blue,0);
  
    Serial.println(x, DEC); //print x to serial monitor
    delay(10000);

    //set the last button time to the current button time
    last_button_time = button_time;

    //Switch colors    
    if (ledMode < 7){
      ledMode++;
    }
    else {
      //start over with Red
      ledMode = 1;
    }

    //reset fade values
    prev_FadeVal = 0;
    current_FadeVal = 0;
  
  }
}

void FadeColor() {
  switch (ledMode) {
    case 1://FADE RED
      analogWrite(RGB_green, 0);
      analogWrite(RGB_blue, 0);
      analogWrite(RGB_red, prev_FadeVal);
      break;
    case 2://FADE YELLOW
      analogWrite(RGB_red, prev_FadeVal);
      analogWrite(RGB_green, prev_FadeVal);
      analogWrite(RGB_blue, 0);
      break;
    case 3://FADE GREEN
      analogWrite(RGB_red, 0);
      analogWrite(RGB_green, prev_FadeVal);
      analogWrite(RGB_blue, 0);
      break;
    case 4://FADE CLEAR BLUE
      analogWrite(RGB_red, 0);
      analogWrite(RGB_green, prev_FadeVal);
      analogWrite(RGB_blue, prev_FadeVal);
      break;
    case 5://FADE BLUE
      analogWrite(RGB_red, 0);
      analogWrite(RGB_green, 0);
      analogWrite(RGB_blue, prev_FadeVal);
      break;
    case 6://FADE MAGENTA
      analogWrite(RGB_red, prev_FadeVal);
      analogWrite(RGB_green, 0);
      analogWrite(RGB_blue, prev_FadeVal);
      break;
      
    default:
      analogWrite(RGB_red, prev_FadeVal);
      analogWrite(RGB_green, prev_FadeVal);
      analogWrite(RGB_blue, prev_FadeVal);
      break;
  }
  delay(100);

  if (increasing == true) {
    current_FadeVal += 5;
  }
  else { //decreasing
    current_FadeVal -= 5;
  }

  if (current_FadeVal > 255) {
    increasing = false;
    prev_FadeVal -= 5;//undo addition
    current_FadeVal = prev_FadeVal;

  }
  else if (current_FadeVal < 0) {
    increasing = true;
    prev_FadeVal += 5;//unto subtraction
    current_FadeVal = prev_FadeVal;
  }

  prev_FadeVal = current_FadeVal;

  if(current_FadeVal == colorSwitch)
  {
    if (ledMode < 7){
      ledMode++;
    }
    else {
      //start over with Red
      ledMode = 1;
    }
  }
}


Note that each time you press the button, you switch to the next color. Perhaps not the most common use case, but visually more obvious how interrupts address immediate needs.

LED fading in and out, button press immediately changes colors