# Very long delay() possible?

I'm trying to make an opening and closing little door that should open or close every 12 hours. I was wondering if I could just make a small looping script with a delay() for 12 hours, delay(43 200 000 000); I guess? However, I have no idea if that's possible and/or recommendable. Some feedback/alternatives(if needed) would be nice :)

• ok, i think delay has a max of 65535 µs, but now i need an alternative... – Fred Pannekoek Aug 21 '14 at 12:20
• Timing in more mature, MCU-alone systems is usually done by programming a hardware timer channel of the MCU to fire an interrupt periodically, and then counting these - that lets the processor do other things in the meantime, and is cumulatively as accurate as the clock crystal. – Chris Stratton Aug 21 '14 at 17:27
• Using delay will magnify an ever so slight overhead error. It is better to use an interrupt to time a known good period and then count from there. Here is a proof of concept on my personal website: blog.linformatronics.nl/213/electronics/… – jippie Aug 21 '14 at 18:20
• If it doesn't have to be perfectly timed, you can use unconventional things, like a light sensor to sense morning and evening. – The Guy with The Hat Aug 21 '14 at 20:05
• yes, I thought about that, however I only have a little light detector part and I'm not sure how to protect it from the weather (the little door is outside) – Fred Pannekoek Aug 21 '14 at 21:28

The real time clock method is the most accurate way but otherwise use `millis`

``````unsigned long startMillis = millis();
while (millis() - startMillis < LONG_DELAY_MS);
``````

This will delay up to approx. 4294967295ms (2^32-1) or 49 days, after which the timer will catch up to the value of `startMillis`

• What is wrong with just using `delay(LONG_DELAY_MS)`? The arduino implementation accepts unsigned longs. I'm also not entirely sure you code works correct when `millis()` wraps around, and is smaller than `startMillis` – Gerben Aug 21 '14 at 15:34
• Delay makes your arduino completely inactive while waiting if I'm correct. I don't know how this will act when millis is back to 0. – Fred Pannekoek Aug 21 '14 at 15:38
• @Gerben good stuff, put it as an answer! – geometrikal Aug 22 '14 at 22:54
• @FredPannekoek overflow will work fine, so long as unsigned long is used. – geometrikal Aug 22 '14 at 22:54
• @23ars The main reason Arduino is so successful is its easy-to-use hardware abstraction library, if you are against functions from libraries you are limiting yourself somewhat. Anyway, the function of comments is to improve the answer, if you have a better solution, write your own answer. ;) – geometrikal May 20 '15 at 9:32

`delay()` has its uses, but for long delays it's no good. It simply tells the microcontroller to do nothing for `x` clock cycles. During that time, your Arduino can't do anything else.

Your best bet would be to use a thing called a Real Time Clock (RTC). These chips are specifically made to keep track of time, and you can connect them to your Arduino with ease. Here's an example of how you could do that.

• +1 - The RTC solution is specially good if you want more accuracy than the MCU can give you. – Ricardo Aug 21 '14 at 15:42
• @Ricardo - an RTC is not likely to be any more accurate than an MCU with a clock crystal using one of its hardware timers to fire a periodic interrupt; what it does usually get you is tracking across power loss, and perhaps some knowledge of calendar schemes. – Chris Stratton Aug 21 '14 at 17:26
• Afaik uno does not use a quartz bit a ceramic resonator for its clock, thus with much less accuracy than an rtc. – jfpoilpret Aug 21 '14 at 17:31
• @ChrisStratton - Right. Point taken. The RTC will be much better option if the OP has to open or close the door at a given time of day. – Ricardo Aug 21 '14 at 17:39

You could use the watchdog interrupt and have your MCU sleep while waiting and save power.

But notice that you'll only save power if your board also saves it. That means you have to have a low quiescent voltage regulator instead of the usual regulators that equip the most common Arduino boards, such as the Uno. Otherwise, it doesn't matter whether your MCU saves energy if your board doesn't.

Here's the code (untested):

``````#include <avr/sleep.h>
// This variable is made volatile because it is changed inside an interrupt function
volatile int sleep_count = 0; // Keep track of how many sleep cycles have been completed.
const int interval = 720; // Interval in minutes between waking and doing tasks.
const int sleep_total = (interval*60)/8; // Approximate number of sleep cycles
// needed before the interval defined above elapses. Not that this does integer math.

void setup(void) {
watchdogOn(); // Turn on the watch dog timer.
// Disable the ADC by setting the ADEN bit (bit 7) to zero.
// Disable the analog comparator by setting the ACD bit (bit 7) to one.
ACSR = B10000000;
// Disable digital input buffers on all analog input pins by setting bits 0-5 to one.
DIDR0 = DIDR0 | B00111111;
}

void loop(void) {
goToSleep(); // ATmega328 goes to sleep for about 8 seconds
// and continues to execute code when it wakes up
if (sleep_count == sleep_total) {
// CODE TO BE EXECUTED PERIODICALLY
}
}

void goToSleep() {
set_sleep_mode(SLEEP_MODE_PWR_DOWN); // Set sleep mode.
sleep_enable(); // Enable sleep mode.
sleep_mode(); // Enter sleep mode.
// After waking from watchdog interrupt the code continues
// to execute from this point.
sleep_disable(); // Disable sleep mode after waking.
}

void watchdogOn() {
// Clear the reset flag, the WDRF bit (bit 3) of MCUSR.
MCUSR = MCUSR & B11110111;
// Set the WDCE bit (bit 4) and the WDE bit (bit 3) of WDTCSR.
WDTCSR = WDTCSR | B00011000;
// Set the watchdog timeout prescaler value to 1024 K
// which will yeild a time-out interval of about 8.0 s.
WDTCSR = B00100001;
// Enable the watchdog timer interupt.
WDTCSR = WDTCSR | B01000000;
MCUSR = MCUSR & B11110111;
}

ISR(WDT_vect)
{
sleep_count ++; // keep track of how many sleep cycles have been completed.
}
``````

The code I copied is from this page: Low-Power Arduino Using the Watchdog Timer.

I just use for loops when I don't want to do stuff in between:

``````for (int Hours = 0; Hours < 12; Hours++) {            //Creates 12 hours
for (int Minutes = 0; Minutes < 60; Minutes++) {    //Creates 1 hour
for (int Seconds = 0; Seconds < 60; Seconds++) {  //Creates 1 minute
delay(1000);                                    //Creates 1 second
}
}
}
``````
• Explaing how this is better than a simple `delay(43200000)`. – user31481 Jan 23 '18 at 9:49
• Well for starter it would be easier to modify how long you want to wait. Just change the number for each hour, minutes and seconds without needing to convert into miliseconds. – GeneCode Jun 11 '18 at 13:27

Do you have a sleep(unsigned int seconds) available?

If not, this would allow you to delay() a very long time:

``````for (unsigned int bigloop=0; bigloop<65535; bigloop++)
{
for (unsigned int smallloop=0; smallloop<65535; smallloop++)
{
for (unsigned int tinyloop=0; tinyloop<65535; tinyloop++)
{
delay(65535);
}
}
}
``````
• I could try this if I don't manage to get an rtc like Tom said. Thanks for helping! – Fred Pannekoek Aug 21 '14 at 13:59

This will work:

``````longDelayInSeconds = 120; //two minutes;
while (p < longDelayInSeconds) {

delay(1000);
p++;

}
``````
• not the best solution and the OP asked for 12 hours, not 2 minutes. – Madivad Dec 8 '15 at 4:05