Arduino Sketch with millis() instead of delay()

Are you trying to build a project using Arduino and you need to program repetitive timed events?

Are you looking for alternatives to the delay() function to achieve this?

Have you heard of the millis() function?

The wait is over. This lesson is for you.

How we got here

If you’ve watched the previous lessons, we’ve described the basics of millis function in general (part 1), we’ve talked about tight loops and blocking code (part 2), and we’ve discussed some issues that arise when using the delay function (part 3 and part 4).

In this lesson

  • Quick review of the millis function
  • The millis timeline
  • Create once-off timed events
  • Create repetitive timed events
  • How black holes can alter space-time

Millis Review

The easiest way to review this function is to look at it in a simple sketch. Let’s write a sketch that prints the value of millis to the serial monitor window.

In the Arduino IDE we’re going to begin in the setup section and use this Serial.begin function to enable serial communication.

Then in the loop we’re going to use the Serial.println (println = print line) function to print the value of millis.

void setup() {

  Serial.begin(9600);

}

void loop() {

  Serial.println( millis() );

}

Each time through the loop, this program will print the current value of the millis function. If we load this sketch onto our Arduino and open up the serial monitor window, you’ll see the value of millis is increasing rapidly.

Arduino Millis function value printed to serial monitor

So what is this value that the millis function returns?

The millis function returns the number of milliseconds that your Arduino board has been powered up.

Programming Electronics Academy members, check out the Writing Functions section of the Arduino Course for Absolute Beginners to master coding your own functions.

Not a member yet?  Sign up here.

In other words, when you upload your sketch to your Arduino, as soon as the upload is complete, the clock starts. Millis returns the number of milliseconds that have passed since this upload was completed.

Essentially, it’s a timer for how long the current program has been running. This is independent of the number of times the “void loop ()” has iterated.

So how high can it count up? It can count to 4,294,967,296… it would take 49 days to reach this number. Once it hits this number it “overflows”, which is just a fancy way of saying it then starts back over at zero and resumes counting up.

The way millis is able to track the number of milliseconds that have passed is by using the timer counter module that is built into the integrated circuit on the Arduino.

We don’t have to start the clock or start millis in our code, it starts all by itself in the background.

If you want to learn more about how the millis function works, definitely check out the first lesson in the series.

Millis timeline concept

To conceptualize millis so that we can use it to create timed repetitive events, let’s start by thinking of millis as moving along a timeline.

The timeline starts at zero and it goes all the way up to four billion and some change, and these numbers represent milliseconds.

So at any point during our program, we can call the millis function, and find out exactly where on the timeline we are.

Arduino millis timeline

Let’s take a look at the first five seconds of a program. The little dot (in the picture below) represents where millis is on the timeline.

As soon as we power up Arduino, the millis function starts counting. You can see the value is increasing and moving to the right along the time axis. If we want to create timed repetitive events, how could we use this timeline to our advantage?

Programming Electronics Academy members, check out the Control Structures section of the Arduino Course for Absolute Beginners to learn and practice your programming control flow.

Not a member yet?  Sign up here.

Once-Off Millis Event

Let’s look ahead (in time) and create an event. When the value of millis gets to our predetermined time, we want a specific action to occur.

Arduino timeline gif

In code it might look something like this:

const unsigned long event_1 = 1000;

void setup() {

}

void loop() {

  if ( millis() > event_1 ) {

    //Make fish taco...
    
  }
}

Let’s talk through this sketch from the point when power is first applied. Power is applied, we get into the loop, and the first thing our sketch does is check millis.

Since it just began, the value of millis is low (less than 1000 ms). Since event_1 is equal to 1000, the if statement condition is false, and the code in the curly brackets doesn’t run.

This loop will continue to execute over and over, and the if statement will continue to get passed over since the condition is still false.

This won’t last long, however, as the value of millis is increasing rapidly. Once millis exceeds the value of event_1, the if statement condition becomes true, and the code within the if statement begins to execute.

Congratulations, we’ve officially created a timed event using millis!

Arduino millis chef

