Using milllis() for sequencing LED's

Hi,

I have a series of 6 LED's and am trying to use millis() to get it turn on and off in a sequence.
I need the LED's to turn on every 5 seconds and then turn off in the reverse sequence with 5 seconds interval between each LED's. To put it in a sequence:

Turn On Sequence : LED1 - 5 Sec - LED2 - 5 Sec .... LED 6
Now wait for 5 seconds and then
Turn Off Sequence : LED 6 - 5 Sec - LED5 - 5 Sec ... LED 1.

But using the below program, the LED's turn on in a sequence, but after that, all the LED's turn off together and the cycle begins again to turn on. Can someone please help?

Note: LED's are connected as active low.

class Flasher
{
  // Class Member Variables
  // These are initialized at startup
  int ledPin;      // the number of the LED pin
  unsigned long OnTime;     // milliseconds of on-time
  unsigned long OffTime;    // milliseconds of off-time

  // These maintain the current state
  int ledState;                 // ledState used to set the LED
  unsigned long previousMillis;   // will store last time LED was updated

  // Constructor - creates a Flasher 
  // and initializes the member variables and state
  public:
  Flasher(int pin, unsigned long on, unsigned long off)
  {
  ledPin = pin;
  pinMode(ledPin, OUTPUT);

  OnTime = on;
  OffTime = off;
  
  ledState = HIGH; 
  previousMillis = 0;
  }

  void Update()
  {
    // check to see if it's time to change the state of the LED
    unsigned long currentMillis = millis();

    if((ledState == HIGH) && (currentMillis - previousMillis >= OnTime))
    {
      ledState = LOW;  // Turn it on
      previousMillis = currentMillis;  // Remember the time
      digitalWrite(ledPin, ledState);  // Update the actual LED
    }
    else if ((ledState == LOW) && (currentMillis - previousMillis >= OffTime))
    {
      ledState = HIGH;  // turn it off
      previousMillis = currentMillis;   // Remember the time
      digitalWrite(ledPin, ledState);   // Update the actual LED
    }
  }
};

// Pegasus specific LED pin assignments
int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

Flasher led1(LED1, 1000, 6000);
Flasher led2(LED2, 2000, 5000);
Flasher led3(LED3, 3000, 4000);
Flasher led4(LED4, 4000, 3000);
Flasher led5(LED5, 5000, 2000);
Flasher led6(LED6, 6000, 1000);

void setup()
{
  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, HIGH);
  digitalWrite(LED3, HIGH);
  digitalWrite(LED4, HIGH);
  digitalWrite(LED5, HIGH);
  digitalWrite(LED6, HIGH);
}

void loop()
{
  led1.Update();
  led2.Update();
  led3.Update();
  led4.Update();
  led5.Update();
  led6.Update(); 
}

This is similar and simpler
Let me know if this helps

// Pegasus specific LED pin assignments
int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

void setup() {
 Serial.begin(115200);
}

void loop() {
 static int FiveSecondsCtr = 0;
 static unsigned long ExactTimer;
 if ( millis() - ExactTimer >= (5000)) {
   ExactTimer += (5000);
   FiveSecondsCtr++;
   if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
   Serial.println(abs(FiveSecondsCtr));
   digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? HIGH : LOW);
   digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? HIGH : LOW);
   digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? HIGH : LOW);
   digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? HIGH : LOW);
   digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? HIGH : LOW);
   digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? HIGH : LOW);
 }
}

Z

This is perfect. I modified the code a little bit since it was active low. Now I get the cycle as expected

Is there any way to create a delay of 3 minutes between one cycle?
One cycle is all led's turning on in a sequence and then turning back off. Wait for 3 minutes and then repeat the cycle again? I need the delay in millis since I also use an IR remote and delay stops any inputs.

// Pegasus specific LED pin assignments
int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

