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.