But this really isn’t exactly what we’re after. You could achieve the same thing with a delay function. What’s nice with using millis, however, is we can do other stuff in a loop (unlike delay). We can read a sensor, update a display, or whatever we want.

Said another way, the millis function won’t block other code from running like the delay function would. Furthermore, we could add additional events that trigger at later times.  Next let’s see how we can use millis to create repetitive timed events.

Repetitive events using Millis

For example, every 30 seconds could read the water temperature, or every minute we could have a servo motor move left and then right again. For these types of programs, this simple use of millis won’t do it.

Let’s go back to our timeline. We still have our event_1, and when millis exceeds this value, the event is triggered. But in addition to triggering an action, the event_1 time will also need to be reset to further down timeline.

Arduino repetitive event using millis

Essentially what we’re doing is every time our event is triggered, we create a new updated time for our event, allowing us to repeat this timed event over and over again. Let’s try some code and see what this might look like.

The first thing we’re going to do is set the interval of the event. So let’s create a constant named eventInterval. We have it as a constant because the interval isn’t going to change. We’ll set it to 1 second, or 1000 milliseconds.

Next we’re going to create a variable that we’re going to use to update the time, called previousTime. It’s an unsigned long because the value of millis gets extremely large, and we want to be able to hold that value in our variable.

We’ve talked about this in one of the previous lessons (part 1), so make sure to check it out to learn more about storing millis values.

In setup we’re going to start serial communication using the Serial.begin function. We do this to enable data to be sent to the serial monitor in the loop. Here’s what the code looks like so far:

const unsigned long eventInterval = 1000;
unsigned long previousTime = 0;

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

void loop() {
}

Programming Electronics Academy members, check out the Arduino Course for Absolute Beginners to practice using the Serial Library in your code.

Not a member yet?  Sign up here.

Down in the loop we’re going to create a variable that gets updated every time through the loop with the current time.

How do we get the current time? We just call the millis() function.

Remember, the millis function is going to report back to us where we are on that millis timeline. So let’s create a variable called currentTime and set it equal to the output of the millis function.

So every time through the loop, currentTime is going to be holding the current value of the millis function.

Now comes the key step. We want to create some type of function that is only going to happen when we’re at our eventInterval (which is 1000ms).

So every 1000 milliseconds, we want something to happen.  The code is below, and it may look like a doozy, but we’ll go through it step by step:

const unsigned long eventInterval = 1000;
unsigned long previousTime = 0;

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

void loop() {

  /* Updates frequently */
  unsigned long currentTime = millis();

  /* This is the event */
  if (currentTime - previousTime >= eventInterval) {
    /* Event code */
    Serial.println("Ice Ice Baby");
    
   /* Update the timing for the next time around */
    previousTime = currentTime;
  }
}

So what does this if statement do? It takes the current time (… remember the current time is constantly being updated at the beginning of each iteration of the loop), and it subtracts from the previous time. It then checks to see if the resultant value is greater than or equal to the eventInterval.

This will make more sense if we assign some numbers and do a few iterations as examples.

We know eventInterval is never going to change, it’s a constant, and we set it to 1000.

What about currentTime? Since it’s assigned to the value of the millis function, we know it’s constantly going to be increasing. Think of current time as just a big arrow up. It’s always getting bigger, and bigger, and bigger.

What about previousTime? Right now it’s set to zero. Let’s take a look at the code with these substitutions:

Arduino if statement values

Let’s talk about a few iterations through the loop. At first, currentTime will be very small number since the program has just begun (i.e. not much time has passed since millis started counting up from zero).

If you’d like to see the following explanation in tabular format, just scroll to the bottom of the lesson and find the table that summaries the iterations. Some people’s brains work best like this!

Iteration 1

Looking at an early in time example (let’s say 100 milliseconds have passed so far), currentTime is equal to 100. The difference between currentTime (100) and previous time (0) is 100, which is NOT greater than or equal to eventInterval (1000).

Therefore the if statement is false, none of the code inside the { } brackets is executed, and we go back the the beginning of the loop.

Iteration 2