void setup() {
 Serial.begin(115200);
  pinMode(LED1, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(LED4, OUTPUT);
  pinMode(LED5, OUTPUT);
  pinMode(LED6, OUTPUT);

  digitalWrite(LED1, HIGH);
  digitalWrite(LED2, HIGH);
  digitalWrite(LED3, HIGH);
  digitalWrite(LED4, HIGH);
  digitalWrite(LED5, HIGH);
  digitalWrite(LED6, HIGH);    
}

void loop() {
 static int FiveSecondsCtr = 0;
 static unsigned long ExactTimer;
 if ( millis() - ExactTimer >= (5000)) {
   ExactTimer += (5000);
   FiveSecondsCtr++;
   if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
   Serial.println(abs(FiveSecondsCtr));
   digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
   digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? LOW : HIGH);
   digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? LOW : HIGH);
   digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
   digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
   digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
 }
}

praveen_khm:
This is perfect. I modified the code a little bit since it was active low. Now I get the cycle as expected

Is there any way to create a delay of 3 minutes between one cycle?
One cycle is all led's turning on in a sequence and then turning back off. Wait for 3 minutes and then repeat the cycle again? I need the delay in millis since I also use an IR remote and delay stops any inputs.

// Pegasus specific LED pin assignments

int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

void setup() {
Serial.begin(115200);
 pinMode(LED1, OUTPUT);
 pinMode(LED2, OUTPUT);
 pinMode(LED3, OUTPUT);
 pinMode(LED4, OUTPUT);
 pinMode(LED5, OUTPUT);
 pinMode(LED6, OUTPUT);

digitalWrite(LED1, HIGH);
 digitalWrite(LED2, HIGH);
 digitalWrite(LED3, HIGH);
 digitalWrite(LED4, HIGH);
 digitalWrite(LED5, HIGH);
 digitalWrite(LED6, HIGH);    
}

void loop() {
static int FiveSecondsCtr = 0;
static unsigned long ExactTimer;
if ( millis() - ExactTimer >= (5000)) {
  ExactTimer += (5000);
  FiveSecondsCtr++;
  if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
  Serial.println(abs(FiveSecondsCtr));
  digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
  digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? LOW : HIGH);
  digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? LOW : HIGH);
  digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
  digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
  digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
}
}

Yes
Here is where the timer is

if ( millis() - ExactTimer >= (5000)) {
   ExactTimer += (5000);
   FiveSecondsCtr++;

We need to change the fixed 5000 millisecond delay value to a variable. And now we can extend the delay time to 3 minutes before we count again when we get to the desired count 0 all lights off.
1000 (1 second) * 60 * 3

static unsigned long delayTime = 5000;
if ( millis() - ExactTimer >= (delayTime)) {
   FiveSecondsCtr++;
   delayTime  = (abs(FiveSecondsCtr) == 0) ? (1000 * 60 * 3) : 5000;
   ExactTimer += (delayTime);
// code continues on

The = (if) ? True : false; is a nice shortcut to a multi line if else statement.
Z

Thank you. It worked at last. I am not sure why, but it seems to have trouble using (1000 * 60 * 3) in the condition. I finally wrote (30000) as a number and it started working. Not sure where the error is, but did a lot of trial and error and ended up with below working code.

One last request (if I may) is to fade one of the LED's. One of the LED is connected to PWM pin. (Pin 3 or LED2). Can this fade in and out along with the other LED's in the same sequence? I mean once LED1 is turned on, LED2 should fade in followed by turning on other LED's. On the reverse, it should be LED3 off followed by LED2 fade out and LED1 off.

I know I have been asking for too much. But if this one works, I have a complete code.

Thanking you again for all the help.

 if ( millis() - ExactTimer >= (delayTime)) {
   ExactTimer += (delayTime);
   FiveSecondsCtr++;
   if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
   delayTime =  (abs(FiveSecondsCtr) == 0) ? 300000 : 5000;
   digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
   digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? LOW : HIGH);
   digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? LOW : HIGH);
   digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
   digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
   digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
 }

