Animating LEDs

Hi all

About to start programming my project and I have some questions before I get started.

I'm wanting to create about 4 or 5 different animation cycles that forever loop one after the other. However, if a button is pressed I need the animation to skip directly to the next one in line, or even randomly if that's possible (basically visually acknowledges that the button was pressed by starting the next animation). Do multiple "loops" need to be created or can this all exist inside 1? My animations are essentially small loops anyway, so they're loops inside loops.

I would also like to have only one value I need to change in the entire sketch to change the timing/pace of each animation. Is this something I can define at the start of the sketch?

Do multiple "loops" need to be created or can this all exist inside 1?

There will only be one loop() function if that is what you mean. Which code is executed inside loop() will be determined by the value of a state variable. Do not use a for loop for the animation or delay() for timing.

Use loop() to do the looping and millis() for timing and switch/case to control which animation is currently being run. Read the input each time through loop() and you can change the state variable to move to the next state.

I would also like to have only one value I need to change in the entire sketch to change the timing/pace of each animation. Is this something I can define at the start of the sketch?

Yes, but you could also change it using a couple of inputs for faster/slower

Read the post Multiple things at the same time

@UKHeliBob - thank you sir!

@blh64 - many thanks for the post link! I will play with this example prior to getting too deep into my own project.

Cheers

Hi guys

I feel I need to ask for more help with getting this going. I've reviewed the example sketches and the 'SeveralThingsAtTheSameTime' sketch and I understand how they're set up. I'm struggling to understand how to:

  1. code 4 or 5 different animations, each with their own timings.
  2. make each animation "loop" three times before advancing to the next one.

I know it's a matter of storing which animation is "active" and which iteration of it is happening - it's just laying out the code which is where I'm struggling.

I have created a basic sketch using digitalWrite() and delay() and it works well, so I know my schematic is working, but the code is long I know it's not practical for what I'm trying to achieve.

Moving forward, I'm essentially re-creating this design to give you an idea. There's 7 LED groups which animate, loop, etc. If the button isn't pushed the animations play one after the other. Pushing the button forces the next animation in the sequence to start. At this point I haven't implemented the button. I just want to create a few animations and go from there. I'm hoping someone can help me hone in on this a little better.

This is what I have so far with defining my constants:

const int groupOne = 2; // outer red LED ring
const int groupTwo = 3;
const int groupThree = 4;
const int groupFour = 5;
const int groupFive = 6;
const int groupSix = 7;
const int groupSeven = 8;
const int pushBtn = 9; // for implementation of button further down the line

const int pushBtnInterval = 300 // future

In here I would've thought to add the duration and intervals for the animations, but as each animation "group" has a few different timings, so I'm not too sure.

byte groupOneState = LOW; // record if the group is on or off
byte groupTwoState = LOW;
byte groupThreeState = LOW;
byte groupFourState = LOW;
byte groupFiveState = LOW;
byte groupSixState = LOW;
byte groupSevenState = LOW;

unsigned long currentMillis = 0;

Here again I would've thought to add the variables for timing using 'unsigned long' - but again each animation is different...

void setup () {

  pinMode(groupOne, OUTPUT);
  pinMode(groupTwo, OUTPUT);
  pinMode(groupThree, OUTPUT);
  pinMode(groupFour, OUTPUT);
  pinMode(groupFive, OUTPUT);
  pinMode(groupSix, OUTPUT);
  pinMode(groupSeven, OUTPUT);
}

void loop() {
  currentMillis = millis();
  
  readButton();
  updategroupOneState();
  updategroupTwoState();
  updategroupThreeState();
  updategroupFourState();
  updategroupFiveState();
  updategroupSixState();
  updategroupSevenState();

  switchLEDS();
}

Getting into the loop section is where I get confused.

void switchLEDS() {

  digitalWrite(groupOne, groupOneState);
  digitalWrite(groupTwo, groupTwoState);
  digitalWrite(groupThree, groupThreeState);
  digitalWrite(groupFour, groupFourState);
  digitalWrite(groupFive, groupFiveState);
  digitalWrite(groupSix, groupSixState);
  digitalWrite(groupSeven, groupSevenState);
}

