RGB LED STRIP programming question

Im using the spark fun rgb w2801 addressable led strips with the fast_spi library Google Code Archive - Long-term storage for Google Code Project Hosting.
my code is very basic, if the button on analog pin 5 is pressed the leds with flash random rgb values one at a time down the strip until each one has blinked once. then nothing happens until the button is pressed again.
i have a for loop that turns each led on and off until the loop has reached the last led. i want to make it so that if the button is pressed again while the leds are in motion, another led goes blinking down the strip. think of it as several button presses making several drops of light go down the same strip. how do i go about doing this? how can i break out of the for loop whenever the button is pressed?
heres my code

#include <FastSPI_LED.h>

//GREEN pin13
//RED pin11
#define NUM_LEDS 96
long RAND;
long RAND2;
long RAND3;

struct CRGB { unsigned char r; unsigned char g; unsigned char b; };

struct CRGB *leds;

#define PIN 4

void setup()
{
  
  pinMode(5, INPUT);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);
  
  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
}

void loop() { 


int button = analogRead(5);

if(button>1000) { 

     memset(leds, 0, NUM_LEDS * 3);
    for(int i = 0; i < NUM_LEDS; i++ ) {
       RAND = random(256);
       RAND2 = random(256);
       RAND3 = random(256);

           
          leds[i].r = RAND;
          leds[i].g = RAND2;
          leds[i].b = RAND3;
       
     
          FastSPI_LED.show();
      delay(30);
 
         
          leds[i].r = 0;
          leds[i].g = 0;
          leds[i].b = 0;
       
     
      FastSPI_LED.show();
      delay(30);
   
              }
          }


}

I think this will do close to what you want.

#include <FastSPI_LED.h>

#define NUM_LEDS 96

struct CRGB { 
  unsigned char r; 
  unsigned char g; 
  unsigned char b; 
};

struct CRGB *leds;

#define PIN 4

void setup() {
  pinMode(5, INPUT);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);

  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
  memset(leds, 0, NUM_LEDS * 3);
}

void loop() { 
  int button = analogRead(5);

  //  If the button is down, insert a random color at the beginning of the strip
  if(button > 1000) {
      leds[0].r = random(256);
      leds[0].g = random(256);
      leds[0].b = random(256);
  }
  
  // Show the current pattern
  FastSPI_LED.show();
  delay(30);
 
  // Move all the lights down one step
  for(int i = NUM_LEDS-1; i > 0; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;

      leds[0].r = 0;
      leds[0].g = 0;
      leds[0].b = 0;
  }
}

EDIT: Oops. The loop should have started at NUM_LEDS-1. Fixed it

thanks for the reply john. unfortunately your code didnt really work. if you push the button, nothing really happens. if you hold down the button, the first led changes random colors then nothing happens. i tried to add the fastspi_led.show; in the for loop but it didnt help. i think i understand what you were trying to do, have the first led light up when the button is pressed then have that led "move" in the for loop.

i messed around with my code a bit and tried to use a switch case where case 0: is leds off and case: 1 is the leds chasing down. i ran into a problem when trying to put an if statement before the switch case which would have the button control the variable for the switch. i tired to use an if without brackets before my switch but it doesnt get declared when the button is pressed.
here is my switch code. notice the comments at the beginning of the loop. let me know what you think.

#include <FastSPI_LED.h>

//GREEN pin13
//RED pin11
#define NUM_LEDS 96

struct CRGB { 
  unsigned char r; 
  unsigned char g; 
  unsigned char b; 
};

struct CRGB *leds;

#define PIN 4

void setup() {
  pinMode(5, INPUT);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);

  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
  memset(leds, 0, NUM_LEDS * 3);
}