praveen_khm:
Thank you. It worked at last. I am not sure why, but it seems to have trouble using (1000 * 60 * 3) in the condition. I finally wrote (30000) as a number and it started working. Not sure where the error is, but did a lot of trial and error and ended up with below working code.

The numeric default in doing Atmega math is a 16-bit signed int which is limited to 32767 in the positive range.

As 1000*60 is a lot more than 32767, you'll get an "integer math overflow" at that point in your code, and the "*3" multiplication is then done with an overflowed result value already, which will lead to a wrong end result.

Overflow result in intermediate calculation leads to wrong end result of whole calculation.

AVOID NUMERIC MATH OVERFLOW EXPRESSIONS!

"numeric default "
I would have thought there was no default, only what the program assigned.
Use unsigned long for all variables associated with time, as that is what millis() and micros() returns.
Range is then 0 to 2^32-1 (4.29+ billion)

jurs:
The numeric default in doing Atmega math is a 16-bit signed int which is limited to 32767 in the positive range.

As 1000*60 is a lot more than 32767, you'll get an "integer math overflow" at that point in your code, and the "*3" multiplication is then done with an overflowed result value already, which will lead to a wrong end result.

Overflow result in intermediate calculation leads to wrong end result of whole calculation.

AVOID NUMERIC MATH OVERFLOW EXPRESSIONS!

Now I have a question... How do you avoid this?

unsigned long X;
X = (unsigned long)  1000 * (unsigned long)  60 * (unsigned long)  3;

Z

zhomeslice:
Now I have a question... How do you avoid this?

unsigned long X;

X = (unsigned long)  1000 * (unsigned long)  60 * (unsigned long)  3;




Z
unsigned long X = 1000UL *  60UL *  3UL;

AWOL:

unsigned long X = 1000UL *  60UL *  3UL;

Thanks AWOL good to know of these Multiplication issues with long numbers and yes I knew about UL but rarely use it. This is a good reminder as to why we need it.

I should have done the following:

static unsigned long delayTime = 5000UL;
if ( millis() - ExactTimer >= (delayTime)) {
   FiveSecondsCtr++;
   delayTime  = (abs(FiveSecondsCtr) == 0) ? (1000UL * 60UL * 3UL) : 5000UL;
   ExactTimer += (delayTime);
// code continues on

Adding UL is appropriate, while not necessary in every spot I placed it, I believe it doesn't hurt to define the numbers as unsigned long where they will be used as such.
Z

Delta_G:

(1000UL * 60UL * 3UL)

You really only need it on one of those to force the whole thing.

5000UL;

Single numbers by themselves don't ever need it. The compiler is smart enough to figure it out if it is just one number. That's why the OP could go hard code 60000 and it works. It's the intermediate results that the compiler doesn't work through.

I assumed as much but being mostly self taught It is good to hear it from the experts Thank You
Z

Hi,

There is a lot of learning here. I knew it was not working, but did not know why. Thanks for answering the why.

Secondly, sticking to my question, is there a way to fade in and out one of the LED in between other LED's?

Best Regards,
Praveen

praveen_khm:
Hi,

There is a lot of learning here. I knew it was not working, but did not know why. Thanks for answering the why.

Secondly, sticking to my question, is there a way to fade in and out one of the LED in between other LED's?

Best Regards,
Praveen

Sorry for the deviation from your core question I've learned more helping than I've helped at times :slight_smile:

The fading led answer is yes. Although it may be more difficult than expected. There is only one way I know of with traditional LED's and that is to use analogWright and the PWM (pulse width modulation) pins marked with the ~ pins 3, 5, 6, 9, 10 & 11 are the pins in question. PWM changes the duty cycle of fixed frequency square wave from OFF to100% on over 256 steps (0~255) allowing the illusion of dimming of the LED. I say illusion because the LED is actually blinking full on then off rapidly, it is just off more than it is on as it dims.
There is another way. But let's start her since we are on this path.
Z

Thanks for the response. I am aware of the PWM and since the LED is connected to pin3, I have successfully made it fade in and fade out using the fade LED program available on Arduino IDE.

However, I need a solution without using the delay (as in the program) as that would again make it wait the program wait for 5 seconds. Secondly, since the program you have given is already in a continuous loop, I am not sure how to add that LED fade in between so that it is in sync with other LED's.

I am been trying from my side and if it works, will definitely share it in this forum.

Thanks,
Praveen

praveen_khm:
Thanks for the response. I am aware of the PWM and since the LED is connected to pin3, I have successfully made it fade in and fade out using the fade LED program available on Arduino IDE.

However, I need a solution without using the delay (as in the program) as that would again make it wait the program wait for 5 seconds. Secondly, since the program you have given is already in a continuous loop, I am not sure how to add that LED fade in between so that it is in sync with other LED's.

I am been trying from my side and if it works, will definitely share it in this forum.

Thanks,
Praveen

Post an updated version with the LET's linked to PWM pins of your choice. I have another truck up my sleeve to accomplish your needs and I'll be happy to share it :slight_smile:
I may post the concept here in a few hours when I have more time to work on it if I don't have your new version to work with.
Z

The general question you need to ask yourself in order to write non-blocking code is "What do I need to remember so that when I go away from this task and do something else, I can pick up exactly where I left off when I come back to it".

For example, each LED will need an array that defines its fading sequence. It would include such information as the target intensity of each interval and the length of the fading interval.

Then, each LED needs its operating information. This might include things like:

  • Pin number
  • Starting intensity
  • Target intensity
  • millis() time of the beginning of the current interval
  • length of the current interval
  • current position in the sequence array

Then every time you run a check on the LED, check if the interval is over. If it is, advance your position in the sequence array and load the next set of intensity and timing values from the array.

If the interval is not over, you can use map with your current position in the interval to derive what intensity value to send to the LED's PWM.

Either way, each LED only takes a very brief amount of time to service, and you can have as many as you want fading independently (within reason).

The key shift is to train yourself to use variables to control your program's timing, instead of a series of delay statements.

This will work best if you package all those variables together in a struct or class, rather than have disjointed sets of global variables.

Ok Try This out. I've not tested it.
Added notes and a special function that allows me to easily see what I put in the PWM registers to adjust there values.

Alternatively you could store that value and assign it to the output of your choice using more variables.
(I personally like being able to get the value directly knowing that I could change it anywhere else and the code would still function correctly.)

How I would do it :slight_smile:

#define DimmingStepRate 10 // in milliseconds


// Pegasus specific LED pin assignments
int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

void setup() {
  Serial.begin(115200);
}

void loop() {
  static int FiveSecondsCtr = 0;
  static unsigned long ExactTimer;
  if ( millis() - ExactTimer >= (5000)) {
    ExactTimer += (5000);
    FiveSecondsCtr++;
    if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
    Serial.println(abs(FiveSecondsCtr));

  }
  static unsigned long DimTimer;
  if ( millis() - DimTimer >= (DimmingStepRate)) {
    DimTimer += millis();
    // the following 2 lines do the following
    //The first line determines if the pin has PWM capabilities and then runs the dimming routine
    //The Next line runs when the pins is not hooked to a PWM Capable output
    if(digitalPinToTimer(LED1)) analogWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? min(255, analogReadPWM(LED1) + 1) : max(0, analogReadPWM(LED1) - 1)); // using the function below get the last value we set to this PWM pin and add or subtract 1 from it 
    else  digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
    if(digitalPinToTimer(LED2)) analogWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? min(255, analogReadPWM(LED2) + 1) : max(0, analogReadPWM(LED2) - 1));
    else  digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? LOW : HIGH);
    if(digitalPinToTimer(LED3)) analogWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? min(255, analogReadPWM(LED3) + 1) : max(0, analogReadPWM(LED3) - 1));
    else  digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? LOW : HIGH);
    if(digitalPinToTimer(LED4)) analogWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? min(255, analogReadPWM(LED4) + 1) : max(0, analogReadPWM(LED4) - 1));
    else  digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
    if(digitalPinToTimer(LED5)) analogWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? min(255, analogReadPWM(LED5) + 1) : max(0, analogReadPWM(LED5) - 1));
    else  digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
    if(digitalPinToTimer(LED6)) analogWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? min(255, analogReadPWM(LED6) + 1) : max(0, analogReadPWM(LED6) - 1));
    else  digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
  }
}