Should each "animation" be defined under loop() as

AnimateOne();
AnimateTwo();
...

and then create the animation and timing preferences under that state?

In the video you'll see once he pushes the button the outer red ring (groupOne) illuminates and then groups three - seven light up in sequence and loop several times until the next one begins. groupTwo is the center 5 LEDs which aren't illuminated in the first animation.

If someone would be kind enough to help me code the first animation loop I think I'll have a solid starting point for getting the rest going.

Cheers

A couple of things.

  1. If you install the FastLED library, they have a DemoReel100 example that shows how they sequence through multiple patterns on the LEDs. It could get you pointed in the right direction.

  2. Think of the code as a state machine (there are actually finite state machine libraries available). Every time through loop() you check the current state and call the appropriate function for the current animation.

This pseudo code is the basic framework for a state machine

const int maxAnnimations = 2;
int currentAnnimation;
int currentIteration;
unsigned long currentTime;

void loop()
{
  currentTime = millis();

  // check for button push
  buttonState = digitalRead( pushBtn );
  if ( buttonState != lastButtonState ) {
    lastButtonState = buttonState;
    if (buttonState == LOW ) {
      beginAnnimation( (currentAnnimation + 1) % maxAnnimations );
    }
  }
  updateAnnimation( currentAnnimation );
}


void beginAnnimation( int which ) {

  currentAnnimation = which;
  currentIteration = 0;

  switch ( which ) {
    case 0:
      iterationLimit = 3;
      delayInterval = 1000;
      startTime = millis();
      // toggle your leds however you need to
      break;

    case 1:
      iterationLimit = 2;
      delayInterval = 100;
      startTime = millis();
      // toggle your leds however you need to
      break;

    case 2:
      iterationLimit = 30;
      delayInterval = 10000;
      startTime = millis();
      // toggle your leds however you need to
      break;

    default:
      Serial.print( "Bad Annimation number" );
      while (1);
  }
}

void updateAnnimation( int which ) {

  switch ( which ) {
    case 0:
      if ( currentTime - startTime >= delayInterval ) {
        // time to udpate the sequence and/or change the pattern
        // toggle your leds however you need to
        startTime += delayInterval;
        currentIteration++;
        if ( currentIteration >= iterationLimit ) {
          beginAnnimation( 1 );
        }
      }
      break;

    case 1:
      if ( currentTime - startTime >= delayInterval ) {
        // time to udpate the sequence and/or change the pattern
        // toggle your leds however you need to
        startTime += delayInterval;
        currentIteration++;
        if ( currentIteration >= iterationLimit ) {
          beginAnnimation( 2 );
        }
      }
      break;

    case 2:
      if ( currentTime - startTime >= delayInterval ) {
        // time to udpate the sequence and/or change the pattern
        // toggle your leds however you need to
        startTime += delayInterval;
        currentIteration++;
        if ( currentIteration >= iterationLimit ) {
          beginAnnimation( 0 );
        }
      }
      break;

    default:
      Serial.print( "Bad Annimation number" );
      while (1);
  }

}

If you need more complications and/or fancier patterns, you can have sub-states within each animation

@blh64 - such a huge help. Thank you. After posting yesterday I spent a few hours playing with states and eventually got something working, but I was finding it hard avoiding delays and for loops. One solution would basically crush the next.

I’m going to play with your pseudo code and see what I can work with off that. Thanks again!

Ok, hit a small brick wall. When it comes to just toggling my LEDs in your state machine example I'm not quite sure how I would go about managing such a wide variety of timing functions within one case statement. The variety of these timings more or less create the animation.

In the code below I've used delay() to better demonstrate what it is I'm trying to do.