void loop() { 
int j=0;  //declare switch variable as 0
int button = analogRead(5);   //if button is pressed my switch variable
    if(button > 1000) int j=1;  //should change to 1 but it doesnt
       switch(j) {        //when running the sketch, variable stays 0 and button doesnt change it.
                      //i could put everything after the if statement in brackets but,
                      //the switch doesnt work the way i want it to- i have to wait for
                   //it to run through all the leds before the button works again. 
                   //i thought if the button could declare the variable then the switch
                   //could work each time i press the button, regardless whether or not 
                   //the loop has run through all the leds.
          case 0:
               for(int i=0; i<NUM_LEDS; i++){    
               leds[i].r = 0;
               leds[i].g = 0;
               leds[i].b = 0;
               FastSPI_LED.show();
               delay(30);
               }          break;
           
          case 1:
               for(int i=0; i<NUM_LEDS; i++){
               leds[i].r = 255;
               leds[i].g = 255;
               leds[i].b = 255;
               FastSPI_LED.show();
               delay(30); 
               leds[i].r = 0;
               leds[i].g = 0;
               leds[i].b = 0;
               FastSPI_LED.show();
               delay(30);
               }          break;
      }
  }

My mistake. I was going off the end of the array. Fixed above.

thanks john, i got it to work by taking the leds[0].r = 0; leds[0].g = 0; leds[0].b = 0; out of the for loop.
any suggestions on helping me make the leds fade in and out as they chase?
thanks again,
tom

Maybe this will work for leaving a fading trail:

#include <FastSPI_LED.h>

#define NUM_LEDS 96

struct CRGB { 
  unsigned char r; 
  unsigned char g; 
  unsigned char b; 
};

struct CRGB *leds;

#define PIN 4

void setup() {
  pinMode(5, INPUT);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);

  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
  memset(leds, 0, NUM_LEDS * 3);
}

void loop() { 
  int button = analogRead(5);

  //  If the button is down, insert a random color at the beginning of the strip
  if(button > 1000) {
      leds[0].r = random(256);
      leds[0].g = random(256);
      leds[0].b = random(256);
  }
  
  // Show the current pattern
  FastSPI_LED.show();
  delay(30);
 
  // Move all the lights down one step
  for(int i = NUM_LEDS-1; i > 0; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
  }
  // Fade out the color.  After 8 steps the color should be completely gone.
  leds[0].r /= 2;
  leds[0].g /= 2;
  leds[0].b /= 2;
}

awesome! thanks john.
another question-
i am using a max/msp patch to generate the random number (0-255) going to arduino via serial usb. when the button is pressed it streams these values live and when it lets go the trail stops building and trails off, continuing down the strip with the last values it received with the fade just like the code says it will. what i want to do is- when the button is released and the trail starts to fade as it travels down in its group, instead of just keeping the last values it received, i want it to keep displaying live values as the trail goes down. so lets say the light trail is two feet long going down the 20 foot strip, instead of a bunch of old values going from one to the next led, i want the trail to keep changing with live serial values but remain in its two foot section after the button is released.

TomK:
What i want to do is: when the button is released and the trail starts to fade as it travels down in its group, instead of just keeping the last values it received, I want it to keep displaying live values as the trail goes down. So lets say the light trail is two feet long going down the 20 foot strip, instead of a bunch of old values going from one to the next led, I want the trail to keep changing with live serial values but remain in its two foot section after the button is released.

I can't quite picture what you mean. I don't know what you mean by "its group" or a "section".

sorry for the poor description.
so right now, when the button is pressed, an led goes fading down the strip. i have a max/msp patch constantly feeding the arduino a value for the led. when the button is pressed, it only shoots one of these random values down the strip. i want it so that when the led goes fading down the strip, it keeps changing with the live values it is receiving via max/msp, instead of just one received value.
hope that makes some sense.
heres my code-

#include <FastSPI_LED.h>

#define NUM_LEDS 288

struct CRGB { 
  unsigned char r; 
  unsigned char g; 
  unsigned char b; 
};

struct CRGB *leds;

long RAND;

#define PIN 4

void setup() {
  Serial.begin(115200);
  pinMode(5, INPUT);
  pinMode(0, INPUT);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(PIN);

  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
  memset(leds, 0, NUM_LEDS * 3);
}

