# Time delay without using delay() and millis()

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. – Edgar Bonet Mar 17 '17 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 '17 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 '17 at 2:47

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 '17 at 13:11
• 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 '17 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 '17 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 '17 at 7:07
• 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 '17 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 '17 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 '17 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. – Edgar Bonet Mar 17 '17 at 20:23