AnsweredHot!Timer accuracy and interrupts

Page: 12 > Showing page 1 of 2
Author
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
2018/02/09 13:45:47 (permalink)
0

Timer accuracy and interrupts

I have a PIC24F Curiosity Board -PIC24FJ128GA204- and I'm trying to get an accurate second timing with the TIM1. As a source I'm using the secondary oscillator, which uses a 32678 kHz xtl.
The timer is configured with a 32 period, which corresponds to 1 ms


void TMR1_Initialize (void)
{
//TMR1 0;
TMR1 = 0x0000;
//Period = 0.001 s; Frequency = 32000 Hz; PR1 32;
PR1 = 0x0020;
//TCKPS 1:1; TON enabled; TSIDL disabled; TCS External; TECS SOSC; TSYNC enabled; TGATE disabled;
T1CON = 0x8006;

IFS0bits.T1IF = false;
IEC0bits.T1IE = true;
tmr1_obj.timerElapsed = false;
}

So, every 1 ms the following interrupt is called, where the count of ms is stored on a uint32_t variable


void __attribute__ ( ( interrupt, no_auto_psv ) ) _T1Interrupt ( )
{
tmr1_obj.count++;
tmr1_obj.timerElapsed = true;
IFS0bits.T1IF = false;
}

In the main loop I do a busy wait on the tmr1_obj.count variable, and when it reaches 1000 a message is sent in UART.

int main(void)
{
// initialize the device
SYSTEM_Initialize();
TMR1_Start();

char msg[] = "A\r\n";
while (1)
{
// Add your application code
int value = TMR1_SoftwareCounterGet();
if (value == 1000) {
printf("%s", msg);
TMR1_SoftwareCounterClear();
}
}
return -1;
}


On the other side of the UART I have an application that reads the message and logs the time when it was received and the difference in milliseconds with respect to the previous message.
The problem is that I have an accumulation of ~8ms for each message.

22:05.026 1008
22:06.035 1009
22:07.045 1010
22:08.054 1008
22:09.063 1008

Suspecting it could be something related to the UART transmission being often interrupted I tried to send the message every 10 seconds instead of 1. The delay was consistently accumulated to ~80ms each 10 seconds.
Finally, it could be that the 32 ticks do not correspond to 1 ms but to 1.x ms. To test that I changed the period to be 32768, that is, 1 second. I expected the results to be roughly the same, but they weren't

31:15.216 999
31:16.216 999
31:17.216 1000
31:18.216 999
31:19.216 999
31:20.215 999
31:21.216 1000

It seems that the period affects the accuracy of the timer. And I don't understand how. Could it be that for each interruption some microseconds were lost ? I don't see anything on the data sheet, but I can't find any other explanation.
#1
dan1138
Super Member
  • Total Posts : 2814
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 14:36:50 (permalink) ☼ Best Answerby perencia 2018/02/09 15:10:22
4 (1)
Your accuracy issues depend on the actual frequency of the crystal you have connected to the TIMER1 oscillation amplifier.
 
In your post you have said this is a 32.768KHz crystal. With this frequency a divisor of 32 results in a period of 0.9765625 milliseconds not 1 millisecond as you stated in your post.
 
So what is the actual frequency of the actual crystal that you actually used?
#2
Gort2015
Klaatu Barada Nikto
  • Total Posts : 2645
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 14:54:10 (permalink)
4 (1)
Try setting the pre-scaler to 256.
 
32768 / 256 = 128 and setting the period to 127.
 
That should make the isr fire once every second.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#3
NorthGuy
Super Member
  • Total Posts : 5019
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 15:32:29 (permalink)
4 (1)
Regardless of the timer accuracy, the time since the timer reaches 1000 to the point where you clear it is added to the period of your actions, so you should expect your period to be longer than the timer would produce.
 
To get an accurate period you need a free-running timer which rolls over by itself, without extra delays. You can do this by setting PR1 register.
#4
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 15:38:29 (permalink)
0
You're right, a divisor of 32 doesn't result in a period of 1 ms. As I'm only concerned with counting seconds, I should count to 1024 periods instead of 1000. I've corrected it and the delay has increased to ~30ms for each round of 1024 periods.

int main(void) {
    // initialize the device
    SYSTEM_Initialize();
    TMR1_Start();
    char msg[] = "A\r\n";
    while (1) {
        // Add your application code
        int value = TMR1_SoftwareCounterGet();
        if (value == 1024 - 1) {
            printf("%s", msg);
            TMR1_SoftwareCounterClear();
        }
    }
    return -1;
}

 
22:59.783 1030 A
23:00.814 1030 A
23:01.844 1030 A
23:02.874 1029 A
23:03.904 1030 A
23:04.935 1030 A
23:05.965 1030 A
 