void loop() { 
  
  int button = analogRead(5);
  if (Serial.available()>=1) {
      RAND=Serial.read(); 
  
  if(button > 1000) {
     
      leds[0].r = RAND;
      leds[0].g = RAND;
      leds[0].b = RAND;
     
      }
  

  
  // Move all the lights down one step
  for(int i = NUM_LEDS-1; i > 0; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
      
      }

      leds[0].r /= 2;
      leds[0].g /= 2;
      leds[0].b /= 2;  
      
  }

      FastSPI_LED.show();
    delay(30);
}

Are you saying you want it to act like the button is pressed once for each character that is received? Like this:

#include <FastSPI_LED.h>

#define NUM_LEDS 288

struct CRGB { 
  unsigned char r; 
  unsigned char g; 
  unsigned char b; 
};

struct CRGB *leds;

const int SS_PIN = 4;

void setup() {
  Serial.begin(115200);
  FastSPI_LED.setLeds(NUM_LEDS);
  FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);
  FastSPI_LED.setDataRate(3);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_LPD6803);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_HL1606);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_595);
  //FastSPI_LED.setChipset(CFastSPI_LED::SPI_WS2801);

  FastSPI_LED.setPin(SS_PIN);

  FastSPI_LED.init();
  FastSPI_LED.start();

  leds = (struct CRGB*)FastSPI_LED.getRGBData(); 
  memset(leds, 0, NUM_LEDS * 3);
}

void loop() {
  if (Serial.available()>=1) {
      unsigned char value=Serial.read(); // Read a brightness value
     
      leds[0].r = value;
      leds[0].g = value;
      leds[0].b = value;
      }
  
  // Move all the lights down one step
  for(int i = NUM_LEDS-1; i > 0; i-- ) {
      leds[i].r = leds[i-1].r;
      leds[i].g = leds[i-1].g;
      leds[i].b = leds[i-1].b;
      }

  leds[0].r /= 2;
  leds[0].g /= 2;
  leds[0].b /= 2;

  FastSPI_LED.show();
  delay(30);
}

i want it to act like this-
button is pressed, first led lights up as one of the values being received from serial, then as that led moves down each step it keeps changing color according to the incoming serial value (instead of just keeping the first value received).

lets say i have the serial values changing the leds from bright to dim, slowly fading in and out. RIGHT NOW with my code, pushing the button lights up the first led as bright (or whatever value the max patch is at in the fade), but then it holds this bright value as it steps down the strip. i would like it to constantly change value, fading from bright to dim and back, as it is stepping down after button press.

I think I understand now what you are looking for. Unfortunately I don't have the time to design or write the code to do it. Perhaps you should post under Gigs and Collaborations or find help at a 'hacker space' in your area: http://hackerspaces.org/wiki/List_of_Hacker_Spaces

If you can't find someone to do it for free you can hire me to do it for $50.

hey john, i didnt have much luck finding help. i would glady pay you to help me out with this.

TomK, in the same fashion that you're constantly checking for a button press (which should be happening with every loop), you can also read in serial data and pass it on to the LED being lit. Where things get complicated is when you have multiple LEDs going at the same time (when the button was pressed multiple times). Now you have to read enough serial data for all of the LEDs. How does your serial device (sending the data) knows how many LEDs are on? Does it send one set of data, or does it send multiple? What's the purpose of this serial input?

What's the purpose of this serial input?

its an oscillator in max/msp that inputs values 0-255 in a random sine wave to the arduino. so when the leds light up they pulse according to these values.

Does it send one set of data, or does it send multiple?

it sends one number, 0-255, constantly over and over.

How does your serial device (sending the data) knows how many LEDs are on?

it doesnt know how many leds are on.

Where things get complicated is when you have multiple LEDs going at the same time (when the button was pressed multiple times).

yes this is where i hit a wall.

sorry for the delay in response. the storm took my internet for a few days.

anyone willing to help me out on this? i will compensate for your time.