RGB Crossfade & millis

Hey guys, I am a total noob at Arduino, sorry if the question has been answered before.

I am trying to cross-fade an RBG, which is all good, the thing is I want to add a switch state button to turn the RBG on the first click and off on the second, thing is that it only turns the RBG’s on but doesn’t turn them off.

I have scoured the forums for hours now, tried adding break; to the end of each fade but this messes with the timing of the RGB’s, I know I have to use millis and I think I understand the basic concept of it and tried to modify my code using it, except the timing is all off and there’s not a smooth transition.

Thanks for the help.

I will add below the original code I have and the one I tried using milli’s with, I haven’t added the switchstate button code because I have tested the millis code and it works fine with the button the timing and transitions are just off.

RGB fade code:

const int redLed = 11; //the number of the LED pin
const int blueLed = 10;// where the green pin is connected to
const int greenLed = 9; // where the blue pin is connected to
int DELAY = 20; // 20ms internal delay; increase for slower fades

void setup() {
Serial.begin(9600);
pinMode(greenLed, OUTPUT);
pinMode(blueLed, OUTPUT);
pinMode(redLed, OUTPUT);
}

void loop() {
// fade from green to red
for(int i=0; i<255; i++) {
analogWrite(redLed, i);
analogWrite(greenLed, 255-i);
analogWrite(blueLed, 0);
delay(DELAY);
}

// fade from red to blue
for(int i=0; i<255; i++) {
analogWrite(redLed, 255-i);
analogWrite(greenLed, 0);
analogWrite(blueLed, i);
delay(DELAY);
}

// fade from blue to green
for(int i=0; i<255; i++) {
analogWrite(redLed, 0);
analogWrite(greenLed, i);
analogWrite(blueLed, 255-i);
delay(DELAY);
}
}

This is the milli’s code I have tried to add to the code above.

unsigned long grStartMillis;
unsigned long rbStartMillis;
unsigned long bgStartMillis;
unsigned long currentMillis;
const unsigned long grPeriod = 1000;
const unsigned long rbPeriod = 1000;
const unsigned long bgPeriod = 1000;
const byte redLed = 13;
const byte blueLed = 10;
const byte greenLed = 9;

void setup()
{
Serial.begin(115200); //start Serial in case we need to print debugging info
pinMode(redLed, OUTPUT);
pinMode(greenLed, OUTPUT);
pinMode(blueLed, OUTPUT);
grStartMillis = millis(); //start time of blinking LED
rbStartMillis = millis(); //start time of fading LED
bgStartMillis = millis();
}

void loop()
{
currentMillis = millis(); //get the current time
if (currentMillis - grStartMillis >= grPeriod) //test whether the period has elapsed
{
for(int i=0; i<255; i++) {
analogWrite(redLed, i);
analogWrite(greenLed, 255-i);
analogWrite(blueLed, 0);
}
grStartMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
if (currentMillis - rbStartMillis >= rbPeriod) //test whether the period has elapsed
{
// fade from red to blue
for(int i=0; i<255; i++) {
analogWrite(redLed, 255-i);
analogWrite(greenLed, 0);
analogWrite(blueLed, i);
}
rbStartMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
if (currentMillis - bgStartMillis >= bgPeriod) //test whether the period has elapsed
{
// fade from red to blue
for(int i=0; i<255; i++) {
analogWrite(redLed, 255-i);
analogWrite(greenLed, 0);
analogWrite(blueLed, i);
}
bgStartMillis = currentMillis; //IMPORTANT to save the start time of the current LED state.
}
}

Where is the button?

Jacques

A suggestion. Don't use for loops, let the loop() function do what it is best at, that is looping.

Each crossfade happens when the system is in a particular state. Give each state a number starting at zero

Let's imagine that we are in state 0 fading from red to green. Each time through loop() test whether it is time to change the values written to the LEDs. Do this using millis(). When the period has elapsed change the LEDs, update the value to be written next time and save the millis() value for the next period start. Carry on like this until the next value has reached its limit. When it has, change the state variable to 1 and execute the code for that state, which will be very similar to state 0 but will write to different LEDs.

You can execute the code for the current state using an if test or, my favourite, using switch/case.

So, why all this messing about ? Well, because loop() is repeating very fast you can read inputs each time through and act on them. No need to scatter input reading throughout the code. Note that you should detect when inputs change state not when they are in a particular state. See the StateChangeDetection example in the IDE

See Using millis() for timing. A beginners guide and Several things at the same time