void setAnimation() {

switch(currentAnimation) {

  case 1:

  for (int iteration = 1; iteration < 5; iteration++) {

  digitalWrite(groupOne, HIGH);
  digitalWrite(groupTwo, LOW);
  digitalWrite(groupThree, HIGH);
  delay(700);
  digitalWrite(groupThree, LOW);
  delay(90);
  digitalWrite(groupFive, HIGH);
  delay(90);
  digitalWrite(groupFour, HIGH);
  delay(50);
  digitalWrite(groupFive, LOW);
  delay(90);
  digitalWrite(groupFour, LOW);
  delay(50);
  digitalWrite(groupSix, HIGH);
  delay(90);
  digitalWrite(groupSeven, HIGH);
  delay(90);
  digitalWrite(groupSix, LOW);
  delay(700);
  digitalWrite(groupSeven, LOW);
  delay(90);
  digitalWrite(groupSix, HIGH);
  delay(90);
  digitalWrite(groupFour, HIGH);
  delay(90);
  digitalWrite(groupSix, LOW);
  delay(90);
  digitalWrite(groupFour, LOW);
  delay(90);
  digitalWrite(groupFive, HIGH);
  delay(90);
  digitalWrite(groupThree, HIGH);
  delay(90);
  digitalWrite(groupFive, LOW);
  delay(90);
  digitalWrite(groupThree, LOW);
  digitalWrite(groupOne, LOW);
  digitalWrite(groupTwo, LOW);
  }
  
  break;
...

I mentioned you may need sub-steps within an animation sequence. This is how you would code up your first sequence.

void beginAnimation( int which ) {

  currentAnnimation = which;
  switch (which) {

    case 1:
      iteration = 0;
      digitalWrite(groupOne, HIGH);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, HIGH);
      interval = 700;
      startTime = currentTime;
      sequenceStep = 1;
      break;
  }
}

void updateAnimation() {
  switch (currentAnnimation) {
    case 1:
      if ( currentTime - startTime >= interval ) {
        sequenceStep++;
        startTime = currentTime;
        switch ( sequenceStep ) {
          case 1:
            digitalWrite(groupOne, HIGH);
            digitalWrite(groupTwo, LOW);
            digitalWrite(groupThree, HIGH);
            interval = 700;
            break;
          case 2:
            digitalWrite(groupThree, LOW);
            interval = 90;
            break;
          case 3:
            digitalWrite(groupFive, HIGH);
            interval = 90;
            break;
          case 4;
            digitalWrite(groupFour, HIGH);
            interval = 50;
            break
          case 5:
            digitalWrite(groupFive, LOW);
            interval = 90;
            break;
          case 6:
            digitalWrite(groupFour, LOW);
            interval = 50;
            break;
          case == 7:
            digitalWrite(groupSix, HIGH);
            interval = 90;
            break;
          case 8:
            digitalWrite(groupSeven, HIGH);
            interval = 90;
            break;
          case 9:
            digitalWrite(groupSix, LOW);
            interval = 700;
            break;
          case 10:
            digitalWrite(groupSeven, LOW);
            interval = 90;
            break;
          case 11:
            digitalWrite(groupSix, HIGH);
            interval = 90;
            break;
          case 12:
            digitalWrite(groupFour, HIGH);
            interval = 90;
          case 13:
            digitalWrite(groupSix, LOW);
            interval = 90;
          case 14:
            digitalWrite(groupFour, LOW);
            interval = 90;
            break;
          case 15:
            digitalWrite(groupFive, HIGH);
            interval = 90;
            break;
          case 16:
            digitalWrite(groupThree, HIGH);
            interval = 90;
            break;
          case 17:
            digitalWrite(groupFive, LOW);
            interval = 90;
            break;
          case 18:
            // final step, see if we need to iterate any more
            digitalWrite(groupThree, LOW);
            digitalWrite(groupOne, LOW);
            digitalWrite(groupTwo, LOW);
            iteration++;
            if ( iteration >= 5 ) {
              beginAnnimation( (currentAnnimation + 1) % maxAnnimations);
            } else {
              sequenceStep = 1;
            }
            break;
        }
      }
  }
}

@blh64 - thank you for your help!

Question - what is the purpose of running the updateAnimation() function? Can't the code all go under the beginAnimation()? Not arguing your logic, just wondering.

Anyway, this is what I have so far. The code runs fine for the first two groups of animations. Then with animation groups three and four the code goes wacky and stops. I've pasted the serial monitor results starting from group 3 below the code. I can't find what I have done wrong.

Because of forum limitations I've removed group one and two code and replaced with "..."

const int groupOne = 2; // outer red LED ring
const int groupTwo = 3; //green eye center
const int groupThree = 4; //left SMALL blue circle
const int groupFour = 5; //large CENTER blue circle
const int groupFive = 6; //left MED blue circle
const int groupSix = 7; //right med blue circle
const int groupSeven = 8; //right small blue circle
const int pushBtn = 9;

const int maxAnimations = 5;
const int pushBtnInterval = 300;

int buttonState;
int lastButtonState;
int currentAnimation;
int currentIteration;
int iterationLimit;
int iteration;
int interval;
int sequenceStep;

//int var = 1;

unsigned long currentTime;
unsigned long startTime;
unsigned long delayInterval;
long unsigned int millis();

//==================


void setup () {

  Serial.begin(9600);
  Serial.println("Doorbell.ino");

  pinMode(groupOne, OUTPUT);
  pinMode(groupTwo, OUTPUT);
  pinMode(groupThree, OUTPUT);
  pinMode(groupFour, OUTPUT);
  pinMode(groupFive, OUTPUT);
  pinMode(groupSix, OUTPUT);
  pinMode(groupSeven, OUTPUT);
  pinMode(pushBtn, INPUT);

}

//==================

void loop() {

  currentTime = millis();

  //check button & reset if necessary
  int buttonState = digitalRead (pushBtn);
  if ( buttonState != lastButtonState ) {
    lastButtonState = buttonState;
    if (buttonState == LOW) {
      beginAnimation( (currentAnimation + 1) % maxAnimations );
      digitalWrite(groupOne, LOW);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, LOW);
      digitalWrite(groupFour, LOW);
      digitalWrite(groupFive, LOW);
      digitalWrite(groupSix, LOW);
      digitalWrite(groupSeven, LOW);
    }
  }
  updateAnimation( currentAnimation );

}

