Multiple LED fade

Hi!

I am a total beginner of Arduino Uno and I'm working on a project that requires the fade function.
I researched some codes on fading and have something working but wanted to see if I could take it a little further.

I have 3 LED lights set to cycle through fade loops, each with different brightness.

What I would like to be able to do is have each light running through it’s cycle at an independent rate (all six are running at the same time). But the problem is that I want the LEDs to be off at most, then fade on and off sometimes.

I’ve taken a look at a few sketches for fades and running multiple things at once but I don’t seem to be able to
Could somebody please help me solve this problem..

Thank you!

int led_1 = 9;
int led_2 = 10;
int led_3 = 11;

int brightness1 = 0;
int brightness2 = 100;
int brightness3 = 10;

int fadeAmount1 = 1;
int fadeAmount2 = 1;
int fadeAmount3 = 1;


void setup() {
  
pinMode(led_1,OUTPUT);
pinMode(led_2,OUTPUT);
pinMode(led_3,OUTPUT);

}

void loop() {
  
  analogWrite(led_1, brightness1);
    analogWrite(led_2, brightness2);
      analogWrite(led_3, brightness3);

  brightness1 = brightness1 + fadeAmount1;
    brightness2 = brightness2 + fadeAmount2;
      brightness3 = brightness3 + fadeAmount3;

  if(brightness1 == 200 || brightness1 == 0){
    fadeAmount1 = -fadeAmount1;

  }else if  (brightness2 == 200 || brightness2 == 0){
    fadeAmount2 = -fadeAmount2;
    
  }else if  (brightness3 == 200 || brightness3 == 0){
    fadeAmount3 = -fadeAmount3;
  }
  
  delay(30);
}
    
  

Thanks for using code tags!

First suggestion: use arrays so that your code does not have to contain copies of the same code for each led.

const byte led[3] = {9, 10, 11};

int brightness[3] = {0, 100, 10};

int fadeAmount[3] = {1, 1, 1};

Then you can use for-loops like this:

for(byte n=0; n<3; n++) {
  pinMode(led[n],OUTPUT);
}

Do you mean that you want the fading of each set of LEDs to start at random ?

Thanks for asking!
For example I would like it to be like the following:
LED off 30sec → LED fades on then fades off → LED stays off again for 20sec
Each LED at different timing but simultaneously.

You need to use non blocking timing so that the fading of each LED does not interfere with other LEDs

Start by looking at the BlinkWithoutDelay example in the IDE and implement 3 different fade loops with different timing using different variables. It is not quite what you want but it will show you the principle

Thank you for your reply!!

I understood the arrays part but I'm trying to figure out what this code means... could you kindly explain what "n" is?
Sorry for asking such a question.

Next suggestion: this code works ok, but only because fadeAmount1 is either 1 or -1. If you wanted to fade faster, and you tried, for example, -3 and -3, it would not work because brightness1 would never be 200, it would skip from 198 to 201. So use >= and <= instead of == here.

