Easy and Accurate Clocks without RTC IC


Closed Thread
Results 1 to 19 of 19
  1. #1
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517

    Default Easy and Accurate Clocks without RTC IC

    Greetings,

    Attached are two programs that demonstrate how to easily make accurate clocks WITHOUT the use of Interrupts or Real Time Clock (RTC) chips. Both are based on TMRO but do not require preloading, adjusting, or tweaking the TMRO register before or after overflows. These programs also give the user lots of time to do other stuff between clock updates. The only time error is 100% related to crystal tolerance and drift (these examples require a 4 MHz crystal). The programs are based on the PIC12F629 but can be changed to your controller of choice. Extensive comments and schematics are in the code.

    These programs maintain the time as accurately as a DS1307 RTC or similar at +/-2 sec/day. If you need super accuracy, I suggest a MAXIM DS3231 RTC which boasts +/- 1 min/year accuracy.

    The algorithms used here have been adapted from Roman Black's “1 second timer” (www.romanblack.com). We have simplified and adapted these algorithms for easy implementation with PicBasic Pro. Comments welcome (in this forum for all to benefit) ...

    Enjoy,

    Paul Borgmeier
    Salt Lake City, Utah USA
    www.cruxanalysis.com

    Program 1 : EZCLOCK1.bas
    A simple program to set and show the time on an alphanumeric serial LCD (HH:MM format with blinking colon). Most of the code is dedicated to setting the initial time. Only about 30 lines of the code are required to accurately maintain the time and LCD updates, including colon blink.

    Program 2: EZCLOCK2.bas
    A technique we have used in our own consulting – most of EZCLOCK1.bas is dedicated to setting the initial time and then maintaining the display. This takes lots of valuable code space and additional hardware. For some projects, we just set the time in code at 12:00 (noon) and then start the device at precisely noon. Since the clock is highly accurate, a display is not required for many non-critical applications (e.g., sprinkler timer, fish feeder, water softener, while away lamp turn on relay, etc.). We have the code toggle a line high for 1.0 second on the hour so that we can check that the clock is running (e.g., LED, buzzer, counter, VOM, nothing, etc). Daylight savings time is the ideal time to stop and restart the device, which removes the crystal tolerance error while adjusting for the time change. The entire program is about 30–40 lines of code (depending on how you count), including register settings, variable declarations, initial values, and time keeping.

    As an example of doing something useful, we turn on GP0 at 8:00PM and then turn it off at 8:15PM. You can adjust to meet your own needs.

    A Note on Displays:

    EXCLOCK1 is written for a serial LCD alphanumeric display - probably the most popular style of display out there. Most of us have one or have made one. There are lots of displays options. The code also could easily be changed to work with parallel displays since the instruction set is essentially identical.

    How to make a Serial LCD
    search PicBasic List and/or Forum “serial LCD backpack'”

    Alphanumeric Displays
    google search “serial LCD”

    Larger 4 Digit Displays
    google search “serial LCD 4 digit”

    Enjoy ...
    Attached Images Attached Images  
    Attached Files Attached Files

  2. #2
    micro's Avatar
    micro Guest


    Did you find this post helpful? Yes | No

    Default

    hello
    i would ask you how could he calculated the total error 0.0052% ???

  3. #3
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Smile

    micro,

    This short/simple algorithm uses TMRO with a prescaler of 256. This equates to 65,536 uS per TMR0 overflow (w/ a 4.000 MHz Xtal). Once TMRO is started, it is not stopped or reloaded with values – it is just monitored. 16 minutes 40 seconds = 1,000 S = 1,000,000,000 uS.

    1,000,000,000 uS / (65,536 uS / TMRO overflow) = 15,258.78906 overflows for 1,000 S.

    Since overflows come in integer values, the time error is

    0.78906 overflow * 65,536 uS / overflow = 51,711.99345 uS error.

    51,711.99345 uS / 1,000,000,000uS * 100 = .00517%.

    As you can see, the longer the clock runs the more accurate the clock becomes because you divide by a larger number (e.g., at exactly 1 year, error is .000000181%. The error approaches zero! Again, not too bad!

    The only real error is associated with the crystal. I use +/-20ppm crystals, which results in a maximum of 1.728 S per day (or 0.002% time error max in the long run). Let me know if I can answer any more questions.

    The provided code attachments in the original post are heavily commented and easy to use - Anybody had any luck with these programs?

    Note: This website comes in handy for testing
    http://nist.time.gov/

    Paul Borgmeier
    Salt Lake City, Utah
    USA
    Last edited by paul borgmeier; - 26th March 2006 at 08:39.

  4. #4
    micro's Avatar
    micro Guest


    Did you find this post helpful? Yes | No

    Default

    i have another choice
    if u set prescale to 256 and TMR0 is intialzed on 194
    that is mean 256-194=62, so overflow ocurs in 62*256 =15.872 ms
    according to your calculation to calculate error

    1,000,000,000 uS/(15,872 uS/TMR0 overflow)=63,004.03226 overflow for 1,000 S

    the time error is

    0.03226 overflow * 15,872 uS/oveflow= 0.51203 ms error

    0.51203 ms/1000 S * 100=0.0000512%


    back to your approach
    i understand your method on another way as below
    the overflow takes 65.536 ms with this time we can not
    reach 1 S because of prescaler set to 256,so one approaches to get approximately 1 S is
    256*256 uS * 15= 0.98304 S this closes to 1 S
    or
    256*256 uS * 16 = 1.04857 S this exceedes 1 S

    note after 15 times you get 0.98304,so to complete 1 S you need 1-0.98304=16.96ms
    but this time is less than overflow time.

    but with my aprroach
    62*256uS*63=0.999936 S

    if someone set 0.98304 = 1 S in his program, then he will get accumulated errors by the time
    but your softer uses a methode makes the accumulated error = 0 whe you used
    0.98304 one time and the next time you used 1.04857 and the next time back to 0.98304
    so you increase and decrease on the normal time with a fixed.

  5. #5
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Smile

    Micro,
    Let me follow up with some comments. I think you are missing the goal of the “Easy and Accurate Clocks without RTC IC.” The goal was just that - to make an easy and accurate clock without a RTC. The way it is set up now (prescaler=256), the user has lots of time to do stuff between TMR0 roll overs – and the long term accuracy is amazing. The user also does not need to do much overhead to keep the clock running other than add time to a counter every so often.

    The “lots of time” is handy for updating serial displays, reading other sensors, turning on other things, doing something else, etc. (For example, depending on how it's done, to update the clock from 9:59.59 to 10:00.00 would require about 15 bytes sent to a display. Serially at 9600 baud, this is about 15.6 mS just to send. The user still has about 50mS to prepare the data for sending and to do other stuff!)

    With the algorithm in the examples above, you could easily reduce the the prescaler, which would reduce the second to second jitter – but the overall long-term accuracy remains the same. For example, if the prescaler was changed to 1 instead of 256. The second to second error would be: 1,000,000/256 = 3906.25 overflows, error = .25*256 = 64uS. For 1000 seconds, the total error would be 0 (which is hard to beat). The trade off for the second to second reduction in jitter is less time between overflows (with a prescaler of 1, the rollovers are every 256 uS – forget updating a display). But the point is- who cares about the jitter! When I look at my alarm clock every morning I do not care if if it is off by 34uS. When I am turning on lawn sprinklers every third day at 1:00AM, I do not care if it is 21 uS early., etc. What I do care about is the long term accuracy of my clocks.

    These algorithms are meant to be easy to use. There are only about 30 lines of code required to keep the time and maintain a display (including colon blinking). On the Internet or in this forum I have not seen anything close to this little amount of code for keeping good time with or without a RTC. If you are worried about the second to second variations, or making accurate short time timers, then check out Melanie's “Olympic Timer” or Darrel's “Elapsed Timer Demos”. They are both excellent!. Or, with my examples, you can look inside the TMRO counter at anytime and know your exact error. Skinning cats is fun!

    A comment about your option of initializing TMR0 to 194. This approach works, but you must note that you need to account for the fact that the timer does not start up immediately after you write to it. You also have to ask yourself what the Timer is doing while you are writing to it, i.e., is it counting? Because of these, you usually have to add a “fudge-factor” and reduce the initialized value even more. This can be done but takes more overhead code and you are getting farther away from “easy” (in my opinion). The nice thing about PICs is you truly do have lots of options. Everybody should use the option that best suits them.

    Paul Borgmeier
    Salt Lake City, Utah
    USA

  6. #6
    4Lewis's Avatar
    4Lewis Guest


    Did you find this post helpful? Yes | No

    Red face Clock

    Hi All: This looks really amazing. I am new to microcontrollers, so if you see any problems with me using the PIC16F819 for this project please let me know.

  7. #7
    Join Date
    Dec 2005
    Posts
    24


    Did you find this post helpful? Yes | No

    Default

    Paul,
    Clever code, if the crystal oscillator is running at 20 MHz instead of 4 MHz, how would the code be modified, thanks.
    Terry

  8. #8
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Smile

    My version of the algorithms are set up around a 4 MHz Xtal. They track 0.5 second intervals. On the half second (Col = 0 ), the colon is turned off, on the whole second (Col = 1), the time and colon are updated.

    A 20MHz Xtal is five times as fast as a 4 MHz. Therefore, with everything the “same” in the code the tracked interval would be 0.1 Sec instead of 0.5 Sec. Although I have not tried this, I believe all you need to do is change the Col variable from a BIT to a BYTE and use it for updating the colon blink and time.

    IF Col = 10 then update time (instead of IF Col = 1)
    IF Col = 5 then turn off blink (instead of the “THEN” part of IF Col =1)

    IF Col = 11 then Col =1 (add after Col=Col+1 to reset Col variable)

    Note, however, that you will have 1/5 the time to do other stuff in between overflows. With a 4 MHz Xtal, this gives over 65 ms. With a 20 MHz Xtal, this gives 13 ms (you may need to watch those serial LCD times)

    Since TMRO is maxed out with the prescaler of 256, the ideal solution would be to move to TMR1 or TMR2 (or to an 18F series where TMR0 = 2^16). With these other timers and a few code changes, you could get longer overflow times with your 20MHz Xtal. I encourage you to see Roman Black's original (www.romanblack.com) - he describes how to get any time period with any Xtal.

    Good Luck,

    Paul Borgmeier
    Salt Lake City, Utah
    USA

  9. #9
    Eng4444's Avatar
    Eng4444 Guest


    Did you find this post helpful? Yes | No

    Arrow Parallel LCD display

    Quote Originally Posted by paul borgmeier

    A Note on Displays:

    EXCLOCK1 is written for a serial LCD alphanumeric display - probably the most popular style of display out there. Most of us have one or have made one. There are lots of displays options. The code also could easily be changed to work with parallel displays since the instruction set is essentially identical.
    __________________________________________________ ______________

    How to make it work for a parallel LCD? can anyone help?

  10. #10
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Smile

    ENG4444,

    See SEROUT and LCDOUT commands in PBP manual. You will need to set up your LCD as shown in the LCDOUT section.

    A few of the first SEROUTS in the first program convert as follows (the rest should be relatively straight forward if you read SEROUT and LCDOUT sections of the manual):

    Serial LCD Commands
    Parallel LCD Commands

    SEROUT GPIO.0,6,[254,1]
    LCDOUT 254, 1

    SEROUT GPIO.0,6,[72,72,58,77,77]
    LCDOUT 72,72,58,77,77

    SEROUT GPIO.0,6,[254,X,#HH]
    LCDOUT 254,X,#HH

    Good Luck,

    Paul Borgmeier
    Salt Lake City, Utah USA
    www.cruxanalysis.com

  11. #11
    Join Date
    Jun 2006
    Location
    Bangalore, India
    Posts
    136


    Did you find this post helpful? Yes | No

    Question

    Is there any way someone can create a Roman black kind (one_sec.asm) of accurate tmr0 timer using picbasic?

  12. #12
    Join Date
    Feb 2008
    Posts
    7


    Did you find this post helpful? Yes | No

    Default

    Hi Paul, that is a very neat and professional implementation of my 1-sec system for PICBASIC.


    Would you be interested in creating a PICBASIC version of my BTc Picsound playback to enable PICBASIC users to play their own speech etc on PICBASIC hardware?

    I have released v2.0 of my BTc Encoder and would like to get some playback projects that in can list on my own page, pref in languages I don't use like PICBASIC and for micros I don't use.

    www.RomanBlack.com/picsound.htm

    [email protected] (remove the FURNITURE to email me)

  13. #13
    Join Date
    Dec 2005
    Posts
    24


    Did you find this post helpful? Yes | No

    Default

    Paul,
    In one of you earlier posts on this thread, you mention that you use a 20ppm crystal, can you share your source for this crystal. All the crystals I have found have a 50ppm tolerance at 25 deg and then a another 50ppm over temperature or then a worst case frequency tolerance of 100ppm, I would like to stay away from using a TXCO and 20ppm would be the right amount of acceptable tolerance for my project.
    thanks,
    Terry

  14. #14
    Join Date
    Feb 2003
    Location
    Salt Lake City, Utah USA
    Posts
    517


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by Terry View Post
    Paul,
    In one of you earlier posts on this thread, you mention that you use a 20ppm crystal, can you share your source for this crystal. All the crystals I have found have a 50ppm tolerance at 25 deg and then a another 50ppm over temperature or then a worst case frequency tolerance of 100ppm, I would like to stay away from using a TXCO and 20ppm would be the right amount of acceptable tolerance for my project.
    thanks,
    Terry
    Hi Terry,

    I am not near my lab so I cannot check right now ... however, I know I got them at either Digi-Key or Mouser. I just saw this part http://www.mouser.com/Search/Refine....t=815-ABL-4-B2
    and will check in my lab and confirm if that is what I used. Back when I posted this example I let my trial circuits run for months and found the tolerance to always be +/- 20ppm or less with the xtals I used. I will let you know here shortly.
    Paul Borgmeier
    Salt Lake City, UT
    USA
    __________________

  15. #15
    Join Date
    Sep 2003
    Location
    Vermont
    Posts
    373


    Did you find this post helpful? Yes | No

    Default

    I use the Abracon line. They have both SMT and through hole packages @20 ppm. They have some higher speed @ 10 ppm. Very reasonable, besides!

  16. #16
    Join Date
    Jan 2009
    Posts
    22


    Did you find this post helpful? Yes | No

    Default

    Shouldn't it HzTimer be initialized to $7A120 (dec500000), rather than to $7A12 (dec31250)? And incremented by the same $7A120 for 1/2 second.

  17. #17
    Join Date
    Jan 2009
    Posts
    22


    Did you find this post helpful? Yes | No

    Default

    Never mind; now I see you're dividing by $10.

  18. #18
    Join Date
    Aug 2003
    Posts
    985


    Did you find this post helpful? Yes | No

    Default

    Err, Did you realise you ignored the author of your one second timer when he posted here?

    Anyway, I was looking around for an explaination of why my clock drifts out
    a couple of seconds in a few hours. Now I know.
    I didn't know you could buy different qualities of crystals. Perhaps I should chase a better one.

  19. #19
    Join Date
    Oct 2009
    Posts
    583


    Did you find this post helpful? Yes | No

    Default Re: Easy and Accurate Clocks without RTC IC

    Quote Originally Posted by Terry View Post
    Paul,
    Clever code, if the crystal oscillator is running at 20 MHz instead of 4 MHz, how would the code be modified, thanks.
    Terry
    Ok I know this is an old thread, but having just modified the code to run on an 18F4520 using a 20 Mhz crystal I thought I would post the code here. It also uses a parallel LCD (20 x 4) so hopefully answers one of the other questions raised. The LCD display needs some tidying up to overwrite previous digits (other wise you get 29,39,49 etc until 10 seconds turns over) but then that should be a simple matter to sort out

    Code:
    ASM 
      __CONFIG    _CONFIG1H, _OSC_HS_1H
      __CONFIG    _CONFIG2L, _PWRT_ON_2L  
      __CONFIG    _CONFIG2H, _WDT_ON_2H & _WDTPS_512_2H
      __CONFIG    _CONFIG3H, _MCLRE_ON_3H & _LPT1OSC_OFF_3H & _PBADEN_OFF_3H  
      __CONFIG    _CONFIG4L, _LVP_OFF_4L & _XINST_OFF_4L
    ENDASM
    
    DEFINE  OSC 20  ; 48 was old config settings 18F4520, 20mhz crystal
    ADCON1 = $0F
    clear
    
    
    DEFINE LCD_DREG  PORTB           ' LCD Data port
    DEFINE LCD_DBIT  0               ' starting Data bit (0 or 4)
    DEFINE LCD_EREG  PORTB           ' LCD Enable port
    DEFINE LCD_EBIT  5               '     Enable bit  (on EasyPIC 5 LCD)
    DEFINE LCD_RSREG PORTB           ' LCD Register Select port
    DEFINE LCD_RSBIT 4               '     Register Select bit   (on EasyPIC 5 LCD)
    DEFINE LCD_BITS  4               ' LCD bus size (4 or 8 bits)
    DEFINE LCD_LINES 4               ' number of lines on LCD
    DEFINE LCD_COMMANDUS 2000        ' Command delay time in us 
    DEFINE LCD_DATAUS 50             ' Data delay time in us 
    
    LED var portA.7
    
    
    
    CMCON=7                'all digital 
    T0CON = %11000111
    INTCON=0               'interrupts off
    '**********************************************************
    HzTimer VAR Word         '1/2 second counter (2 Hz)    
    HH VAR Byte  ' Hours 0-23
    MM VAR ByTE  ' Minutes 0-59
    SS VAR Byte  ' Seconds 0-59
    col VAR Byte  ' colon 1=on, 0=0ff
    
    HzTimer=$7A12        'for 1/2 Sec
    HH=12:MM=0:SS=0:col=0 'initial conditions (12:00 O'clock noon)
    '**********************************************************
    
    LCDOUT $FE,1:FLAGS=0:PAUSE 250:LCDOUT $FE,1:PAUSE 250 ' Initialize LCD 
    
    Main:
    
    ClockLoop: IF intcon.2=0 THEN ClockLoop	'Poll for TMRO overflow
    INTCON.2=0 ' Clear TMRO overflow flag
    
    HzTimer=HzTimer-$1000	'decrement timer count
    
    IF HzTimer < $1000  THEN
        IF Col=10 THEN    ' update time'
            SS=SS+1
            LED =0    ' Turn off GP1
            IF SS=60 THEN   ' minute
                SS=0 
                MM=MM+1
                IF MM=60 THEN    ' hour            
                    MM=0
                    HH=HH+1
                    IF HH=24 THEN HH=0
                    IF HH=20 then LED = 1    ' Turn on GP0 at 8:00pm
                   LED =1    ' Turn On  GP1 for 1 second on the hour
                ENDIF                           ' Adjust these to meet your needs
                if MM=15 then LED = 0        ' Turn off GP0 at 8:15pm  
            ENDIF
        ENDIF
        Col=Col+1
    
        HzTimer=HzTimer+$7A12	' Add 0.5 seconds to count
    ELSE
        ' Do something here but must be less than 65.5 mSec
    ENDIF
          if Col=11 then 
        Col=1
        endif
       
        LCDOut $FE,$D4,#HH,":",#MM,":",#SS
        
    GOTO  Main 'forever
    ' **************************************************************
    END

Members who have read this thread : 2

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts