Using "millis" to create 2 different delays at the same time

I need to create a timing/delay for 2 outputs.
The first output would comes to HIGH at 0 seconds and stays HIGH for 20 seconds, then goes to LOW and remains LOW
The second output is LOW at 0 seconds and goes HIGH at 15 seconds and remains HIGH.
I would like accomplish this with using "millis", however I do not know if it is possible and how to do it.
Any guidance will be appreciated.
Thank You !

Show us your attempts at doing this.


BTW
Always show us a good schematic of your proposed circuit.

Show us a good image of your ‘actual’ wiring.

Great tutorial on how to do what you want: https://www.gammon.com.au/blink

this is programming question, I have no issue with anything schematic /circuit/wiring
so far I started with this....2 leds, and mixing millis and delay

int led2 = 11;
int led1 = 8;
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
void setup() {
pinMode(led1, OUTPUT); // initialize the digital pin as an output.
pinMode(led2, OUTPUT); // initialize the digital pin as an output.

digitalWrite(led1, 0); // turn led on
digitalWrite(led2, 1); //turn led2 off

delayStart = millis(); // start delay
delayRunning = true; // not finished yet
}
void loop() {
// check if delay has timed out after 20sec == 20000mS
if (delayRunning && ((millis() - delayStart) >= 20000)) {
delayRunning = false; // prevent this code being run more then once
digitalWrite(led1, 1); // turn led off
Serial.println("Turned LED Off");
}
// Other loop code here . . .
delay(5000);
digitalWrite(led2,0);
Serial.println("Run Other Code");
}

Please edit your post to add code tags.

Hint: in the Arduino editor, use CTRL-T to indent the code before copy/paste to the forum. The indenting helps with readability and to catch errors in program structure.

(post deleted by author)

(post deleted by author)

int led2 = 11;
int led1 = 8;
unsigned long delayStart = 0; // the time the delay started
bool delayRunning = false; // true if still waiting for delay to finish
void setup() {
  pinMode(led1, OUTPUT); // initialize the digital pin as an output.
  pinMode(led2, OUTPUT); // initialize the digital pin as an output.

  digitalWrite(led1, 0); // turn led on
  digitalWrite(led2, 1); //turn led2 off

  delayStart = millis(); // start delay
  delayRunning = true; // not finished yet
}
void loop() {
  // check if delay has timed out after 20sec == 20000mS
  if (delayRunning && ((millis() - delayStart) >= 20000)) {
    delayRunning = false; // prevent this code being run more then once
    digitalWrite(led1, 1); // turn led off
    Serial.println("Turned LED Off");
  }
  // Other loop code here . . .
  delay(5000);
  digitalWrite(led2, 0);
  Serial.println("Run Other Code");
}

Using delay() defeats the purpose of using millis() for timing.

If you want to solve the problem, please take a look at the tutorial I linked earlier.

Are you really need a delayRunning flag?

I think you can easily rid of the flag and use similar code for second led.

Well, it does "prevent this code being run more then once" :thinking:

consider

struct Tmr {
    byte            pin;
    byte            startState;
    unsigned long   msec;
    bool            done;            
};

Tmr tmrs [] = {
    { 8,  HIGH, 20000 },
    { 11, LOW,  15000 },
};

#define Ntmr    (sizeof(tmrs)/sizeof(Tmr))
unsigned msecLst;

// -----------------------------------------------------------------------------
void loop ()
{
    unsigned long msec = millis ();

    Tmr *t = tmrs;
    for (unsigned n = 0; n < Ntmr; n++, t++) {
        if (! t->done && msec - msecLst >= t->msec)  {
            digitalWrite (t->pin, ! t->startState);
            t->done = true;
        }
    }
}

void setup ()
{
    Tmr *t = tmrs;
    for (unsigned n = 0; n < Ntmr; n++, t++) {
        pinMode (t->pin, OUTPUT);
        digitalWrite (t->pin, t->startState);
    }

    msecLst = millis ();
}

Demo-Code that shows how to execute 3 parts of code at 3 different periods

unsigned long DemoTimerA = 0; // variables that are used to store timeInformation
unsigned long DemoTimerB = 0; 
unsigned long DemoTimerC = 0; 
unsigned long DoDelayTimer = 0; 

