How to make an Arduino clock - without using external oscillators or clock chips:
(more of my projects on our research website - click the arduino logo top of home page)
You will need:
An Arduino board (just about any flavor will work fine) and software
1 Jumper Wire
(Wiring Example Updated Below...)
I'm an Electrical Engineer of 20+ years and just discovered the Arduino platform a few months ago. Needless to say I fell in love with it and am now hooked on projects. For Christmas this year, I wanted to make some very heart-felt, one-of-a-kind gifts for my parents. For my Mother, it was definately a 'one-of' clock design. I was not concerned with keeping up with daylight savings time or leap years - simply accurately keep the day of week and time.
How to generate the clock pulses in a unique but accurate manner though? Sure I could use a fancy embedded clock IC or the common 32,768 crystal oscillator, but I wanted something different than the rest. I started using a 555 timer to output a steady 100Hz square wave. This worked pretty well but I was losing about 1 second per hour. No problem - I just wrote an algorithm to correct the missing second in software. I was happy. Then I discovered that although the Arduino's internal timer was not totally reliable for time keeping, the analog PWM outputs did have a very steady square wave of 490Hz. The duty cycle is determined by the value written to the analog pin. (i.e. - 0 is zero volts, 127 is a 50% duty cycle, 255 is a logic high/5V).
I decided to try the PWM analog output wired directly to the interrupt pin 2 and it worked great! Plus, it kept up perfectly with my computer's real time clock to the second without need for software compensation. I've been running it for days now and it continues to perform just as I had hoped....all with one wire and some code.
The finished gift will have Eagle CAD custom PCB's for the power supply and logic, housed in a plexiglass enclosure. The entire theme is ice blue LED lighting to simulate an analog clock. While the enclosure has a white on blue LCD displaying the day, time, and room temperature, a serial cable connects from the project box to the actual clock. Using a 12 bit decade counter, a servo, and lots of blue LED's I am lighting the appropriate hour segments on a custom-designed analog clock face printed on plexiglass. The servo is mounted in the center of the clock face and has an armature attached with an LED mounted to light up the minutes behind the glass. (each minute the servo turns 6 degrees, lighting up the appropriate minute). I hope to have it finished soon and will make a video of the final product....I hope she loves it !!
Simple Arduino wiring diagram and demo code to make your own clock using this method. Also a link to Circuit Lab demonstrating how to use the 555 timer @ 100Hz method if you so choose.
Code and links below...
555 Timer Oscillator Circuit (if you wish to try this method)
Clock Demo Code:
/* Simple internal clock demo: by Joseph Unik aka Relic1974
Uses analog PWM output of 490Hz with a 50% duty cycle to
keep very accurate time ;). Connect an LED to pin 13 to
watch seconds blink. Connect a jumper from Analog pin 0
to Digital Pin 2 (interrupt 0). Minutes output to serial
monitor. http://www.planetxresearch.com 'Arduino' logo
for more projects and tricks...
(Feel free to use this code to expand into a fully-functional
clock or other project under Creative Commons ;)
int clockInt = 0; // digital pin 2 is now interrupt 0
int masterClock = 0; // counts rising edge clock signals
int seconds = 0; // variable
int minutes = 0; // variable
int ledPin = 13;
attachInterrupt(clockInt, clockCounter, RISING);
// clockInt is our interrupt, clockCounter function is called when
// invoked on a RISING clock edge
analogWrite(0, 127); // this starts our PWM 'clock' with a 50% duty cycle
void clockCounter() // called by interrupt
masterClock ++; // with each clock rise add 1 to masterclock count
if(masterClock == 489) // 490Hz reached
seconds ++; // after one 490Hz cycle add 1 second ;)
masterClock = 0; // Reset after 1 second is reached
tone(13, 100, 500); // using tone to pulse LED without delay call ;)
if(seconds == 60) // NOW GETTING IN TO REAL TIME KEEPING
minutes ++; // increment minutes by 1
seconds = 0; // reset the seconds variable
Serial.print("Minutes = ");
Demo of my project in the works here