Blinky Belt Software

The Blinky Belt is pretty cool. Lots of LEDs that you can sequence. But I like a bit of variety, so I connected a couple of switches up to the controller to allow me to select from a number of patterns.

This is especially great, since you don’t have to hook up to your computer to download new patterns whenever you want a change. Just poke a few buttons and select the pattern you want to switch to.

I thought of a few types of patterns that would be interesting.

  1. Normal on-off blink – like a movie marquee. Every other, every third, chase, rainbow.
  2. Random pattern – random number generator, floating sensor pin, etc.
  3. Fixed pattern – a set of belt patterns that are presented in timed sequence.
  4. Parametric Pattern – code to generate the LED color values depending on time and position – sine wave, etc.
  5. Feedback Pattern – reactive patterns to environmental inputs.

Most of the functionality to cause the belt to blink is the same for all of these, we just have to have a way to specify which LED gets what color, when.

The Pattern class has evolved as I worked on this software. Here is the current definition:

class Pattern {
  public:
    int cycleMax;  // maximum iteration value for a cycle
    int cycleCur;  // current iteration
    int cycleMin;  // minimum iteration value for a cycle
    int dir;       // direction of increment for a cycle ( 1 or -1 )
    int delayMS;   // minimum delay between iterations

    // constructors
    Pattern(HL1606strip *inStrip);
    Pattern(HL1606strip *inStrip, int cycleMin, int cycleMax, int dir, int delayMS);

    void cycle();               // called once per loop() cycle
    virtual void display();     // sets the LEDs for the current iteration
    virtual void reset();       // back to the start of the cycle
    virtual int isDone();       // is curent cycle done?

    HL1606strip *strip;
};

This is sub-classed for the different pattern types. Currently, cycle(), reset() and isDone() is the same for all, but I can imagine the need for variation there.

The basic Pattern just sets an LED matching the current iteration. So for iteration 1, LED 1 is lit. For iteration 15, LED 15 is lit.

Each of the subclasses optionally has an additional variation parameter to allow creation of a kind of instance of that pattern.

PatternFixed::PatternFixed(HL1606strip *inStrip, int variation);

In the setup() routine, I create the set of patterns I want to load up, in what order. Pressing the up/down selector buttons cycles through this list of patterns. Multiple instances of each pattern can be created.

void setup() {
  patterns[0] = new PatternFixed(&strip, 2);
  patterns[1] = new PatternRandom(&strip, 1);
  patterns[2] = new PatternRandom(&strip, 2);
  patterns[3] = new PatternFixed(&strip, 0);
  patterns[4] = new PatternFixed(&strip, 1);
  patterns[5] = new PatternRandom(&strip, 0);
  patterns[6] = new PatternParametric(&strip, 0);
  patterns[7] = new PatternParametric(&strip, 1);
  cur = patterns[currentPattern];
}

The Random Pattern has a few variations. Once randomly chooses a color for each LED. Another reads a floating analog input pin. Another variation introduces more dark pixels for a blinkier effect.

The Fixed Pattern is pretty simple. It just iterates through an array of values, setting all of the LEDs to match a specified row.

int bpattern[][32] = {
 { R, B, R, B,  R, B, R, B,  R, B, R, B,  R, B, R, B,   R, B, R, B,  R, B, R, B,  R, B, R, B,  R, B, R, B },
 { B, R, B, R,  B, R, B, R,  B, R, B, R,  B, R, B, R,   B, R, B, R,  B, R, B, R,  B, R, B, R,  B, R, B, R }
};

int cpattern[][32] = {
  { R, B, B, R,  B, B, R, B,  B, R, B, B,  R, B, B, R,   B, B, R, B,  B, R, B, B,  R, B, B, R,  B, B, R, B },
  { B, R, B, B,  R, B, B, R,  B, B, R, B,  B, R, B, B,   R, B, B, R,  B, B, R, B,  B, R, B, B,  R, B, B, R },
  { B, B, R, B,  B, R, B, B,  R, B, B, R,  B, B, R, B,   B, R, B, B,  R, B, B, R,  B, B, R, B,  B, R, B, B }
};

The b pattern here cycles Red and Black. The c pattern cycles Red, Black, Black. Arbitrarily complex patterns can be specified by array. The display routine just selects the row based on the cycle iteration, then sets the LEDs as the array row specifies. For the next iteration, the next row gets displayed.

The Parametric Pattern is kinda fun. A function can be written to take the inputs (iteration cycle, time, LED position) and generate the proper color. This can be used to display mathematical functions (ie. sine wave) or animations (1 pixel high!)

#define SINE_HEIGHT  31

#define A (SINE_HEIGHT/2)               // we want 16 levels
#define P ((2 * PI) / BELT_LENGTH)      // divided by 32 (BELT_LENGTH) pixels
      for (i=0; i<BELT_LENGTH; i++) {
        y = A * sin(i * P) + A;
        if ((int)y == cycleCur)         // if the calculated y value is the same as our iteration, display
          strip->setLEDcolor(i, FG_COLOR);
        else
          strip->setLEDcolor(i, BG_COLOR);
      }

The Feedback Pattern hasn’t been implemented yet. I expect to add a microphone, thermistor, and perhaps an accelerometer to make a wearable VU meter, thermometer, and colorful dance partner.

 

This entry was posted in Arduino, Build, Software. Bookmark the permalink.

Leave a Reply