'PROGRAM: EZCLOCK2 ' Paul R. Borgmeier, PhD ' Crux analysis & design, LLC ' www.cruxanalysis.com ' June 02, 2005 ' Initial Release '*********************************************************** 'DESCRIPTION: This bare bones program demonstrates how to ' create a very simple yet accurate clock without the use of ' a RTC IC. ' ' This version of the code tracks time in an HH:MM:SS format. ' Time is tracked by the program but not displayed. The initial ' starting time is arbitrarily set to 12:00 noon but can be ' changed to meet your needs. ' ' This version requires a 4.000 MHz Xtal - accuracy is ' controlled 100% by Xtal tolerance: (schematic is below) ' ' 100ppm tolerance gives < 9 sec/day error ' 50ppm tolerance gives < 5 sec/day error ' 30ppm tolerance gives < 3 sec/day error ' 20ppm tolerance gives < 2 sec/day error ' '*********************************************************** 'HOW IT WORKS: This clock is based on Roman Black's "Zero-error ' One Second Timer!" (www.romanblack.com) but has been optimized ' for simplicity and implementation using PicBasic Pro. This ' program keeps track of .5 second intervals. On the ' whole second, the time is udated. ' ' The version here makes use of TMRO with a prescaler of 256 and ' manual polling for TMRO overflow (interrupts could easily by ' added if needed). This makes the TMRO period equal to 65,536 ' microseconds(65.536 mSec), which gives the user lots of time to ' do other stuff between TMRO overflows. ' Note that although the overall accuracy of the clock is as accurate ' as the Xtal tolerance, individual seconds are not and vary slightly ' from second to second - however,the cummulative error of the second ' to second variation appraoches ZERO! Each half second calculated by ' the program is either 0.4588 seconds or 0.5243 seconds in length. ' The program combines these so that the total error approaches zero ' when compared to a perfect timer - the only error left is due to ' crystal tolerance. Note that the longer the program runs, the more ' accurate the clock becomes. For example, after 1000 seconds, the ' total error is just 0.0052% (this equates to 52mSec—not bad!). ' ' The news gets even better. If you cannot live with this accuracy, ' for example in a timer application, once the timer or program has ' been stopped, the error can be determined in software and corrected. ' The correction can be determined from the values of TMRO, HzTimer, ' and Col at the time of interest. Most will not have to deal with ' this correction because the error approaches zero the longer the ' clock runs anyway. The value of the error from any second is always ' less than 65.5mSec regardless of the elapsed time. ' ' Black's timer uses three separate byte-sized variables to track the ' instruction counts for one second periods. His method is fast and ' clever, but requires manually watching and maintaining addition ' overflows and carries between three variables. ' ' With a 4 MHz crystal, 0.5 seconds equals 500,000 instructions (h7A120), ' which is larger than a word-sized variable in PicBasic Pro. The TMRO ' time period used in the code is 65,536 (h10000). The trick used here is ' to divide both the instruction count and timer count by 16 (h10), which ' makes the instruction count trackable in a single word-sized variable, ' HzTimer. ' ' This bare bones program demonstrates how to implement this clock. ' The program has one sections: ' ' (1) Maintains time internally. Hours are HH 0-23, Minutes are ' MM 0 - 59, Seconds are SS 0-59 ' ' The user can add code to perform tasks as needed. To demonstrate ' this, the code below toggles GP1 for 1 second on the hour. The code ' also turns of GP0 at 8:00 pm and turns it off at 8:15 pm. ' ' The entire code is amazingly short—just about ' 30 to 40 lines of code, depending on how you count. ' '*********************************************************** 'PIC: 12F629 ' GP0: Turn Something On (relay, FET, alarm, etc) ' GP1: Test Location LED, Buzzer, VOM, nothing? ' GP2: ' GP3: (MCLR Internal) ' GP4: XTAL 4.0000 Hz (w/tolerance = 30 ppm) w/ cap to GND ' GP5: XTAL 4.0000 Hz (w/tolerance = 30 ppm) w/ cap to GND ' ' -_- ' +5V--| |--GND ' Xtal-|12F|--to turn on circuit (relay, FET, alarm, etc) ' Xtal-|629|--test location (LED, buzzer, etc. if required) ' -| |- ' --- ' (Xtal caps to GND not shown) ' ' CONFIGURATION SETUP ' Oscillator: XT ' Watchdog Timer: OFF ' Power up Timer: OFF ' Master Clear Enable: Internal ' Brown Out Detect: OFF ' Code Protect: OFF ' Data EE Read Protect:OFF '********************************************************** CMCON=7 'all digital for low power use GPIO=0 TRISIO=0 OPTION_REG=%10000111 'weak pullups off, TMRO prescale = 256 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 Bit ' 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) '********************************************************** 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=1 THEN ' update time' SS=SS+1 GPIO.1=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 GPIO.0 = 1 ' Turn on GP0 at 8:00pm GPIO.1=1 ' Turn On GP1 for 1 second on the hour ENDIF ' Adjust these to meet your needs if MM=15 then GPIO.0 = 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 GOTO Main 'forever ' ************************************************************** END