Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

PICs and keeping time

Status
Not open for further replies.

NJ Roadmap

New Member
What's the most accurate way to get the PIC to keep time well for weeks together. I mean with +/- 1 min accuracy per month for example. Obviously using an external crystal would be a good start, but any other pointers?

And what about the software? I'm currently getting it to count 100ms per interrupt and then keeping the time from there, currently using the TMR1 of the PIC18F4520 (clocked using internal OSC at 8MHz, which I know isnt the most accurate!).
 
Another approach would be to use the AC mains as your frequency reference.

The power companies make the average frequency of their mains very accurate.

If you want to run it from a battery during mains failures, you could use a crystal as the freq standard. In other words, the PIC would monitor the mains supply, and if it fails, switch to the crystal for the duration. If the mains failure is only an hour or three, the gain or loss of time would be minimal.
 
Right, now comes the more interesting question: How can you make sure that whatever else you PIC is doing, it still stops it, counts up a second or 100ms or whatever the increment is without ever missing one. I know I can use a timer interrupt, but are there any pointers with respect to the coding in the main()? Obviously the timer isr() shouldn't take longer than the timer period to execute, but what other parts of a program could possibly affect the timer accuracy?
 
Here's a reprint from a Forum.Microchip post that I hope may prove useful.

Happy Holidays. Mike, K8LH


Software version of Xtal Oscillator Trimmer Capacitor

A 20-MHz crystal oscillator doesn't necessarily oscillate at exactly 20-MHz which can be a 'bummer' in RTC applications (grin). Normally I would use a ceramic trimmer capacitor to 'tune' the oscillator circuit but last year I tried a "software" trimmer capacitor in a couple projects. So far it's proven very reliable and accurate.

The "software" trimmer code consists of 8 instruction words in two locations within the ISR;
Code:
;
;  ISR_Trim routine is used to adjust the RTC 1-second period to
;  within plus or minus 200-nsecs to make up for a crystal which
;  may be slightly off frequency.  The routine adds or subtracts
;  one 200-nsec count (1 Tcyc) from Timer 2 for the first 'CCTR'
;  number of 1-msec interrupts each second. Theoretical accuracy
;  to within 6.3 secs/year, not including temperature drift and
;  crystal aging.
;
;   variables:  CCNT, correction count from EEPROM [00 to FF]
;               CVAL, correction value from EEPROM [FF or 01]
;               CCTR, correction counter reloaded from 'CCNT'
;                     variable each 1-second period
;
;       range:  ±255 200-nsec counts/second (±51.0 usecs/sec)
;
ISR_Trim
        movf    CCTR,W          ; correction counter 0?           |B0
        bz      ISR_Sw_Input    ; yes, branch, else               |B0
        decf    CCTR,f          ; decrement counter               |B0
        movf    CVAL,W          ; get correction value FF or 01   |B0
        addwf   TMR2,f          ; apply 1 Tcyc timer correction   |B0
;
I reset the CCTR 'correction counter' var with the CCNT 'correction count' value after each 1-second RTC period a little further down in my ISR;
Code:
;
;  the Real Time Clock 1-second 'heartbeat' timer/counter code
;  counts 1,000 1-msec interrupts before performing all of the
;  once-per-second procedures and functions
;
ISR_RTC    
        decfsz  RTCL,f          ; RTC counter lo = 0?             |B0
        goto    ISR_Calibrate   ; no, branch, else                |B0
        movlw   d'250'          ;                                 |B0
        movwf   RTCL            ; reset RTCL for 250-msecs        |B0
        decfsz  RTCH,f          ; all four 250-msec periods?      |B0
        goto    ISR_Calibrate   ; no, branch, else                |B0
        bsf     RTCH,2          ; reset RTCH for 4 (x 250)        |B0
;
;  reload timer Trim correction counter
;
        movf    CCNT,W          ; reload correction counter var   |B0
        movwf   CCTR            ;                                 |B0
;
A couple caveats apply when using the code; (1) writing to TMR2 clears the prescaler and postscaler but I don't use the prescaler and the postscaler hasn't yet incremented when I write TMR2, (2) You can apply the correction to shorter overall periods (100-msecs, 200-msecs, etc.) as long as the correction to your particular crystal can be accomplished within the shorter period.

Adjusting the CVAL 'correction value' and CCNT 'correction count' values and saving them to EEPROM is entirely up to you. In one of my projects I use a PCB jumper to display the values, a rotary encoder to edit them, and then remove the PCB jumper to save the edited values back to EEPROM.

Have fun. Kind regards, Mike
 
typical watch crystals are 20 ppm accurate. 1 min/month is 23 ppm so you should be good with that. You should definitely us interrupts.
 
