CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Timer1 and milliseconds
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
leto



Joined: 02 Aug 2005
Posts: 14

View user's profile Send private message

Timer1 and milliseconds
PostPosted: Wed Sep 07, 2005 9:13 am     Reply with quote

Hi,

I am trying to make a chronometer. I am using timer1 each a millisecond, but he is not very exact.

Code:

#define COUNTER1 60585

setup_counters(RTCC_INTERNAL,RTCC_DIV_1);
set_rtcc(COUNTER1);

#int_rtcc
void crono(){
   set_rtcc(COUNTER1);
   ++tick;
}


Anybody can help me ?. May be using another function or something.I need to obtain exactitude. Im using 18F452.

thank you
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Sep 07, 2005 9:47 am     Reply with quote

(Isn't rtcc actually Timer 0?)
Anyways,
Is your 1.0 ms off by a few MICROseconds?

This would be due to all the overhead of saving interrupt context before you actually get to the meat of your interrupt service routine. And it will get worse if you have other interrupt sources enabled.

You can try a "fast interrupt" to get some of the latency reduced, but I don't know how to implement one.

One way to get a 'guaranteed' 1ms delay would be to write:

Code:

disable_interrupts(GLOBAL);
delay_ms(1);
enable_interrupts(GLOBAL);


This is an awkward way to do things since you are now starving interrupts from executing, but it is a guaranteed way to get 1ms.

There are other options you can do such as using the CCP.
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Sep 07, 2005 9:54 am     Reply with quote

Oh, I think I veered off-topic above.

You are designing a "chronometer", which is just like a watch, right?

Hey, then all you need is a 32.768khz external clock source hooked up to the PIC's timer pins!

32,768 ticks = 0x8000 counts in a 16-bit timer.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Sep 07, 2005 10:36 am     Reply with quote

Code:
#int_rtcc
void crono(){
   set_rtcc(COUNTER1);
   ++tick;
}
This way of setting the timer is easy but not very accurate. It is very difficult to get the value for COUNTER1 exactly right because as MikeValencia already mentioned you have to account for interrupt overhead as well. The amount of interrupt overhead can be determined from studying the generated assembly code. Problem is that this might change with a new compiler version so is not a very stable solution.

Your main problem is that your clock frequency is not a multiple of 256, if this was the case you could have chosen a prescaler value that would give you an exact 1ms interrupt and no setting of the timer value was required.

I see the following solutions:
1) Choose another clock frequency that gives you exact 1.0ms intervals with the possible prescaler values.
2) Use timer2 which has an extra compare register for exactly this purpose.
3) Attach a 32.768kHz crystal to the timer inputes as MikeValencia suggested.
MikeValencia



Joined: 04 Aug 2004
Posts: 238
Location: Chicago

View user's profile Send private message Send e-mail Yahoo Messenger

PostPosted: Wed Sep 07, 2005 10:50 am     Reply with quote

ckielstra wrote:
Code:
#int_rtcc
void crono(){
   set_rtcc(COUNTER1);
   ++tick;
}


Your main problem is that your clock frequency is not a multiple of 256, if this was the case you could have chosen a prescaler value that would give you an exact 1ms interrupt and no setting of the timer value was required.

I see the following solutions:
1) Choose another clock frequency that gives you exact 1.0ms intervals with the possible prescaler values.


I'm looking at Digikey right now, and have found crystals with the following frequencies:
8.192MHz
4.096MHz

You wouldn't need an external 32.768khz clock source if you can use one of the crystals above and just play with the prescaler settings. With that being said, I don't know now if you truly need 1ms precision or 1-second precision. Anyways, you should do as ckielstra said and find a frequency whose number of ticks would be exactly divisible by the time granularity you want.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Wed Sep 07, 2005 11:11 am     Reply with quote

From you code I figured that you are using a 20MHz crystal. Here's what I do.
Code:

/* setup timer2 - 1ms counter */
setup_timer_2(T2_DIV_BY_4, 0xFA, 5);
Guest