//==================

void beginAnimation( int var ) {

  currentAnimation = var;
  //currentIteration = 0;

  switch (var) {


    ...

    case 3: //ANIMATION GROUP 3
      Serial.println("loop three");
      iteration = 3;
      digitalWrite(groupOne, LOW);
      interval = 90;
      startTime = currentTime;
      sequenceStep = 3;

      break;

    case 4: //ANIMATION GROUP 4
      Serial.println("loop four");
      iteration = 4;
      digitalWrite(groupOne, LOW);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, HIGH);
      digitalWrite(groupSeven, HIGH);
      interval = 50;
      startTime = currentTime;
      sequenceStep = 4;

      break;
  }
}

//======================

void updateAnimation( int var ) {

  switch (currentAnimation) {

    ...

    case 3:
      Serial.println("loop three update");
      if (currentTime - startTime >= interval ) {
        sequenceStep++;
        startTime = currentTime;
        switch ( sequenceStep ) {
          case 1:
            digitalWrite(groupFour, HIGH);
            interval = 200;
            Serial.println("loop three update 1");

            break;

          case 2:
            digitalWrite(groupOne, LOW);
            interval = 1000;
            Serial.println("loop three update 2");

            break;

          case 3:
            digitalWrite(groupTwo, HIGH);
            interval = 1000;
            Serial.println("loop three update 3");

            break;

          case 4:
            digitalWrite(groupFour, LOW);
            digitalWrite(groupOne, HIGH);
            Serial.println("loop three update 4");
            interval = 5000;
            iteration++;
            if ( iteration >= 1) {
              beginAnimation( (currentAnimation + 1) % maxAnimations);
            } else {
              sequenceStep = 1;
            }
            break;
        }
      }

      break;

    case 4:
    Serial.println("loop four update");
      if (currentTime - startTime >= interval ) {
        sequenceStep++;
        startTime = currentTime;
        switch ( sequenceStep ) {
          case 1:
            digitalWrite(groupOne, LOW);
            digitalWrite(groupTwo, LOW);
            digitalWrite(groupThree, HIGH);
            digitalWrite(groupSeven, HIGH);
            interval = 500;
            Serial.println("loop four update 1");

            break;

          case 2:
            digitalWrite(groupThree, LOW);
            digitalWrite(groupSeven, LOW);
            interval = 500;
            Serial.println("loop four update 2");

            break;

          case 3:
            digitalWrite(groupFive, HIGH);
            digitalWrite(groupSix, HIGH);
            interval = 1000;
            Serial.println("loop four update 3");

            break;

          case 4:
            digitalWrite(groupFive, LOW);
            digitalWrite(groupSix, LOW);
            interval = 1000;
            Serial.println("loop four update 4");

            break;

          case 5:
            digitalWrite(groupFour, HIGH);
            digitalWrite(groupTwo, LOW);
            interval = 300;
            Serial.println("loop four update 5");

            break;

          case 6:
            digitalWrite(groupFour, LOW);
            digitalWrite(groupTwo, LOW);
            interval = 50;
            Serial.println("loop four update 6");

            break;

          case 7:
            digitalWrite(groupFive, HIGH);
            digitalWrite(groupSix, HIGH);
            interval = 100;
            Serial.println("loop four update 7");

            break;

          case 8:
            digitalWrite(groupFive, LOW);
            digitalWrite(groupSix, LOW);
            digitalWrite(groupOne, LOW);
            interval = 150;
            Serial.println("loop four update 8");
            iteration++;
            if ( iteration >= 5) {
              beginAnimation( (currentAnimation + 1) % maxAnimations);
            } else {
              sequenceStep = 1;
            }
            break;
        }
      }
  }
}
loop three
loop three update
loop three update
loop three update
loop three update 4
loop four
loop four update
loop four update 5
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update 6
loop four update
loop four update
loop four update 7
loop four update
loop four update
loop four update
loop four update
loop four update
loop four update 8

