Led Fading sketch crashes after a few loops

I've had a few people look at my code now, and we cant figure out why the program seems to crash after a few loops through the program. I'm running my ardweeny off USB power. With the code below, it runs the pattern about 12 times or so, and stops.

// data definitions

#define MAX_COLOR 255 // defined to make math easier later can be changed if the need arises

struct patterns // defines a pattern state
{ 
  int red;
  int green; 
  int blue; 
  int time; 
  int steps; 
};

enum state  // defines the current LED run state 
{
  RUN,
  DONE,
  PTRN
};

//  Order in which the led will run through the patterns before looping
//byte led1pattern[] = {0,1,2,3,1,1,4,4,5,6,5,5,6,6,4,4,4,1,1,254};
//const byte led1pattern[] = {1,1,4,4,4,4,4,4,5,254};
const byte led1pattern[] = {4,4,4,4,4,4,4,4,4,254};
// pattern data

// All the available patterns to run
// ,{0,0,0,0,40}  is a termination value, indicating end of pattern
const patterns patternMain[][7] = 
{
  {   
    {255,0,0,2000,8},
    {0,250,0,2000,8},
    {0,0,250,2000,8},
    {255,0,0,2000,15},
    {0,250,0,2000,15},
    {0,0,250,2000,15},
    {0,0,0,0,40}
  },// red-green-blue x2 0
  {   
    {255,0,0,1000,8},
    {0,0,0,1000,8},
    {255,0,0,1000,8},
    {0,0,0,1000,8},
    {0,0,0,0,40}
  }, //flash red slowly twice 1
  {
    {0,250,0,1000,8},
    {0,0,0,1000,8},
    {0,250,0,1000,8},
    {0,0,0,1000,8},
    {0,0,0,0,40}
  }, //flash green slowly twice 2 
  {
    {0,0,250,1000,8},
    {0,0,0,1000,8},
    {0,0,250,1000,8},
    {0,0,0,1000,8},
    {0,0,0,0,40}
  },  //flash red slowly twice 3
  {
    {255,0,0,50,1},
    {0,0,0,100,1},
    {0,0,0,0,40}
  }, //flash red once quick 4
  {
    {0,250,0,50,1},
    {0,0,0,100,1},
    {0,0,0,0,40}
  }, //flash green once quick 5
  {
    {0,0,250,50,1},
    {0,0,0,100,1},
    {0,0,0,0,40}
  } //flash blue once quick 6
};

class Led // led class definition
{
  public:
    Led(int, int, int, int);
    void transition_to(int, int, int, int, int);
    void update();
    void lerp();
    void transition_complete();
    void patternGroupSelect();
    
    state ledState;    // status of the led
    
  private:
    int redPin;      // should be in the led constructor
    int greenPin;    // same as above
    int bluePin;     // same as above

    int startRed;    // colors at the start of the transition
    int startGreen;
    int startBlue;
    
    int redVal;      // current color during transition
    int greenVal;
    int blueVal;
     
    int dstRed;      // color at the end of the transition
    int dstGreen;
    int dstBlue;
     
    unsigned long transition_start;    // ticks at start of transition
    unsigned long transition_end;      // ticks at end       
     
    unsigned long previousMillis;
    unsigned long currentTime;
    unsigned int increment;
     
    int pattern;
    int patternGroup;
    int ledNum;
    int patternIndex;
    float progress;
    int stepAmt;
    int stepChk;
};    // end of LED Class 

Led::Led(int red, int green, int blue, int num)
{
  ledNum = num;
  ledState = RUN;
  
  redPin   = red;
  greenPin = green;
  bluePin  = blue; 
  
  pattern = 0;
  patternIndex = 0;
  
  analogWrite(redPin, 0);
  analogWrite(greenPin, 0);
  analogWrite(bluePin, 0);
  patternGroup = led1pattern[patternIndex];
}

void Led::transition_to(int R, int G, int B, int length, int I) 
{
    dstRed   = R;
    dstBlue  = B;
    dstGreen = G;
 
    startRed   = redVal;
    startBlue  = blueVal;
    startGreen = greenVal;
 
    increment = I;
 
    transition_start = millis();
    transition_end = transition_start + length;
    ledState = RUN;
    previousMillis = currentTime;
}

void Led::update() 
{
  analogWrite(redPin, redVal);
  analogWrite(greenPin, greenVal);
  analogWrite(bluePin, blueVal);
}

void Led::lerp() 
{ 
  if (ledState == RUN) 
  {
    currentTime = millis();  
    // linear interpolation
    progress = 1.0 - (float)(transition_end - currentTime)/(transition_end - transition_start);
     
     // Gets the value for the color based on progress
    redVal   = startRed   + (dstRed - startRed) * progress;
    greenVal = startGreen + (dstGreen - startGreen) * progress;
    blueVal  = startBlue  + (dstBlue - startBlue) * progress;
 
      if (increment <= 1) // If the increment value is set to 1 or 0, it will just update and do a smooth
      {                   // fade
          update();
      } 
      else if(increment >1) // Only updates the leds the specified amount of times
      {                     // allows for a low frame rate type transition (looks cool, ok?!)
          stepAmt = 100 / increment;
 
          for( int z = 0; z <= increment; z++) 
          {
             stepChk = stepAmt * z;
             if (stepChk == (int)(progress * 100)) 
             {
                update();
             }
          }
      }
      
      if ( progress >= 1.0 ) 
      {
          redVal   = dstRed;  // Progress is finished, so set the color values to what they should be.
          greenVal = dstGreen;
          blueVal  = dstBlue;
          pattern++;  // advances the pattern
          ledState = DONE; 
      }
    }
} // end of lerp()
 