//--------- Created by ZhomeSlice: analogReadPWM() reads the current value set for the PWM Output it behaves like digitalRead() retrieves the low or High value set in the output.
// This Does not read analog pin input values 

// THE FOLLOWING FUNCTION IS DERIVED FROM:

/*
  wiring_analog.c - analog input and output
  Part of Arduino - http://www.arduino.cc/

  Copyright (c) 2005-2006 David A. Mellis

  This library is free software; you can redistribute it and/or
  modify it under the terms of the GNU Lesser General Public
  License as published by the Free Software Foundation; either
  version 2.1 of the License, or (at your option) any later version.

  This library is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General
  Public License along with this library; if not, write to the
  Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  Boston, MA  02111-1307  USA

  Modified 28 September 2010 by Mark Sproul

  $Id: wiring.c 248 2007-02-03 15:36:30Z mellis $
*/


// Right now, PWM output only works on the pins with
// hardware support.  These are defined in the appropriate
// pins_*.c file.  For the rest of the pins, are default
// to digital output.
byte analogReadPWM(uint8_t pin) {
  byte val;
  switch (digitalPinToTimer(pin)) // returns timer location if it is on a timer see NOT_ON_TIMER
  {
      // XXX fix needed for atmega8
#if defined(TCCR0) && defined(COM00) && !defined(__AVR_ATmega8__)
    case TIMER0A:
      val = OCR0;  // get pwm duty
      break;
#endif

#if defined(TCCR0A) && defined(COM0A1)
    case TIMER0A:
      val = OCR0A; // get pwm duty
      break;
#endif

#if defined(TCCR0A) && defined(COM0B1)
    case TIMER0B:
      val = OCR0B; // get pwm duty
      break;
#endif

#if defined(TCCR1A) && defined(COM1A1)
    case TIMER1A:
      val = OCR1A; // get pwm duty
      break;
#endif

#if defined(TCCR1A) && defined(COM1B1)
    case TIMER1B:
      val = OCR1B; // get pwm duty
      break;
#endif

#if defined(TCCR2) && defined(COM21)
    case TIMER2:
      val = OCR2; // get pwm duty
      break;
#endif

#if defined(TCCR2A) && defined(COM2A1)
    case TIMER2A:
      val = OCR2A; // get pwm duty
      break;
#endif

#if defined(TCCR2A) && defined(COM2B1)
    case TIMER2B:
      val = OCR2B; // get pwm duty
      break;
#endif

#if defined(TCCR3A) && defined(COM3A1)
    case TIMER3A:
      val = OCR3A; // get pwm duty
      break;
#endif

#if defined(TCCR3A) && defined(COM3B1)
    case TIMER3B:
      val = OCR3B; // get pwm duty
      break;
#endif

#if defined(TCCR3A) && defined(COM3C1)
    case TIMER3C:
      val = OCR3C; // get pwm duty
      break;
#endif

#if defined(TCCR4A)
    case TIMER4A:
      val = OCR4A; // get pwm duty
      break;
#endif

#if defined(TCCR4A) && defined(COM4B1)
    case TIMER4B:
      val = OCR4B; // get pwm duty
      break;
#endif

#if defined(TCCR4A) && defined(COM4C1)
    case TIMER4C:
      val = OCR4C; // get pwm duty
      break;
#endif

#if defined(TCCR4C) && defined(COM4D1)
    case TIMER4D:
      val = OCR4D; // get pwm duty
      break;
#endif


#if defined(TCCR5A) && defined(COM5A1)
    case TIMER5A:
      val = OCR5A; // get pwm duty
      break;
#endif

#if defined(TCCR5A) && defined(COM5B1)
    case TIMER5B:
      val = OCR5B; // get pwm duty
      break;
#endif

#if defined(TCCR5A) && defined(COM5C1)
    case TIMER5C:
      val = OCR5C; // get pwm duty
      break;
#endif

    case NOT_ON_TIMER:
    default:
      val = digitalRead(pin);
  }
  return (val);
}