Next, let’s say 200 milliseconds have passed so far. Therefore, currentTime (200) – previousTime (0) = 200, which is still NOT >= eventInterval (1000).

We will continue through the loop over and over again until the if statement is true, which will happen after 1 second, or 1000 milliseconds.

Iteration 3

In the next example, 1000 milliseconds have passed. Therefore, currentTime (1000) – previousTime (0) = 1000, which IS equal to eventInterval (1000). Now the code in the if statement is executed.

Serial.println will print “Ice Ice Baby” to the serial monitor.

But here comes the clever part, where we scooch down the event so that the next time around, we can have this event happen again in another thousand milliseconds.

Let’s take the previousTime, which was zero, and update it with the current time. The currentTime is 1000, so now previousTime is also equal to 1000. So we’ve printed to the serial monitor, we’ve updated the time, and now we exit the if statement and go right back into the loop.

Iteration 4

Now let’s say 1010 milliseconds have passed. If we subtract currentTime (1010) from the new previousTime (1000), we get 10. This is not greater or equal to 1000, so we skip over the if statement code.

You can see what’s going on here: we’re going to keep skipping over this code until another second has passed.

Iteration 5

After 2000 milliseconds have passed, the difference between currentTime and previousTime is 1000, therefore our if statement is true, and we print to the serial monitor.  We also update the previousTime again.

This right here is the coding paradigm that allows you to create repetitive timed events using your Arduino.

Admittedly, this can look a little tricky at first, and there seems to be a lot of variables. The best way to really get a handle on this, however, is to just write the program yourself and mess around with it.

Arduino millis iteration table
Tabular summary of the iterations

Review

First, we did a quick review of the millis function. You don’t have to “start” the millis function, it’s always counting. It starts at zero and represents how long, in milliseconds, the Arduino has been powered up (or since the last sketch upload). Remember it can count up to 4 billion and some change, and then it starts over again once it gets to the top.

Next, we discussed how it’s best to think about millis as a value moving down a timeline in our program. This helps us conceptualize how we can use millis to create timed events.

Then, we talked about creating “once-off” timed events using the millis function, and how that’s not much different that using the delay function.

Finally, we talked about creating repetitive timed events using the millis function.

We hope you found this lesson helpful. We’re going to have a couple more lessons about the millis function and how to use it in some interesting cases, so stick around and stay tuned for the next lesson! Have a great day.

Arduino black hole
installing Arduino libraries

Installing Arduino Libraries | Beginners Guide

IoT sewage project

Pumping poo! An IoT sewage project

ESP32 webOTA updates

How to update ESP32 firmware using web OTA [Guide + Code]

error message Brackets Thumbnail V1

expected declaration before ‘}’ token [SOLVED]

Compilation SOLVED | 1

Compilation error: expected ‘;’ before [SOLVED]

Learn how to structure your code