// Runs through a given pattern
void Led::transition_complete() 
{
  if (patternMain[patternGroup][pattern].steps < 30) // 30+ is a EOL value
  { // Sets up the next transition
    transition_to(
                    patternMain[patternGroup][pattern].red, 
                    patternMain[patternGroup][pattern].green, 
                    patternMain[patternGroup][pattern].blue, 
                    patternMain[patternGroup][pattern].time,
                    patternMain[patternGroup][pattern].steps
                    );
  } 
  else 
  { 
    ledState = PTRN;  
  }
 
}

void Led::patternGroupSelect() 
{
  pattern = 0;  //When selecting a new pattern, resets it to the beginning
  switch(ledNum) // Each LED number will have its own set pattern
  {
    case 1:
      //advances the pattern index
      patternIndex++;
      //Resets pattern to start
      if (led1pattern[patternIndex] == 254) 
      {
        patternIndex = 0;
      }
      //retrieves pattern group number
      patternGroup = led1pattern[patternIndex];
    break;
 
  }
}
 
// global variables and constants
 
unsigned int timer = 0;

Led Led1(9, 10, 11, 1);
 
void setup() 
{
  Led1.transition_complete(); //Gets it going
  
}

void loop() 
{
  switch(Led1.ledState) 
  {
    case RUN:
      Led1.lerp();
      break; 
    case DONE: // Finishes transition
      Led1.transition_complete();
      break;
    case PTRN: //Pattern finished
      Led1.patternGroupSelect();
      Led1.ledState = RUN;
      Led1.transition_complete();
      break;
  }
}

If you can see any problems, let me know. Some people have said floats and division are no good, but I cant figure out a way to do this without that progress line and variable.

SO much bloat to simply fade 3 leds?
Awesome!!!! :o :o :o

lol

Its fading a single RGB led at the moment. The goal is to fade 8 RGB leds (with an octobrite module from macetech) through set patterns. each led will be doing something different, and there will be some input from Midi. I need linear interpolation to fade between colors smoothly. The method used in the code above may not be the best method tho...

Well, you can save loads of ran space using chars instead of ints, as an int is 16 bits and a char only takes up 8 bits, every variable that is between 0 and 255 can use an char or better an uint8_t as that you save you a lot of ran, and that covers almost all your color variables and you seen to have a load of then, try that.

That is a lot just to fade 3 leds why not just use analogWrite() and some loops to fade the colours.

It is a lot, but its basically just a bunch of loops. The code allows me to write patterns in an array, and then call those patterns in a specific order. Each led can do the patterns in a different order, but they can use the same patterns. It was working up until a little while ago.

Nobody able to figure out whats wrong?

I did find some code that done the same thing I used it for a rgb led pov display I'll see if I can find it for you all you had to do was put in the main loop was pwmwrite(pin, 255); 255 being the pwm value
it used shift registers I would think it would be just the thing your trying to do as you mite need more pwm pins than you arduino has

here is the link hope it helps
http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1278251011/7

Hm, that code is a bit beyond my skill level, couldnt really tell what was going on.

I removed the use of my pattern arrays from the code, and now the program loops over and over with no hiccups. So I'm guessing I've done something wrong with the arrays. No idea what though.

I was going to suggest a few Serial.print() statements might be useful. Put one in the LED class constructor, to verify that you aren't creating more instances than are reasonable.

I'd Serial.print() the sizeof some of the arrays. Just how big is that patterns array?

How big is the LED instance?

I suspect that you are running out of memory.

I see what you mean it just stops looping i've put it on my arduino should be fixable I reckon. :wink:

It may be the pins I'm using, but last time I tried using the serial mode to debug, it messed up the whole program.

SHOULD be fixable, but after a few days, and several people looking, a solution has yet to be found :frowning:

I can't find it I guess you are running out of memory sorry I can't help.

Well, you can save loads of ram space using chars instead of ints, as an int is 16 bits and a char only takes up 8 bits, every variable that is between 0 and 255 can use an char or better an uint8_t as that you save you a lot of ran, and that covers almost all your color variables and you seen to have a load of then, try that.

Your problem is running out of ram, if the color sequences are static then save then using the PROGMEM attribute or get a better way of doing your thing with less ram.

Probably not causing the problem, but isn't "patterns" a 3D array? It has been declared as a 2D array.

I'm not going to rule out of memory as possible issue, the problem seems to stem from the use of a short transition length. There seems to be an issue inside the lerp code, something with the progress and the color value math, where a length of 50 seems to make it screw up over time. It may be something to do with the float and the division? I've adjust the values to 100, and its been running for 20+ minutes now.

"patterns" is a struct, and I dont actually know enough about arrays to be able to tell you! :-?

Thanks for you guys looking at it tho!