4

I programmed an Arduino Uno R3 to trigger a relay once every 24 hours from the moment it is powered on.

I calculated milliseconds and used the function delay().

24 hours * 60 minutes each hour * 60 second every minute * 1000 milliseconds every second

so I used :

delay(86400000)

for 86 million and 400 thousands milliseconds.

Currently, I'm still testing it...

Will this work? If not, is there a better built-in function/library or even external library to do it?

The relay trigger doesn't have to be very accurate at the very exact time each day.

I don't need it to be very accurate, it can shift few minutes every few months or so, thats okay with me.

But how about after few months or years of use ? Will it shift the timing much?

I read somewhere about using millis() function and others use an RTC (Real Time Clock) module.

I don't want to use anRTC module, I am looking for a programmatical solution.

OR will my previous method using delay() work for such a very high number of milliseconds?

ocrdu
  • 1,795
  • 3
  • 12
  • 24
Felix0004
  • 43
  • 4

3 Answers3

4

Yes, the delay() will work, as will other methods based on the millis() counter. However, delay() will make it impossible to do something else in the meantime.

Look up Blink without delay for an example of how to accomplish such a delay while being able to do other things in your code while waiting.

Casting

When dealing with large numbers such as your 24-hour delay, make sure to explicitly cast those numbers as unsigned long, or expressing them with the "UL" extension (like for example 86400000UL). This explicitly tells C++ to expect an "unsigned long" (which in Arduino Uno terms is a 32-bit unsigned number).

In your case (with such an obviously large number), the compiler will automatically choose the right type. In other cases (for example, if you change the expression to 24*60*60*1000), the compiler will not automatically generate an unsigned long and you need to force it by changing the first part of the expression to an unsigned long: 24UL*60*60*1000 or, alternatively (unsigned long) 24*60*60*1000.

Accuracy

The accuracy of the timing will be dependent on the type of oscillator on your particular Arduino board. Many Arduinos or their clones use a Ceramic Oscillator that generally have an accuracy of about 0.1 to 0.5%, meaning a possible deviation of 43 seconds per day and as such maybe too inaccurate for your purposes. If your Arduino has a Crystal oscillator, it will be much more accurate (to something like 150ppm, meaning a maximum deviation of about 1 second per day under normal conditions).

StarCat
  • 1,671
  • 1
  • 7
  • 15
3

delay() takes an unsigned long; I think what you do will work.

When in doubt, you could always do something like this:

for (int hours = 0; hours < 24; hours++) {
  for (int mins = 0; mins < 60; mins++) {    
    for (int secs = 0; secs < 60; secs++) {  
      delay(1000);                                    
    }
  }
}

It will be wildly inaccurate though, because the clock is inaccurate and will also drift with temperature, made worse because a resonator is used instead of a crystal.

You will get nowhere near an accuracy of a few minutes per month this way, whatever "delaying" method you use; the hardware isn't up to it.

ocrdu
  • 1,795
  • 3
  • 12
  • 24
1

You could try enclosing the Uno in a temperature controlled "oven", say a plastic enclosure with a very low power heater (even a suitable resistor might do) and thermo sensor in with it. It should reduce some of the variation in the crystal frequency.

JRobert
  • 15,407
  • 3
  • 24
  • 51