Ammar
Ammar

Reputation: 1233

How to make Timer1 more accurate as a real time clock?

I have PIC18F87J11 with 8 MHz oscillator and I am using timer1 as real time clock. At this moment I have it toggle an LED every 1 minute. I noticed it does work perfect fine the first few times but slowly it starts toggling the LED every 59 seconds. Then every few minutes it keeps going down to 58, 57, etc. I don't know if its impossible to get an accurate clock using internal oscillator or if I need external oscillator. My settings look right for timer1, I just hope I can resolve this issue with the current hardware.

Prescaler 1:8, TMR1 Preload = 15536, Actual Interrupt Time : 200 ms

    // Timer 1 Settings
    RCONbits.IPEN = 1; // Enable interrupt system priority feature
    INTCONbits.GIEL = 1; // Enable low priority interrupts
    // 1:8 prescalar
    T1CONbits.T1CKPS1 = 1;
    T1CONbits.T1CKPS0 = 1;
    // Use Internal Clock
    T1CONbits.TMR1CS = 0;
    // Timer1 overflow interrupt
    PIE1bits.TMR1IE = 1;
    IPR1bits.TMR1IP = 0; // Timer 1 -> Low priority interrupt group
    PIE1bits.TMR1IE = 1; // Enable Timer1 interrupt

    // TMR1 Preload = 15536;
    TMR1H = 0x3C;
    TMR1L = 0xB0;

Interrupt Routine

void interrupt low_priority lowISR(void) {
    if (PIR1bits.TMR1IF == 1) {

        oneSecond++;
        if (oneSecond == 5) {

            minute_Counter++; 

            if (minute_Counter >= 60) {
                // One minute passed
                Printf("\r\n One minute Passed");
                ToggleLed();
                minute_Counter = 0;

                            }
        oneSecond = 0;

        }



    // TMR1 Preload = 15536;
    TMR1H = 0x3C;
    TMR1L = 0xB0;

    PIR1bits.TMR1IF = 0;
}}

Upvotes: 1

Views: 2930

Answers (4)

OH2AXE
OH2AXE

Reputation: 1

For all timing, time and frequency applications the first and most important thing to do is to CALIBRATE THE CRYSTAL OSCILLATOR!!! The oscillator itself and its crystal MUST run exactly (to better than 1 part per million = 1ppm) of its nominal frequency. Crystals straight out of a factory (except some very specialized and expensive ones = 100's of $) are not running exactly at their nominal frequency. If the calibration is not done, all time and frequency related functions will be off, because the oscillator frequency is used as reference for all PICs internal functions. The calibration must be done against an accurate frequency counter by adjusting one of the capacitors from crystal pins to ground. Any processor routines for frequency (and time) calibration are not accurate enough.

Upvotes: -1

francis
francis

Reputation: 9817

There are some stuff in the datasheet you linked, "2.5.3 INTERNAL OSCILLATOR OUTPUT FREQUENCY AND TUNING", on p38

The datasheet says that

The INTOSC frequency may drift as VDD or temperature changes".

Are VDD and temperature stable ?

It notes three ways to deal with this by tuning the OSCTUNE register. The three of them would need an external "oscillator" :

  • dealing with errors of EUSART...this signal should come from somewhere.
  • a peripheral clock
  • cpp module in capture mode. You may use any stable AC signal as input.

Good luck !

Upvotes: 3

Dr. Sahib
Dr. Sahib

Reputation: 166

Reload the Timer as soon as it expires, the delay between timer overflow and rearm is affecting the total time. So this will solve your problem.

void interrupt low_priority lowISR(void) 
{
    if (PIR1bits.TMR1IF)
    {
        PIR1bits.TMR1IF = 0;
        TMR1H    = 0x3C;
        TMR1L    = 0xAF;

        /* rest of the code here */
        . . . .
    }
 }

One more recommendation is not to load up the isr, keep it simple.

Upvotes: 0

Clifford
Clifford

Reputation: 93556

The internal oscillator is a simple RC oscilator (a resistor/capacitor time constant determines its frequency), this kind of circuit may be accurate to only +/-10% over the operating temperature range of the device, and the device will be self-heating due to normal operating power dissipation.

From the data sheet: datasheet INTOSC spec

An external crystal or other accurate external clock source is required to get accurate timing. Alternatively, if you have some other stable and accurate, but low frequency clock source, such as output from an RTC with a 38768 Hz crystal, you can use that to calibrate the internal RC oscillator and dynamically adjust it with the OSCTUNE register - by using a timer gated by the low frequency source, you can determine the actual frequency of INTOSC and adjust accordingly - it will not be perfect, but it will be better - but no better than the precision of the calibrating source of course.

Some devices have a die temperature sensor that can also be used to compensate, but that is not available on your device.

The RC error can cause serial communications mistiming to the extent that you cannot communicate with a device using asynchronous (UART) serial comms.

Upvotes: 3

Related Questions