September 20, 2005, 5:02 pm
Hi folks,
I've been doing lots of tests with controlling R/C servos lately, some good
experiences and some bad experiences. I even wrote an introduction paper on
how to interface the PC with R/C servos using the serial port and a PIC
microcontroller.
The strategy I present in that paper is very basic, and although it works
fine, it is kind of jittery and does not support too many servos. Now I'm
working on a improved version of my servo controller that will theoretically
get rid of the flicker and support unlimited servos (in theory).
I am a firm believer that the best way to learn something is to teach it.
Therefore I will try to make another paper exposing this new method (of
course, if it works). Before doing that, I need to know if someone else
already did such tutorial paper, and if yes, if it is similar to my
strategy.
Here's an outline of my strategy, please express yourself if you find a flaw
in it as I'm going to test it tonight.
1-Assume there is an array of servos controlled by the uP
and this array has the following fields:
servo_idx, pulse_width_uS, servo_no
Whenever the array is updated (through serial commands), it is
sorted in by pulse_width_uS
2-Drive all servo lines high, set TMR0 with the time interval
of the first servo of the array
3-When TMR0 triggers, set the respective servo low.
Also set low all the subsequent servos from that list that
have the same pulse_width_uS. Set new TMR0 interval
as the difference between next servo pulse width and current
one.
4-Repeat this operation for all servos until there are no
more servos to drive low. At that point, set TMR0 with
20ms - current pulse_width_uS
And that goes forever. There are a couple more quirks to it, but that's the
overall outline. If you are controlling 4 servos, TMR0 should trigger 5
times in the worst case, 1 time for driving all servo lines up and 4 times
(less if some of them share the same time interval) to drive them low.
That gives me lots of time in between pulses to do whatever I want (receive
USART bytes for example) without interfering too much with the PWM timing
mechanism.
Do you think it is a good approach to try? If yes, do you think it would be
worthy to write a short paper on that?
Cheers
Padu
I've been doing lots of tests with controlling R/C servos lately, some good
experiences and some bad experiences. I even wrote an introduction paper on
how to interface the PC with R/C servos using the serial port and a PIC
microcontroller.
The strategy I present in that paper is very basic, and although it works
fine, it is kind of jittery and does not support too many servos. Now I'm
working on a improved version of my servo controller that will theoretically
get rid of the flicker and support unlimited servos (in theory).
I am a firm believer that the best way to learn something is to teach it.
Therefore I will try to make another paper exposing this new method (of
course, if it works). Before doing that, I need to know if someone else
already did such tutorial paper, and if yes, if it is similar to my
strategy.
Here's an outline of my strategy, please express yourself if you find a flaw
in it as I'm going to test it tonight.
1-Assume there is an array of servos controlled by the uP
and this array has the following fields:
servo_idx, pulse_width_uS, servo_no
Whenever the array is updated (through serial commands), it is
sorted in by pulse_width_uS
2-Drive all servo lines high, set TMR0 with the time interval
of the first servo of the array
3-When TMR0 triggers, set the respective servo low.
Also set low all the subsequent servos from that list that
have the same pulse_width_uS. Set new TMR0 interval
as the difference between next servo pulse width and current
one.
4-Repeat this operation for all servos until there are no
more servos to drive low. At that point, set TMR0 with
20ms - current pulse_width_uS
And that goes forever. There are a couple more quirks to it, but that's the
overall outline. If you are controlling 4 servos, TMR0 should trigger 5
times in the worst case, 1 time for driving all servo lines up and 4 times
(less if some of them share the same time interval) to drive them low.
That gives me lots of time in between pulses to do whatever I want (receive
USART bytes for example) without interfering too much with the PWM timing
mechanism.
Do you think it is a good approach to try? If yes, do you think it would be
worthy to write a short paper on that?
Cheers
Padu
Re: Multiple R/C servo control
---snip---
Padu... if I spoke Greek I might be able to give you an intelligent answer
to your question. Now let me ask you a question: How many people out here in
the real world could understand a word you said?
First of all, what kind of servo and what kind of interface are you using?
If I buy a sail winch servo from Hitec, how do I connect it to what without
going through the radio? How do I power it if not through the existing radio
from the vendor?
Should you not set up the experimental parameters first for those of us with
interest in this subject to duplicate your work in a scientific manner?
I've met you and recognize you as a brilliant automation engineer and only
make this note from my own ignorance on behalf of others who may not be
willing to share their own lack of experience but who would like to know
more and who could appreciate your insight.
Wayne
Re: Multiple R/C servo control
It's always good to learn a new language right? ;-)
I'm sorry if my post carried too many assumptions, I should have disclaimed
that a certain knowledge on the subject was necessary beforehand. I am
usually more explicit, but my post was long enough so I decided to summarize
my request. I'm sure that some of the habitue PIC gurus will make some sense
on what I said.
Just to prove that I usually try to be more methodic, please read the paper
I mentioned in my email:
http://www.merlotti.com/EngHome/Computing/servo_controller.pdf
If I fail to convey my point in the above paper, then blame it on me,
because its intention is to bean introductory text on how to interface R/C
servos with a PIC microcontroller.
R/C servos, the ones you buy in R/C hobby stores (hitec or futaba are good
examples)
From my knowledge, it is usual for these types of servos to use a PWM signal
of 20ms pulsetrain with a pulse width varying from 1 to 2 ms.
It will probably have 3 wires: VCC, GND and Signal. I don't know about sail
servos, but usually R/C servos are powered out of 5VDC (current varies from
manufacturer to manufacter). Signal line is the one you have to generate the
PWM signal.
As mentioned above, any 5VDC will do. (but take a look at the specs first in
order to determine current requirements)
I intend to do that if I write the paper. My previous post was only a feeler
if someone else hasn't already written similar material... I don't like to
write redundant stuff without adding something substantial to it.
Not a problem. I love to share my knowledge of things I know as well as
things I don't know. 8^)
Cheers
Padu
Re: Multiple R/C servo control
Thank you Padu.. You have illuminated a few chunks of darkness in my brain.
My son Lyle, originator of the RCWindjammer (www.rcsailcars.com) has a few
servos left over from some production runs. I'll have to take one apart and
play with it. I do have a Basic Stamp X-24, so... I should be in the shop
playing instead of here writing!
Wayne
Re: Multiple R/C servo control
board 9 or 10 bit accuracy?
Re: Multiple R/C servo control
I'm not exactly sure what you are asking for but just in case this is of
use:
The XCSB servo library uses 8 bit resolution and it controls multiple RC
servos. You can buy the source and change this to 9 or 10 bit resolution
yourself very easilly.
There is a simple circuit at http://www.xcprod.com/titan/XCSB/CONTRIB
labelled "PIC Servo Controller" that shows how to control 4 servos with
this library using a VERY low cost PIC.
The software for this circuit is compiled using the LITE edition of the
compiler and the servo library that comes with it (not source).
Regards
Sergio Masci
http://www.xcprod.com/titan/XCSB - optimising PIC compiler
FREE for personal non-commercial use
.
Re: Multiple R/C servo control
Another shameless plug: Look at my servo controller (which is an open
design) http://www.modularcircuits.com/servo_32.htm . Right now it's 8-bit,
but it has the HW capability do go to ~12 bits of precision for 16 of its 32
channels. I have plans to change the FW to support it but for now, you are
welcome to make the change yourself. It's not that complicated actually.
Regards,
Andras Tantos
Re: Multiple R/C servo control
The below servo chip has up to 1us resolution if desired. I did
some testing with a standard servo and with ~190 deg of rotation,
I could only get ~425 descrete steps in the 190 deg rotation. It
appears that a regular cheap servo will get little improvement
from higher than 8 bit resolution at ~255 steps.
http://www.kronosrobotics.com/xcart/customer/product.php?productid 273&cat)2&page=1
Re: Multiple R/C servo control
If you want a really simple and cheap start with controlling
servos via the pc, check my page below. I use the servos for a
pan/tilt cam, but you could use them for robotic stuff too. I've
given up on trying to program my own servo conrol chips, as
Kronos robotics sells them for $7 which fits my budget. You can
check the bottom link to see how simple it is to control the
servos over the net.
http://www.geocities.com/zoomkat/ezservo.htm
http://www.geocities.com/zoomkat/ezservo1.htm
Re: Multiple R/C servo control
I could. All of it.
Anyway, Padu, the problems I see are:
1) You have to make TMR0 tick fast enough to give you the resolution
you need. My digital Futaba RC gear gives 1024 steps over the 1-2ms
range of pulse widths. To match that you'd need a 1MHz tick on TMR0.
2) you have to make sure everything you do takes <1 tick of TMR0
(imagine you want one servo off at 1.501ms and one at 1.502ms). On a
20MHz PIC that's 5 instructions, ignoring whatever overhead firing the
interrupt adds.
Me? I use an AVR with hardware PWM :)
Tim
--
You are being watched. This gives you power.
Re: Multiple R/C servo control
Yes, the AVR ATmega128 has two 16bit timers, each capable of controlling
three pins. Set few bits, then update the 6 registers for the 6 servos, no
interrupt code required. AVRs rule, and the Linux environment works great
with them.
--
Mike Ross
Instructions said Win98 or better, so I used Linux.
Re: Multiple R/C servo control
Padu:
Controlling servos from a PIC has been done before. My PIC based
servo controller can be found at the URL below:
<http://gramlich.net/projects/robobricks/servo4/rev_j/index.html>
There is a subtle issue with servos -- they are very sensitive
to the pulse width. Changing the pulse width by a uSec or two
will cause the servo to move a small but noticable amount.
The scheme you propose will have a difficult time producing pulse
widths that are close to one another. Changing the pulse width
of one servo might cause the pulse widths of the other servos
to change a little.
The simpler strategy is to forget all the sorting and just
pulse one servo at a time in sequence. Turn on servo 1,
set TMR1, turn off servo 1, and repeat for each servo in sequence.
Given a maximum pulse width of 2.5uSec, you can visit 8 servos
every 20uSec.
Lastly, remember that PIC's are really really cheap. If you
find yourself doing all sorts of tricks to get them to do what
you want, consider using more PIC's. For example, suppose that
you are using a digital servo and need a really fast update rate.
Dedicating a PIC to each digital servo is not unthinkable.
Once you get your PIC code working, by all means write it up.
My $.02,
-Wayne
Re: Multiple R/C servo control
That's a very nice write up! I also found some literature about a guy named
Scott Edwards who has a similar board. I don't know if he's around here
though.
I noticed that in my previous experiments...
Yes, I realize that, but the way I'm planning to do is to do very little
computing in the first 2 miliseconds of the pulse train. The sorting
procedure (heck, I'm a software engineer, I SHOULD know how to write a very
efficient sort procedure) will be done in the remaining 18ms, while the PIC
is sitting there doing nothing.
I'm not sure I understood completely this last part. What you are saying is
to generate each one of the pulses back to back? If yes, then how do you
guarantee the 20ms interval between pulse rises? Are you taking advantage on
the fact that pulse train in most rc servos is very forgiving? (I've heard
people saying that even 5ms pulse trains worked fine)
I'm aware of that, and that's probably what I'm going end up doing, driving
two servos per uC, but I always like to think in more abstract terms.
Actually, if I write up this, I think I will completely abstract which
processor I am using. (but maybe I'll post the source code as an appendix)
I'll let you know tomorrow what are my findings, I'll pay special attention
to your (and mine) concerns about two servos with very close positions.
Thanks for your comments
Padu
Re: Multiple R/C servo control
A number of us have done PIC based servo controllers over the
years. The first one I saw was the one by Dennis Clark.
[snip pulse width sensitivity]
The sort time is a non-issue.
The issue is that there is a delay from the time that you get
an interrupt until you stuff the next difference number into
the TMR1 register. You have to take that into account. Also,
you have to get out of the interrupt routine before TMR1 wants
to generate another interrupt. There is a great deal of tricky
programming to be done. It is best to avoid all of that tricky
stuff.
It is simpler than that. Set TMR0 to interrupt every 2.5ms.
It picks the next servo delay from the array and stuffs it into
TMR1 and returns from interrupt. When TMR1 fires, clear the
servo line. The pulses look as follows:
0 ---XXX-----------------------------XXX-------------------------XXX--
1 ----------XX-----------------------------XX-------------------------
2 -----------------XXXX--------------------------XXXX-----------------
3 -------------------------XXX---------------------------XXX----------
It should be a piece of cake to keep 8 servos running with 20ms
between servo pulses.
I always wind up doing 4 servos, since I put resistors in series
with the servo ground return to measure stall current. I simply
run out of pins on the smaller PIC's.
[snip PIC's are cheap]
[snip write-up]
-Wayne
Re: Multiple R/C servo control
The strategy you explained in here plus Sergion Masci's argument have
convinced me of that. Perhaps my strategy would work in most of the cases,
where values were far apart (or exactly coincident). As you said, the
advantage of being able to control an undefined number of servos is quickly
lost in an environment with as many restrictions (physical time to compute,
number of pins, etc).
And now I know how hard it is to debug this type of application.
0 ---XXX-----------------------------XXX-------------------------XXX--
1 ----------XX-----------------------------XX-------------------------
2 -----------------XXXX--------------------------XXXX-----------------
3 -------------------------XXX---------------------------XXX----------
Very simple idea and I don't see why it wouldn't work. If you don't mind
I'll borrow your idea and implement it on my robot... Now looking at my
flowchart (yes, I can only program if I flowchart it first), it looks like a
nice piece of logic, but I spend a good amount of time to implement it and
find out that it wouldn't work as I expected.
Thanks for your help!
Cheers
Padu
Re: Multiple R/C servo control
"Wayne C. Gramlich" wrote
I've implemented it on my devboard yesterday, with USART interrupts and all,
and works perfectly! No jitter even when sending a constant flow of serial
data at 9600baud. Thank you very much.
The only thing I noticed was that when I set TMR1 to 1500uS for example, I
would see 1480uS on the oscope. It didn't turn out to be a huge problem, as
the error was constant. I did a quick test, doing a program with the only
purpose of generating a square wave of fixed width, and even there I had a
very small error (about 100uS) between expected (calculated) interval and
measured interval.
I'm using a PIC18F452 with an external crystal can at 4MHz. TMR1 is set to
16 bit and no prescaler. The way I'm calculating the interval is pretty
simple, at 4MHz each instruction cycle takes 1uS (4/FOSC), therefore a full
cycle of TMR1 (0xFFFF) would take 65536uS right? If I want to calculate a
TMR1 interval of 1500uS, then it is 65536-1500-2 right? (the 2 is because
updating TMR1 takes two instruction cycles), that would give me 64034 or
$FA22. Is that correct?
I believe I can compensate for the error and no harm done, but I thought it
was weird. The only thing done in TMR1 interrupt is driving servo lines low,
nothing else.
Cheers and thanks for all contributions!
Padu
Re: Multiple R/C servo control
[snippage]
You are welcome.
I think you are witnessing classic interrupt latency. I suspect
that you have 20uSec between the time the interrupt occurs until
you actually clear the servo pulse. You can verify this by inspecting
your interrupt service routine and counting instruction times.
Remember, there is "psuedo" CALL instruction required to initiate
the interrupt. I'm more familiar with the 16F series, but I think
the 18F series CALL takes 3 cycles (I could be wrong.)
Also, if you crank of the beam intensity on your oscilliscope,
I suspect that you discover that there is 1-2 uSec of jitter
on the pulse. If an interrupt occurs in the middle of a multi-cycle
instruction, the interrupt is delayed until the instruction is
done. The vast majority of instructions on PIC's are one cycle,
but some instructions such as CALL, RETURN, GOTO, etc. take more
than one cycle. If the interrupt occurs during one of those
instructions, there will be an extra cycle (or two) before the
servo pulse is cleared. Given that your servos are not experiencing
jitter, I would not recommend worrying about the issue.
-Wayne
Re: Multiple R/C servo control
For this to work your processor would need to be VERY fast.
Say you divided the full travel of your servo into 256 steps so that a
value placed in a byte wide veriable mirrors the position of the servo.
The full travel is covered by a 1ms pulse (1ms being one end and 2ms being
the other end).
So you would divied your 1ms pulse into 1/256 ms units.
If you had servo A set to position 10 and servo B set to position 11, the
amount of time you have available to complete servicing the interrupt that
handles servo A and start processing the interrupt to service servo B is
1/256 ms.
this is about 3.9 microseconds. On a fast PIC executing instructions at
about 5 MIPS this is about 20 instructions between servicing servo A and
servo B. ***ANY*** delay (such as servicing another interrupt - maybe a
heartbeat system clock or serial I/O) would give jitter.
You might be able to get away with building groups of servos
that have a minimum position difference that is greater than
5. Then you could interleave servicing of the groups say every 10ms.
but this would only allow you two groups. if you did this for every 5ms
you could interleave 4 groups but this would limit minimum position
difference to 4.
Even with this interleaving I still think you would have problems with
other interrupts causing jitter.
Regards
Sergio Masci
http://www.xcprod.com/titan/XCSB - optimising PIC compiler
FREE for personal non-commercial use
.
Site Timeline
- » Electronic motor speed control.
- — Next thread in » General Robotics Forum
-

- » Robot's control board - how to?
- — Previous thread in » General Robotics Forum
-

- » evoMUSART 2013: First CFP (with correct dates)
- — Newest thread in » General Robotics Forum
-

- » Bending 1/8 inch thick 7075-T6 aluminum
- — The site's Newest Thread. Posted in » General Metalworking
-

- » Rysunek techniczny-pytania
- — The site's Last Updated Thread. Posted in » Engineering Science (Polish)
-


Subject







