3 Attachment(s)
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 ...
Re: Easy and Accurate Clocks without RTC IC
Quote:
Originally Posted by
Terry
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