35 Comments

  1. Stephen Mann on April 22, 2019 at 12:14 am

    What happens if you set currenttime just a bit before millis() overflows?

    void loop() {
    /* Updates frequently */
    unsigned long currentTime = millis();
    /* This is the event */
    if (currentTime – previousTime >= eventInterval) {
    /* Event code */
    Serial.println(“Ice Ice Baby”);
    }
    }

    So, if previoustime= 4,294,967,296 will it take 49 days for currenttime to catch up?

    • Deve on July 2, 2019 at 3:05 am

      You skipped the line:

      previousTime = currentTime;

      that was added inside the if statement.

      With this line present the if statement after currentTime overflow will be something like

      0 -5x10E9 >= interval

      Since we’re dealing with unsigned integers, the above evaluates to true (5x10E9 >= interval) and the next value for previousTime will be 0 (a low currentTime).

      The interval in this iteration will not be correct but it will not crash or fail.

      • Michael James on July 2, 2019 at 10:12 am

        Thanks for pointing that out Deve, I added that line of code to the written lesson above.

      • JohnR on April 4, 2021 at 1:41 am

        Provided currentTime, previousTime and timeInterval are all assigned as unsigned long, an interval that overlaps the rollover will, in fact, still be correct.

        For example, if previous time was 4294967096 (i.e. 200 before rollover) and currentTime is 800 (i.e. 800 after rollover, currentTime – previousTime is exactly 1000 as an unsigned long.

  2. Preston on August 12, 2019 at 11:19 am

    I’m using the Arduino to program a robotic arm and currently we are using the delay function but some of the actions we need the robot to do are longer than others. How would you use the millis function in this code?

    }
    #define rxPin 10
    #define txPin 11

    SoftwareSerial mySerial(rxPin, txPin);
    LobotServoController myse(mySerial);

    void setup() {
    pinMode(13,OUTPUT);
    mySerial.begin(9600); //opens software serial port, sets data rate to 9600 bps
    Serial.begin(9600);
    digitalWrite(13,HIGH);

    void loop() {
    int START = 1;
    int STOP = 2;
    int RCVD = 0;
    if (Serial.available()) {
    RCVD = Serial.read() – ‘0’;
    Serial.println(RCVD, DEC);
    }
    if (RCVD == 1) {
    myse.runActionGroup(1,200); //loop run No.1 action group
    delay(9000);
    myse.stopActionGroup(); //stop running action group
    delay(1000);
    RCVD = 0;
    }
    }

    • Michael James on August 12, 2019 at 5:12 pm

      Great question Preston. My advice is to keep it as simple as possible.

      You might be able to get away with using delay for your actions and using variables to store different delay times for your different “Action Groups”

      Do you know if your “Action Groups” run blocking code? That is, once those functions are called, do they halt the rest of the program?

  3. saleh on August 15, 2019 at 11:17 pm

    best

    • Michael James on August 16, 2019 at 7:56 am

      Thanks Saleh!

      • Khaled on September 5, 2021 at 12:50 pm

        I would like to thank you for your efforts, your talent presenting these lessons and videos.
        I learned a lot from them and I appreciate your entertaining method in your lessons. I ignored the videos in the past as soon as I heard the starting music, however, it’s a matter of tase, I found it kind of scary 50s, wild, and dull; a heavy metal riff would be inviting, for me at least. I wish you success and relief.
        looking forward to more videos.
        Regards

  4. […] Arduino Sketch with millis() instead of delay() […]

  5. Will on March 27, 2020 at 5:18 am

    This is so well explained! thank you

  6. Christian on April 29, 2020 at 12:05 pm

    Salve, a tutti, vorrei una risposta in merito all’utilizzo di millis().
    Ho questo codice:

    void timer()
    {
    static unsigned long start_time = millis();

    if (millis() – start_time >= 1000) // Ogni secondo
    {
    start_time = millis();

    DateTime now = rtc.now();

    short days = now.day();
    short months = now.month();
    short years = now.year();
    short hours = now.hour();
    short minutes = now.minute();
    short seconds = now.second();

    Serial.print(days);
    Serial.print(F(“/”));
    Serial.print(months);
    Serial.print(F(“/”));
    Serial.print(years);
    Serial.print(F(” “));
    Serial.print(hours);
    Serial.print(‘:’);
    Serial.print(minutes);
    Serial.print(F(“:”));
    Serial.print(seconds);
    Serial.println();
    }

    E’ una semplice funzione che ogni secondo stampa l’ora.
    Se utilizzo if (millis() – start_time >= 1000) quando millis() raggiungerà il suo valore massimo dopo 49 giorni e varrà zero che succede? Si blocca la stampa delle ore o viene superato questo if?

    Grazie a tutti 🙂

  7. Christian on April 29, 2020 at 12:10 pm

    Hi, everyone, I would like an answer regarding the use of millis ().
    I have this code:

    void loop()
    {
    timer();
    }

    void timer()
    {
    static unsigned long start_time = millis();

    if (millis() – start_time >= 1000) // Ogni secondo
    {
    start_time = millis();

    DateTime now = rtc.now();

    short days = now.day();
    short months = now.month();
    short years = now.year();
    short hours = now.hour();
    short minutes = now.minute();
    short seconds = now.second();

    Serial.print(days);
    Serial.print(F(“/”));
    Serial.print(months);
    Serial.print(F(“/”));
    Serial.print(years);
    Serial.print(F(” “));
    Serial.print(hours);
    Serial.print(‘:’);
    Serial.print(minutes);
    Serial.print(F(“:”));
    Serial.print(seconds);
    Serial.println();
    }

    It is a simple function that prints the hour every second.
    If I use if (millis () – start_time> = 1000) when millis () reaches its maximum value after 49 days and will it be worth zero what happens? Is the printing of hours blocked or is this if exceeded?

    Thank you all ????

  8. Piero on June 16, 2020 at 10:00 am

    (millis() – start_time >= 1000 || millis()< start_time )

  9. Rupesh on July 19, 2020 at 7:32 am

    my question is

    upload this sketch in Arduino (LED blinking)

    how many cycles work Arduino program

    void setup() {
    // initialize digital pin LED_BUILTIN as an output.
    pinMode(LED_BUILTIN, OUTPUT);
    }

    // the loop function runs over and over again forever
    void loop() {
    digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
    delay(1000); // wait for a second
    digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
    delay(1000); // wait for a second
    }

  10. Tim on September 28, 2020 at 4:50 am

    //Hey! Thanks for the lesson! But I cant realize how the millis counter works. If I try to make multiple events I cant control every event independently.

    const unsigned long interval = 1400;
    const unsigned long LEDinterval = 100;
    const unsigned long interval2 = 1500;
    unsigned long previousTime = 0;
    int Led = 13;

    void setup()
    {
    Serial.begin(9600);
    pinMode (Led, OUTPUT);
    }

    void loop()
    {
    unsigned long currentTime = millis();

    if(currentTime – previousTime >= LEDinterval)
    {
    digitalWrite(Led, HIGH);
    }

    if (currentTime – previousTime >= interval)
    {
    Serial.println(“I’m not a break, I’m just a slow trottle!”);
    }
    if (currentTime – previousTime >= interval2)
    {
    Serial.println(“WINNER WINNER VEGAN DINNER”);
    previousTime = currentTime;
    }

    }

    • Michael James on September 28, 2020 at 10:02 am

      If I am not mistaken, you might what to try using an additional variable to track the previous time for the second event. For example:
      unsigned long previousTimeEvent_2 = 0;

      This will also need updated in the second event loop code.

      Hope this helps some!

      • Tim on September 30, 2020 at 10:06 pm

        //YES! It was next lesson))) Now it works! Thank you!

        const unsigned long interval = 800;
        const unsigned long LEDinterval = 500;
        const unsigned long interval2 = 2000;
        unsigned long previousTime = 0;
        unsigned long previousTime2 = 0;
        unsigned long previousTime3 = 0;
        int Led = 13;

        void setup()
        {
        Serial.begin(9600);
        pinMode (Led, OUTPUT);
        }

        void loop()
        {
        unsigned long currentTime = millis();

        if(currentTime – previousTime >= LEDinterval)
        {
        digitalWrite(Led, HIGH);
        previousTime = currentTime;
        }

        if (currentTime – previousTime2 >= interval)
        {
        Serial.println(“I’m not a break, I’m just a slow trottle!”);
        previousTime2 = currentTime;
        }
        if (currentTime – previousTime3 >= interval2)
        {
        Serial.println(“WINNER WINNER VEGAN DINNER”);
        previousTime3 = currentTime;
        }

        }

  11. Sonny on November 7, 2020 at 11:19 pm

    Hi Michael,
    Thanks for this series of millis tutorial, it helped me a lot with my projects. Just a quick question on this code:
    void loop() {
    unsigned long currentTime = millis();
    if (currentTime – previousTime >= eventInterval) {
    Serial.println(“Ice Ice Baby”);
    previousTime = currentTime;
    }
    }
    when the currentTime rolls to 0 after 49days, then we can no longer satisfy the IF statement
    because currentTime will now mostly be lower than previousTime (say in the 4billions mark).
    i think the previousTime should also be rolled-over when the currentTime(from Millis) rolls-over to zero after 49days?

  12. Sonny on November 7, 2020 at 11:25 pm

    Here’s my input, will this work?

    void loop() {
    unsigned long currentTime = millis();
    if (currentTime – previousTime >= eventInterval) {
    Serial.println(“Ice Ice Baby”);
    previousTime = currentTime;
    }
    else if (currentTime < previousTime) { // this only get executed when currentTime re-start at 0 after 49days of continues run.
    previousTime = currentTime;
    }
    }

  13. soroush on February 2, 2021 at 3:08 pm

    wow thank you so much. useful indeed. But I WANNA ASK A QUESTION .
    why did you use unsigned long for interval due to the fact it is not going to increase up again and again?

    • Michael James on February 4, 2021 at 6:42 pm

      I lean toward thinking it’s a good idea to keep all values dealing with time to be unsigned longs. Though I don’t always follow my own advice!

  14. Joseph on March 11, 2021 at 7:32 pm

    Hi I am new to this but take a look at this code
    Im trying to make a servo turn every x amount of time but instead it just loops back and forth
    what did i miss?

    const unsigned long eventInterval = 100000;
    unsigned long previousTime = 0;

    #include

    Servo myservo;

    int pos = 0;

    void setup() {
    myservo.attach(9); // attaches the servo on pin 9 to the servo object
    }

    void loop() {

    /* Updates frequently */
    unsigned long currentTime = millis();

    /* This is the event */
    if (currentTime – previousTime >= eventInterval)

    for (pos = 0; pos = 0; pos -= 1) { // goes from 180 degrees to 0 degrees
    myservo.write(pos); // tell servo to go to position in variable ‘pos’
    delay(15); // waits 15ms for the servo to reach the position

    /* Update the timing for the next time around */
    previousTime = currentTime;
    }
    }

    • Michael James on March 15, 2021 at 4:53 pm

      Nice work so far, but it looks like your for loop needs some work:

      for (pos = 0; pos = 0; pos -= 1).

      Take a closer look at the middle condition.

      You’ll want to start pos at 180, then reduce it. If pos gets to zero, you’ll want to add code so that instead of pos bing decremented, it gets incremented.

  15. Adrian on April 2, 2021 at 6:15 pm

    Hello, Please help me to understand how to use milis(). I have an Arduino mega with Ethernet shield a rain sensor and a relay linked with home assistant. If I use delay() when I try to reach relay I need to wait to much time, if I remove delay function I have to many request from rain sensor.This is the reason that I search an alternative to delay() function.

    int sensorValue = analogRead(rainPin);
    Serial.print(sensorValue);
    if(sensorValue < thresholdValue){
    Serial.println(" – Warning Rain!!!");
    strRaining = "Warning Rain!!!";
    }
    else {
    Serial.println(" – Clear sky");
    strRaining = "Clear sky";
    }
    Serial.print("Raining?: ");
    Serial.println(strRaining);
    client.publish("ha/zona/rain" , String(strRaining).c_str() );

    Thank you so much.

    • Adrian on April 3, 2021 at 5:09 am

      Hi again,
      I think I solved the problem :), Thanks 🙂

      const unsigned long eventInterval = 1000;
      unsigned long previousTime = 0;

      unsigned long currentTime = millis();
      if (currentTime – previousTime >= eventInterval) {
      int sensorValue = analogRead(rainPin);
      if(sensorValue < thresholdValue){
      Serial.println(" – Warning Rain!!!");
      strRaining = "Warning Rain!!!";
      }
      else {
      Serial.println(" – Clear sky");
      strRaining = "Clear sky";
      }
      client.publish("ha/zona/rain" , String(strRaining).c_str() );

      previousTime = currentTime;
      }

  16. ALHAM on June 22, 2022 at 7:45 am

    I want to write a code as below and I want to replace delay() function with millis().
    Please can you tell me how to write code for this?
    If you can show a example code I would appreciate that.

    digitalWrite(column[0], LOW);
    delay(40); //wait for 40ms before start below statement
    digitalWrite(column[1], LOW);
    delay(40);
    digitalWrite(column[2], LOW);
    delay(40);
    digitalWrite(column[3], LOW);
    delay(40);

    • Michael James on June 22, 2022 at 9:17 am

      Does this repeat over and over? Also, do the LEDs ever turn off?

      Something like this might work…

      /**
      1. Create Array for LEDs
      -Initialize LEDs
      2. Create variables for timing
      3. Create timing construct
      – increment array through each time, and then reset to start?
      */

      // LED Array
      const byte LEDPinArraySize = 4;
      const byte column[LEDPinArraySize] = {6, 7, 8, 9};

      //Timing variables
      unsigned long previousMillis = 0; // will store last time LED was updated
      const long interval = 40;

      void setup() {
      for (int i = 0; i < LEDPinArraySize; i++) { pinMode(column[i], OUTPUT); } } void loop() { //Update time unsigned long currentMillis = millis(); //Counter for increment LED static byte nextLED = 0; if (currentMillis - previousMillis >= interval) {
      // save the last time you blinked the LED
      previousMillis = currentMillis;

      // Light next LED and increment counter
      //If all LEDs lit, turn them off and reset counter
      if (nextLED < LEDPinArraySize) { digitalWrite(column[nextLED], HIGH); nextLED++; } else { nextLED = 0; for (int i = 0; i < LEDPinArraySize; i++) { digitalWrite(column[i], LOW); } } } }

      • ALHAM on June 25, 2022 at 11:38 am

        You are awesome!
        I think this will work for me. this is a example code and there are many delay values; I will try to program as suit for me.
        Thank you so much for concentrating your valuable time.

      • Bryan Wilkins on April 24, 2023 at 3:21 am

        I would love to see something similar with multiple servos with array and millis without delay function. I try my multiple servos with delay and they keep blocking each other. I am not that experienced on how to involve array of servos with millis.

  17. Federico on January 11, 2023 at 9:55 am

    Hi, I think that you can accumulate delay with current code, so it is not that precise:

    /* Update the timing for the next time around */
    previousTime = currentTime;

    I would rather write:

    /* Update the timing for the next time around */
    previousTime = previousTime + eventInterval;

    In fact currentTime could have increased of – for example – eventinterval + 1

  18. Tabish on February 28, 2023 at 11:13 am

    This is a code for a bot it turn right than go straight than
    Turn left as we are reading 0 and 1oppenent_fc when it’s
    Not detecting it’s value is 1
    So when it become 1 the while loop become true and execute but I am completely confuse by this milli function
    Please explain in simple words please
    Are we using two millis () one starting from the beginning and the second stars within the while loop
    I am so confuse
    void startRoutine() {
    // Start delay.
    delay(1000);

    // Turn right around 45 degress.
    motorL.setSpeed(255);
    motorR.setSpeed(0);
    delay(180);

    // Go straight.
    motorL.setSpeed(255);
    motorR.setSpeed(255);
    delay(450);

    // Turn left until opponent is detected.
    motorL.setSpeed(-0);
    motorR.setSpeed(255);
    uint32_t startTimestamp = millis();
    while (digitalRead(OPPONENT_FC)) {
    // Quit if opponent is not found after timeout.
    if (millis() – startTimestamp > 400) {
    break;
    }
    }

    • Michael James on February 28, 2023 at 10:34 pm

      The first millis() valuse is saved to startTimestamp, which is the time your robot starts turning left. The second millis is used to measure the passing time, and if the time exceeds 400ms, then the robot exist the while loop.

      Let’s use an example.

      If the robot start turning left at 400ms, then timestamp is 400ms.

      Assuming you detect no opponent, then It would enter the while loop and check “if (millis() – startTimestamp > 400)” This millis will go and check the current time, say it 401ms.

      So you have 401 – 400 > 400 -> this would be false, becuase 1 is not greater than 400, so the if statement code would not execute.

      But when 400 more ms has passed int his manner, then the if statement will run, and that break will get you out of the while loop.

Leave a Comment