Arduino as a clock :)

Guys, very simple question

I need to build clock. From Arduino I’m asking only to gave me 1 impuls per minute, but the impuls must be exact (obviously).

What I’ve did is this:

void setup() {
  pinMode(10, OUTPUT);

void loop() {
  digitalWrite(10, HIGH);  
  digitalWrite(10, LOW);    

Very simple program, using delay(), but it’s not working. Time is not exact.

I need to have every minute 2s inpuls for relay.

Thank you guys :slight_smile:

The resonators used on the cheap boards isn't very accurate.
Replace it with a crystal, or get a real-time clock, or get a GPS module with a 1 pulse-per-second output, and count pulses.

Ceramic resonator as often used to clock the micro is not accurate. Crystal oscillators are far more accurate but might still not meet your needs.

You can add corrections to your timing (might work) or consider the use of an accurate rtc.

AWOL beats me :wink:

Thank you guys, I will buy RTC module

Your timers don't compensate for the time it takes to do the digitalWrite() calls or the loop overhead. This will at least compensate for that:

const int OutputPin = 10;
const unsigned long Interval = 60UL * 1000UL;
const unsigned long PulseLength = 2000UL;
unsigned long StartTime;

void setup() {
  digitalWrite(OutputPin, HIGH);
  pinMode(OutputPin, OUTPUT);

void loop() {
  if (millis() - StartTime >= Interval) {
    StartTime += Interval;
    digitalWrite(OutputPin, LOW);
    digitalWrite(OutputPin, HIGH);

Very simple program, using delay(), but it's not working. Time is not exact.

Yes, of course it's not very exact.

Which Arduino board do you use?

Accuracy of internal Arduino board timing g depends directly on accuracy of controller clocking.

So if you have a 16 MHz board which is clocked by a ceramic resonator, your timing done by "delay()" or "millis()" functions may be inaccurate up to 0.8%, which means:

  • runtime of delay(1000); might be something between 992 and 1008 milliseconds, actually.

delay(2000) might be in the range 1984 ... 2016 milliseconds actually
and delay(58000) might be in the range 57536 ... 58464 milliseconds actually
(with 16 MHz AVR Atmega boards in R3 design like "UNO R3" or "MEGA2560 R3"

BTW: Switching time of mechanical relays may vary, too.
Relay switching time from OFF to ON might differ from switching time ON to OFF

You can achieve much better accuracy on the long run by

  • using an Arduino board which creates system clocking from a crystal oscillator instead ceramic resonator
  • or by using a RTC with square wave output enabled and simply counting pulses from the SQW output of the RTC module

Thank you guys, I will buy RTC module

get a DS3231 or DS3232 they are now the same price as the older 1307 modules but much more accurate.
They also have a temperature sensor if you want or need temperature readings.

--- bill

Thank you guys, I will buy RTC module

good idea,

Get yourself a DS3231 RTC module!

I'd then recommend this as a programming logic for the loop function:

  • read the current second from the RTC over and over (current second is running from 0 to 59 always)
  • and in case the current second has changed from the last reading, simply take proper action:
  • either on second==58 switch output to HIGH and on second==0 switch output to LOW
  • or on second==0 switch HIGH and on second==2 switch to LOW

This should create very accurate timings (accurate two-second-pulses accurately each minute

Hello there,

Another option is to calibrate the timing functions such as millis().
I dont think i would recommend this method with a ceramic resonator, but with a crystal yes, as long as you can get the results you need of course and you did not state the tolerance you are after so i dont know that info yet.

The idea is very simple but it does take some time and effort to get it right because you are basically calibrating something that needs to be checked over minutes or even hours to get the right tolerance, and the program may vary slightly depending on the accuracy requirement.

The calibration code simply adds or subtracts one, two, or more milliseconds to the millis() function once for every so many millis(), in order to make a count over say an hour very close to an actual hour which is 3600000 milliseconds. If the clock is slow you add milliseconds, and if the clock is fast you subtract milliseconds. The amount you add or subtract comes first from your testing where you compare the count at the end of one full (and exact) hour as measured by a trusted timepiece. Once you get it set, it should work for as long as the board stays at that same temperature. This also means that it only works in an environment that stays at about the same temperature, unless of course you want to add temperature compensation.

Of course it takes some time to get this right, so it is not for someone in a hurry.

The best solution though for a reasonable price is the RTC module as others here have pointed out. The one with the internal crystal though, not the one with the external crystal as that is less accurate and can drift more.

Good luck with it whatever you decided to do. Sounds like you want to go with the RTC so far though which i think is a good choice.