Millis() led alternative blink

Hi to all, I'm new at this forum but I like too much my UNO!!!

I have a little problem like this:
I need to blink three leds but not all at the same time, using millis(), al this sequence:

first led on for two minutes, than off for four minutes
second led on for two minutes but start only after the first led turned off
third led on for two minutes, after the second led turned off

and than loop starting with the first led on for two minutes and than forever.

this because I need to have a continuos loop to switch on and off leds for my application.

It works fine with delay, but I need to display temperature in real time and so this is impossible beacuse I need to wait every delay counting before to have temperature update.

// On and Off Times
const unsigned long ELT1onTime = 2000;
const unsigned long ELT1offTime = 2000;
const unsigned long ELT2onTime = 2000;
const unsigned long ELT2offTime = 2000;
const unsigned long ELT3onTime = 2000;
const unsigned long ELT3offTime = 2000;
 
// Tracks the last time event fired
unsigned long previousMillisELT1=0;
unsigned long previousMillisELT2=0;
unsigned long previousMillisELT3=0;
 
// Interval is how long we wait
int intervalELT1 = ELT1onTime;
int intervalELT2 = ELT2onTime;
int intervalELT3 = ELT3onTime;
 
// Used to track if LED should be on or off
boolean ELT1state = false;
boolean ELT2state = false;
boolean ELT3state = false;
 
