Glitch and the LED Sneakers – Final Code

I had a couple of sets of changes I needed to make to my test code.

Firstly I needed the ability to change the effects mode using the button. I originally added this by testing to see if the button was down, incrementing a global variable that I used for the mode, a switch statement to divert program flow depending on the current mode value and different functions for each effects mode. The effect was pretty to look at but the code was even worse than the previous test: overly long and the patterns were defined by the actual program logic – meaning that more program code would have to be written in order to add more patterns and the code to control 8 LEDs would be twice as long. You can see that particular iteration here:

When I was trying to come up with a clever design for storing the LED patterns, I kept wanting to use objects… it was very hard to constrain myself to simple procedural C!

I chose to do a lot of work with arrays. To start with, I could put the pins used by the LEDs into an array:

 int ledPins[] = { 5, 6, 7, 8, 9, 10, 11, 12 };

and then reset them all in setup() like this:

for (int pin = 0 ; pin < numLeds ; pin++) {
  pinMode(ledPins[pin], OUTPUT);
  digitalWrite(ledPins[pin], LOW);

And I put the effects modes into an array. The first design looked like this:

int pattern[][5] = { { 100, OFF, OFF, OFF, OFF},
                     { 200,  ON, OFF, OFF, OFF},
                     { 200,  ON,  ON, OFF, OFF},
                     { 200,  ON,  ON,  ON, OFF},
                     { 500,  ON,  ON,  ON,  ON},
                     { 200, OFF,  ON,  ON,  ON},
                     { 200, OFF, OFF,  ON,  ON},
                     { 200, OFF, OFF, OFF,  ON},
                     { 400, OFF, OFF, OFF, OFF}};

with the first parameter being the number of milliseconds to hold a specific display. You can see a version of code that uses that array format here:

Then I realized I could use binary for the individual on/off LEDs (which scaled very easily for the 8 LEDs I needed) plus I needed a way to store the different effects modes. So I ended up with an array structure like this:

 int pattern[][3] = { { 0,9000, B00000000},  // mode 0: Everything off
                      { 1,  80, B10000000},  // mode 1: 2 LEDs run down the length of the line
                      { 1,  80, B11000000},
                      { 1,  80, B01100000},
                      { 1,  80, B00110000},
                      { 1,  80, B00010000},
                      { 1,  80, B00001000},
                      { 1,  80, B00001100},
                      { 1,  80, B00000110},
                      { 1,  80, B00000011},
                      { 1,  80, B00000001},
                      { 2, 150, B10001000},  // mode 2: 1 LED runs down the length of the line
                      { 2, 150, B01000100},
                      { 2, 150, B00100010},
                      { 2, 150, B00010001},
                      { 2, 150, B00100010},
                      { 2, 150, B01000100}};

Here the first parameter of each row is the effects mode that this line refers to, the second parameter is the length of time to hold that display and the third parameter is a binary bit-field for the 8 LEDs. Now any time I want to add a new effects mode it’s as simple as adding new lines to the array – no new program logic required. The program code steps through the array after each timing period looking for the next line that applies to the current effects mode and, if it reaches the end of the array, loops back to the start.

I was able to decouple the program logic from the size of the arrays by having the program work out the array sizes for itself in setup():

    numSteps = sizeof(pattern)/sizeof(pattern[0]);
    numLeds = sizeof(ledPins)/sizeof(ledPins[0]);

Again, in an OO language I’d have just used foreach to step through the arrays, but here I had to work without that luxury.

At one point I had the button generating an interrupt to increment the effects mode. But, as I was wiring up the hardware, I thought “it’s damn awkward having this button floating around… I wish there was some way I could use the button that’s already on the Lilypad board”. That button’s the reset button… so obviously I couldn’t do that because everything’s erased when the board’s reset. Hmmm… except the microcontroller has some EEPROM for storage that isn’t erased on reset. So I changed the code to store the effects mode in the EEPROM and increment the mode each time it resets. Then I didn’t need the separate button at all – every time the reset button’s pressed the Lilypad starts up in the next sequential effects mode. This had another major benefit: if the board reset itself (and I was initially fearing possible power-drain related resets for modes that illuminated too many LEDs at the same time) then when it restarted it would magically skip over the problematic mode.

The only other oddity in the code was how to deal with detecting when we’d stepped through all the available effects modes and had to set the mode back down to zero. In hindsight, I probably should have run through the pattern array in setup() to determine the highest mode value and then compared against that whenever I incremented the current mode. What I actually did was: when I was about to go hunting for the next line that referred to the current pattern, the code memorizes where in the pattern array it’s starting its search and then if it steps all the way around and back to the same line without finding a match, that means the mode variable is now too high and has to be set back to zero. So my “find the next matching pattern line” code looks like:

int startStep = currentStep; // Remember where we started from in the pattern array
// Loop through the array looking for the next pattern line that matches our
// current effects mode
while (true) {
  currentStep++; // move to next step
  if (currentStep >= numSteps) currentStep=0; // at end of array, loop back to start
  if (pattern[currentStep][0] == modeGet()) break; // this pattern line applies to this mode, so use it
  if (currentStep == startStep) { // if been all the way around, we have nothing for this mode
    modeSet(0); // so reset the mode back to the first mode
    currentStep = -1; // and start searching from the beginning of the pattern array
    Serial.println("Looped around - clearing mode");

The full and final code can be seen here:

Comments are closed to reduce the spam. If you'd like to add something, please use the contact form to let me know and I'll reopen comments for you. Thanks