Easy and Accurate Clocks without RTC IC


Closed Thread
Results 1 to 19 of 19

Hybrid View

  1. #1
    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

  2. #2
    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.

  3. #3
    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

  4. #4
    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

  5. #5
    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