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

setttingup timer 3

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

setttingup timer 3
PostPosted: Fri Aug 25, 2006 2:08 pm     Reply with quote

I'm working with Timer3 to control an rc servo. I use timer2 for the 20ms part, now I need to time the pulse, so I would like us resolution. I'm looking at the pic18f542 spec and the ccs manual and just want to make sure I'm thinking of this correctly. if I'm wrong then someone please tell me where.

at 20Mhz, the instruction cycle is 5Mhz, so the timer will increment every 200ns if I setup_timer_3 with T#_internal and T3_Div_By_1, is that correct?
so that is 5 ticks per us which is more than enough. It is a 16bit counter so I can time up to 13K us. So if I want a 1500us pulse I can just do a set_timer3(0) and just wait until get_timer3 returns at least a 1500 correct?

Am I missing anything here?
Thanks
Ringo
_________________
Ringo Davis
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Fri Aug 25, 2006 2:25 pm     Reply with quote

There's a bit of a better way, requiring just a slight change in your thinking.

First, you're right about timer 3 and its resolution, counting rate, etc.

If I remember correctly, a servo requires a 1 - 2 ms wide pulse every 20 ms or so. You said that you're already using timer 2 to give you the 20 ms portion (good).

How about this:

When the timer 2 interrupt "fires", set the output line high - this is the beginning of your servo pulse. You then enable & set up timer 3 at this point too. Just assume that timer 3's interrupt has been disabled - you'll see why as you read on.

For instance if you require a 1.5 ms pulse, 1.5ms = 1500us = 7500 counts @ 200ns/count. So within the timer 2 interrupt, set timer 3 to be 65,536 (overflow - which will trigger a timer 3 interrupt) MINUS 7500. This can simply be:

Code:
set_timer3(65536 - 7500);


Similarly, a 1.0 ms pulse would be 5000 counts and a 2.0 ms pulse would be 10,000 counts.

Before you exit the timer 2 interrupt service routine, you enable the timer 3 interrupt. You'll probably also need to manually clear any outstanding timer 3 interrupts (its flag may be set) before enabling timer 3's interrupt.

Now timer 3 will "fire" at the proper time - anywhere from 1 - 2 ms later, depending on what you loaded timer 3 with.

When timer 3's interrupt occurs, set your output line low - this is the end of your servo's pulse. Disable the timer 3 interrupt, and you're done. The cycle will repeat in about 20 ms when timer 2 interrupts again.

Hope this is clear.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Fri Aug 25, 2006 2:33 pm     Reply with quote

That sounds like a great idea. I'm actually controlling 2 servos. so I can start both pulses at the same time, use your example for the shorter pulse and subtract that number from the longer pulse. Then when the first t3 fires I lower that pin, and reset T3 for the longer pulse. Then when that fires I disable T3 and start over. does that make sense? I just need a variable so I know which servo I'm accessing at a time. I guess this is extensible to any number of servos.
Thanks
Ringo
_________________
Ringo Davis
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Fri Aug 25, 2006 2:42 pm     Reply with quote

Ringo42 wrote:
That sounds like a great idea. I'm actually controlling 2 servos. so I can start both pulses at the same time, use your example for the shorter pulse and subtract that number from the longer pulse. Then when the first t3 fires I lower that pin, and reset T3 for the longer pulse. Then when that fires I disable T3 and start over. does that make sense? I just need a variable so I know which servo I'm accessing at a time. I guess this is extensible to any number of servos.
Thanks
Ringo


This should work. You may have a little problem if both pulses are about the same duration, but only real world testing will reveal this. The problem in my mind is when the difference in pulse widths is smaller than the PIC's interrupt latency. But @ 20MHz, we're talking about small times, much smaller than the 1 - 2ms servo pulse width. Shouldn't really add up to anything a person would be able to notice.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Fri Aug 25, 2006 2:45 pm     Reply with quote

ok I think I see an error in my logic.
T3 fires and I set my first servo low,
now if I reset T3 for the 2nd servo it is not going to be exact because clock cycle are ticking by while I'm doing stuff, so couldn't the 2nd one be off a little? Or what if both servo positions are very close? It seems like T3 could fire before I finish serving T3 so I could miss it, correct?
Actually I guess to get it exact I could do something like Set_timer3(65536-Servotime+get_timer3()); would this work? that way when I set it I'm using however much time has passed. I guess a simple test could see if they are too close to each other.
Thanks
Ringo
_________________
Ringo Davis
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sat Aug 26, 2006 11:02 am     Reply with quote

I think the best solution would be to use another timer, if you have one available. Timer 0 in 16 bit mode would work, as would timer 1.

For the instances where the on time of each servo pulse is about equal, you could implement a little trick talked about on this board a few times (sorry, can't remember whose idea it was).

The gist of it is that in the timer 3 ISR, you also check to see if timer 0's interrupt flag is set (or 1 - whatever other timer you end up using). If it is, you can then immediately set the other servo pulse low and disable timer 0's ISR. Same thing happens in timer 0's ISR: check if timer 3's interrupt flag is set and set its servo pulse low and disable timer 3's interrupt.

This approach saves some clock cycles.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sat Aug 26, 2006 11:51 am     Reply with quote

I'm using the PWM pins, does this interfere with any of the timers?
_________________
Ringo Davis
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sat Aug 26, 2006 12:03 pm     Reply with quote

As long as you're NOT using them for PWM, no, that won't affect the timers at all.
Ringo42



Joined: 07 May 2004
Posts: 263

View user's profile Send private message

PostPosted: Sat Aug 26, 2006 12:09 pm     Reply with quote

guess I said it wrong, I am using them for pwm, is that timer 1 that it uses for that? Does that mean 0 is available? or do I have it backward?
_________________
Ringo Davis
newguy



Joined: 24 Jun 2004
Posts: 1907

View user's profile Send private message

PostPosted: Sat Aug 26, 2006 12:58 pm     Reply with quote

I'm pretty sure that timer 2 is the one used for pwm. Check the datasheet to be sure.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
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