I have only one code which is the fade LED code available on Arduino IDE which is customized as below:

// brightness and fadeamount is set to 5 initially
void salonledon() {
  while (brightness > 0) {
    brightness = brightness - fadeAmount;
    analogWrite(salonled, brightness);
    delay(50);
  }
}

salonledon function is called where salonled is mapped to Pin3 of arduino Leonardo.

Thanks for posting the code and sorry for the delay in response.

I tried it on the arduino with LED's and it seems to have messed up the sequence. D3 turns on (Just turns on without any fade effect) followed by other LED's. However, D3 turns on in between again randomly and turns off.

Your previous code was easier as I was able to follow it. The last option is to use the previous code and add the above function. The only drawback is that until the salonled function is complete, the board does not respond to IR remote control.

If I have not been clear enough on the project, here is a brief description of the same since if I am not clear enough, I might end up in confusing everyone.

  1. IR Remote power button is pressed to initiate the project
  2. Two Green LED's connected to D2 turns on (all LED's are active low. Giving a LOW turns it on)
  3. This follows one Warm white LED connected to D3 which fades in from 5 to 255 and stays on, connected to D7
  4. Four White LED's connected to D8 turn on
  5. One Cool White LED connected to A0 turns on
  6. Four Cool White LED's connected to A1 turns on

Once all the LED's are turned on, it reverses the cycle in turning off the last turned LED. Last In First Out concept. There is a 5 second delay between each steps and once the complete cycle of turn on and turn off is complete, it stays off for 5 minutes and repeats the cycle.

IR remote code is decoded and each button press turns on an LED. This part is already done and should be ok.

Regarding the problem, the previous code you provided was awesome with the exact delay I expected. The only addition was to include one LED fading in between.

I will try to expand the same solution if feasible and also check the latest code provided though it seems very expansive. Thanks again.

praveen_khm:
I have only one code which is the fade LED code available on Arduino IDE which is customized as below:

// brightness and fadeamount is set to 5 initially

void salonledon() {
 while (brightness > 0) {
   brightness = brightness - fadeAmount;
   analogWrite(salonled, brightness);
   delay(50);
 }
}




salonled is called mapped to Pin3 of arduino Leonardo.

Thanks for posting the code and sorry for the delay in response. I tried it on the arduino with LED's and it seems to have messed up the sequence. D3 turns on (Just turns on without any fade effect) followed by other LED's. However, D3 turns on in between and turns off. Your previous code was easier as I was able to follow it. The last option is to use the previous code and add the above function. The only drawback is that until the salonled function is complete, the board does not respond to IR remote control.


If I have not been clear enough on the project, here is a brief description of the same since if I am not clear enough, I might end up in confusing everyone. 

1. IR Remote power button is pressed to initiate the project
2. Two Green LED's connected to D2 turns on (all LED's are active low. Giving a LOW turns it on)
3. This follows one Warm white LED connected to D3 which fades in from 5 to 255 and stays on, connected to D7
4. Four White LED's connected to D8 turn on
5. One Cool White LED connected to A0 turns on
6. Four Cool White LED's connected to A1 turns on

