Can someone rewrite this basic delay code in this post into millis as a reference

Hi Arduino forum users,

I have been told time and time again that millis is much better than delay as it does not stop the code.

I am having trouble with the logic and understanding of how to actually convert a delay to millis in the code.

Someone on the board posted a very lengthy post about how to use millis but it's all too complex.

I would like to see a before and after of a bunch of code of how millis would be implemented.

Here is the Arduino.cc's delay code. How do you convert the delays into Millis
would someone be so kind as to rewrite the two delays below into millis.

int ledPin = 13;              // LED connected to digital pin 13

void setup() {
  pinMode(ledPin, OUTPUT);    // sets the digital pin as output
}

void loop() {
  digitalWrite(ledPin, HIGH); // sets the LED on
  delay(2000);                // waits for 2 seconds
  digitalWrite(ledPin, LOW);  // sets the LED off
  delay(500);                // waits for half a second
}

Many thanks.
Shaun.

First, have you seen the BlinkWithoutDelay sketch? It's not complicated.

...and this comment is wrong

  delay(500);                // waits for a second
1 Like

I just used google, but this guide has a pretty simple explanation. Arduino Tutorial: Using millis() Instead of delay() – Norwegian Creations

1 Like

Hi aarg,
I Fixed the comment,

Hi Asyork,
I will take a good look at the page you provided, I will try follow it along later after work and see if I can convert the code here into millis myself.

Cheers

This tutorial is good: https://www.baldengineer.com/blink-without-delay-explained.html

In the code above, there is no reason to not use delay(mS);
Putting the effort into rewriting the code to be non-blocking is a good exercise in understanding how to write better code, but as the code stands with the example, there is absolutely nothing wrong.

Good advice when dealing with sketches that do not tolerate blocking code; that is you want the loop() to complete as fast as it can run. Often the forum will recommend reading about state-machines or other stuff, great knowledge, but for newbies, it can sometime be frustrating. The bottom line is that experience will make you a better coder but if you write code and the program does everything correctly to your satisfaction, then smile and go to the next project. Consider that if delay(mS) was so evil, why would the smart developers put the function into Arduino in the first place?
Arduino Reference - Arduino Reference

Guys I need help,

This stuff if frustrating.

How is it that those examples given can assist me? none of them show how to create the different delays. I need some kind of delay1+delay2

I am not seeing any way to make millis do as my delay does above, having the two different values.

I have been playing around with the code,

all the examples just use repeating values. like millis delay1 2000ms, meaning reoccurs at (2,4,6,8s etc) I need the delay2 factored into the timing to alter delay1. to add the 500ms on top.

if I add code to double up and have millis delay2 at 2500ms, (2.5s, 5s, 7.5s) works fine first time (delay1=2s, delay2=2.5s), but then the timing is way off. delay1=4s, delay2=5s. Then more off. delay1=6s, delay2=7.5s

as millis repeats the timed event, I am not sure how to stack the time. for example millis delay1 + millis delay2

I am also concerned for if the delay1 changes from 2000ms to 3000ms I would for coding sake want the delay2 added to delay1, creating a situation that needs the LED to turn off at 3500ms.

eg: this was a good example of showing what millis can do, the repeated delayed messages, I simply added line to turn on and turn off the LED. .

/*

int ledPin = 13;              // LED connected to digital pin 13
#define INTERVAL_MESSAGE1 2000 // turn on for 2000ms
//#define INTERVAL_MESSAGE2 500 //THIS REPEATS EVERY 500MS :(
#define INTERVAL_MESSAGE2 2500 //THIS REPEATS EVERY 2500ms works fine first time.

 
unsigned long time_1 = 0;
unsigned long time_2 = 0;
 
void print_time(unsigned long time_millis);
 
void setup() {
    Serial.begin(115200);
}
 
void loop() {
    if(millis() >= time_1 + INTERVAL_MESSAGE1){
        time_1 +=INTERVAL_MESSAGE1;
        print_time(time_1);
        Serial.println("Light On");
        digitalWrite(ledPin, HIGH);
    }
   
    if(millis() >= time_2 + INTERVAL_MESSAGE2){
        time_2 +=INTERVAL_MESSAGE2;
        print_time(time_2);
        Serial.println("Light Off");
        digitalWrite(ledPin, LOW);
    }

}
 void print_time(unsigned long time_millis){
    Serial.print("Time: ");
    Serial.print(time_millis/1000.00);
    Serial.print("s - ");
}
*/

I was looking to see if I can somehow make the delay2 stack on top of the delay1 by trying lines like this
time_2 +=INTERVAL_MESSAGE2 + INTERVAL_MESSAGE1;

the 2000ms and 500ms will when my project is complete would vary with adjustable potentiometers and I would like to find a way to make both the delays know what the other is doing.

basically want to use delay which may be variable, but using millis in it's place as I might want to run another code while thats occuring instead of using two arduinos.

Also, I taken a look at the blink without delay,
I understand that the blink without delay using if commands, I would like to avoid if command

I am so lost.

Regards,
Shaun.

Because what you are asking is impossible. If you replace a delays with one written with millis you get exactly the same blocking code as you would get with a delay.
it is not so much the millis that is the magic ingredient it is how it is used in writing code that is not blocking.

Simply define a variable for each delay you want to use, fill it with a value mapped from the pot reading and call delay( delay1 + delay2)

Then you can read these values.

What exactly do you mean by "delays know what the other is doing"?

you need think in terms of state machine when you have multiple actions that need to happen based on some events.

may be something like this

the code

const byte ledPin = LED_BUILTIN;

const unsigned long timeout_ON = 2000;
const unsigned long timeout_OFF = 500;
unsigned long lastEvent;

enum : byte {LED_ON, LED_OFF} state = LED_OFF;

void ledOn() {
  digitalWrite(ledPin, HIGH);
  state = LED_ON;
  lastEvent = millis();
  Serial.println(F("ON"));
}

void ledOff() {
  digitalWrite(ledPin, LOW);
  state = LED_OFF;
  lastEvent = millis();
  Serial.println(F("OFF"));
}

void process() {
  switch (state) {
    case LED_ON:
      if (millis() - lastEvent >= timeout_ON) ledOff();
      break;

    case LED_OFF:
      if (millis() - lastEvent >= timeout_OFF) ledOn();
      break;
  }
}

void setup() {
  pinMode(ledPin, OUTPUT);
  ledOff();
  Serial.begin(115200);
}

void loop() {
  process();
}
2 Likes

Hi,

Thanks for the code update, this works as intended, I am excited to see what you have done to make this work,

I will experiment this to bring into my code and see if I can improve performance.

Thanks,
Shaun

Even if J-M-L's code is more versatile, a solution could be much simpler:

const uint8_t LED_PIN = 13;
const uint16_t STATE_DELAY[] = {500, 1000};

uint32_t last_change = 0;
uint8_t led_state = 0;

void setup()
{
  //Initialize LED pin
  pinMode(LED_PIN, OUTPUT);
  digitalWrite(LED_PIN, LOW);
}

void loop()
{
  uint32_t ms = millis();
  if (ms - last_change >= STATE_DELAY[led_state])
  {
    led_state ^= 1; //Flip between 0 and 1
    last_change = ms;
    digitalWrite(LED_PIN, led_state == 0 ? LOW : HIGH);
  }
}

yes I tried to illustrate a more generic approach. for such a simple example alternating between two delays is enough

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