View previous topic :: View next topic |
Author |
Message |
Ringo42
Joined: 07 May 2004 Posts: 263
|
setttingup timer 3 |
Posted: Fri Aug 25, 2006 2:08 pm |
|
|
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: 1908
|
|
Posted: Fri Aug 25, 2006 2:25 pm |
|
|
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
|
|
Posted: Fri Aug 25, 2006 2:33 pm |
|
|
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: 1908
|
|
Posted: Fri Aug 25, 2006 2:42 pm |
|
|
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
|
|
Posted: Fri Aug 25, 2006 2:45 pm |
|
|
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: 1908
|
|
Posted: Sat Aug 26, 2006 11:02 am |
|
|
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
|
|
Posted: Sat Aug 26, 2006 11:51 am |
|
|
I'm using the PWM pins, does this interfere with any of the timers? _________________ Ringo Davis |
|
|
newguy
Joined: 24 Jun 2004 Posts: 1908
|
|
Posted: Sat Aug 26, 2006 12:03 pm |
|
|
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
|
|
Posted: Sat Aug 26, 2006 12:09 pm |
|
|
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: 1908
|
|
Posted: Sat Aug 26, 2006 12:58 pm |
|
|
I'm pretty sure that timer 2 is the one used for pwm. Check the datasheet to be sure. |
|
|
|