Do I need a Real Time Clock module to make a clock?

Hello! I am working on a mechanical clock with a very simple movement: a stepper motor advances a gear every minute. There is no second hand, or other data (day, month, year, etc.) that I am tracking.

I was planning on using a very simple code calling on the millis() timer in the arduino to keep track of the time, and each minute turn the motor. But a friend suggested that the millis() timer may lose some accuracy over time, and that it may be better to use a Real Time Clock breakout to keep more accurate time.

Is this true? It seems like the RTC modules are great for keeping track of date and driving digital displays, etc, but I don't need that. I just want to make sure that my clock doesn't drift over a period of weeks or months. Other than setting it up and waiting, I'm not sure where I can find this type of information. Do any of you know?

Thanks!
Ben

All watches and clocks drift. 1 sec / day, 1 sec / week adds up.
The more stable the time-base (reference), the less any drift.

Millis () is not an accurate timebase. It is good for short times but not days. The RTC will drift as well but is still more accurate than millis().

Weedpharma

A high tech and extremely accurate option would be to use the 1 PPS (pulse per second) output of an inexpensive GPS module to run the stepper motor circuitry. Also, some RTC modules output a 1 PPS pulse.

A downside is that the GPS module will need a clear view of the sky to work. However, some of the more expensive modules will work indoors, at least in a one story building.

Arduinos use either a crystal oscillator or a ceramic resonator to generate the processor clock.

Ceramic resonators typically have accuracies on the order of a few tenths of a percent, that is a few parts per thousand. With such a time base you would expect the clock to drift something on the order of 10 seconds per hour. For time keeping over extended periods, this is usually not acceptable accuracy.

Crystals come in a wide range of accuracies, but inexpensive one's used for computers and time keeping are on the order of a few parts per hundred thousand accuracy so your clock error would likely wind up on the order of a few tens of seconds per month.

If you are using a Arduino with a crystal oscillator, a real-time clock probably isn't going to perform a great deal better that your board by itself, excepting that it will continue time keeping if power goes out.

tinkertinker:
it may be better to use a Real Time Clock breakout to keep more accurate time.

Is this true?

Essentially, yes; but there are RTCs and RTCs. For you, their chief assets are the pulse output and the backup backup battery. I understand the popular DS1307 is not really any more accurate than Arduino's on board counter. The DS3231 is still cheap and more accurate than most. I'm sure sure you don't really need to use an Arduino for what you propose but, if you do use one, you might be tempted to make better use of it. One way to do that is have it occasionally check with a PC to update the clock. I imagine relating this accurate digital time to a mechanical clock might be an interesting exercise. With the clock that chimes Big Ben, it is so interesting that they don't bother, but at least you have the advantage of stepper motors.

I don't know whether you have access to WIFI. If so, you could use an ESP8266-board and programm it to fetch the time from a NTP-server at regular intervals. Like the arduino it's a microcontroller and the nice part is that you can programm it using the Arduino IDE.

MrMark:
If you are using a Arduino with a crystal oscillator, a real-time clock probably isn't going to perform a great deal better that your board by itself, excepting that it will continue time keeping if power goes out.

An RTC won't help here unless the Arduino is able to read the position of the clock hand or whatever mechanical device OP has in mind. This is much more effort. I would agree that using a quartz based Arduino achieves the same accuracy as a normal mechanical quartz clock

Thanks for the notes everyone! I think I will get Adafruit's DS3231-based ChronoDot, which claims to have less than 1 minute of drift per year (ChronoDot - Ultra-precise Real Time Clock [v2.1] : ID 255 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits)

tinkertinker:
Thanks for the notes everyone! I think I will get Adafruit's DS3231-based ChronoDot, which claims to have less than 1 minute of drift per year (ChronoDot - Ultra-precise Real Time Clock [v2.1] : ID 255 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits)

That's my favourite, in spite of the round PCB, LOL. I like that they brought out all the pins in an uncommitted fashion. It's easier if you want to play with the advanced functions of the chip.

Or just run a simple time sketch based on micros().

unsigned long currentMicros;
unsigned long previousMicros;
unsigned long elapsedTime;

// Initial time to start, 10:00:00 with 90 years, 240 days. (around start of May),
// adjust as needed.

// Get this working, then more display code if needed

