RGB LED fade using millis()

Hey, how to modify this code to get fading effect? I used State Machine Tutorial but still have got problems with fade function.

Whole fade is happening immediately and interval is after whole cycle. I know that interval should be on every color.

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 9;

long int fade_goTime;
int fade_break = 100; 

void setup() 
{
  fade_goTime = millis();  
}

void loop() 
{
  if(  millis() >= fade_goTime) fade();
}

void fade()
{
  
  unsigned int rgbColour[3] = {255,0,0}; //Start on red
  int incColour;

  // Choose the colours to increment and decrement.
    for (int decColour = 0; decColour < 3; decColour += 1) 
    {  
  
      if (decColour == 2)  incColour = 0;
      else incColour = decColour +1;

      // cross-fade the two colours.
      for(int i = 0; i < 255; i += 1) 
      {
        
        rgbColour[decColour] -= 1;
        rgbColour[incColour] += 1;
        
        setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
        
       fade_goTime = millis() + fade_break;
       
      }
    }
      
}

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
 }

You need to remove the for loops and replace them with the equivalent function that only makes one step per entry into the fade function.
So make the for loop index variable into a global variable and then increment it every time the fade function is entered. After you increment it make sure that you wrap round the variable when necessary. That is test to see if it has exceeded the loop limit and then reset ( or something else depending on what you want to do ) the loop variable.

Hey, I just tried your tips. I have got now something like that.

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 9;

long int fade_goTime;
int fade_break = 100;

int fade_state=0;

void setup() 
{
  setColourRgb(0,0,0); //Start on red
  fade_goTime = millis();  
}

void loop() 
{
  if(  millis() >= fade_goTime) 
  {  
    fade_state+=1;
    fade();
  }


}

void fade()
{
  
      unsigned int rgbColour[3] = {255,0,0};
  
      //number of decrement and increment colors -> 0 is red,1 is green,2 is blue
      int incColour, decColour;

      if (decColour == 2)  incColour = 0;
      else if (decColour == 1)  incColour = 2;
      else if (decColour == 0)  incColour = 1;
             

    
       if (fade_state >= 255) decColour+=1;
       else 
       {
        rgbColour[decColour] -= 1;
        rgbColour[incColour] += 1;
       }
       
       setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);
       fade_goTime = millis() + fade_break;
    
}

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
 }

I add flash_state variable and removed for loops. It is not working. Something is messed up but can't figure out what. Maybe should I use boolean variable to make fade function active when it is necessary?

if( millis() >= fade_goTime)

Take a look at the blink without delay example and compare what you are doing to it.

.

Take a look at the blink without delay example and compare what you are doing to it.

The differences are not important unless you run the code for 50 odd days.

Try this code, not tested but compiles:-

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 9;

long int fade_goTime;
long int fade_break = 100;

void setup()
{
  fade_goTime = millis(); 
}

void loop()
{
  if(  millis() >= fade_goTime) fade();
}

void fade()
{
 
  static unsigned int rgbColour[3] = {255,0,0}; //Start on red
  static int incColour;
  static int decColour = -1; // so it is zero first time round
  static int i = -1;
      
      decColour ++;
      if(decColour >2) decColour = 0;
      
      if (decColour == 2)  incColour = 0;
      else incColour = decColour +1;

      // cross-fade the two colours.
      i++;
      if(i > 255) i=0;
       
        rgbColour[decColour] -= 1;
        rgbColour[incColour] += 1;
       
        setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);      
       fade_goTime = millis() + fade_break;       
   }

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
 }

OK i see what I had done wrong on the previous post. You only need to increment the arrays you are using once the parameter i reaches it's wrap around point. You might also want to add a function to clear these arrays once they are full with 255.

const int redPin = 5;
const int greenPin = 6;
const int bluePin = 9;

long int fade_goTime;
int fade_break = 100;

void setup()
{
  fade_goTime = millis(); 
}

void loop()
{
  if(  millis() >= fade_goTime) fade();
}

void fade()
{
 
  static unsigned int rgbColour[3] = {255,0,0}; //Start on red
  static int incColour = 1;
  static int decColour = 0;
  static int i = -1;
      
      // cross-fade the two colours.
      i++;
      if(i > 255) {
        i=0;
        decColour ++;
        if(decColour >2) decColour = 0;      
        if (decColour == 2)  incColour = 0;
        else incColour = decColour +1;
      }

       
        rgbColour[decColour] -= 1;
        rgbColour[incColour] += 1;
       
        setColourRgb(rgbColour[0], rgbColour[1], rgbColour[2]);      
       fade_goTime = millis() + fade_break;       
   }

void setColourRgb(unsigned int red, unsigned int green, unsigned int blue) {
  analogWrite(redPin, red);
  analogWrite(greenPin, green);
  analogWrite(bluePin, blue);
 }

Yes! It works now very good.

I changed only

if(i > 255)

to

if(i > 254)

because without it values tried to go under zero, but array is unsigned, so I get values about 65232.

Because your first solution didn't work, I started wonder why and I after some time was close to this, but I didn't know many about static variables declarations.

Thank you.

Yes! It works now very good.

Excellent :slight_smile:

You can use global variables in place of static ones and they will do much the same thing but with a static variable the function you declare it in is the only place you can use it. Which is seen as a good thing when your code gets much more complex.

I just found this and it works good! I was just wondering how I can speed up the fading between the colours? Are there any variables to change?

Simply alter the value of the fade_break variable.

Thanks, I tried setting it to 0 but the cycle is still pretty slow. Are there any more ways to make it faster?

I tried setting it to 0 but the cycle is still pretty slow

Setting it at zero should not work at all! If it is still slow then you are doing something wrong. Please post your code in code tags and I will see if I can spot it.

If you don’t understand the reference to code tags then please read the how to use this forum sticky post.