I need some suggestions here guys. Need to make this run better. I have a string of RGB LEDs that I'm trying to fade up then back down. Sounds easy enough, however it's not. The string consists of 8 LEDs now, it will have more later. I want each LED to fade up and down on its own, and each one will be fading up to a random color, as well as on their own timing (meaning they're not all doing it at the same time.) The LEDs are controlled with WS2801 and the code I'm using maintains an array representing the LEDs. When I need the various colors to be pushed down the string, there's a specific routine that does that. The array looks like this:strip_colors{0xff0000,0xffff00,0x00ff00,0x00ffff,0x0000ff, etc., etc}
So what I thought of doing was this:
a) maintain an array of currentMillis for each individual LED
b) maintain an array of colors for each individual LED
c) maintain an array for how many steps up or down they've already faded
Now, the code itself looks like this:
//fill in the various array with relevant data
if (!filled) {
for (int px = 0; px < STRIP_LENGTH; px++) {
// Pre-fill colors, delays, and timers
randomColor(COLOR, r, g, b, 1); // returns an RGB color value (and individual r, g, and b values), how, is not important for this exercise :)
strip_fChase[px] = rColor;
strip_delays[px] = random(0, 1000); // set individual, random delays for each LED
strip_pmills[px] = millis(); // keep track of when each LED was last updated
strip_cnters[px] = 1; // keep track of how many steps down or up the LEDs have faded
}
filled = 1;
}
Now for the up/down part. The way I figured this was, first, stick random colors on the array strip_fChase (it's an arbitrary name). Then, take that value, manipulate it, and store it in the strip_colors array so I can push (shift out) the data down the string. In order to fade UP, I step through each color up to 8 steps till it's at its actual value that it needs to be, and then step back 8 steps down. Here's what I'm doing for the fade down part:
for (int px = 0; px < STRIP_LENGTH; px++) {
if (millis() - strip_pmills[px] > strip_delays[px]) {
// Extract individual colors to manipulate
oColor = strip_fChase[px];
// This is the Fade Down part
r=0xFF;
g=0xFF;
b=0xFF;
b &= oColor;
oColor >>= 8;
g &= oColor;
oColor >>= 8;
r &= oColor;
for (int steps = 0; steps < strip_cnters[px]; steps++) {
r >>= 1;
if (r < 0) r = 0;
g >>= 1;
if (g < 0) g = 0;
b >>= 1;
if (b < 0) b = 0;
}
nColor = r;
nColor <<= 8;
nColor |= g;
nColor <<= 8;
nColor |= b;
strip_colors[px] = nColor;
if (nColor == 0) {
// if we've reached 0, pick a new random color, a new delay and store
randomColor(COLOR, r, g, b, 1);
strip_fChase[px] = rColor;
strip_delays[px] = random(250, 1000); // create an 'off' delay
}
strip_cnters[px]++;
if (strip_cnters[px] > 7) strip_cnters[px] = 1;
post_frame(0);
delay(1);
strip_pmills[px] = millis();
strip_delays[px] = pause - 5; // this 'pause' is the full loop pause (think Blink without delay), and it's set at 10ms
}
}
Basically, it steps through 0 to whatever the counter is (between 0 and 8 steps) and divides the color in half. So as the counter increases, it does less steps, causing the color to be brighter and brighter. I do the reverse when I have to fade up, the code is the same, except the counter is from -8 to 0 so the calculations are reversed.
Here's the problem, this is dog slow. The first one or two LEDs that come up are fine, but the moment the rest of them start to also blink, it crawls. I can set the delay to 0 for that matter and it's just too slow. My suspicion is because I'm stepping up to 8 times through each and every single LED as I loop through. 8 LEDs, up to 8 steps, that's a possible 64 loops for each time I go through the whole thing. Consider that I have 2 strings, that starts to really add up.
So, is there a better way of doing this?
Also, when shifting by 1 like I'm doing (r >>= 1), that effectively halves the value. Can I make that division even smaller? I realize 256 is 2^8, so halving it down to 0 is technically 8 steps ... how can I make that, say 16 steps?