Regarding the actual frequency, I haven't measured it on this board, but, actually, this is happening to me in two different boards with two different PICs -the other being a PIC24FJ256GB406-. On that other board I measured it and it was actually 32768 kHz and the delay was the same as I'm getting here ~30ms. I'm kind of replicating the problem here.
 
But, even if the frequency was not 32.768 kHz, if it is constant, I don't see why the number of interruptions triggered should affect the accuracy. Regardless of the period, the delay should be the same, I think.
 
 
 
#5
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 15:39:43 (permalink)
0
Gort2015
Try setting the pre-scaler to 256.
 
32768 / 256 = 128 and setting the period to 127.
 
That should make the isr fire once every second.


I can't do that, other parts of the system relay on the 32 period.
#6
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 15:47:39 (permalink)
0
I expect some time to be added - returning from the interrupt, compare with 1024 and clear the timer- but not as much as ~30 microseconds per interrupt. Anyway, I can try not resetting the timer.
post edited by perencia - 2018/02/09 15:51:23
#7
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/09 15:56:48 (permalink)
0
Same results without clearing the timer.
 

int main(void) {
    // initialize the device
    SYSTEM_Initialize();
    TMR1_Start();
    char msg[] = "A\r\n";
    while (1) {
        // Add your application code
        int value = TMR1_SoftwareCounterGet();
        if (value > 0 && value % (1024 - 1) == 0) {
            printf("%s", msg);
        }
    }
    return -1;
}

 
53:14.522 1029 A
53:15.553 1030 A
53:16.583 1030 A
53:17.613 1029 A
53:18.643 1030 A
#8
Gort2015
Klaatu Barada Nikto
  • Total Posts : 2645
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/10 09:02:50 (permalink)
0
Use another timer.
 
If you want accuracy then get a RTC chip like the Maxim Integrated extremly accurate DS3231.
 
Besides being a RTC with 2 timers, it can also output a square wave of 1, 1024, 4096, 8192 and 32768 per second.  It has it's own xtal inside the chip.  All you need is the chip, backup battery and pullups on the i2c bus.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#9
Chris A
Super Member
  • Total Posts : 797
  • Reward points : 0
  • Joined: 2010/07/20 04:37:07
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/10 11:41:50 (permalink) ☄ Helpfulby dan1138 2018/02/10 11:57:13
5 (1)
I think you missed the fact that you need to put one less into the PR register.  So use 31 instead of 32.
 
1000/32 * 33 = 1031
i.e. the error you are getting!
 
You should not clear the count.  The PR match will do that:  29,30,31,0,1 etc
post edited by Chris A - 2018/02/10 11:43:32
#10
Gort2015
Klaatu Barada Nikto
  • Total Posts : 2645
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/10 14:46:32 (permalink)
0
As in post #3.
 
 

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#11
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 04:41:16 (permalink)
0
Thanks, I forgot subtracting 1 to  period, you were right.
 
The results have certainly improved

50:01.479 999 
50:02.478 999 
50:03.477 998 
50:04.476 998 
50:05.475 999 
50:06.474 999 
50:07.473 999 
50:08.472 998 
50:09.471 999 
50:10.470 999 
50:11.469 998 
50:12.468 998 
 
As you see, now I'm ~1ms per second ahead, which is an error of ~0.1%. I don't know the specs of the xtl, but this is way more than even a 50 ppm deviation, in the worst case. If it were a delay I could blame it on some processing, though it is still too much, but being so much ahead is something I don't understand. What could be the cause ?
 
post edited by perencia - 2018/02/11 04:43:38
#12
NorthGuy
Super Member
  • Total Posts : 5019
  • Reward points : 0
  • Joined: 2014/02/23 14:23:23
  • Location: Northern Canada
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 07:17:20 (permalink)
0
Do you still have this:
 
         if (value > 0 && value % (1024 - 1) == 0) { 
            printf("%s", msg);
        }

 
?
 
If so, removing "-1" should fix it.
#13
perencia
New Member
  • Total Posts : 12
  • Reward points : 0
  • Joined: 2018/02/04 03:27:27
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 11:12:13 (permalink)
0
I didn't had this code, I had this

 
int main(void) {
// initialize the device
    SYSTEM_Initialize();
    TMR1_Start();
 
    char msg[] = "A\r\n";
    while (1) {
        // Add your application code
        uint32_t value = TMR1_SoftwareCounterGet();
        if (value == 1023) {
            TMR1_SoftwareCounterClear();
            printf("%s", msg);
        }
    }
return -1;
}
 

 
but I have changed the 1023 to 1024 and the accuracy is much better now. I understand that i was not letting the 1023th period to end, resetting it before it has fully completed. That would explain being ahead. Was that your reasoning, NorthGuy?.
These are the results now
 
