Make an Accurate Arduino Clock Using Only One Wire - NO External Hardware Needed!





Introduction: Make an Accurate Arduino Clock Using Only One Wire - NO External Hardware Needed!

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. '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;

void setup()
  attachInterrupt(clockInt, clockCounter, RISING);
      //  clockInt is our interrupt, clockCounter function is called when
      //  invoked on a RISING clock edge
  pinMode(ledPin, OUTPUT);
  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 ;)

void loop()
  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




    • Science of Cooking

      Science of Cooking
    • Trash to Treasure

      Trash to Treasure
    • Paper Contest 2018

      Paper Contest 2018

    We have a be nice policy.
    Please be positive and constructive.




    I tried to use this clock with a project I'm working on. The only differance I really noticed was that I'm running an UNO and that I'm running at 9600 baud. I'm very new at this so I may have done something else wrong that I don't even realize but anyway the end result is that my clock gains about 17 seconds every hour. Any suggestions? I'm working on getting my code transfered to this PC so I can post it but in the mean time was wondering if my baud rate would have any effect.

    OK, some differences were found that I forgot to mention (my fault) between different arduino boards.  I have only tried this with success with the mega2560 and the ATMega328-based Nano v3.0. 

    On the mega2560, which is the board that I developed my uber clock upon, a few of the first analog pins DO have PWM output ability.  For that board, my interrupt routine was counting only the RISING clock signals @ 490hz.  When I ported the code to the nano, I realized that it did not have the same PWM on analog 0 as the mega did.  So I kept the same interrupt pin (D2, int 0) and moved the masterClock pulses to D3 on the nano. 

    Then another issue appeared.  When counting RISING clock edges @ 490hz on the nano, my clock was almost double speed!   So I changed the interrupt to look for CHANGE in clock signal instead of RISING and changed the frequency (number of clock CHANGES) to 979, or 0 thru 979 which = 980.  I had to change the frequency not because the PWM signal was 980hz on the nano, but because I was now counting any CHANGE in PWM signal.  So either a low to high OR  a high to low clock edge would invoke the interrupt.  WHY this worked I still am puzzled about. 

    Your serial port baud rate should not affect the clock at all btw.

    Here's some example code (just the basics) of what I did differently when using the nano.   The same might apply to your UNO board.

    In setup try this instead:

    attachInterrupt(0, clockCounter, CHANGE);   // Still using interrupt 0 pin D2

    analogWrite(3, 127);          // PWM clock heartbeat !!!  (or any other PWM pin)

    Then try this instead for your interrupt / masterClock function:

    void clockCounter()             // called by interrupt
      masterClock ++;               // with each clock rise add 1 to masterclock count
      if(masterClock >= 979)      
        seconds ++;                 // also add one second
        masterClock = 0;            // Reset after 1 second is reached
        ledpinstate = !ledpinstate;
      digitalWrite(ledPin, ledpinstate);


    This got the nano keeping EXACT time with my PC's real time clock, which is very hard to believe, but I have the results to prove it ! 

    Here is another thing to try IF you have an oscilloscope (don't have mine yet).  Perfrom the same analogWrite(pin, 127) on any PWM pin and note the frequency.  It SHOULD be 490hz on all boards but I could be wrong.  So, say the UNO's PWM freq is a bit different ... then you would need to adjust your clock pulse counts to match.

    I hope this helps, and feel free to contact again if more assistance is needed.  I also have many other projects, from beginner to advanced, on my website at this URL -!__arduino

    I'll be adding a guide in the next day or two on getting results with the infamouse JY-MCU cheap bluetooth breakout board.  I finally have code for the radio that is reliable, allows for board programming with AT commands, and also provides 2-way communication.

    Hi, I need output clock with variable frequency (100KHz +- 10%)...using timers

    Hi, I need output clock with variable frequency (100KHz +- 10%)...using timers

    Your PWM is powered from the exact same clock that drives your timers, since the PWM signals are generated by the timers. Using the timers you will achieve the exact same accuracy as using the PWM - just without the need of an external wire...

    This fact might be hidden behind the shell of the Arduino programming environment, but it becomes clear if you look into the details on how PWM works on an ATmega microcontroller...

    People, really. There is no need for this method. Just use the timer interrupt. It is exactly the same, if not better. *Facepalm*

    Ahan ahan just use the internal interrupt based on a timer to accomplish the same, and I am not an electrical engineer but mechanical... This intractable should be deleted.

    I don't really see the point of this. The PWM is directly divided out of the main system clock. You can just program the interrupt registers to do the exact same thing without having to touch hardware.

    you can use the millis() function instead and obtain similar results...
    here's the code-

    unsigned long lastTick=0;
    unsigned int sec=1;
    unsigned int minute=0;
    unsigned int hour=0;

    void setup()

    void loop()

    if (millis() - lastTick >= 1000) {

    Serial.print(" : ");
    Serial.print(" : ");

    if (sec==60)
    { hour++;
    lastTick = millis();