PostPosted: Wed Sep 07, 2005 7:17 pm     Reply with quote

Thank you. But I think I have a oscilator problem because the timing diferences has not constant. I thing the osc change the frecuency.
Im using a 20mhz crystal and two 15pf.

regards, leto
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Thu Sep 08, 2005 4:40 am     Reply with quote

Do you have other interrupts active besides the timer interrupt?

How large are the timing deviations you get?
Ttelmah
Guest







PostPosted: Thu Sep 08, 2005 4:51 am     Reply with quote

It might be because the line that Mark has posted will actually give 1.004mSec. The count value needs to be 0xF9, not 0xFA. The count includes zero remember, so needs to be 0....249, not 250.
Te sort of arithmetc slip I do all the time, and which the CCS 'wizard' used to do as well. :-)

Best Wishes
Guest








PostPosted: Thu Sep 08, 2005 6:50 am     Reply with quote

Yes, I have activated other interrupts: #ext, #rb and #rda, but there is no events fired while I check the time. The only one fired is #rb that I use to start-stop counting but just twice per count.

The follow result is using: setup_timer_2(T2_DIV_BY_4, 0xFA, 5);
and

#INT_TIMER2
void crono{
++tick;
}

Manual
Chrono PIC
=============
05:02.65 - 05:01.29
00:59.91 - 00:59.28
12:14.25 - 12:11.20

PIC is slower than a standard chronometer.
Ttelmah
Guest







PostPosted: Thu Sep 08, 2005 7:19 am     Reply with quote

Assuming the first figure is minutes, then this is _exactly_ the error expected from the arithmetic fault I pointed out.
The first example 302.65secs versus 301.29 = 1.0045*
The third example (the best, since with the largest count, it reduces other possible error sources the most), gives 734.25/731.2 = 1.0041*

Correct the count as I have already posted.

Best Wishes
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Thu Sep 08, 2005 8:02 am     Reply with quote

Ttelmah wrote:
It might be because the line that Mark has posted will actually give 1.004mSec. The count value needs to be 0xF9, not 0xFA. The count includes zero remember, so needs to be 0....249, not 250.
Te sort of arithmetc slip I do all the time, and which the CCS 'wizard' used to do as well. :-)

Best Wishes

Yep, I learned something today Very Happy Time to rev all my firmware Wink
Guest








PostPosted: Thu Sep 08, 2005 8:09 am     Reply with quote

thank you Ttelmah. It works much better, but look: I still have aprox. 1/300 seg of difference when I test short times 4 or 10 seconds. When I test more time, 30 or 40 minutes it difference disappear and it works well.


Could you tell me how can I improve the accurate. May be using PWM or something. I have a PIC18F452.

Regards,
leto
Guest








PostPosted: Thu Sep 08, 2005 8:19 am     Reply with quote

Yes Mark, so the manual about setup_timer2 is wrong.

setup_timer_2 ( T2_DIV_BY_4, 0xc0, 2);

// At 20mhz, the timer will increment every 800ns,

// will overflow every 153.6us,

// and will interrupt every 307.2us.
Ttelmah
Guest







PostPosted: Thu Sep 08, 2005 9:38 am     Reply with quote

Anonymous wrote:
thank you Ttelmah. It works much better, but look: I still have aprox. 1/300 seg of difference when I test short times 4 or 10 seconds. When I test more time, 30 or 40 minutes it difference disappear and it works well.


Could you tell me how can I improve the accurate. May be using PWM or something. I have a PIC18F452.

Regards,
leto

How are you actually 'triggering' the two counters?. I saw that the shorter time was in error by more than the other two, and assumed this was probably something like the actual change being detected differently by the two systems. Remember that there will _always_ be differences in short times, unless the clocks are synchronous, and these will be made worse if (for instance), the triggering signal has a fairly slow edge, and one circuit detects it at 2.4v, and the other at 4v.

best Wishes
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group