byte hundredths;
byte tenths;
byte secondsOnes = 0;
byte oldsecondsOnes;
byte secondsTens = 0;
byte minutesOnes = 0;
byte minutesTens = 0;
byte hoursOnes= 0;
byte hoursTens = 1;
int days = 240; //
byte years = 90;
void setup(){

Serial.begin(115200); // make serial monitor match
Serial.println (Setup Done");
}

void loop(){

currentMicros = micros();

// how long's it been?
elapsedTime = currentMicros - previousMicros;
if ( elapsedTime >=10000UL){  // 0.01 second passed? Update the timers
previousMicros  = previousMicros + 10000UL;
hundredths = hundredths+1;
if (hundredths == 10){
    hundredths = 0;
    tenths = tenths +1;
    if (tenths == 10){
        tenths = 0;
        secondsOnes = secondsOnes + 1;
        if (secondsOnes == 10){
            secondsOnes = 0;
            secondsTens = secondsTens +1;
            if (secondsTens == 6){ 
                secondsTens = 0;
                minutesOnes =  minutesOnes + 1;
                if (minutesOnes == 10){
                    minutesOnes = 0;
                    minutesTens = minutesTens +1;
                    if (minutesTens == 6){
                        minutesTens = 0;
                        hoursOnes = hoursOns + 1;
                          if (hoursOnes == 10){
                              hoursOnes = 0;
                              hoursTens = hoursTens +1;
                                if ( (hoursTens == 2) && (hoursOnes == 4){
                                      hoursOnes = 0;
                                      hoursTens = 0;
                                      if (days>1){
                                          days = days-1;
                                           }
                                      else {
                                         days = 365;
                                         years = years - 1;
                                         }
                                    
                                      } // 24 hr rollover check
                                   } //hoursTens rollover check
                              } // hoursOnes rollover check
                        } // minutesTens rollover check
                     } // minutesOnes rollover check
                 } // secondsTens rollover check
              } // secondsOnes rollover check
          } // tenths rollover check
       } // hundredths rollover check
} // hundredths passing check

if (oldSecondsOnes != secondsOnes){  // show the elapsed time
oldSecondsOnes = secondsOnes;
Serial.print (years);
Serial.print(":");
Serial.print(days);
Serial.print(":");
Serial.print(hoursTens);
Serial.print(hoursOnes);
Serial.print(":");
Serial.print(minutesTens);
Serial.print(minutesOnes);
Serial.print(":");
Serial.print(secondsTens);
Serial.println(secondsOnes);

} // end one second check

} // end loop

tinkertinker:
Thanks for the notes everyone! I think I will get Adafruit's DS3231-based ChronoDot, which claims to have less than 1 minute of drift per year (ChronoDot - Ultra-precise Real Time Clock [v2.1] : ID 255 : $17.50 : Adafruit Industries, Unique & fun DIY electronics and kits)

The DS3231 is a nice chip, it's software compatible with the ds1307, which is used in loads of projects. I've built clocks with both and the DS3231 ones are far better as the ds1307-clocks.

Adafruit does tend to create modules, give them a flashy name like chronodot and ask quite a lot of money though.

This module uses the same chip, has a 4KB Eeprom chip as well and you can buy 15 (!) of 'm, for the price of a single Chronodot.

That's the module I use, and is a pretty obvious choice. Be aware that it is quite bulky, particularly when compared with a Tiny DS1307. This is mainly due to the battery carrier. I wouldn't go near that Adafruit thing but I see it has less components. I don't know what that would be about.

CrossRoads:
Or just run a simple time sketch based on micros().

Great code. Thank you very much for sharing. Really appreciate your time and expertise.

If your clock is powered by the AC mains instead of batteries, you could use the mains frequency as a time base. The power company does try to synchronize the power line frequency with the clock.

Dumb clocks running straight off a plug into the wall AC outlet do manage to keep pretty good time.

Obviously you would need a safe circuit that could count or trigger on the AC peaks or zero crossings. That should be a real protection circuit but it could be as simple as one resistor.

jremington:
A high tech and extremely accurate option would be to use the 1 PPS (pulse per second) output of an inexpensive GPS module to run the stepper motor circuitry. Also, some RTC modules output a 1 PPS pulse.

He said he wanted one pulse per minute.