Hi all,
I'm trying to accomplish something which I thought would be easy, but to my surprise it has caused some serious hair pulling.
What I want to do is to use ShiftPWM to make 7 RGB LED strips crossfade through a colour sequence simultaneously. They are supposed to change from white to amber to red and back to white through amber, but I want to have a delay of (for instance) 2 seconds between each strip -- so strip 1 should be 2 seconds ahead of strip 2, 4 seconds ahead of strip 3, and strip N should be 2*N ahead of strip 1.
I think the problem is that I'm using a series of while loops to change the colours. The crossfade subroutine looks like this:
void colourFade(int idex){
int hueRed = 0;
int hueAmber = 22;
int satWhite = 190;
int satFull = 255;
int fadeTime = 3500;
int waitTime = 1500;
int fadeSteps1 = satFull - satWhite;
int fadeSteps2 = hueAmber - hueRed;
int interval1 = fadeTime/fadeSteps1;
int interval2 = fadeTime/fadeSteps2;
int sat = satWhite;
while(sat < satFull){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval1)
{sat++; previousMillis = currentMillis; ShiftPWM.SetHSV(idex, hueAmber, sat, 255);}
}
int hue=hueAmber;
while(hue>hueRed){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval2)
{hue--; previousMillis = currentMillis; ShiftPWM.SetHSV(idex, hue, satFull, 255);}
}
while(hue<hueAmber){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval2)
{hue++; previousMillis = currentMillis; ShiftPWM.SetHSV(idex, hue, satFull, 255);}
}
while(sat>satWhite){
unsigned long currentMillis = millis();
if(currentMillis - previousMillis > interval1)
{sat--; previousMillis = currentMillis; ShiftPWM.SetHSV(idex, hueAmber, sat, 255);}
}
}
So what I was thinking that I could do was to start this subroutine for each strip with a delay between the start of each; I tested this using the following (very ugly) loop:
void loop(){
colourFade(0);
delay(2000);
colourFade(1);
delay(2000);
colourFade(2);
delay(2000);
colourFade(3);
delay(2000);
colourFade(4);
delay(2000);
colourFade(5);
delay(2000);
colourFade(6);
delay(2000);
}
But of course, this does not work. The while loops are blocking, so the result of this is merely that the first strip goes through the whole sequence, followed by a 2 second wait, then the next one starts, and so on. What I want is for the first one to start, then the second one to start two seconds after that, and so on.
Any ideas on how to accomplish this? I have a feeling that I'm overlooking something very fundamental, but I haven't managed to find out what. I have looked at examples that are supposed to be non-blocking (hence the use of millis), but this isn't non-blocking enough.
Any hints would be much appreciated!