if(brightness1 == 200 || brightness1 == 0){
    fadeAmount1 = -fadeAmount1;

"n" is just a variable. You could call it anything you want. This variable only exists inside the for-loop, inside the { }, you cannot use or update it anywhere else in your code. The for-loop will execute 3 times and n will have the values 0, 1 and 2.

Thank you for the explanation.
I've tried something like this...

const byte led[3] = {9, 10, 11};

int brightness[3] = {0, 100, 10};

int fadeAmount[3] = {1, 1, 1};


void setup() {
for(byte n=0; n<3; n++) 
  pinMode(led[n],OUTPUT);
}

void loop() {

  if(brightness[10] >= 200 || brightness[10] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
  }else if 
  
  (brightness[20] >= 200 || brightness[20] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
  }else if  
  
  (brightness[0] >= 200 || brightness[0] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
  }
  delay(30);
}
    
  

And what happened? I imagine nothing happened. You seem to have lost analogWrite(), and code lines that updated brightness.

You changed post #9!

if(brightness[10]

The brightness array only has 3 elements, 3 values. Their indexes are 0, 1 and 2. There is no index 10. If you try to access index 10, there will be no error message, but some very strange things could happen, so always make sure you use only the indexes that are good.

1 Like

Oh no!!!

Thank you for being patient.. Now I understand what you were saying!!

Yes! it is fading away again!!
Now what should I change to get it to turn off most of the time and fade on and off sometimes?

Thanks again!

const byte led[3] = {9, 10, 11};

int brightness[3] = {0, 10, 100};

int fadeAmount[3] = {1, 1, 1};


void setup() {
for(byte n=0; n<3; n++) 
  pinMode(led[n],OUTPUT);
}

void loop() {
  analogWrite(led[0], brightness[0]);
    analogWrite(led[1], brightness[1]);
      analogWrite(led[2], brightness[2]);

  brightness[0] = brightness[0] + fadeAmount[0];
    brightness[1] = brightness[1] + fadeAmount[1];
       brightness[2] = brightness[2] + fadeAmount[2];
  
  
  if(brightness[0] >= 200 || brightness[0] <= 0){
    fadeAmount[0] = -fadeAmount[0];
  
  }else if 
  
  (brightness[1] >= 200 || brightness[1] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
  }else if  
  
  (brightness[2] >= 200 || brightness[2] <= 0){
    fadeAmount[2] = -fadeAmount[2];
  
  }
  delay(30);
}
    
  

Another for-loop needed!

  for(byte n=0; n<3; n++) {
    analogWrite(led[n], brightness[n]);
    brightness[n] = brightness[n] + fadeAmount[n];
    ...
    ...
   }

Also you can use += if you like:

brightness[n] += fadeAmount[n];

Thank you again.
I've tried adding the other for-loop but don't see a difference.
I think i might be doing something wrong but don't know where...

const byte led[3] = {9, 10, 11};

int brightness[3] = {100, 20, 10};

int fadeAmount[3] = {1, 1, 1};


void setup() {
for(byte n=0; n<3; n++) 
  pinMode(led[n],OUTPUT);

   }


void loop() {

  analogWrite(led[0], brightness[0]);
    analogWrite(led[1], brightness[1]);
      analogWrite(led[2], brightness[2]);

//  brightness[0] = brightness[0] + fadeAmount[0];
//    brightness[1] = brightness[1] + fadeAmount[1];
//       brightness[2] = brightness[2] + fadeAmount[2];

    
  for(byte n=0; n<3; n++) {
    analogWrite(led[n], brightness[n]);
    brightness[0] = brightness[0] += fadeAmount[0];
    brightness[1] = brightness[1] += fadeAmount[1];
    brightness[2] = brightness[2] += fadeAmount[2];
  
  if(brightness[0] >= 200 || brightness[0] <= 0){
    fadeAmount[0] = -fadeAmount[0];
  
  }else if 
  
  (brightness[1] >= 200 || brightness[1] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
  }else if  
  
  (brightness[2] >= 200 || brightness[2] <= 0){
    fadeAmount[2] = -fadeAmount[2];
  
  }
  delay(20);
}
}    
  

Check my suggested code again. In your code, analogWrite() is both before and inside the loop. You don't need both. Also, you are explicitly using [0], [1], [2] inside the loop where you should be using [n], and everything is repeated 3 times instead of just once.

Hello
My suggestion is to put all information like LED pin, fade direction, fade value, fade time, repeat time, etc. into a data structure. This data structure can be used to build an array per connected LED. One code block called method will take care and process the information provided by the data structure to fade the LED in/out/on/off.
Have a nice day and enjoy coding in C++.

Apologies for the belated reply...
I've tried what you suggested. Is this correct?

const byte led[3] = {9, 10, 11};

int brightness[3] = {0, 10, 100};

int fadeAmount[3] = {1, 1, 1};


void setup() {
for(byte n=0; n<3; n++) 
  pinMode(led[n],OUTPUT);

   }


void loop() {
      analogWrite(led[0], brightness[0]);
      analogWrite(led[1], brightness[1]);
      analogWrite(led[2], brightness[2]);

       brightness[0] = brightness[0] + fadeAmount[0];
       brightness[1] = brightness[1] + fadeAmount[1];
       brightness[2] = brightness[2] + fadeAmount[2];


  for(byte n=0; n<3; n++) {
     analogWrite(led[n], brightness[n]);
     brightness[n] = brightness[n] + fadeAmount[n];
     if(brightness[0] >= 200 || brightness[0] <= 0){
    fadeAmount[0] = -fadeAmount[0];
   }
  
  
  
   for(byte n=0; n<3; n++) {
    analogWrite(led[n], brightness[n]);
    brightness[n] = brightness[n] + fadeAmount[n];
  if (brightness[1] >= 200 || brightness[1] <= 0){
    fadeAmount[1] = -fadeAmount[1];
  
   }
  
     for(byte n=0; n<3; n++) {
    analogWrite(led[n], brightness[n]);
    brightness[n] = brightness[n] + fadeAmount[n];
   if (brightness[2] >= 200 || brightness[2] <= 0){
    fadeAmount[2] = -fadeAmount[2];

  
  }
  delay(200);
}
}
}
}
    
  

I'm getting a little confused here...

To translate what I'm doing here,

  1. Use arrays so its more convenient when I'm changing the rate of brightness or fade amount.

  2. for(byte n=0; n<3; n++) { pinMode(led[n],OUTPUT); }
    This is saying I'm outputting the 3 LEDs.

  3. for(byte n=0; n<3; n++) { analogWrite(led[n], brightness[n]); brightness[n] = brightness[n] + fadeAmount[n]; ... ... }
    I got a little confused why I would have to add this bit to achieve my purpose....
    The "if" statement is saying if the brightness is higher or equal to 200, OR if the brightness is smaller or equal to 0, reverse the fadeamount.
    I thought my problem of not being able to control the LEDs to stay dark and then turn ON sometimes, lays in my "if" statement. Because I'm asking it to bounce back on.
    I would have to control the timing of when it fades on and off.

Sorry for the late reply.
I was trying another way to achieve my problem.

For the "millis" way. I've researched some ways of doing it, but I don't fully comprehend it.
How could I use a similar function as "delay" which waits for the fade, without blocking other LEDs program.

uint32_t CMillis = 0; 
class PulseLed
{
  private :
    const byte ledPin;                       // has to be a GPIO with PWM
    uint8_t interval = 200;                   // the intervall in milliseconds for each change
    uint32_t previousMillis = 0;             // stores the last change
    uint8_t pwm = 0;                         // actual value of PWM
    uint8_t start = 0;                       // range from (lowest PWM value)
    uint8_t end =  255;                      // range to (highest PWM value
    uint8_t pulsecount = 0;
    int y =0;
    bool dir = true;
  public :
    PulseLed ( byte ledPin) :
      ledPin(ledPin)
    {}

    void begin() 
    {
      pinMode(ledPin, OUTPUT);
    }
    void setInterval(byte newInterval)
    {
      interval = newInterval;
    }

    void setRange( byte newStart, byte newEnd)
    {
      if (newEnd > newStart)
      {
        start = newStart;
        end = newEnd;
      }
    }
    void setpulsecount(byte newpulsecount)
    {
      pulsecount = newpulsecount;
    }
    
  void tick() 
{
  if ((millis() - previousMillis > interval) && (pulsecount != 0))
  {
  previousMillis = millis();
  if  (y >= start && dir == true) 
    {
    if ((y <= end -1) && (dir == true)) y = y + 1;  
    else dir = false;
    }
    else 
    {
    if ((y > start) && (dir == false)) y = y - 1;
    else dir = true;
    }
    analogWrite(ledPin, y);
    if (y == start)
    {
    pulsecount = (pulsecount - 1);
    }
  }  
}
  
};

PulseLed pulseLed[] {10, 11, 9, 5, 6, 7}; 

void setup() 
{
  Serial.begin(9600);
  for (int i = 0; i < 6; i ++)
  {  
  pulseLed[i].setRange(0, 255);   // set an individuall PWM range from ... to ...
  pulseLed[i].setInterval(5);    // set the interval/speed of pulsing
  pulseLed[i].setpulsecount(100000);  // set number of times to pulse
  }
CMillis = millis();
}

void loop()
{
pulseLed[0].tick();  
if (millis() - CMillis <= 100) {return;}
pulseLed[1].tick();  
if (millis() - CMillis <= 1000) {return;}
pulseLed[2].tick();  
if (millis() - CMillis <= 1500) {return;}
pulseLed[3].tick();  
if (millis() - CMillis <= 2000) {return;}
pulseLed[4].tick();  
if (millis() - CMillis <= 2500) {return;}
pulseLed[5].tick();  
}




Hello ccccfffff
Do you are happy with the solution presented?

please provide the link/source where you got this code from.

The class cares about pulsing a LED - respective like implemented in the code pulsing several LEDs.

you missed to call the begin() method for all objects in the setup.

If you want to start / stop dimming of a LED i would add two things:
make a start and a stop member function in the class
use some kind of if (millis() - ...) method to start or stop blinking.