Can my Arduino be a clock?

Hello All !

May I first say that I am very excited to have discovered the Arduino. I became aware of it through an article in the Linux Format magazine in the UK (I think they are hoping to run more articles soon). I have come across, and used, a few microcontroller platforms through my work. Whilst these development kits are useful at work, I've never seen anything I'd liked enough to spend my own money on, for my own personal use at home (expensive kit, expensive compilers, etc). That was until I discovered the Arduino! I really like how simple it is to program ... no complicated configuration of the low-level devices. I'd like to congratulate everyone involved, what a great job!

Now to my question ...

I have a project idea where I'd like to implement a clock. A simple 24hr clock is all I need ... no date is needed. It doesn't have to be incredibly accurate. I could probably put up with one or two minutes drift a month if that is the best that can be acheived.

I have searched this forum the best I can but the only ideas I have found are to interface to a real-time clock chip. However, I was wondering if this could be done entriely on the Arduino? I was thinking that I could do something with either (a) a hardware timer and an interrupt service routine or (b) use the millis() function in some way. [I have another question about the millis() function but I'll post that separately.]

Can someone advise me if this is possible? If not, then what are the problems (e.g. accuracy)? If it is possible then maybe someone has come across a project or tutorial I could reference?

Any help will be most gratefully received.

My best regards to everyone .... Matt

Your problem would be accuracy. The Arduino's crystal is 16MHz, not 16.00000000MHz. The problem is that the error will accumulate. That actual error will likely vary from crystal to crystal.

Having said that, I say go ahead! I assume this clock will have an interface, so you'll be learning to handle an interface as well as the arduino code. Even if you find later your accuracy is not what you wish, you've got your display already and you can just add a RTC (like the DS1307) to get the accuracy in line.

-j

Yeah its easiest just to get a simple RTC.
A small chip and a crystal gives you very accurate time for under a dollar.

this topic comes up from time to time. the extra realtime component is a save bet if you use it correctly. still an arduino should be enough to build an accurate clock. if you notice an offset (because of crystal tolerances) you should also be able to compensate for it in your code. as kg4wsv wrote, the actual frequency is dependant on the crystal but shouldn't change over time. me too says go ahead! and keep us informed. it's a shame that there's no arduino-only clock code out there yet.

ku

Thanks for all the replies, I wasn't expecting any so soon.

Whilst I appreciate that a separate real-time clock IC will the most accurate solution, I think I'll have a go at doing it on the arduino first ... more for the challenge of it than just to be difficult.

My design will have a keypad and a LCD, so there will be a mechanism to set the clock ... I think I'll also introduce a 'fiddle-factor' to give me a certain amount of tuning.

In case anyone is interested, my design is for a controller to for my fish tanks (I keep freshwater and a small marine). The main thing it will do is control the lights, there are 3 sets; daytime, dusk/dawn and nighttime, which go on and off at different times. I currently use plug-in mechanical timers at each socket. These are cheap but take a bit of setting up to get the lights to sequence as you want them to. There are commercially available controllers but they are expensive (£200 min). My idea is to build something from an arduino (say ~£25). Then if I'm not happy switching the mains electricity directly, I'll set it up to do X10 automation. I'll also pull in temperature monitoring, and maybe a system to run an automatic water top-up system (using float switches and a small water pump) ... saving even more money. I guess projects like these are more more about the hbby factor than purely money driven.

As for the clock thing, I'd be happy to share whatever I come up with, for interest and comment. Maybe even have a go at building a library? I'm not a strong programmer so can't promise super-efficient code but if it helps, I'm happy to participate.

Thanks All ..... regards ..... Matt

A small chip and a crystal gives you very accurate time for under a dollar.

Which chip and which vendor do you have in mind? I've just done a little poking around for RTCs to use with my Arduino, and while none are more than a few bucks, I haven't found any nearly as cheap as you're describing. Any specific suggestions you could make would be really helpful. Thanks!

Maxim DS1307 Mixed-signal and digital signal processing ICs | Analog Devices is an 8pin DIP RTC that uses a tiny standard clock crystal. If you do a search on the forums and also in the playground there are code and examples on how to use it. You can order samples from maxim for nothing and I got my crystals from toys in cornflakes boxes(no joke!) and old motherboards. Just look on any toy or old motherboard for a small round metal can that looks similar to an electrolytic capacitor, thats usually the crystal.

Ok yes there is the free option which requires diving in to cereal boxes. ;D

While under a dollar might have been a stretch, its damn cheap.
At Futurlec for quantities of one, a 32khz crystal is 75c and the DS1307 is $3.50.
Buying a couple slashes the price and the SMD chip is 60 cents less.

Futurlec also has a $6.90 board with the DS1307, a crystal, pull up resistors, decoupling capacitor and backup battery.
A pretty good deal. I've got one. :slight_smile:

I have been playing around with this clock script. Its not very accurate but could be used to control things measured in hours or days. Every time you add to the script, you will have to recalibrate the clock, which takes a few days to zero in.

//  Variable clockadjust will be about 1000 milliseconds per second
//  If clock lags realtime, decrease clockadjust
//  If clock preceeds realtime, increase clockadjust
//  http://www.time.gov
//  Adjust variables to desired set time 
//  Press reset two seconds prior to desired set time

int clockadjust = 986;
int day = 0;
int hour = 21;
int min = 36;
int sec = 0;

void setup()
{
  Serial.begin(9600);

}

void loop()
{
delay(clockadjust);
  
  sec = sec + 1;

if (sec > 59)
{
  sec = 0;
  min = min + 1;
}

if (min > 59)
{
  min = 0;
  hour = hour + 1;
}

if (hour > 23)
{
  hour = 0;
  day = day + 1;
}
  Serial.print("Day ");
  Serial.print(day);
  Serial.print(" - ");
  Serial.print(hour);
  Serial.print(":");
  Serial.print(min);
  Serial.print(":");
  Serial.print(sec);
  Serial.print("\n");
}

skylark, here is a tweek to your sketch you may want to play with. some of the time delay error you noticed will be do to the delays outputting to the serial port, however you avoid this as follows.

int start;
int clockadjust = 1000;

void loop() {
     
   while(millis() - start  < clockadjust)  // wait for clockadjust milliseconds to elapse
       ;
   long start = millis();          // save the next start tick
   // now update time variables and do serial output  
   // paste your calculation and serial code here

}

void setup()                    // run once, when the sketch starts
{
   Serial.begin(9600);
   start = millis();          // get the start tick for the first iteration through the loop
}

The code is untested but I hope it gives a useful idea of how to make the clock more accurate

I also found delayMicroseconds() - http://www.arduino.cc/en/Reference/DelayMicroseconds .

That should allow for fine tuning of the clock.

I have the current clock script accurate to about 1 second per hour.

Does millis() start over every time the loop cycles? Or does it continue counting from when the loop starts the first time?

Hi,
millis() starts counting from the beginning of the sketch, IE when the arduino boots up. It doesn't ever really "reset". So your initial grab of millis() in the setup routine is fine.

However, millis() DOES rollover. This could lead to a condition where your clock "freezes" for a long time, because 'start' is a really big value and millis() is returning a small value. There's another thread on the forum somewhere about detecting and handling rollover of the timer. Use the search, Luke. :wink:

You might want to investigate using the timer interrupt directly to update the current time. Interrupts are a bit tricky, but in this case it would be more accurate.

HTH,

To combat the rollover you have another variable which you put millis() in every time you use it.
The you compare the current millis() to the stored variable. If its smaller then you work out (4294967296 - stored_millis) + current_millis to compensate.

Cheater, how do you connect the DS1307 chip?

Cheater, how do you connect the DS1307 chip?

It uses I2C so you'll be wanting to look at the Wire library to communicate with it.
You hook it up to the SDA and SCL pins. On the Arduino they are Analog pins 4 and 5 respectively.

More info can be found by searching.