whoa hold yer horses. this would be so much easier and organized with arrays.
here is an example so you can see what i'm talking about.

if you use a three dimentional array.
(or an array of arrays of arrays)

the first index can be wich movie you want to play
sencond index is which frame is playing
and the third index is the on/off values of each group for each frame.

then use a loop inside a loop for playback.

and for simplisity i use a loop to set all your pins!!!

run this example scetch!!!!

int pins[6]; 
int f;
bool p [3][4][6]
{
  //movie one
  {
  //frames
  {1,0,1,0,0,0},
  {0,1,0,0,0,0},
  {0,0,0,1,0,0},
  {0,1,0,0,0,0}
  },
  // movie two
  {
  {0,1,0,0,0,0},
  {0,1,0,0,0,0},
  {0,1,0,1,0,0},
  {0,0,0,0,0,0}
    },
  //movie 3
  {    
  {0,0,0,0,0,1},
  {0,1,0,0,0,1},
  {0,0,0,1,0,1},
  {0,0,0,0,0,1}
    } };

void setup() {
  Serial.begin(9600);
 byte i = 6;
 while(i>0){i--;
// sets all 6 of your groups 2 through 8;
 pins [i] = i+2;
 }}
void loop() {
  play(0);
  delay(1000);
    play(1);
  delay(1000);
    play(2);
  delay(2000);
  }
void play(int m) {

   Serial.println("----------playing movie #"+String(m));
  f = 0;
  while(f<4){
    int i = 0;
    while(i<6){
      Serial.print(p[m][f][i]);
      if(p[m][f][i]){
      digitalWrite(pins[i],HIGH);}else{
      digitalWrite(pins[i],LOW); }
    i++;}
     Serial.println("");
     delay(500); f++;}
      

}

@taterking

cheers for the example code.

With the other code I can follow it quite easily. But with yours I'm a little confused about what I'm looking at - could you explain to me whjat the combination of 1's and 0's are doing before the setup()? What is telling pin 2, for example, to turn on?

