Using a Button to Control LED Animation

Hello Everyone!

I'm new to the forums and fairly new to Arduino so thank you in advance for any help

I've made a top hat with 86 leds on it. I have 3 animations that I have made, and at the moment they are looping. Instead of looping them, I would like to place a small button on the brim of the hat to select the desired animation.

So far I know I'll need a momentary button and then detect a state change. I know how to create an action based on that, according to the tutorial at:

But I'm having trouble wrapping my head around the code needed to create the action that will rotate between each animation. Ideas?

You need to post your current code or we have no idea what is possible with your current setup.

Make each animation a function then use Switch Case to select each one with a button press.

To make the code shorter put each LED animation sequence in an array that can used by the functions.

Lakes:
Make each animation a function then use Switch Case to select each one with a button press.

To make the code shorter put each LED animation sequence in an array that can used by the functions.

This was what I wanted, Thanks!

I'll post the code in a little bit when it's completed.

OK, got it in, but it isn't really working. The first button press works, but then it wants to play the animation and not detect the button presses. I tried to do an interrupt for the button, but to no avail. What am I doing wrong here? Sorry, the code is so messy, I've tried about 100 things:

#include <LEDPixels.h>

////Example to control RGB LED Modules with Spectrum Analyzer
//Bliptronics.com
//Ben Moyes 2010
//Use this as you wish, but please give credit, or at least buy some of my LEDs!


LEDPixels LP;  //LEDPixels library
   
//For spectrum analyzer shield, these three pins are used.
//You can move pinds 4 and 5, but you must cut the trace on the shield and re-route from the 2 jumpers. 
int spectrumReset = 5;
int spectrumStrobe = 4;
int spectrumAnalog = 0;  //0 for left channel, 1 for right.

const int spectrumPower = 10;  //pin used to power the spectrum analyzer on/off

const int buttonPower = 7;  //pin used to power the button on/off
const int buttonPin = 6;  //button read pin
int buttonPushCounter = 0;  // counter for the number of button presses
int buttonState = 0;  // current state of the button
int lastButtonState = 0;  // previous state of the button

//This holds the 15 bit RGB values for each LED.
//You'll need one for each LED, we're using 25 LEDs here.
//Note you've only got limited memory, so you can only control 
//Several hundred LEDs on a normal arduino. Double that on a Duemilanove.

const int ledCount = 92;
int MyDisplay[ledCount];

byte bgColor[] = {0, 0, 31};

const int gridWidth = 23;
const int gridHeight = 4;

const int updateDelay = 30;

// Spectrum analyzer read values will be kept here.
int Spectrum[1];

int xx;
int yy;

void setup() {
  
  attachInterrupt(1, increment, RISING);
  Serial.begin(9600);
  
  /*___ Power ___*/
  pinMode(spectrumPower, OUTPUT);  //Makes spectrum shield power an output pin
  digitalWrite(spectrumPower, HIGH);  //Turns the spectrum shield on
  
  pinMode(buttonPower, OUTPUT);  //Makes button power an output pin
  digitalWrite(buttonPower, HIGH);  //Brings power to the button
  
  /*___ Button Setup ___*/
  pinMode(buttonPin, INPUT); //Reads the power from the button
  
  /*___ LED Setup ___*/
  byte Counter;

  //Initialize the LEDPixels library.
  //            (refresh delay, address of data, number of LEDs, clock pin, data pin)
  LP.initialize(25, &MyDisplay[0], 92, 9, 8);

  // Setup the grid in the LEDPixels library to the setFastxxx calls work
  LP.gridWidth = gridWidth;
  LP.gridHeight = gridHeight;

  //Setup pins to drive the spectrum analyzer. 
  pinMode(spectrumReset, OUTPUT);
  pinMode(spectrumStrobe, OUTPUT);

  //Init spectrum analyzer
  digitalWrite(spectrumStrobe,LOW);
    delay(1);
  digitalWrite(spectrumReset,HIGH);
    delay(1);
  digitalWrite(spectrumStrobe,HIGH);
    delay(1);
  digitalWrite(spectrumStrobe,LOW);
    delay(1);
  digitalWrite(spectrumReset,LOW);
    delay(5);
  // Reading the analyzer now will read the lowest frequency.
  
  // Turn all LEDs off.
  LP.setRange(0,91,LP.color(0,0,0));
  LP.show();                             //Write out display to LEDs
  
}

