Using millis for different time increments

how would I code using millis if I want an LED to turn on for 5 seconds, and then turn off for 30 seconds, and to repeat

In principle :
have one pair of constant variables for each length of time.
have one variable to store the 'start' time for each loop
one variable to store the state of the LED.
Then
Start a loop
check the state of the LED
get the current time
check if it's 'X' milliseconds later than the stored time (X being the right amount for on or off depending what it is )
If it is, change the state and set the LED to the new state and get the current time and store that to the stored time
Back to the start of the loop

1 Like

Is it without blocking the MCU? If yes, then we may execute the following sketch:

unsigned long prMillis = 0;
byte ledState = HIGH;
bool flag = false;


void setup()
{
  Serial.begin(9600);
  pinMode(13, OUTPUT);
  digitalWrite(13, ledState);   //LED is ON
  flag = true;
  prMillis = millis();
}

void loop()
{
  if (flag == true)
  {
    if (millis() - prMillis >= 5000)//5-sec is over
    {
      ledState = !ledState;
      digitalWrite(13, ledState); //LED is OFF
      flag = false;
      prMillis = millis();
    }
  }
  else
  {
    if (millis() - prMillis >= 30000)//30-sec is over
    {
      ledState = !ledState;
      digitalWrite(13, ledState); //LED is OFF
      flag = true;
      prMillis = millis();
    }
  }
}
long int lastchange = millis();
bool on = false;

void blikit(){
 int interval = (on)? 5*1000 : 30*1000;
 if (millis() > lastchange + interval){
on = !on;
lastchange = millis();
digitalWrite(whateverpin, on);
}
}

void setup(){
// your setup here
}

void loop(){
blinkit();
// your loop here
}
2 Likes

using:

Noiasca Took Kit for LEDs (rothschopf.net)

#include <Noiasca_led.h>
BlinkPin blinkLed {13};              // declare one blinking LED and assign pin 13

void setup() {
  blinkLed.begin();                   // you have to call the .begin() method for this LED
  blinkLed.setInterval(5000, 30000);  // optional: you can define the ON and OFF times in milliseconds
  blinkLed.on();                      // switch the blinking on
}

void loop() {
  blinkLed.update();                 // call the update function in loop() to refresh the LED
}

Well, if you all gonna show a sketch with different on and off times, then I can join :smiley:

// ---------------------------------------------
// millis_different_on_and_off_times.ino
// ---------------------------------------------
// License: The Unlicense, Public Domain.
// Author: Koepel
// 2019 january 23
// ---------------------------------------------
// 
// millis() demo with different "on" and "off" times.
//
// The led of the Arduino board is used.
// It is "on" for a short time, with a few seconds in between.
//
// Created and tested at Tinkercad.com
//

unsigned long previousMillis;
unsigned long interval = 1000; // start value set to 1 second
int ledState = LOW;            // led is off at start.

void setup()
{
  pinMode( LED_BUILTIN, OUTPUT);
}

void loop()
{
  unsigned long currentMillis = millis();
  
  if( currentMillis - previousMillis >= interval)
  {
    previousMillis = currentMillis;
    
    if( ledState == HIGH) // led was on ?
    {
      interval = 3000;    // new interval is a few seconds
      ledState = LOW;     // new led state is off
    }
    else                  // led was off
    {
      interval = 400;     // new interval is a short time
      ledState = HIGH;    // new led state is on
    }
    
    digitalWrite( LED_BUILTIN, ledState); // set new led state
  }
}

I have more examples at my "Fun with millis" at Github.

Example by GolamMostafa : I think it can be simpler. It is allowed to change the interval value itself. The digitalWrite() function takes a HIGH or LOW, not a true or false.

Example by YOS : I'm sorry, but your sketch does not fix the rollover problem. Read the Blink Without Delay once more. There is no rollover problem when "unsigned long" variables are used and the subtraction "millis() - previousMillis" is used.

Example by noiasca : Sometimes a library is easier for new users. Are you willing to put the library on Github ?

1 Like

===> void blinkit()

The sketch is working well!

it's on my todo list but not before Christmas, year unknown :wink:

Wait 25 days and (if I'm reading it right), the blinking will go crazy fast. Reason: lastchange is long int (which is signed), so around 25 days after startup millis() will be a very large negative number when cast to long int, so millis() > lastchange + interval will be true for another 25 days or so.

Whatever the case, the code is buggy. Only comparisons of the form millis() - lastchange >= interval are correct, and lastchange must be unsigned long.

1 Like

That variable should be an unsigned long as you have meticulously detected; time cannot be a negative quantity.

It can if you travel back in time. :wink:

Very well spotted.
Thinking about it, defining lastchange as unsigned long will give us more time, but the program is still buggy, as eventually millis() will overflow and start from zero again. When this happens, lastchange will be a very big number and millis() will be a small number, so the condition
millis() > lastchange + interval won't ever be true (until millis() overflows again).

Hello shadowspear

This sketch is using an array to control the timing.
Check it, test it and have fun.

constexpr unsigned long Duration[] {30000,5000};
unsigned long currentTime;
void setup() 
{
    pinMode(LED_BUILTIN,OUTPUT);
    digitalWrite(LED_BUILTIN,HIGH);
}
void loop() 
{
    if (millis()-currentTime >= Duration[digitalRead(LED_BUILTIN)])
    {
      currentTime=millis();
      digitalWrite(LED_BUILTIN,!digitalRead(LED_BUILTIN));
    }
}

You can make it easy by using this led library.

#include <ezLED.h> // ezLED library

ezLED led(9);  // create a LED object that attach to pin 9

void setup() {
  led.blink(5000, 30000);         // 5sec ON, 30sec OFF
}

void loop() {
  led.loop(); // MUST call the led.loop() function in loop()
}

The library already used mills() inside. You do not need to care about timing.

Not if you use the standard form mentioned in post #9, because the subtraction instead of addition avoids the wraparound issue. It works.

1 Like

Are you referring to "Wrist-Watch Time" or the "Time Component" of "Space-Time"?

This will fail when millis() rolls over. Always use

 if (millis() - lastchange >= interval){

Works fine!

However, library named ezLED.h is not found in the net. The led-main.zip file is included in the IDE and now the ezLED.h is recognized and the sketch works.

You can install via Library Manager on Arduino IDE like below:

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