// Usual Setup Stuff
void setup() {
  pinMode(7, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(8, OUTPUT);
}
 
void loop() {
  // Set Pin 13 to state of LED13state each timethrough loop()
  // If LED13State hasn't changed, neither will the pin
  digitalWrite(7, ELT1state);
  digitalWrite(9, ELT2state);
  digitalWrite(8, ELT3state);
 
  // Grab snapshot of current time, this keeps all timing
  // consistent, regardless of how much code is inside the next if-statement
  unsigned long currentMillis = millis();
 
  // Compare to previous capture to see if enough time has passed
  if ((unsigned long)(currentMillis - previousMillisELT1) >= intervalELT1) {
    // Change wait interval, based on current LED state
    if (ELT1state) {
      // LED is currently on, set time to stay off
      intervalELT1 = ELT1offTime;
      
      
    } 
    else {
      // LED is currently off, set time to stay on
      intervalELT1 = ELT1onTime;
      
    }
    // Toggle the LED's state, Fancy, eh!?
    ELT1state = !(ELT1state);
 
    // Save the current time to compare "later"
    previousMillisELT1 = currentMillis;
  }
if ((unsigned long)(currentMillis - previousMillisELT2) >= intervalELT2) {
    // Change wait interval, based on current LED state
    if (ELT2state) {
      // LED is currently on, set time to stay off
      intervalELT2 = ELT2offTime;
      
    } 
    else {
      // LED is currently off, set time to stay on
      intervalELT2 = ELT2onTime;
    }
    // Toggle the LED's state, Fancy, eh!?
    ELT2state = !(ELT2state);
 
    // Save the current time to compare "later"
    previousMillisELT2 = currentMillis;
  }
if ((unsigned long)(currentMillis - previousMillisELT3) >= intervalELT3) {
    // Change wait interval, based on current LED state
    if (ELT3state) {
      // LED is currently on, set time to stay off
      intervalELT3 = ELT3offTime;
      
    } 
    else {
      // LED is currently off, set time to stay on
      intervalELT3 = ELT3onTime;
    }
    // Toggle the LED's state, Fancy, eh!?
    ELT3state = !(ELT3state);
 
    // Save the current time to compare "later"
    previousMillisELT3 = currentMillis;
  }
}

This code works fine, but only to have all the leds on and off at the same time,
I try to make thousends tests, but everytime I think to be near to the solution...nothing,
Please help me.
Thanks in advance

Best help is to read and study the logic in the first posting under "project guidance" called "
Demonstration code for several things at the same time".

You will need to think about the logic of how you are dealing with the LED on and off, but will let you control each LED the way you require. And will let you handle the temperature as well.

Paul

And do you also note you have the same timing for each led...

Another way to look at it is
led1 on, two minutes later move to led2, another two minutes later move to led 3 etc. Aka, switch to the next led every two minutes :wink:

Thanks for the answer,

but I'm still far away from the solution.

What I'm looking for is:

led 1 on for a time and than turn off till to the next loop
led 2 the same
led 3 the same

With delay there is no problem, but I need to display different sensors in real time and delay stop arduino waiting to count.
Really I try different way with millis, but I didn't find a solution.

Please help me.

Thanks

I had the code below in my stash from 2-3 years ago.

It's standard blink without delay (in functions though) but it caters a) for 3x leds and b) their on and off times can all differ.

I just added a 4th led controlled by a switch to prove that the blinking doesn't block.

(Edit: My code's not a full solution btw, since the starting of the 2nd and 3rd phases will need to be timed to lag so they start after the 1st and 2nd phases.)

/* Blink without Delay on Steroids

  This one puts bwod code in a function and
  allows for differing off and on times
  and for that to be with 2x independent LEDs

  ardy_guy 2017

  Turns on and off a light emitting diode(LED) connected to a digital
  pin, without using the delay() function.  This means that other code
  can run at the same time without being interrupted by the LED code.

  The circuit:
   3x blinking leds attached from pin 14, 15, 16 to ground.
   another led on 17
   at switch on pin 8 with pullup
   the switch turns the 4th led off and on to prove there's no blocking



  created 2005
  by David A. Mellis
  modified 8 Feb 2010
  by Paul Stoffregen

  This example code is in the public domain.


  http://www.arduino.cc/en/Tutorial/BlinkWithoutDelay
*/

// constants won't change. Used here to
// set pin numbers:
const int ledPin =  14;      // the number of the LED pin
const int led2Pin =  15;
const int led3Pin =  16;
const int led4Pin =  17;
const int switchPin =  8;

// Variables will change:
//led1
int ledState = LOW;             // ledState used to set the LED
long previousMillis = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval;           // interval at which to blink (milliseconds)
long onTime = 890;
long offTime = 105;

//led2

int led2State = LOW;             // ledState used to set the LED
long previousMillis2 = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval2;           // interval at which to blink (milliseconds)
long onTime2 = 275;
long offTime2 = 260;

//led3

int led3State = LOW;             // ledState used to set the LED
long previousMillis3 = 0;        // will store last time LED was updated

// the follow variables is a long because the time, measured in miliseconds,
// will quickly become a bigger number than can be stored in an int.
long interval3;           // interval at which to blink (milliseconds)
long onTime3 = 125;
long offTime3 = 1575;



void setup() {
  // set the digital pin as output:
  pinMode(ledPin, OUTPUT);
  pinMode(led2Pin, OUTPUT);
  pinMode(led3Pin, OUTPUT);
  pinMode(led4Pin, OUTPUT);
  pinMode(switchPin, INPUT_PULLUP);
}//end setup

void loop()
{
  // here is where you'd put code that needs to be running all the time.

  //control the 4th led to prove no blocking
  digitalWrite(led4Pin, !digitalRead(switchPin));

  //and bwod() is where all the bwod stuff is done
  bwod();
  bwod2();
  bwod3();
}//end loop

void bwod()
{

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis > interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;

    // if the LED is off turn it on and vice-versa:
    if (ledState == LOW)
    {
      ledState = HIGH;
      interval = onTime;
    }
    else
    {
      ledState = LOW;
      interval = offTime;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(ledPin, ledState);
  }
} //end bwod


void bwod2()
{

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis2 = millis();

  if (currentMillis2 - previousMillis2 > interval2) {
    // save the last time you blinked the LED
    previousMillis2 = currentMillis2;

    // if the LED is off turn it on and vice-versa:
    if (led2State == LOW)
    {
      led2State = HIGH;
      interval2 = onTime2;
    }
    else
    {
      led2State = LOW;
      interval2 = offTime2;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led2Pin, led2State);
  }
}//end bwod2

void bwod3()
{

  // check to see if it's time to blink the LED; that is, if the
  // difference between the current time and last time you blinked
  // the LED is bigger than the interval at which you want to
  // blink the LED.
  unsigned long currentMillis3 = millis();

  if (currentMillis3 - previousMillis3 > interval3) {
    // save the last time you blinked the LED
    previousMillis3 = currentMillis3;

    // if the LED is off turn it on and vice-versa:
    if (led3State == LOW)
    {
      led3State = HIGH;
      interval3 = onTime3;
    }
    else
    {
      led3State = LOW;
      interval3 = offTime3;
    }

    // set the LED with the ledState of the variable:
    digitalWrite(led3Pin, led3State);
  }
}//end bwod3

The demo Several Things at a Time is an extended example of BWoD and illustrates the use of millis() to manage timing. It blinks some LEDs and may help with understanding the technique.

...R

Well, you could do it by just setting the timing of each LED independently and starting them all at "zero". But this looks more like a state machine. It starts in one state, with one set of outputs then after 2 minutes it moves to another state with different outputs then there's a 3rd state and then it goes back to the first state again.

www.thebox.myzen.co.uk/Tutorial/State_Machine.html

MorganS:
But this looks more like a state machine. It starts in one state, with one set of outputs then after 2 minutes it moves to another state with different outputs then there's a 3rd state and then it goes back to the first state again.

When I posted the code* I had knocking around, I was thinking state machine too. But it's not quite that simple: in the OP's code the on/off times although the same, have their own variables. The implication of that is that they may vary one day, perhaps due to a rethink of the timings for optimal cleaning. In the general case it's not 3 sequential phases.

(*My code's not a full solution btw, since the starting of the 2nd and 3rd phases will need to be timed to lag so they start after the 1st and 2nd phases.)

ardy_guy:
When I posted the code* I had knocking around, I was thinking state machine too. But it’s not quite that simple: in the OP’s code the on/off times although the same, have their own variables. The implication of that is that they may vary one day, perhaps due to a rethink of the timings for optimal cleaning. In the general case it’s not 3 sequential phases.

As @Danpis78 described it, it’s N sequential phases :wink:

Danpis78:
first led on for two minutes, than off for four minutes
second led on for two minutes but start only after the first led turned off
third led on for two minutes, after the second led turned off

led1 on for two minutes, then off; the four minutes is redundant information as far as I can see.
2)
next led2 on for two minutes, then off
3)
next led3 on for two minutes, then off
4)
back to (1)

