![]() |
![]() |
![]() |
|
|
|||||||
| Micro Controllers Discuss all aspects of micro controllers - building them, coding them, etc. All controllers are welcome - PIC, BASIC, Z8 Encore!, etc. |
|
|
Thread Tools | Display Modes |
|
|
(permalink) |
|
Experienced Member
|
Hi,
I'm kinda new to microcontrollers and I've got some code going that controls 1 hobby servo via a delay loop that controls the pulse width. What I want to do is drive serveral servos now from the same pic. I was thinking I could just use concurrently running threads and run each servo from a thread. Is it possible to do threads on a pic? If so, can anyone point me to an example? If threads are not possible, what is the standard way of running multiple servos on the same board? My chip, the pic18f4550 has 16 digital outputs so in theory I can run up to 16 servos from this board. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
What language are you using?
How much resolution do you have or do you need per step between the 1.0-msec and 2.0-msec pulse range? What's the oscillator frequency to the core on your '4550? Mike |
|
|
|
|
|
(permalink) |
|
Super Moderator
|
The simple answer is timer interrupts, but as Mike asks it depends on what resolution you're wanting, and the clock speed you're using.
Another question is what else is it doing?, depending on that you may simply be able to run the 16 servos using delay loops, in sequential order. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Mike,
Im using C and the the C18 compiler from Microchip. I do not know what resolution between steps I really need. I would like the servos to operate the same as they would on a standard r/c transmitter/receiver. As of now, I am driving one servo. I pass in a value in the range of 120-240 to give me the desired pulse width. Im using the following: Delay100TCYx(120) = 1ms, Delay100TCYx(240) = 2ms (found in delays.h). 120 steps seem fine and I would be happy if I could still get this but more steps would be nice! Nigel, The pic is going to be doing nothing else but driving the servos, a dedicated servo controller. My original idea was to drive the servos sequentially like you mentioned but wont this cause a problems if all 16 servos take 2ms pulses? Right now I have the 1-2ms pulses being sent every 20ms. This works fine for one servo but 16 *could* cause a 36ms period. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Nigel's idea of consecutive/sequential time delay functions is incredibly clever and intuitive. Simply execute 16 consecutive 1-msec time delays, one for each of your PWM outputs, then delay for an additional 4-msecs before starting over. Way to go Nigel. Staggering the 1 to 2-msec processing for each output is simple, elegant, and insightful.
PWM output 01 -- 1-msec total time Turn output 01 on for #01's "on-delay" time Turn output 01 off and delay for (1-msec minus #01's "on-time") PWM output 02 -- 1-msec total time Turn output 02 on for #02's "on-delay" time Turn output 02 off and delay for (1-msec minus #02's "on-time") ~~~~~~~~~~~~ PWM output 16 -- 1-msec total time Turn output 16 on for #16's "on-delay" time Turn output 16 off and delay for (1-msec minus #16's "on-time") PWM output last -- 4-msec total time Simply delay for 4-msecs and start over Regards, Mike Last edited by Mike, K8LH; 17th July 2006 at 03:13 PM. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Oops. I goofed on that flow chart. I forgot about the minimum 1-msec on-time. Back to the drawing board for a new flow chart (grin).
Mike <later> How about this? Is this doable guys? Period 01 (1-msec total) Turn on Output 01 (on for entire 1-msec) Delay 1-msec Period 02 (1-msec total) Turn on Output 02 (on for entire 1-msec) Delay (Output 01 "on-time" minus 1-msec), turn off output 01 Delay (2-msecs minus Output 01 "on-time") Period 03 (1-msec total) Turn on Output 03 (on for entire 1-msec) Delay (Output 02 "on-time" minus 1-msec), turn off output 02 Delay (2-msecs minus Output 02 "on-time") ~~~~~~~~~~ Period 16 (1-msec total) Turn on Output 16 (on for entire 1-msec) Delay (Output 15 "on-time" minus 1-msec), turn off output 15 Delay (2-msecs minus Output 15 "on-time") Period 17 (1-msec total) Delay (Output 16 "on-time" minus 1-msec), turn off output 16 Delay (2-msecs minus Output 16 "on-time") Period 18-20 (3-msecs total) Delay 3-msecs and start over Last edited by Mike, K8LH; 17th July 2006 at 03:32 PM. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Mike,
That would work, but a hobby servos can pulse up to 2ms, making a total period of 36ms (if all servos were to pulse at 2ms). Id like to keep the 20ms period if at all possible. It seemed like the servos had more holding power at a 20ms period versus a 50ms period for example. If I wanted to use this method and retain the 20ms period it seems like I could only control a max of 10 servos with this method. Ah, you beat me to it.... |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Hopefully you've gone back and seen my addition. 16 Staggered and overlapping outputs that use 17-msecs of the overall repeating 20-msec period.
I'm not familiar with C but I suspect that code would work very well in a while procedure, wouldn't it? Period 01 and period 17 would be handled differently with a final 3-msec delay before repeating. Mike Last edited by Mike, K8LH; 17th July 2006 at 03:42 PM. |
|
|
|
|
|
(permalink) | ||
|
Super Moderator
|
Quote:
Quote:
|
||
|
|
|
|
|
(permalink) |
|
Experienced Member
|
I remember looking at some *old* RC receiver schematics, and they tended to use a 4017 chip pretty much exactly as you are describing now. (It's probably also the reason why the timing pulses and RC update frequencies are setup as they are). The big plus is that if you use a 4017 (or some other shift register chip), you only tie up 2 IO's.
Staggering two sets so that the active edges don't overlap makes sense, and you should be able to drive 16 (20?) servos at 50Hz using only 3 IO's (reset/data line, 2 clock lines) and 2 extra shift-reg chips. Dumping this into an hardware timer interrupt would seem really worthwhile. Last edited by hjames; 17th July 2006 at 04:00 PM. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Mike,
Excellent! That makes sense now. I will implement it tonight. Nigel, I did not test the holding power with exact measuring equipment but I could notice a very big jump in holding power when I lowered my period from 50ms to 20ms. I could not move the servo by hand when it was set to 20ms but it was very easy to stop operation when at 50ms. I would not have thought that 30ms extra would have made a difference but it did, thats the reason im worried about not meeting the 20ms period. Ill give it a shot thought and let you know my findings. |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Just an idea. Could you use a 1ms timer ISR and 16 counter bytes (one per pin), if byte is not 0, flip coresponding pin high, decrement the counter each time (if not 0). When zero flip the pin low and ignore it? Then feed the 16 bytes from you program, 20 is 20ms high then back to 0. Main program could track the delay times?
Or would this cause a power issue and why the delay routine is better? Or you maybe need some blocking to let them get were they are going to? |
|
|
|
|
|
(permalink) |
|
Experienced Member
|
Mike,
Sorry, forgot to mention this. The frame rate might not be exactly between 1-2ms. It could slightly more or less. Any ideas? |
|
|
|
|
|
(permalink) | |
|
Experienced Member
|
Quote:
Please tell me why, I'm very curious. Mike |
|
|
|
|
|
|
(permalink) |
|
Experienced Member
|
This is only what I've heard from others in the forum but most servos operate outside of the advertised range to some degree. The pulse width may also vary slightly from brand to brand.
1-2ms will work, but I would like the user to be able to adjust this in the pc side app that will run the servos. Most of the applications/controllers I've seen allow the user to give the servo a pulse outside of the normal range. Makes the code a litte more complicated. |
|
|
|