There is a 5 second delay between each steps and once the complete cycle of turn on and turn off is complete, it stays off for 5 minutes and repeats the cycle. 

IR remote code is decoded and each button press turns on an LED. This part is already done and should be ok. 

Regarding the problem, the previous code you provided was awesome with the exact delay I expected. The only addition was to include one LED fading in between. 

I will try to expand the same solution if feasible and also check the latest code provided though it seems very expansive. Thanks again.

Every detail helps :slight_smile:
Here is the code you are looking for

// Pegasus specific LED pin assignments
int LED1 = 2;
int LED2 = 3;   //slowly turn on
int LED3 = 7;
int LED4 = 8;
int LED5 = A0;
int LED6 = A1;

void setup() {
  Serial.begin(115200);
}

void loop() {
  static int fadeAmount = 5;
  static int brightness = 5;
  static int FiveSecondsCtr = 0;
  static unsigned long ExactTimer;
  if ( millis() - ExactTimer >= (5000)) {
    ExactTimer += (5000); // This BWD timer is exact because it shifts the time for next event by an exact amount. it is prone to triggering rapidly to catch up if other code delays too long
    FiveSecondsCtr++;
    if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
    Serial.println(abs(FiveSecondsCtr));
    digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
    digitalWrite(LED2, (abs(FiveSecondsCtr) >= 2) ? LOW : HIGH);
    fadeAmount = (abs(FiveSecondsCtr) >= 3) ? -5 : 5; // fading faster or slower or instantanious set this between 0 and 255
    digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
    digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
    digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
  }
  static unsigned long DimTimer; 
  if ( millis() - DimTimer >= (50)) { // this BWD timer is not exact but it doesn't have to be
    DimTimer += millis();
    brightness = constrain(brightness - fadeAmount, 5, 255);
    analogWrite(LED2, brightness);
  }
}

much simpler with only one fading in and out and your IR remote code shouldn't be affected
Z

Thanks for the solution. I modified the code a little bit as the here is the working code.
Of course, the IR does not work for 5 seconds when the LED fades in and fades out, but I guess I need to execute it as is. Thanks for every support provided and for the great learning :slight_smile:

void loop() {
static unsigned long ExactTimer;
int brightness = 255;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by
  if(powerstatus){
    static int FiveSecondsCtr = 0;
    static unsigned long delayTime;
    if ( millis() - ExactTimer >= (delayTime)) {
      ExactTimer += (delayTime);
      FiveSecondsCtr++;
      if (FiveSecondsCtr > 6) FiveSecondsCtr = -5;
      delayTime =  (abs(FiveSecondsCtr) == 0) ? 15000 : 5000;
      digitalWrite(LED1, (abs(FiveSecondsCtr) >= 1) ? LOW : HIGH);
      if (FiveSecondsCtr == 2) salonledon();
      else if (FiveSecondsCtr == -2) salonledoff();
      digitalWrite(LED3, (abs(FiveSecondsCtr) >= 3) ? LOW : HIGH);
      digitalWrite(LED4, (abs(FiveSecondsCtr) >= 4) ? LOW : HIGH);
      digitalWrite(LED5, (abs(FiveSecondsCtr) >= 5) ? LOW : HIGH);
      digitalWrite(LED6, (abs(FiveSecondsCtr) >= 6) ? LOW : HIGH);
    }
  }
}

void salonledon() {
  int brightness = 255;
  int fadeAmount = 5;
  while (brightness > 0) {
    brightness = brightness - fadeAmount;
    analogWrite(LED2, brightness);
    delay(50);
  }
}

void salonledoff() {
  int brightness = 0;
  int fadeAmount = 5;
  while (brightness < 255) {
    brightness = brightness + fadeAmount;
    analogWrite(LED2, brightness);
    delay(50);
  }
}