I am designing an industrial control panel using arduino. I have to use time delays as long as 10 seconds and since using delay() makes a halt in the controller I tried using millis(). But it is complicated and it will work only for 50 days. I want the system to work continuously without any maintenance and I need to control as many as 6 relays. So, I need a better solution (hardware or software based) to tackle this problem. How can I do this?

  • See How can I handle the millis() rollover?. In short: the correct way to handle the rollover is to write rollover-safe code, like in the standard example Blink Without Delay. Mar 17, 2017 at 20:28
  • I use double loops. The outer loop is your entire delay time, (say, 10 minutes = 10,000 ms divided by the duration of the inner loop delays) and the inner loop is how often you need to check for a condition that necessitates calling some function, (maybe every 1000 ms) - so your halt times are determined by the inner loop delay. And the outer loop can be used to update a display on a less-periodic basis. The 50 day thing is not relevant.
    – SDsolar
    Mar 17, 2017 at 22:59
  • i would "upgrade" to relays to latching, or at least driven by a 1-bit state machine, like an "SR Latch" that the MCU can read and write. That way, an MCU crash won't affect the relays at all.
    – dandavis
    Mar 18, 2017 at 2:47

3 Answers 3


You misunderstand the 50 day thing. Yes it rolls over after 50 days but that doesn't mean it stops working. As long as you program your comparisons correctly (something people often don't do in online examples) then all it means is the maximum delay you can have is 50 days.

  • > all it means is the maximum delay you can have is 50 days. it is pretty trivial to extend millis beyond 50 days. so yes, you can generate much longer delay sout of millis().
    – dannyf
    Mar 17, 2017 at 13:11
  • 1
    Well yes, but without writing your own code to extend it the maximum is 50 days. And anyway millis() is not that accurate, so anything more than an hour or two you really need to use an RTC.
    – Majenko
    Mar 17, 2017 at 13:36

You may have to find a library that eases the use of what you're trying to do.
I made some timer library, called SeqTimer.
You can find it here: Link
or use the Arduino library manager, it's there too.

It's a simple library using millis(), without callback, so it's pretty straightforward.
If you need more advanced timer, search for 'timer' for example in the arduino library manager, there's a bunch of libs related to timers.

Yet, I'm not really sure what you mean by:

work only for 50 days

  • The function millis () returns an unsigned long, which is the number of milliseconds since the processor was reset (until it overflows). Example: unsigned long startTime = millis (); Since there are 2^32 bits in an unsigned long it can count from 0 to 4294967295. Computing this in terms of days we have: 2^32 / 1000 / 60 / 60 / 24 = 49.710 days So, the number returned will overflow (go back to zero) after around 49 days (almost 50 days, as the reference page says).
    – Vignesh
    Mar 17, 2017 at 6:58
  • That's what I thought you meant. In fact, millis() will rollback to 0, so it shouldn't be a big problem. Anyways, SeqTimer or any other lib would work for you.
    – SMFSW
    Mar 17, 2017 at 7:07
  • 2
    When you do "millis() - previousMillis" it will always return the difference between the two, even at the very moment millis() does a rollover. Both variables must be unsigned long to make it work. When only short delays or intervals are needed, it is allowed to use less bits of millis(), for example 16 unsigned bits. However, I think it is easier to always use 32-bit unsigned long when using millis().
    – Jot
    Mar 17, 2017 at 7:10
  • I'll probably change to 32b compare someday, yet I did tried the lib for a while with the simili rtc sketch with a serial spy displaying frames reception time, it kept working on the whole test, and derived in time just as it should, as not using a timer interrupt.
    – SMFSW
    Mar 17, 2017 at 7:15
  • Might be a solution to the former question. Using a timer interrupt, with a correct prescaler, and maybe counting some to get 10s before launching action.
    – SMFSW
    Mar 17, 2017 at 7:17

it will work only for 50 days.

it overflows in 50 days but comparisons based on it can be good even if it overflows. you just need to recognize the overflow and program accordingly.

so millis() is perfectly fine for what you are trying to do. no need to reinvent the wheels.

  • You wrote: “you just need to recognize the overflow and program accordingly”. If you really need to recognize the overflow, you are doing something wrong. Mar 17, 2017 at 20:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.