So you basically have a sequence of what must happen. Below is one way of implementing it and sufficient for your requirement (if I understood it correctly).

First we define a struct that defines information about the led (pin and ON duration).

struct LED
{
  byte pin;   // the led pin
  unsigned long onDuration; // the duration that it must be on
};

Using this approach it will be easy to give different ON durations if needed.

Next we declare an array of those structs with the pin number and the duration that they must be on.

LED leds[] =
{
  {7, 2000},
  {8, 2000},
  {9, 2000},
};

You need to adjust the durations to your needs
We also need a variable to hold the time

unsigned long currentTime;

The above can be placed somewhere before setup().

Next in setup() we can loop through the array using e.g. a for loop and initialise the led pins

void setup()
{
  // for debugging
  Serial.begin(250000);

  // get the current time
  currentTime = millis();

  // initialise
  for (int cnt = 0; cnt < sizeof(leds) / sizeof(leds[0]); cnt++)
  {
    // led pins output
    pinMode(leds[cnt].pin, OUTPUT);
    // startup setting LOW for all leds
    digitalWrite(leds[cnt].pin, LOW);
  }

  // debug
  Serial.println("starting . . . ");

  // first led on
  digitalWrite(leds[0].pin, HIGH);
  Serial.print("Time = "); Serial.print(currentTime);
  Serial.print(", leds["); Serial.print(0); Serial.println("] = ON");
}

void loop()
{
  // get the current time
  currentTime = millis();


}

At the end of setup(), the first led is switched on.

Note the use of sizeof(leds) / sizeof(leds[0]) which allows you to add or remove leds to /from the array without modifying anything else in the code.

We will fill in the rest of loop() a little later.

Now we need a function to loop through the led array and switch the leds on and off. The code uses two static variables; they are used to keep track of the current led and the start time when a led was switched on and will be remembered when the function ends.

void ledSequencer()
{
  // current led
  static byte currentLed = 0;
  // start time when led was switched on
  static unsigned long startTime = 0;

  // if it's time to switch one led off and another one on
  if (currentTime - startTime >= leds[currentLed].onDuration)
  {
    ...
    ...
  }
}

And we can fill in what needs to happen when it’s time to do something

void ledSequencer()
{
  // current led
  static byte currentLed = 0;
  // start time when led was switched on
  static unsigned long startTime = 0;

  // if it's time to switch one led off and another one on
  if (currentTime - startTime >= leds[currentLed].onDuration)
  {
    // switch current led off
    digitalWrite(leds[currentLed].pin, LOW);
    Serial.print("Time = "); Serial.print(millis());
    Serial.print(", leds["); Serial.print(currentLed); Serial.println("] = OFF");
    // reset start time
    startTime = currentTime;

    // next led
    currentLed++;

    // if at end of sequence
    if (currentLed == sizeof(leds) / sizeof(leds[0]))
    {
      // back to first led
      currentLed = 0;
    }

    // next led on
    digitalWrite(leds[currentLed].pin, HIGH);
    Serial.print("Time = "); Serial.print(millis());
    Serial.print(", leds["); Serial.print(currentLed); Serial.println("] = ON");
  }
}

Note: the code prints millis() instead of currentTime; that way one can see if timing gets out of sync if the code in this function would take longer than 1 ms.

And the last thing to do is call it from loop()

void loop()
{
  // getthe current time
  currentTime = millis();

  // run the led sequence
  ledSequencer();

  // do other work here
  ...
  ...
}