Fun with Arduino 24 Neopixel Sequencer with Flexible Timing and Colors

In video 23 we made a step sequencer for addressable LEDs (Neopixel). The beauty of it is that a LED on/off sequence is created in a visual way by editing a series of ‘1’s and ‘0’s: 1,1,1,1,0,0,0,0,1,1,0,0,1,1,0,0.

The drawback of that sequencer is though that the color of every LED is fixed and also the interval time is fixed.

fotoThe sequencer in this video overcomes both issues … there is full flexibility with every action step, both for timing and for LED color / brightness. We specify the exact millisecond when we want an action to take place. The action is to switch a certain LED to a certain color / brightness.

Sounds like a structure that holds the following data: LED number, R value, G value, B value, time, is what we need. This is the code for one LED, switched on full white (RGB all 255) for 300 ms, then off (RGB all 0) for 1000 ms.

struct LRGBT { // LRGBT is short name for LED, Red, Green, Blue, Time
  byte led, R, G, B; 
  unsigned long steptime;
};
LRGBT seq[NUMSTEPS] = {
  0, 255, 255, 255,  300,
  0,   0,   0,   0, 1000
};

The beauty is we can add as many LEDs, with colors and action times, as we like by just adding more lines to the structure. We can also switch the same LED on/off multiple times in a sequence, with different colors … something that was impossible with the previous sequencer.

Read on below the video …

 

The code for a sequencer with complete flexible timing and color / brightness is quite small (also because this time I left out an on/off switch or any other trigger with a State Transition Diagram):

#define NUMSTEPS   8 // number of steps in the sequence
#define NUMLEDS    8 // number of LEDs in the Neopixel string
#define LEDS_PIN   5 // output pin to neopixel data line

byte stp; // step counter ('stp' because 'step' is a reserved word)
unsigned long time_for_action;

struct LRGBT {
  byte led, R, G, B; 
  unsigned long steptime;
};
LRGBT seq[NUMSTEPS] = {
// the number of lines here has to equal NUMSTEPS
// led, R,  G,  B, interval time [ms]
    0, 12,  9,  3,  789,
    4,  6,  9,  5, 1111,
    2, 12,  12, 0, 1254,
    6,  9,  6,  9, 1500,
    2,  0,  0,  0,  666,
    4,  0,  0,  0,  800,
    0,  0,  0,  0,  955,
    6,  1,  1,  0, 2222
};

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(NUMLEDS, LEDS_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  neopixel.begin();
  for(byte led=0; led<NUMLEDS; led++)
    neopixel.setPixelColor(led, 0, 0, 0);
  neopixel.show();
}

void loop() {
  if (millis() > time_for_action) {
    neopixel.setPixelColor(seq[stp].led, seq[stp].R, seq[stp].G, seq[stp].B);
    neopixel.show();
    time_for_action = millis() + seq[stp].steptime;
    stp = (stp + 1) % NUMSTEPS;
  }
}

A very small code actually … and … it works fine.

With this sequencer we got rid of the rigid interval time of the previous video 23. Still, to make our village even more realistic we could add some randomness. This is easily accomplished … in the line where we load the next ‘time_for_action’ we can add a random number:

time_for_action = millis() + (unsigned long)seq[stp].steptime + random(MIN, MAX);

The complete code for a sequencer with randomness added:

#define NUMSTEPS      8 // number of steps in the sequence
#define NUMLEDS       8 // number of LEDs in the Neopixel string
#define LEDS_PIN      5 // output pin to neopixel data line
#define MIN         100 // minimum random time to add
#define MAX        1500 // maximum random time to add

byte stp; // step counter ('stp' because 'step' is a reserved word)
unsigned long time_for_action;

struct LRGBT {
  byte led, R, G, B; 
  unsigned long steptime;
};
LRGBT seq[NUMSTEPS] = {
// the number of lines here has to equal NUMSTEPS
// led, R,  G,  B, interval time [ms]
    0, 12,  9,  3, 0,
    4,  6,  9,  5, 0,
    2, 12,  12, 0, 0,
    6,  9,  6,  9, 1500,
    2,  0,  0,  0, 0,
    4,  0,  0,  0, 0,
    0,  0,  0,  0, 0,
    6,  1,  1,  0, 2000
};

#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel neopixel = Adafruit_NeoPixel(NUMLEDS, LEDS_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  neopixel.begin();
  for(byte led=0; led<NUMLEDS; led++)
    neopixel.setPixelColor(led, 0, 0, 0);
  neopixel.show();
}

void loop() {
  if (millis() > time_for_action) {
    neopixel.setPixelColor(seq[stp].led, seq[stp].R, seq[stp].G, seq[stp].B);
    neopixel.show();
    time_for_action = millis() + (unsigned long)seq[stp].steptime + random(MIN, MAX);
    stp = (stp + 1) % NUMSTEPS;
  }
}

Rotary_EncoderTesting 123  … yes, works nice.

Enough talk about LED sequencers … on to something new! In the next video we are going to have a look at a ‘rotary encoder’. They are incredibly cheap, about €0,50 a piece, and they are great with all kinds of applications where a value has to be adjusted, like a LED brightness, or a servo angle. We are going to build a ‘servo tune’ application with it.

2 thoughts on “Fun with Arduino 24 Neopixel Sequencer with Flexible Timing and Colors

Leave a comment