the pin numbers are stored in an array called "pins" instead of individually typed in

this way when the code gets to the point of setting the actual pins, it just loops those numbers numbers in the "pins" array and sets them all at once according you the ones and zeros at the top.

the multidementional array at the top just holds bools (or true false) values.

it pages through them in order to know how to assign the pins.

ok so let me break it down a bit.

pins holds 6 pin values.

i set them 2 to 8 for you.

if you look at the digitalwrite part of the code, it is inside a loop.

the variable "i" loops from 0 to 5 in a "while" loop. so that loop happens once for each pin.

so that loop hits all the pins in the "pins" array
then uses the matching true/false value in the big array to set each pin.

if you notice the loop that goes through the pins is nested in an outer loop that repeats the inner pin loop for each frame of zeros and ones.

its a loop inside a loop

the loops are started every time you see the "while" operator.

if you are unfimiliar with arrays and loops then you should definatly do some reading!!!!
they are really cool and make many things possible that normally would't be.

with the exeption of typing the zeros and ones at the top, this same code would run hundreds of frames with hundreds of different movies in the same number of lines of code.

each row of zero and one represent if each of your six light group pins are going to be set on or off each frame

Ok, I think I understand. Will def read up on these.

I need to eliminate delay() and be able to control the timing of each array.

In your example I'm only able to animate 6 of the 7 LED groups. In order to add an additional 1 or 0 to each row do I need to define that also in the boolean function?

Thisisliam:
@blh64 - thank you for your help!

Question - what is the purpose of running the updateAnimation() function? Can't the code all go under the beginAnimation()? Not arguing your logic, just wondering.

When you begin a new animation sequence, there are certain things that need to happen, like setting variables to 0, capturing the time, etc.

These activities are different than than when you are in the middle of a given animation where you are doing things like checking elapsed time, adjusting the light pattern, incrementing counters, etc.

Your code seems to mix up iterations with sequenceSteps somewhat. This version is a little cleaner
It separates the function of generally updating the animations from what each animation update is supposed to do.

const int groupOne = 2; // outer red LED ring
const int groupTwo = 3; //green eye center
const int groupThree = 4; //left SMALL blue circle
const int groupFour = 5; //large CENTER blue circle
const int groupFive = 6; //left MED blue circle
const int groupSix = 7; //right med blue circle
const int groupSeven = 8; //right small blue circle
const int pushBtn = 9;

const int maxAnimations = 5;
const int pushBtnInterval = 300;

int buttonState;
int lastButtonState;
int currentAnimation;
//int currentIteration;
//int iterationLimit;
int iteration;
int sequenceStep;

//int var = 1;

unsigned long currentTime;
unsigned long startTime;
//unsigned long delayInterval;
unsigned long interval;
//long unsigned int millis();

//==================


void setup () {

  Serial.begin(9600);
  Serial.println("Doorbell.ino");

  pinMode(groupOne, OUTPUT);
  pinMode(groupTwo, OUTPUT);
  pinMode(groupThree, OUTPUT);
  pinMode(groupFour, OUTPUT);
  pinMode(groupFive, OUTPUT);
  pinMode(groupSix, OUTPUT);
  pinMode(groupSeven, OUTPUT);
  pinMode(pushBtn, INPUT);

}

//==================

void loop() {

  currentTime = millis();

  //check button & reset if necessary
  int buttonState = digitalRead (pushBtn);
  if ( buttonState != lastButtonState ) {
    lastButtonState = buttonState;
    if (buttonState == LOW) {
      beginAnimation( (currentAnimation + 1) % maxAnimations );
      digitalWrite(groupOne, LOW);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, LOW);
      digitalWrite(groupFour, LOW);
      digitalWrite(groupFive, LOW);
      digitalWrite(groupSix, LOW);
      digitalWrite(groupSeven, LOW);
    }
  }
  if (currentTime - startTime >= interval ) {
    sequenceStep++;
    startTime = currentTime;
    updateAnimation( currentAnimation );
  }
}

//==================