48:26.675 1000
48:27.675 1000
48:28.675 999
48:29.675 999
48:30.675 999
48:31.675 999
48:32.675 1000
48:33.675 999
48:34.675 999
48:35.675 999
48:36.674 999
48:37.674 999
48:38.674 999
48:39.674 999
48:40.674 999
48:41.674 999
48:42.674 999
48:43.674 999
48:44.674 999
48:45.674 999
48:46.674 999
48:47.674 999
48:48.674 999
48:49.674 999
48:50.674 999
48:51.674 999
48:52.674 999
48:53.674 999
48:54.674 999
48:55.674 999
48:56.674 999
48:57.674 999
48:58.674 999
48:59.673 999
49:00.673 1000
49:01.673 999
49:02.673 999
49:03.673 999
49:04.673 1000
49:05.673 999
49:06.673 999
49:07.673 1000
49:08.673 1000
49:09.673 999
49:10.673 999
49:11.673 1000
49:12.673 999
49:13.673 999
49:14.673 999
49:15.673 999
49:16.673 999
49:17.673 999
49:18.673 999
 
~1 ms lost in 23 seconds. I think that may be good enough for me. 
Thank you all!
 
post edited by perencia - 2018/02/11 11:23:54
#14
Chris A
Super Member
  • Total Posts : 797
  • Reward points : 0
  • Joined: 2010/07/20 04:37:07
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 12:34:00 (permalink)
0
The remaining error is just as likely to be at the other end printing those times out! ;-)
#15
PStechPaul
Super Member
  • Total Posts : 2023
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 14:59:29 (permalink)
0
The crystal will have 50 PPM accuracy (or better) only with the specified capacitors (for a parallel resonant type). You need two capacitors, one from each side of the crystal to ground. If it specifies 20 pF, you need two 40 pF capacitors, because they are essentially in series across the crystal with a tap to GND. You can tweak the values by using a variable capacitor or a "gimmick", which is just a pair of enamel coated wires twisted together to form a capacitor of a few pF, and you can adjust by cutting a little off the end while observing frequency with an accurate counter. More capacitance lowers the frequency.

 
#16
Gort2015
Klaatu Barada Nikto
  • Total Posts : 2645
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 15:01:18 (permalink)
0
1ms is a lot.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#17
PStechPaul
Super Member
  • Total Posts : 2023
  • Reward points : 0
  • Joined: 2006/06/27 16:11:32
  • Location: Cockeysville, MD, USA
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 15:03:24 (permalink)
0
1 mSec out of 23 seconds is 0.001/23 = 43 ppm.

 
#18
Gort2015
Klaatu Barada Nikto
  • Total Posts : 2645
  • Reward points : 0
  • Joined: 2015/04/30 10:49:57
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 15:08:30 (permalink)
0
An extra 10hrs in a week.

MPLab X playing up, bug in your code? Nevermind, Star Trek:Discovery will be with us soon.
https://www.youtube.com/watch?v=Iu1qa8N2ID0
+ ST:Continues, "What Ships are Made for", Q's back.
#19
dan1138
Super Member
  • Total Posts : 2814
  • Reward points : 0
  • Joined: 2007/02/21 23:04:16
  • Location: 0
  • Status: offline
Re: Timer accuracy and interrupts 2018/02/11 15:45:18 (permalink)
0
You may still be off by one TIMER1 interrupt.

Please try this code to see if it helps:
int main(void) {
    // initialize the device
    char msg[] = "A\r\n";
    uint32_t Time0;
    uint32_t Time1;
    
    SYSTEM_Initialize();
    TMR1_Start();
 
    // Get initial clock time
    IEC0bits.T1IE = false; // disable TIMER1 interrupt to prevent corrupted read of count from ISR
    Time0 = TMR1_SoftwareCounterGet();
    IEC0bits.T1IE = true;  // enabable TIMER1 interrupt
    
    while (1) {
        // Add your application code
        
        IEC0bits.T1IE = false; // disable TIMER1 interrupt to prevent corrupted read of count from ISR
        Time1 = TMR1_SoftwareCounterGet(); // Sample current clock time
        IEC0bits.T1IE = true;  // enabable TIMER1 interrupt
        
        // Test for at least one second of elapse time
        if (Time1 - Time0 > 1023) {
            Time0 += 1024; // Add the number of TIMER1 interrupts in one second
            printf("%s", msg);
        }
    }
    return -1;
}

#20
Page: 12 > Showing page 1 of 2
Jump to:
© 2018 APG vNext Commercial Version 4.5