// easy to use helper-function for non-blocking timing
boolean TimePeriodIsOver (unsigned long &startOfPeriod, unsigned long TimePeriod) {
  unsigned long currentMillis  = millis();
  if ( currentMillis - startOfPeriod >= TimePeriod ) {
    // more time than TimePeriod has elapsed since last time if-condition was true
    startOfPeriod = currentMillis; // a new period starts right here so set new starttime
    return true;
  }
  else return false;            // actual TimePeriod is NOT yet over
}

void setup() {
  Serial.begin(115200);
  Serial.println("Program started activate Show timestamp in serial monitor");
}

void loop() {
  if (  TimePeriodIsOver(DemoTimerA,1000)  ){
      Serial.println(" TimerA overDue");
    }
       
  if (  TimePeriodIsOver(DemoTimerB,2000)  ){
      Serial.println("                TimerB overDue");
    }

  if (  TimePeriodIsOver(DemoTimerC,3000)  ) {
      Serial.println("                               TimerC overDue");
    }

  if (  TimePeriodIsOver(DoDelayTimer,20000)  ){
      Serial.println("every 20 seconds execute delay(3500)... to make all other timers overdue");
      delay(3500);
    }    
}

taken from this tutorial

shall this be a behaviour that shall happen only once and then never again
or
shall this be a behaviour that will be repeated?

This makes a great difference how to code it.

This is a common question, try this: Flashing 2 or more LEDs at the same time

Hello jenom

Keep it simple and stupid.
Try, check and modify this C++ sketch to you needs.

/* BLOCK COMMENT
  - https://forum.arduino.cc/t/using-millis-to-create-2-different-delays-at-the-same-time/1063664
  - Using “millis” to create 2 different delays at the same time
  - This sketch may contain traces of C++.
  - In case of indisposition:
  - https://www.learncpp.com/
  - Hardware:
  - Thanks to LarryD
  - https://aws1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
  - Tested @ Arduino: Mega[X] - UNO [ ] - Nano [ ]
*/
enum LedColour{Red, Green};
enum TimerControl {Off,On};
constexpr byte LedPins[] {9,10};
struct MYDELAY {
  int identifier;
  const byte Pin;
  const unsigned long Duration;
  unsigned long stamp;
  int onOffControl;
};
MYDELAY myDelays[] {
  {Red,LedPins[Red], 20000, 0, On},
  {Green,LedPins[Green], 15000, 0, On},
};

void setup()
{
  for (auto myDelay:myDelays) pinMode(myDelay.Pin,OUTPUT);
  digitalWrite(myDelays[Red].Pin,HIGH);
}
void loop()
{
  unsigned long currentTime=millis();
  for (auto &myDelay:myDelays)
  {
    if (currentTime-myDelay.stamp>=myDelay.Duration && myDelay.onOffControl)
    {
      switch (myDelay.identifier) 
      {
        case Red:
        digitalWrite(myDelay.Pin,LOW);
        myDelay.onOffControl=Off;
        break;
        case Green:
        digitalWrite(myDelay.Pin,HIGH);
        myDelay.onOffControl=Off;
        break;
      }
    }
  }
}

Have a nice day and enjoy coding in C++.

thank you for all the replies and advises
created a short & simple sketch using only "millis" and "if" commands
--led1comes to HIGH at 0 seconds and stays HIGH for 20 seconds, then goes to LOW and remains LOW
--led2 is LOW at 0 seconds and goes HIGH at 15 seconds and remains HIGH.

int led2 = 11;
int led1 = 8;
unsigned long delayStart = 0;   // the time the delay started
bool delayRunning = false;      // true if still waiting for delay to finish
void setup()
{
  pinMode(led1, OUTPUT);        // initialize the digital pin as an output.
  pinMode(led2, OUTPUT);        // initialize the digital pin as an output.

  digitalWrite(led1, 0);        // turn led1 ON
  digitalWrite(led2, 1);        //turn led2 OFF

  delayStart = millis();        // start delay
  delayRunning = true;          // not finished yet
}
void loop()
{
  if (delayRunning && ((millis() - delayStart) >= 20000)) // delay has timed out after 20 sec
  {
    digitalWrite(led1, 1);            // turn led off
  }

  if (delayRunning && ((millis() - delayStart) >= 15000))  //delay has timed out after 15 sec
  {
    digitalWrite(led2, 0);            // turn led ON
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.