void beginAnimation( int var ) {

  currentAnimation = var;
  iteration = 0;
  sequenceStep = 0;

  switch (var) {

      ...

    case 3: //ANIMATION GROUP 3
      Serial.println("loop three");
      //iteration = 3;
      //digitalWrite(groupOne, LOW);
      //interval = 90;
      //startTime = currentTime;
      //sequenceStep = 3;

      break;

    case 4: //ANIMATION GROUP 4
      Serial.println("loop four");
      //iteration = 4;
      //startTime = currentTime;
      //sequenceStep = 4;

      break;
  }
  updateAnimation( currentAnimation );
}

//======================

void updateAnimation( int var ) {

  switch (var) {

      ...

    case 3:
      Serial.println("loop three update");
      annimation3();

      break;

    case 4:
      Serial.println("loop four update");
      annimation4();
  }
}

void annimation3() {
  switch ( sequenceStep ) {
    case 0:
      digitalWrite(groupOne, LOW);
      interval = 90;
      Serial.print("loop three begin, loop ");
      Serial.println(iteration);

      break;

    case 1:
      digitalWrite(groupFour, HIGH);
      interval = 200;
      Serial.println("loop three update 1");

      break;

    case 2:
      digitalWrite(groupOne, LOW);
      interval = 1000;
      Serial.println("loop three update 2");

      break;

    case 3:
      digitalWrite(groupTwo, HIGH);
      interval = 1000;
      Serial.println("loop three update 3");

      break;

    case 4:
      digitalWrite(groupFour, LOW);
      digitalWrite(groupOne, HIGH);
      Serial.println("loop three update 4");
      interval = 5000;

      break;

    case 5:
      // out of range with sequence step so next iteration
      // or begin next annimation sequence

      iteration++;
      if ( iteration >= 1) {
        beginAnimation( (currentAnimation + 1) % maxAnimations);
      } else {
        sequenceStep = -1;
      }
      break;
  }
}

void annimation4() {

  switch ( sequenceStep ) {
    case 0:
      digitalWrite(groupOne, LOW);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, HIGH);
      digitalWrite(groupSeven, HIGH);
      interval = 50;
      Serial.print("loop four begin, loop ");
      Serial.println(iteration);

      break;

    case 1:
      digitalWrite(groupOne, LOW);
      digitalWrite(groupTwo, LOW);
      digitalWrite(groupThree, HIGH);
      digitalWrite(groupSeven, HIGH);
      interval = 500;
      Serial.println("loop four update 1");

      break;

    case 2:
      digitalWrite(groupThree, LOW);
      digitalWrite(groupSeven, LOW);
      interval = 500;
      Serial.println("loop four update 2");

      break;

    case 3:
      digitalWrite(groupFive, HIGH);
      digitalWrite(groupSix, HIGH);
      interval = 1000;
      Serial.println("loop four update 3");

      break;

    case 4:
      digitalWrite(groupFive, LOW);
      digitalWrite(groupSix, LOW);
      interval = 1000;
      Serial.println("loop four update 4");

      break;

    case 5:
      digitalWrite(groupFour, HIGH);
      digitalWrite(groupTwo, LOW);
      interval = 300;
      Serial.println("loop four update 5");

      break;

    case 6:
      digitalWrite(groupFour, LOW);
      digitalWrite(groupTwo, LOW);
      interval = 50;
      Serial.println("loop four update 6");

      break;

    case 7:
      digitalWrite(groupFive, HIGH);
      digitalWrite(groupSix, HIGH);
      interval = 100;
      Serial.println("loop four update 7");

      break;

    case 8:
      digitalWrite(groupFive, LOW);
      digitalWrite(groupSix, LOW);
      digitalWrite(groupOne, LOW);
      interval = 150;
      Serial.println("loop four update 8");

      break;


    case 9:
      // out of range with sequence step so next iteration
      // or begin next annimation sequence

      iteration++;
      if ( iteration >= 5) {
        beginAnimation( (currentAnimation + 1) % maxAnimations);
      } else {
        sequenceStep = -1;
      }
      break;
  }