void loop() {
  
  /*___ Button Loop ___*/
  buttonCall();
  
  /*___ Button Case Loop ___*/
  switch (buttonPushCounter) {
    case 0:
      LP.setRange(0,91,LP.color(0,0,31));
      LP.show();
      showSpectrum();
      break;
    case 1:
      makeBlack();
      break;
    case 2:  //Color Wipes Animation
      makeBlack();
      MoveLines(LP.color(random(0,31),random(0,31),random(0,31)));  
      break;
    case 3:  //Fading Animation
      makeBlack();
      for(xx=0;xx<32;xx++) { //Fade up from color
        LP.setRange(0,91,LP.color(xx,xx,xx));  
        LP.show();
        delay(30);
      }
      for(xx=31;xx>0;xx--) {  //Fade down from color
        LP.setRange(0,91,LP.color(xx,xx,xx));  
        LP.show();
        delay(30);
      }
      break;
    case 4:
      makeBlack();
      for(xx=0;xx<23;xx++) {
        LP.setPixel(0,xx,LP.color(0,31,0));
        LP.setPixel(1,4-xx,LP.color(0,0,31));
        LP.setPixel(2,xx,LP.color(0,31,0));
        LP.setPixel(3,4-xx,LP.color(0,0,31));
        LP.setPixel(4,xx,LP.color(0,31,0));

        LP.show();
        delay(200);
      }
      break;
  }      

delay(updateDelay);

}

void increment() {
    buttonPushCounter++;
      
  if (buttonPushCounter == 5) {  //Reset the counter when it exceeds a certain number
    buttonPushCounter = 0;
    }
}

void buttonCall(){
  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) {
    // if the state has changed, increment the counter
    while (buttonState == HIGH) {
      // if the current state is HIGH then the button
      // went from off to on:
      buttonPushCounter++;
      Serial.println("on");
      Serial.print("number of button pushes:  ");
      Serial.println(buttonPushCounter);
    }
  }
    else {
      // if the current state is LOW then the button
      // wend from on to off:
      Serial.println("off"); 
    }

  if (buttonPushCounter == 5) {  //Reset the counter when it exceeds a certain number
    buttonPushCounter = 0;
  }
  // save the current state as the last state, 
  //for next time through the loop
  lastButtonState = buttonState;
}

// Read 7 band equalizer.
void readSpectrum() {
  // Band 0 = Lowest Frequencies.
  byte Band;
  for(Band=0;Band < 1; Band++) {
    Spectrum[Band] = (analogRead(spectrumAnalog) + analogRead(spectrumAnalog) ) >>1; //Read twice and take the average by dividing by 2
    digitalWrite(spectrumStrobe,HIGH);
    digitalWrite(spectrumStrobe,LOW);     
  }
}


void showSpectrum() {
  //No I don't use any floating point numbers - all integers to keep it zippy. 
   readSpectrum();
   byte Band, BarSize, MaxLevel;
   static unsigned int  Divisor = 80, ChangeTimer=0, PullTimer = 0; //, ReminderDivisor,
   static boolean Idle = false;
   unsigned int works, Remainder;
  
  MaxLevel = 0; 
  Idle = Divisor < 23;
        
  for(Band=0;Band<4;Band++)//We only graph the lowest 5 bands here, there is 2 more unused!
  {
  //If value is 0, we don't show anything on graph
     works = Spectrum[Band]/Divisor;	//Bands are read in as 10 bit values. Scale them down to be 0 - 5
     if(works > MaxLevel) { //Check if this value is the largest so far.
       MaxLevel = works;  
     }
   
     for(BarSize=1;BarSize <=23; BarSize++)  
        {
           if(	works > BarSize) {
              LP.setLEDFast(LP.Translate(Band,BarSize-1), 0, 31, 0);
           }
            else { 
              LP.setLEDFast(LP.Translate(Band,BarSize-1), 31, 0, 0);
           }
        }
  }
  
  LP.show();

 // Adjust the Divisor if levels are too high/low.
 // If  below 4 happens 20 times, then very slowly turn up.
  if (MaxLevel >= 23)
  {
    Divisor=Divisor+1;
    ChangeTimer=0;
    PullTimer=0;
  }
  else if(MaxLevel < 22)
    {
      if(Divisor > 0)
        if(ChangeTimer++ > 10 || PullTimer > 10)
        {
          Divisor--;
          ChangeTimer = 0;
          PullTimer++;
          
          if(PullTimer > 15) {
                    Divisor--;
          }
        }
    }
    else
    {
      ChangeTimer=0; 
    }
}

//Set all LEDS and wait 1 second.
void All(unsigned int color) {
    LP.setRange(0,91,color);  
    LP.show();
    delay(1000);
}


void MoveLines(int yy) {
  //Draws 5 vertical lines in the requested color.
  //Then follow them with 5 black lines for a wipe effect.
      for(xx=0;xx<23;xx++)
        {
        LP.line(0,xx,4,xx,yy );
        LP.show();
        delay(50);
        }
   
      for(xx=0;xx<23;xx++)
        {
        LP.line(0,xx,4,xx,0 );
        LP.show();
        delay(50);
        }
}

void makeBlack() { // Set LEDs to black.
      // Set LEDs to black.
    LP.setRange(0,91,LP.color(0,0,0));
    LP.show(); //Send out data to LEDs.
}

Using delay() is never a good idea when you are trying to do lots of things at once. If you are delaying for a few (1-2) milliseconds you can get away with it. However if you are delaying a long time or you have a short delay but in a long loop, then it will generally not work well.