Andrew Dodd


LED Flash Patterns...for the last time - Part 3

The last post ended just before the real deal…patterns with colours. However, this post is hot on its heals because adding colour support is straightforward…it is entirely controlled by the “application space” code.

That’s right…all of the “Led Manager” stuff can be used unchanged…as can all of the code that changes the states. The only code that needs to be adjusted is the code that registers the patterns. It needs to be updated to:

  • Encode the desired patterns in strings that have colour information
  • Use a driver function that understands how to map these patterns to the various color pins
  • Provide the details of the pins that will control the actual LEDs.

Yeah….prove it

I’m only going to show the parts of the sketch that are different here, but the full INO file can be seen here

The only parts that have actually changed are:

// Constants for our pins
enum {
  RED_PIN = 13,
  GREEN_PIN = 12,
  YELLOW_PIN = 11,

// A type to represent a three-led module, comprised of red, green and yellow LEDs
typedef struct {
  int red;
  int green;
  int yellow;
} tricolour_led_module;

 * Drive the provided pin to the provided pattern element
 * @param color  the pattern element
 * @param arg    a pointer to a tricolour_led_module
int tricolorDrive(char color, void *arg) {
  tricolour_led_module *pin = (tricolour_led_module *)arg;
  if (color == 'R') {
    digitalWrite(pin->red, HIGH);
    digitalWrite(pin->green, LOW);
    digitalWrite(pin->yellow, LOW);
  } else if (color == 'G') {
    digitalWrite(pin->red, LOW);
    digitalWrite(pin->green, HIGH);
    digitalWrite(pin->yellow, LOW);
  } else if (color == 'Y') {
    digitalWrite(pin->red, LOW);
    digitalWrite(pin->green, LOW);
    digitalWrite(pin->yellow, HIGH);
  } else {
    digitalWrite(pin->red, LOW);
    digitalWrite(pin->green, LOW);
    digitalWrite(pin->yellow, LOW);

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

  // We make this static so that is is always in the same memory location, i.e.
  // to is not placed on the stack of the setup() function and then possibly
  // reused by a different function. We could have also placed this as a global
  // outside of this function, but then we might be tempted to refer to it from
  // other functions, like the loop() function
  static tricolour_led_module leds = {
      .red = RED_PIN, .green = GREEN_PIN, .yellow = YELLOW_PIN};
  // Register the patterns against the states
  LedMgr_addPattern(FOUR_TO_THE_FLOOR, "R__G--G--G--", tricolorDrive, &leds);
  LedMgr_addPattern(SWUNG_BEAT,        "RRR   R   G ", tricolorDrive, &leds);
  LedMgr_addPattern(THREE_FOUR,        "R---G---Y---", tricolorDrive, &leds);

  // Setup Timer1 to create an 8Hz ISR trigger (if CPU Freq is 16 MHz)
  noInterrupts(); // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = TIMER_PRELOAD_VALUE; // preload timer
  TIMSK1 |= (1 << TOIE1); // enable timer overflow interrupt ISR
  interrupts();           // enable all interrupts

All of the changes are directly related to the change to represent colour and handle colour in the patterns.

Seeing it running

Loading in the sketch and setting up the hardware to put three different LEDS (actual colours optional) on pins 13, 12, and 11 should demonstrate clearly what is going on.

The breadboard setup

I have three different coloured LEDs - red, green and yellow - hooked up simply to pins 13, 12, and 11 of my Arduino.

Something sort of like this:

|   Arduino     |
|           GND +---------------------+
|               |                     |
|           13  +--------> Red >------+
|               |                     |
|           12  +-------> Green >-----+
|               |                     |
|           11  +-------> Yellow >----+
|               |
|               |
|               |

Such that when pin 13 is HIGH, the current will flow through the Red LED and back to the ground pin, causing the red light to show.

And you might see something like this video. Neat eh!