A generic micro controller crystal is usually good till 50ppm. If you have a refrence signal of any kind (AC mains) calibrating it over the longer term is very easy. Just use something like a basic zero cross detect on the AC mains line to synchronize a real time clock. Mind you in the U.S. at least there is a 10mhz signal that is recievable in almost every location in the U.S. that can give you sub micro second accuracy using very basic receivers. It comes down to that anyways, comparing your local clock with some sort of standard.
 
You could use timer2 instead of timer1, it has a pre-scaler, post-scaler and a PR reg which makes it flexible for configuring time intervals to trigger interrupts with no need to re-load the counter after each interrupt.

If you have enabled interrupt priorities for using several interrupts, the clock timer interrupt must be set to high priority.

As for time accuracy, I also tried using the internal clock for a very basic timer and found it to be about 1-2% inaccurate. The factory calibration is supposed to be to within 1% but it also varies with temperature and power supply.
There is an OSCTUNE reg to allow adjustment but it is not fine enough for your needs.

A crystal oscillator can give reasonable results, but choose a good quality crystal - cheaper ones are only accurate to 50ppm or worse, better ones are usually about 20ppm or 10ppm.
You will still need some means of fine adjustment and the accuracy is affected by temperature and crystal ageing.

For better accuracy, Dallas/Maxim do a real-time clock chip with built-in temperature compensation but it is more expensive.

Or you could sync with radio time signals, MSF (UK) or DCF77 in Europe.

GPS is also very good if you get one with an accurate 1pps output, but you also need to consider the antenna placement.
 
ljcox said:
.......... you could use a crystal as the freq standard. In other words, the PIC would monitor the mains supply, and if it fails, switch to the crystal for the duration. ...................
Hi,

i feel once crystal is in place, we can safely forget mains as a frequency source. afterall 32.768KHz ones are not costly neither 3.579545MHz.

Only issue is temp maintenance. towards this end, the tinycrystal can be safely pushed into a thermocole or glassfiber stuff and insulated(isolated from atmosphere.(if space permits) and the associated caps could be temp quotient ones as philips(now NXP) was supplying these for RF circuits.
 
Last edited:
mvs sarma said:
Hi,

i feel once crystal is in place, we can safely forget mains as a frequency source. afterall 32.768KHz ones are not costly neither 3.579545MHz.

Mains is far more accurate, at least in most countries - as it's corrected every night. With a crystal you would need to occasionally adjust it, with mains you don't need to.
 
Right, for a zero cross detector - any particular ICs in mind? And what about the associated circuitry?

I'm just sizing up my options. Currently using the internal OSC and after 3 hours of fine tuning, I've got it to <6 mins accuracy per week.
 
NJ Roadmap said:
Right, for a zero cross detector - any particular ICs in mind? And what about the associated circuitry?

I'm just sizing up my options. Currently using the internal OSC and after 3 hours of fine tuning, I've got it to <6 mins accuracy per week.
You don't need a zero crossing detector. Just feed the mains frequency into a Schmitt Trigger (eg. 40106, 74C14, etc). The input of the Schmitt needs to be protected against over and under voltage.

From memory, I believe that some PICs have a Schmitt on some i/o so you may not need an external Schmitt.
 
ljcox said:
You don't need a zero crossing detector. Just feed the mains frequency into a Schmitt Trigger (eg. 40106, 74C14, etc). The input of the Schmitt needs to be protected against over and under voltage.

From memory, I believe that some PICs have a Schmitt on some i/o so you may not need an external Schmitt.

Yes, you can feed mains directly to a pin via a suitable HIGH value current limiting resistor - there are a number of MicroChip application note showing this.

However, I would prefer to do it after the bridge rectifier - simply place a single diode between the output of the bridge and the electrolytic capacitor. You can then take a feed from the output of the bridge, through a resistor to the base of an NPN transistor - it's collector (pulled high via a resistor to 5V) will have a lovely zero-crossing pulse on it!.
 
Neither Nigel nor I are suggesting that it be taken directly from the mains. It should be taken from the secondary of a transformer.

I would also include a capacitor from the resistor (at the input to the PIC end) to gnd in order to filter any high frequency spikes that may be in the mains.
 
Nigel Goodwin said:
Yes, you can feed mains directly to a pin via a suitable HIGH value current limiting resistor - there are a number of MicroChip application note showing this.

However, I would prefer to do it after the bridge rectifier - simply place a single diode between the output of the bridge and the electrolytic capacitor. You can then take a feed from the output of the bridge, through a resistor to the base of an NPN transistor - it's collector (pulled high via a resistor to 5V) will have a lovely zero-crossing pulse on it!.

I think I am going to give your idea a try, but am a bit confused about the orientation of the diode and from exactly where I can take a feed from the bridge o/p?
 
OK, here's how it's done!.
 

Attachments

  • zero_crossing.GIF
    zero_crossing.GIF
    4.2 KB · Views: 213
Status
Not open for further replies.

Latest threads

Back
Top