Download Servo - Servos

Survey
yes no Was this document useful for you?
   Thank you for your participation!

* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project

Document related concepts

Flip-flop (electronics) wikipedia , lookup

Resilient control systems wikipedia , lookup

Switched-mode power supply wikipedia , lookup

Control theory wikipedia , lookup

Stepper motor wikipedia , lookup

Chirp compression wikipedia , lookup

Variable-frequency drive wikipedia , lookup

Control system wikipedia , lookup

Time-to-digital converter wikipedia , lookup

Immunity-aware programming wikipedia , lookup

Oscilloscope history wikipedia , lookup

Metadyne wikipedia , lookup

Rectiverter wikipedia , lookup

Pulse-width modulation wikipedia , lookup

Radar signal characteristics wikipedia , lookup

Opto-isolator wikipedia , lookup

Transcript
R/C SERVO TESTER
This pocket sized servo signal emulator makes it a breeze to test and setup
your servos. It features digital accuracy and is easy to build and use.
Introduction
I recently found myself having to test a large number of R/C servo controlled devices. My normal routine is to grab my
spare receiver, plug in the servo and battery, then fire up the transmitter. As simple as this sounds, it is inconvenient for
me, especially when the "spare" Rx is installed in a plane. When the transmitter nearly fell off the workbench one day, I
decided enough was enough.
I thought about buying a R/C servo signal emulator, but I am a do-it-yourself sort of guy. The various projects I saw on the
internet did not turn me on. What I found were circuits that were usually based on LM555 timers. They all seemed to use
too many components for too few features.
My goal was to use a cheap PIC microcontroller and do everything I could to minimize the component count. The PIC
would ensure precise R/C signal generation and I figured that features could be easily added in firmware rather than by
more components. In the end I met all my expectations. And although I used junk box parts, the cost to duplicate my work
is well under $10.
The R/C Servo Tester (RCST) is easy to use. Just plug in a 4-cell battery and your servo. The variable pot allows you to
set any servo position you wish, within the 1.0mS to 2.0mS range of a modern R/C system. With the press of a button,
you can find the precise center to your servo. Flick a switch and the servo will cycle (run back and forth ) at your chosen
speed.
Servo Control Basics
The servo signal is a simple digital pulse. It spends most of its time at a
logic low (0 V). About every 20mS it goes logic high (3 to 6 VDC) and
then quickly goes low again. It is this tiny window of logic high time,
called the pulse width, that gets the attention of the servo.
Please refer to the drawing. The period labeled "A" is called the frame
rate. In the example it is repeated every 20mS (50 times per second), which is quite typical for most radio systems.
Modern servos define center as a 1.5mS pulse width, as shown by detail "B" in the drawing. Full servo rotation to one side
would require that this pulse width be reduced to 1.0mS. Full rotation to the other side would require the pulse width to
increase to 2.0mS. Any pulse width value between 1.0mS and 2.0mS creates a proportional servo wheel position within
the two extremes. The frame rate does not need to change and is usually kept constant.
The servo will not move to its final destination with just one pulse. The servo amp designers had brilliantly considered that
multiple pulses should be used to complete the journey. This little trick reduces servo motor current draw and it helps
minimize erratic behavior when an occasional corrupt signal is received. To move the servo, you must repeat the pulse
every few milliseconds, at the chosen frame rate. Modern R/C systems use a 40Hz - 60Hz frame rate, but the exact timing
is not critical. If your frame rate is too slow, your servo's movement will become rough. If the rate is too fast the servo may
become very confused.
Circuit Construction:
My board was point-to-point wired using 30 gauge insulated Kynar wire. This wire is normally used for wirewrapping,
but works fine with a soldering iron. I just strip a bit of insulation off and solder it to the parts. I recommend a 40 watt or
less soldering iron (700° tip)
Layout is not critical except that cap C3 should be close to the PIC (mine is
soldered directly across pins 1 and 8). Cap C1 should have 2% tolerance for
best accuracy. Use a socket for the PIC chip. If your servo voltage will be
higher than 5V, such as a five cell R/C pack, then you will need to add an LDO
voltage regulator (e.g. LM2931-5 Vreg).
The connections to the battery pack and servo are handled by female servo
cables or simple 3-pin headers. I built it both ways and prefer the header
version. You can see my stacked 3-pin headers on the upper right of the photo.
Check your work carefully. Do NOT install the PIC chip until you have verified
that pin 8 is ground and the pin 1 has 4.75 to 5.25 VDC on it. Remove power
BEFORE you install the chip. Double check the servo cable for correct polarity
before you plug a servo in. Simple mistakes can destroy electronic parts,
servos, and may generally ruin your day.
Your exact PIC choices have some flexibility. You can use a PIC12C508, PIC12C508A, PIC12C509, and PIC12C509A.
The PIC12C50x is not a "Flash" part, so you will need a traditional PIC chip programmer to "burn" the hex file's object
code into the microcontroller.
Be sure to verify that your chip burning system has selected the proper configuration fuses, as shown below. For
example, if your programmer uses the PICALL software, then press F3 to review the Config fuses.
WDT:
Watchdog Disabled
MCLR:
MCLR Disabled
Oscillator:
IntRC
Memory:
Code Protected
The PIC's Hex file is designed to automatically instruct the programming hardware to chose these values. However, it is
always a good idea to check them for accuracy. By the way, after you program the PIC your programmer will report a
failure if you attempt to verify the PIC again. Do not be alarmed -- everything is OK. Just ignore the "failure." Whatever
you do, do NOT program the chip twice!
If you have trouble burning the PIC, then please check your programmer. Whatever the fault, it is not a RC-CAM hex file
issue. The most common problem is that the user has forgotten to burn the PIC's four configuration fuses, as mentioned
above. More programming information can be found starting here.
The entire firmware is written in "C." You do not need to know anything about the C language to build your system. All you
need is the object code (Hex file) to program the PIC, which is provided at no charge for personal use. A hobbyist can use
the firmware in a personal project at no charge. But, anyone that desires to use it in a product for distribution (or wishes to
offer pre-programmed parts) must first obtain written permission. Sorry, but I will not provide the text based source
code.
Instructions: Servo Signals for all Seasons
With S1 and S2 turned off, the variable pot is used to select the servo's position. The endpoints are software limited to
approximately 0.95mS on the low end and 2.1mS on the high end. The step resolution is 10uS, which allows for very
smooth movement.
To cycle the servo back and forth, enable switch S2. The cycle speed is determined by the pot's position. The seven
sweep times vary from about twice per second to once per twenty-five seconds. Step resolution will vary, depending on
the chosen speed. The servo steps are coarse on the faster speeds.
To find the servo's electronic center, just press and hold S1. The servo pulse will be forced to 1.5mS and the servo wheel
position should move to a nominal center location. You can also use this feature to help calibrate the knob's tick marks,
since it will indicate where they knob needs to be for a centered servo.
The pot position controls an "RC" timing circuit. In effect, R1, C1, and some clever PIC software, are used in place of an
A/D converter to measure the pot's position. Since the reference is not voltage regulated, it is affected by battery voltage.
The decoded pot position can vary about 5% over the voltage range of a typical 4-cell NiCD or NiMH pack. However, the
S1 (Center Switch) timing is not affected by the battery voltage and will remain accurate throughout all expected voltages.
Design Documents:
The technical details are available as file downloads. There is no charge for the information when used in a personal
(hobby) project. Commercial applications must obtain written approval before use.
Please be aware that the information is copyright protected, so you are not authorized to republish it, distribute it, or sell it,
in any form. If you wish to share it, please do so only by providing a link to the RC-CAM site. You are granted permission
to post links to the web site's main page (http://www.rc-cam.com/). Please respect this simple request.
Schematic Files: PDF file of the RCST circuitry. The components are from www.digikey.com.
Hardware Revision: Rev A, dated 02-19-2003
PIC Object Code: Hex file and license details for the compiled RCST firmware. You should occasionally check for
updates.
S/W Version: V1.0, dated 02-19-2003.
The Small Print:
If you need a part then please consult the sources shown in the project (see schematics download). I do not work for, nor
represent, ANY supplier of the parts used in this project. Any reference to a vendor is for your convenience and I do not
endorse or profit from any purchase that you make. You are free to use any parts source that you wish.
All information is provided as-is. I do not offer any warranty on its suitability. That means that if you build and use this
device, you will do so at your own risk. If you find software bugs then please report them to me. I can only make
corrections if I can replicate the bugs, so please give me enough details to allow me to witness the trouble.
Feed Back:
I would enjoy hearing from anyone that uses this useful R/C gadget. Please send me an email if you build it.
What’s a Servo?
A Servo is a small device that has an output shaft. This shaft can be positioned to specific angular positions by
sending the servo a coded signal. As long as the coded signal exists on the input line, the servo will maintain the
angular position of the shaft. As the coded signal changes, the angular position of the shaft changes. In practice,
servos are used in radio controlled airplanes to position control surfaces like the elevators and rudders. They are
also used in radio controlled cars, puppets, and of course, robots.
A Futaba S-148 Servo
Servos are extremely useful in robotics. The motors are
small, as you can see by the picture above, have built in
control circuitry, and are extremely powerful for thier size.
A standard servo such as the Futaba S-148 has 42 oz/inches
of torque, which is pretty strong for its size. It also draws
power proportional to the mechanical load. A lightly loaded
servo, therefore, doesn't consume much energy. The guts of
a servo motor are shown in the picture below. You can see
the control circuitry, the motor, a set of gears, and the case.
You can also see the 3 wires that connect to the outside
world. One is for power (+5volts), ground, and the white
wire is the control wire.
A servo disassembled.
So, how does a servo work? The servo motor has some
control circuits and a potentiometer (a variable resistor, aka
pot) that is connected to the output shaft. In the picture
above, the pot can be seen on the right side of the circuit
board. This pot allows the control circuitry to monitor the
current angle of the servo motor. If the shaft is at the correct
angle, then the motor shuts off. If the circuit finds that the
angle is not correct, it will turn the motor the correct
direction until the angle is correct. The output shaft of the
servo is capable of travelling somewhere around 180
degrees. Usually, its somewhere in the 210 degree range, but
it varies by manufacturer. A normal servo is used to control an angular motion of between 0 and 180 degrees. A
normal servo is mechanically not capable of turning any farther due to a mechanical stop built on to the main
output gear.
The amount of power applied to the motor is proportional to the distance it needs to travel. So, if the shaft needs
to turn a large distance, the motor will run at full speed. If it needs to turn only a small amount, the motor will
run at a slower speed. This is called proportional control.
How do you communicate the angle at which the servo should turn? The control wire is used to communicate
the angle. The angle is determined by the duration of a pulse that is applied to the control wire. This is called
Pulse Coded Modulation. The servo expects to see a pulse every 20 milliseconds (.02 seconds). The length of
the pulse will determine how far the motor turns. A 1.5 millisecond pulse, for example, will make the motor
turn to the 90 degree position (often called the neutral position). If the pulse is shorter than 1.5 ms, then the
motor will turn the shaft to closer to 0 degrees. If the pulse is longer than 1.5ms, the shaft turns closer to 180
degrees.
As you can see in the picture, the duration of
the pulse dictates the angle of the output shaft
(shown as the green circle with the arrow).
Note that the times here are illustrative, and the
actual timings depend on the motor
manufacturer. The principle, however, is the
same.
Controlling Servos - By Aaron Ramsey
Overview
Servos are a very handy resource for people involved in robotics. Servos are basically a small geared motor
with a controller. You send an electrical pulse to the servo to tell it where to turn to. Normally a servo can only
turn in a 120 to 180 degree range and is used for positioning, but a servo can be taken apart and modified so that
it turns the full 360 degrees, essentially creating a geared motor. This article is about how to position the servo
using pulses, not how to hack the servos.
What good it it?
Servos are normally used by hobbyists to position rudders, flaps, etc.. on hobby airplanes. What can we use
them for? Well, as I describe in my GP2D02 article, servos can be used to sweep sensors arrays back and forth.
They can also be used to create legs on a robot. There are many other uses. They come in all different sizes,
from less than an inch in length to several inches long. The larger ones are very strong and can be used to move
very large loads.
Alright, how do we use it?
A servo has three wires. A signal line, power line and ground line. Different manufacturers have a different
orders and colours for the wires, but they are fairly easy to identify which is which. Red and black wires are the
power wires, and the third is the signal line. I have servos with either orange or white signal lines. You can test
a servo by connecting +5V and GND to the appropriate wires, then just tapping the control wire on +5V
quickly. This simulates the control pulse, and the servo will move left or right.
The control pulse?
A servo is controlled by a series of
pulses with certain high and low times.
The high time controls the position of
the servo. A typical servo accepts a 1 ms
to 2 ms high pulse in order to position
itself over a 110 degree sweep. The low
time can vary from 10 ms to 20 ms, and
plays no role in the position of the servo.
The control signals are linear, so that a
pulse of 1.5ms will position the servo very close to centre. Some brands of servos will accept pulses lower than
1ms amd higher than 2ms. This lets you position the servo over a greater angle. I've had servos which can
sweep 180 degree with servo pulses ranging from 0.7ms to 2.4ms. Just how far you can sweep a servo is
determined by experimental means. Just be sure to gradually push the servo rather than feeding it extreme
values to see how far it can go. You can physically damage the servo gears by trying to move it too far in one
direction or the other. You'll know when you are going too far by the sounds that the servo makes. <grin>
Below is a sample servo pulse.
A typical servo that I use is a Cirrus CS-70 Standard Pro Servo. It is rated 0.15 sec/60 degrees at 4.8 volts and
0.12 sec/60 degrees at 6.0 volts. It is powered by 5 volts. In order to position it accurately, I actually need to
give it 6 pulses, each around 12 ms long. Usually 2 pulses are enough to get the servo in the general position
that I want it to be, and the 4 additonal pulses are just fine tuning. If accuracy is not important to your
application, you can cut back on the number of pulses that you send. If you are sweeping the servo over a great
distance, you need to send it more pulses.
Something to note is that the servo is only powered when you are actually sending it a pulse. When it is not
receiving pulses, the motor will not hold the servo arm in place. The gearing helps to hold it in place, but if you
are creating a walker which needs the servo to physically hold it off the floor, you need to continuously send
pulses to the servo. If you are just sweeping a sensor back and forth, you only need to send the pulses while you
are moving the servo.
So, how do I generate that pulse?
Below, I present some C code for the CCS compiler for the PIC processors. The code is fairly readable, even
though I use some functions specific to the CCS compiler. You should be able to easily move this code to
another compiler or language. Basically I loop 6 times. Inside the loop I output a high on pin B0 of the PIC,
delay for 1.5ms, output a low on pin B0, and delay for 10ms. It's really that easy!
Sample Servo Code
#define SERVO_CONTROL
pin_B0
// Move the servo to the centre
// send 6 pulses to make sure it gets there accurately
for (counter2=0;counter2<6;counter2++) {
output_high(SERVO_CONTROL); // high pulse
delay_us(1500);
// 1500us = 1.5ms
output_low(SERVO_CONTROL); // low pulse
delay_ms(10);
}
You don't need a microprocessor to control the servo. You can easily build a 555 timer circuit or other circuits
which will do the same thing as above. All you need is something that can output pulses.
Conclusion
Well, hopefully by now you understand how to use a servo. They are really easy to control, and very useful for
many things. Now, if only I could justify to my wife buying 12 of them to build a 6 legged walker. <grin>
Interfacing the GP2D02 to a PIC and sweeping it with a servo - By Aaron Ramsey
Overview
This article describes part of the sensor system that I used on a series of robots. The robots were built as part of
my degree project in my last semester of university. I was limited by the amount of money that I could spend on
each robot (as we likely all are!), and I had to find solutions to give the robots a reasonable view of the world
around them. For the main sensor, I used a Sharp GP2D02 IR distance sensor mounted on a servo which swept
it back and forth in front of the robot.
Several possibilities were considered for a primary distance measuring device for the front of the robots. Laser,
CCD camera, ultrasonic and infrared were all studied. Laser and CCD both proved to be to expensive and
difficult to implement. Ultrasonics have several good points, such as range of detection and reasonable easy to
implement. I found two problems which I were unable to overcome at the time. The transceivers which I was
able to afford had a very wide angle of detection, and it was difficult to pinpoint objects. Also, because sound
reflects very easily, there were a large amount of false readings. Both shortcomings can be overcome, but I
moved on to IR sensors. I decided to use a Sharp GP2D02 rather than design my own, as the Sharp offered
better resolution and more accurate readings than the sensors that I were able to build ourselves. They are also
very easy to use.
Sharp GP2D02
The Sharp GP2D02 is a sensitive compact distance measuring sensor. It required two lines from a
microcontroller in order to be controlled. One line provides the signal to begin a measurement and also is used
to provide a clock signal when transmitting the distance measure, and the other line is used to transmit the
measurements back to the microcontroller. I interfaced the GP2D02 to a 12CE519 microcontroller rather than
my main CPU (16C77) in order to free up processing time on the 16C77. The GP2D02 requires an open
collector on its input line, so I connected it through a diode to the 12CE519. The GP2D02 output is connected
directly to the 12CE519. As I was limited to one GP2D02 IR sensor per robot, I used a hobby servo motor to
sweep the GP2D02 through a 50 degree pattern in the front of the robot. The servo used was a Cirrus CS-70
Standard Pro Servo.
The GP2D02 is a self contained device which emits an IR pulse and determines the distance of a nearby object
using triangulation. It is able to measure distances up to 80 cm and at that range has a beam width of only 10
cm. I mounted this sensor on servo motor at the front of the robot. The servo sweeps the sensor through a 50
degree pattern. The servo is discussed in more detail later. The sensor is digitally controlled with its Vin line.
The Vin line is pulsed low to tell the sensor to begin a measurement. The sensor will output a high on the Vout
line when it is ready to transmit. The Vin line is then pulsed, and the sensor data is clocked in on the Vout line.
This is illustrated in the figure below.
Figure 1 - GP2D02 Timing
The C code to implement this is fairly easy. I used the CCS C compiler. The code is fairly readable though, and
could be easily converted to any language.
int get_ir_reading() {
int counter=9;
int reading=0;
output_low(GP2D02_VIN); // start cycle with Vin low
delay_ms(1);
// give the sensor a little time before we bug it
while (!input(GP2D02_VOUT)); //wait for Vout to go high
do {
delay_cycles(4);
// minimum wait is 2us, max is 170us, 4 worked
output_low(GP2D02_VIN); // tell the sensor that we want a bit
delay_cycles(2);
// might be as low as 1 (maybe), 2 worked
reading=reading<<1;
// left shift the reading value
reading=reading|(input(GP2D02_VOUT)); // put the newest reading into the
// LSB of reading
output_high(GP2D02_VIN); // we read the bit, and get ready for the next
one
counter--;
} while (counter>0);
// We leave the Vin pin high after finishing the reading
// This resets the sensor in order for a new reading next
// time
// An 8 bit number indicating the distance should now be
// sitting in the variable 'reading'
return(reading);
}
GP2D02 Measurements
The distance measurement is a 8 bit number. It is not linear, as can be seen in Figure 2 below. The distance
measurement can be linearized using the following formula proposed by Sean H. Breheny
(http://www.hobbyrobot.com/info/gp2d02/index.html).
Linearized data = 1.9/(tan((reading-25)/1000))
The constants in the formula above were established by Mr. Breheny through experimental means. Using my
measured data from 3 GP2D02 sensors, I was unable to improve the linearization calculations by manipulating
the constants, and the formula was implemented as is. I later discovered that reasonable linearization can be
achieved by simply inverting the reading received (1/reading) and then multiplying it by some constant. This
eliminates the tan term, which is not a pretty thing in a 8 bit microcontroller to implement. <grin> Actually, I
ended up not linearizing the data at all in the robot. I designed the robot around a behavioural model (ieinstincts rather than brains) and it was just as easy to use the real sensor readings. Linearizing the readings
would be very useful if you were trying to create a map from what the robot was seeing. I will be looking
deeper into this in a future design.
Figure 2 - Raw reading from GP2D02
Figure 3 - Linearized reading from GP2D02
As can be seen from the graphs above, the sensors have a lower limit. At around 7cm, the value read peaks and
then begins to fall again. In other words, an object closer then 7 cm will appear to be further away. If we do not
'see' the object before it enters this zone, this will become a large problem with this particular sensor. This is
another good reason for the robots to move slowly. This is also an excellent reason for having bumpers on a
robot.
Communicating with the Main CPU
The GP2D02 is not connected directly to the main CPU on the robot. It is controlled by a 12CE519, which also
controls the servo. This frees up the main CPU for other tasks and also provided a IR module which can easily
be transferred to projects later. This can be a very useful approach. The 8 pin pics such as the 12C509, etc. are
extremely cheap and are very powerful. By dividing the tasks up and moving them off the main cpu, you can
create a very power design and avoid having to use very expensive processors. Another advantage of this is that
the 'modules' that you create are easily transferred to the next design that you create.
When the 12CE519 has taken a reading from the GP2D02, it transmits the readings to the 16C77. The
GP2D02_TX line is hooked to RB5 on the main CPU. When it goes high, an interrupt vector is created on the
16C77. The main CPU then reads in the eight bits of data. The communication between the two processors
occurs at over 63 kbps and the transmission of data takes around 1 ms of time. The main CPU has quite a bit of
idle time on its hands, so I was able to read in the data entirely from within this interrupt on the 16C77. This
saves us some fancy programming, and also makes the data transfer as fast as possible. We want to have as
many GP2D02 readings as possible as we move, and we don't want the sensor waiting while its controller
communicates to the main cpu. More on the timing considerations later.
The communication protocol between the CE519 and C77 is as follows...
1)The 519 puts the TX line high when it is ready to transmit
2)The C77 recognizes the high on the TX line (it is connected to an interrupt line), and puts a high on the clock
line to tell the 519 to clock the first bit of data on the TX line
3)The 519 sees the 1st clock transition on the clock line and puts up the first bit of data
4)The C77 waits approx. 20 us (16 us min) and then puts the clock line low to tell the 519 to put the next bit of
data on the TX line
5)The 519 sees the transition on the clock line, and puts the next bit of data on the TX line
6)This continues... The C77 waits 20 us, then changes the polarity of the clock line. This transition is what tells
the 519 to transmit the next bit
7)We have a fixed packet size of 8 bits, so after 8 bits are TX'd, the 519 goes back to get another reading, and
the C77 goes about it's merry way.
Relevent code - 12CE519 (GP2D02 and servo controller)
void transmit_data(int data) {
// tell the main CPU that we want to send data
output_high(SERIAL_TX);
while (!input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,7));
while (input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,6));
while (!input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,5));
while (input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,4));
while (!input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,3));
while (input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,2));
while (!input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,1));
while (input(SERIAL_CLK)); //wait for main
output_bit(SERIAL_TX,bit_test(data,0));
CPU to signal
CPU to signal
CPU to signal
CPU to signal
CPU to signal
CPU to signal
CPU to signal
CPU to signal
// make sure that after tx'ing, we leave the data line low
// so that the main cpu does think that we have more data
// to come.
delay_us(10); //make sure the last bit is valid
output_low(SERIAL_TX);
}
Relevent code - 16C77 (main cpu)
#int_rb
b4567_interrupts() {
// check if we have data coming in from the GP2D02 controller
if (input(GP2D02_TX)) {
// send an 'acknowledge' signal and also the first
// clock signal
output_high(GP2D02_CLK);
for (counter=0;counter<4;counter++) {
output_high(GP2D02_CLK);
delay_us(15); // 15 instead of 20
// This next line takes 24 assembly instructions,
// which is just under 5 us
gp_reading[gp_position]=(gp_reading[gp_position]<<1)|((int)input(GP2D02_TX));
output_low(GP2D02_CLK);
delay_us(15); // 15 instead of 20
// This next line takes 24 assembly instructions
gp_reading[gp_position]=(gp_reading[gp_position]<<1)|((int)input(GP2D02_TX));
}
// note that the last clock output is a low, which
// is needed otherwise next time the 519 goes to TX,
// it would see a high on the clock line and would start
// transmitting before the receive_data() procedure was
// ready to go
}
}
How the servo fits in
As I was limited to one GP2D02 IR sensor per robot, I used a hobby servo motor to sweep the GP2D02 through
a 50 degree pattern in the front of the robot. The servo used was a Cirrus CS-70 Standard Pro Servo. It is rated
0.15 sec/60 degrees at 4.8 volts and 0.12 sec/60 degrees at 6.0 volts. It is powered by 5 volts. A servo is
controlled by a series of pulses with certain high and low times. The high time controls the position of the servo.
A typical servo accepts a 1 ms to 2 ms high pulse in order to position itself over a 110 degree sweep. The low
time can vary from 10 ms to 20 ms, and plays no role in the position of the servo.
Servo Pulse Width
After some experimentation, it was found that the speed rating of the servo was not the entire truth. This
application needed to be accurate and repeatable with a relatively small change in position. We are moving only
8.33 degrees per position change. If we were to trust the speed rating, we would be able to achieve this change
in only 20.8 ms. This is not the case though. In order to position it accurately, I actually needed to give it 6
pulses, each around 12 ms long. Originally I had wanted to sweep wider than 50 degrees, but the time to
position the servo left me very few choices.
The controlling 12CE519 takes 7 readings from the Sharp GP2D02 in a pattern over 50.12 degrees, sending the
readings out as they are collected. It operates a sweep in one direction, when sweeps backwards in the opposite
direction to reach the starting position. This saves the wasted time of moving the servo through 50 degrees to
the start position without taking readings.
Sample Servo Code
// do a sweep in the CCW direction
for (position=134;position<175;position=position+8) {
reading=get_ir_reading();
transmit_data(reading);
for (counter2=0;counter2<6;counter2++) {
counter1=0;
output_high(SERVO_CONTROL);
do {
delay_us(4);
counter1++;
} while (counter1<position);
output_low(SERVO_CONTROL);
delay_ms(10);
}
}
Timing Considerations
The GP2D02 takes on average 60 ms to take a reading and transmit it to the 12CE519 controller and the servo
takes approximately 70 ms to move from one position to the next. The 12CE519 takes only 1 ms to transmit to
the 16C77 and will be neglected for these purposes. The GP2D02 takes 7 readings in one sweep. This means
that it takes around 840 ms (6*70+7*60) to do one full sweep. It also means that if an object appears on one
side immediately after a reading is taken, it will be 1560 ms (12*70+12*60) before that object is detected. The
servo will have to sweep to the wrong side and back before the object is in its range. This is worst case of
course. The sweep pattern that I set out is much wider than the robot base. Even if we don't detect an object at
the edges of the pattern, we will not hit it. The more important centre reading will never be more than 710 ms
(5*70+6*60) away from a new reading. This all results in an upper limit on our forward speed. If we travel 80
cm in 710 ms, it is very possible that we might not see an object before hitting it. Our robots are geared so that
they travel 25 cm in 1 second, so we are well under the maximum speed. This slow speed is not a factor in this
design, but if I had wanted faster robots, I would have had to rethink the sensors. Multiple IR sensors on the
front of the robot would allow the robot to travel much faster, as would having an early warning system built
from an ultrasonic sensor.
I am currently experimenting with homebrew ultrasonics again and I would like to combine the two types of
sensors to create a more robust detection system.
Conclusion
Well, I'm surprised that you are still with me at this point. I won't blame you if your eyes glazed over and you
skipped over most of this article. I'll summarize the main points to take away from this discussion for you
then....
1) GP2D02 sensors are very accurate and cool, but bloody expensive
2) The GP2D02 is very easy to interface to a microprocessor 3) A servo can be used to sweep the GP2D02
sensor back and forth in order to simulate multiple GP2D02s
4) A servo is also very easy to interface to a microprocessor
5) The 8 pin PICs can be used to move tasks away from the main robot CPU in order to free up processing
power and ram on the main CPU.
6) Finally, Aaron writes some damn boring stuff
I would be happy to try and explain any of this to anyone who doesn't see the point. Just give me an email at
[email protected] or come to one of ORE's meetings and I will see what I can do. <grin>
***********************************************************
The entire C code that was programmed into the 12CE519 PICs
***********************************************************
//-----------------------------------------------------------------// SERVO_GP2D02.C
Written by Aaron Ramsey, Jan.8th, 2000
//
// This program takes 7 readings from the Sharp GP2D02
// in a pattern over 50.12 degrees, sending the readings
// out as they are collected.
//
// It operates a sweep in one direction, when sweeps
// backwards in the opposite direction to reach the
// starting position. This saves the wasted time of
// moving the servo through 50 degrees without taking
// readings.
//
// It takes approx. 50ms to take a reading, and 60ms to
// move from servo position to servo position.
//
// TO DO - We are planning to possible implement a mode where
//
if GP5 is made high, the servo makes a 25 position
//
sweep rather than the regular 7 position. This
//
would only be a useful mode when the robot is
//
stopped as a full sweep would take almost 3 seconds.
//
// Currently it is implemented on a pic12ce519 running at
// 4MHz.
//
//
PINS USED
//
GP0 - Servo control line
//
GP1 - Serial transmit
//
GP2 - Serial receive
//
GP3 - GP2D02 Vout line
//
GP4 - GP2D02 Vin line
//
GP5 - Sweep Pattern (low for 7 readings over 50
//
degrees ,high for 25 readings over 180 degrees)
//-----------------------------------------------------------------#include <12ce519.h>
//#include <16f84.h>
#fuses INTRC, NOWDT, NOPROTECT, NOMCLR
//#fuses NOWDT,NOPROTECT,HS
//OSCCAL SETTING! MAKE SURE TO READ IT AND CHANGE THIS TO MATCH
//BEFORE PROGRAMMING ANY CHIPS!
//#rom 0x3FF={0xC70}
#use delay(clock=4000000)
#define
#define
#define
#define
#define
#define
SERVO_CONTROL
SERIAL_TX
SERIAL_CLK
GP2D02_VOUT
GP2D02_VIN
SWEEP_PATTERN
pin_B0
pin_B1
pin_B2
pin_B3
pin_B4
pin_B5 // unimplemented
int get_ir_reading();
void transmit_data(int data);
//-----------------------------------------------------------------void main(void) {
int counter1,counter2=0;
int position,num=0;
int reading;
set_tris_b(0b01101100);
//all out except GP2,GP3,GP5
// initialize the servo to a known position... all the
// way to the right
position=126;
for (counter2=0;counter2<50;counter2++) {
counter1=0;
output_high(SERVO_CONTROL);
do {
delay_us(4);
counter1++;
} while (counter1<position);
output_low(SERVO_CONTROL);
delay_ms(10);
}
// main loop
do {
// do a sweep in the CCW direction
for (position=134;position<175;position=position+8) {
reading=get_ir_reading();
transmit_data(reading);
for (counter2=0;counter2<6;counter2++) {
counter1=0;
output_high(SERVO_CONTROL);
do {
delay_us(4);
counter1++;
} while (counter1<position);
output_low(SERVO_CONTROL);
delay_ms(10);
}
}
// do a sweep in the CW direction
for (position=166;position>125;position=position-8) {
reading=get_ir_reading();
transmit_data(reading);
for (counter2=0;counter2<6;counter2++) {
counter1=0;
output_high(SERVO_CONTROL);
do {
delay_us(4);
counter1++;
} while (counter1<position);
output_low(SERVO_CONTROL);
delay_ms(10);
}
}
} while (TRUE);
}
//------------------------------------------------------// int get_ir_reading()
//
// Gets a reading from the sharp GP2D02 IR sensor.
// It reads the data from the GP2D02 1 bit at a time
// by left shifting the data into the varible 'reading'.
// I ran into some trouble with this routine. Originally
// I was clocking in 8 bits of information, but the first
// bit was always 1... giving me a range of values from
// ~170 to 240 or so, which pretty much sucked. After some
// testing, I found that by clocking in 9 bits and simply
// throwing away the first one, I could get readings from
// ~80 to 240. At this point, I do not know why this was
// happening. The data sheets are pretty minimal. Anyways,
// it works well now.
//------------------------------------------------------int get_ir_reading() {
int counter=9; // a kludge, see above
int reading=0;
output_low(GP2D02_VIN); // start cycle with Vin low
delay_ms(1);
// give the sensor a little time before we bug it
while (!input(GP2D02_VOUT)); //wait for Vout to go high
do {
delay_cycles(4);
// minimum wait is 2us, max is 170us, 4 worked
output_low(GP2D02_VIN); // tell the sensor that we want a bit
delay_cycles(2); // might be as low as 1 (maybe), 2 worked
reading=reading<<1; //left shift the reading value
reading=reading|(input(GP2D02_VOUT)); // put the newest reading into the
// LSB of reading
output_high(GP2D02_VIN); // we read the bit, and get ready for the next
one
counter--;
} while (counter>0);
// We leave the Vin pin high after finishing the reading
// This resets the sensor in order for a new reading next
// time
// An 8 bit number indicating the distance should now be
// sitting in the variable 'reading'
return(reading);
}
//----------------------------------------------------------// void transmit_data()
//
// This procedure assumes B1 is TX to main cpu, and B2 is
// clock line. The 519 can't sweep and TX at the same time,
// so we send a high to the main cpu to let it know that we
// want to transmit, then we sit and wait until the main
// cpu provides us with the TX clock. That clock does not
// need to be any particular speed... it simply should be
// as fast as possible, so that we can get the 519 back to
// do another GP2D02 sweep. The main cpu provides a clock
// because we don't trust the internal RC oscillator that
// the 519 is running off of, particularily at the 40+kbps
// that we hope to be running this routine at.
//
// The comm protocol is as follows...
//
1) The 519 puts the TX line high when it is ready
//
to transmit
//
2) The c77 recognizes the high on the TX line, and
//
puts a high on the clock line to tell the 519
//
to clock the first bit of data on the TX line
//
3) The 519 sees the 1st clock transistion on the
//
clock line and puts up the first bit of data
//
4) The c77 waits approx. 20us (16us min) and then
//
puts the clock line low to tell the 519 to
//
put the next bit of data on the TX line
//
5) The 519 sees the transistion on the clock line,
//
and puts the next bit of data on the TX line
//
6) This continues... The c77 waits 20us, then changes
//
the polarity of the clock line. This transistion
//
is what tells the 519 to transmit the next bit
//
7) We have a fixed packet size of 8 bits , so
//
after 8 bits are TX'd, the 519 goes back to get
//
another reading, and the c77 goes about it's
//
merry way.
//-----------------------------------------------------------void transmit_data(int data) {
// tell the main CPU that we want to send data
output_high(SERIAL_TX);
while (!input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,7));
while (input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,6));
while (!input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,5));
while (input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,4));
while (!input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,3));
while (input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,2));
while (!input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,1));
while (input(SERIAL_CLK));
output_bit(SERIAL_TX,bit_test(data,0));
// make sure that after tx'ing, we leave the data line low
// so that the main cpu does think that we have more data
// to come.
delay_us(10); //make sure the last bit is valid
output_low(SERIAL_TX);
}
Convert a Futaba S148 Servo to Continuous Operation
By Michael Simpson
http://www.kronosrobotics.com/an116/GAN116.shtml
Some other Servo Modification Instructions






Modify
Modify
Modify
Modify
Modify
Modify
a
a
a
a
a
a
Futaba S148 Servo
Futaba S3003 Servo
Kronos Robotics HRSERVO1 Servo
Airtronics 94102 Servo
Hitec HS-300 Servo
GWS SO3N Servo
One of the simplest bots you can make is made by converting a couple of servos to free running mode. You get a
small motor, gearbox and speed controller all in one package.
First lets talk a bit about how a servo works.
Most servos are controlled by a series of pulses. The width of the high state pulse is what determines the actual
position of the servo.
Generally a pulse of 1ms will place the servo at one end of its rotation (see figure 1) and 2ms will place it on the
other end (see figure 2)
Figure 1
Figure 2
I say generally because I found that the range can be any where from .2ms to 3ms depending on the servo
manufacture and model. Again generally when the pulse width is 1.5ms the servo will reach the half way point in its
swing.
There is a small potentiometer inside the servo that rotates with the main shaft. This is what tells the electronics
in the servo where it is at any given time. When we convert a servo to free running mode we disconnect the
potentiometer from the shaft and set it at its center position. We also remove any mechanical stops that may
keep the servo from turning completely around.
Once the servo can rotate freely we can find the center spot by slowly adjusting the pulse width. I call this the
neutral position. Now by adjusting the pulse width greater than the neutral position we can move the shaft in one
direction. By adjusting the pulse width less than the neutral position we can move the shaft in the opposite
direction.
Most servos were designed so that when it gets closer to its allocated position it slows down. This will allow us to
adjust the speed of the shaft by varying the amount that deviates from the neutral position.
Modifying the Servo
Note that the following modifications will void your servo warranty.
Step 1
Remove the 4 screws on the back of the servo.
Note that its not necessary to remove the back of the servo.
Step 2
Remove the top of the servo by lifting.
Note that the two pins shown may stay attached to the top of the
servo. If they do remove them and insert into position as shown.
Step 3
Remove the intermediate gear by just lifting.
Step 4
Remove the main shaft by lifting.
Step 5
With your fingers or some small pliers place the
potentiometer shaft into the center position as shown.
Update
Step 5b
Using a thin blade of a razor saw or a cutting disk on a
rotary tool place a small slot in the main shaft of the servo
as shown. This will allow you to calibrate the servo later.
Step 6
There is a small stop that must be removed from the main
shaft. I found that using small wire cutters and then
cleaning up with and exact knife works the best.
Update
Step 6b
Use a 5/64" Drill bit and drill through the top of the main gear as
shown. You are making an access for you micro screw driver to adjust
the main shaft (potentiometer).
Step 7
Insert the shaft into the top of the servo case as shown
and test that you can rotate the shaft completely.
Step 8
It is now necessary to remove the small catch located on the underside of the
main shaft. You can remove it by simply placing a small screw driver into the
shaft and prying out. The bushing will also pop out. Just place it back in place
once the catch has been removed.
Step 9
A: Place the main shaft back in place.
B: Place the intermediate gear back in place.
C: Replace the servo top.
D: Reattach the 4 rear screws.
Update
Step 10
To calibrate the servo just set it to a neutral (center position)
1500us. Use a small screw driver to adjust the main shaft as
shown. Adjust until the drive shaft stops moving.
You can use the following program calibrate the servo's neutral
position.
func main()
SERVOinit(1)
SERVO1us 1500
endfunc
include \lib\DiosHSServo.lib
Variable Speed Control Modification
to the Futaba S3003 RC Servo
Lee Buse (c) August 2000 (Edited by Steven D. Kaehler)
Note: Making the physical and electrical modifications described in this article to a RC servo will void its
manufacturer's warranty. The author makes no guarantees regarding the success or suitability of this
modification for any particular application or purpose. The reader takes full responsibility for the
success or failure of the servo to perform as indicated or described. In other words, perform this
procedure at your own risk.
Introduction
The Radio Controlled (RC) servo is an ingenious device that allows remote, proportional actuation of
mechanisms by the simple movement of a lever on a controller or the software of a robot. For hobby robotics,
this enables scanning sensors, walking machines, animatronic devices, and a host of other interesting moving
machines. With a simple hack, these servos can be converted from proportional actuators to drive motors. This
is especially nice since they come complete with interface electronics, and can be directly connected to and
controlled by a microcontroller's I/O port. Unfortunately, one limitation of these wonderful little gadgets has
been speed control when used as drive motors. By design, servos drive to their commanded position fairly
rapidly. So the command input normally provides only full forward, stop, and full reverse control of the drive
motor, with nothing in between. This article will describe in detail how you can modify a commonly available
servo (Futaba S3003) such that good variable speed control will not only be possible, but very practical. With
proper technical data (or dumb luck), this technique can be applied to many different brands of servos.
RC model servos are fairly sophisticated devices that incorporate both position and speed feedback with a goal
to provide precise position control. In normal use they compare the 1-2 ms, 50 hertz (50 Hz, 5-10% duty cycle)
input pulse signal with an internal linear pulse generator controlled by the feedback servo position
potentiometer (pot.) and by the motor back-EMF (voltage generated between power pulses) which is used as a
speed sensor. See Figure 1. The difference in pulse width (the error signal) is then "amplified" with a pulse
stretcher. This circuit provides the servo control gain. The pulse stretcher output drives the servomotor through
an H-bridge circuit to close the servo loop. The speed sensor feedback is normally used only to stabilize the
position of the servo so the servo drives quickly to its commanded position with minimal overshoot. Figure 1
shows the S3003 circuit diagram along with the circuit functions believed to be in the BA6688.
Figure 1 - The inside of the S3003 RC servo and the speed control modifications
The Technical Details
When the servo is hacked by replacing the feedback position pot. with fixed equal value resistors, only the
speed control response remains in the feedback path. The servo now drives the motor forward or reverse when
it see pulse widths less or greater than 1.5 mS. Unfortunately, the hacked servo circuit has a very narrow input
control range and is difficult to impossible to speed control accurately, though it has adequate speed and torque.
The main cause of this problem is that while the existing speed control feedback level is adequate for normal
position servo stabilization, it is insufficient to match the 1 mS (1-2 mS) input pulse width variation when the
servo is used as a drive motor. The result is that the motor is just driven to maximum speed most of the time.
A fix to this problem is to increase the scale factor (gain) of the speed control feedback so that the maximum
motor speed range corresponds to the full 1 mS range (1-2 mS) of the input signal. Since this increases the total
servo loop gain by the same factor, the servo will tend to become unstable. That problem can be solved by
decreasing the pulse stretcher gain by a similar factor. The result is a well-behaved speed-controlled servo drive
with full-range speed control, good torque, and stable operation.
The Modifications
So far, I have made these modifications to a Futaba S3003 (the replacement for the S148), a popular,
inexpensive, currently available servo. They can be purchased from Tower Hobbies among others. The S3003
uses BA6688 and BAL6686 integrated circuits for which I have been unable to obtain data sheets. Tests
indicate that the BA6688 contains the servo control circuits with the BAL6686 as a separate H-bridge motor
drive circuit. Earlier RC servo designs combined these functions within a single chip (i.e. NE544 and
M51660L).
Figure 2 shows the 330K 1/4-watt resistor attached between the motor terminal and pin 10 of the BA6688. This
resistor causes am increase in the speed control feedback. Use insulation on the resistor wire and keep it down
close to the board. If you are skilled at surface mount techniques, just replace the 910K resistor (just to the left
of 330K, "914") with a 220K-240K surface mount resistor. The round silver button to the right of the 330K
resistor is the bottom of the motor.
Figure 2 - The bottom of the RC servo circuit board with the 330K shunt resistor installed.
Figure 3 shows the 0.1 uF 10% ceramic capacitor (yellow component next to motor), which replaced the 0.47
uF capacitor originally installed. This capacitor causes a decrease in the pulse stretcher gain. You can also see
the 22-turn 5K trimpot (gray "box" with brass screw on top) in this photo. The two black brick-like objects
between the motor and the trimpot are the servo chips.
Figure 3 - View of the insides of the RC servo showing the new trimpot (gray) and capacitor (yellow).
Components Needed for Hack
1 ea - 5K miniature multi-turn trim pot.
1 ea - 1/4W or 1/8W, 220K-240K surface mount or 330K shunt resistor
1 ea - Short length (~1") of insulating sleeving for resistor lead
1 ea - 0.1 uF <50V ceramic capacitor (good quality)
You will need a low-power soldering iron with a very small tip to complete these changes without damaging the
board. Make you connections quickly minimizing the board and component heating. Use solder wick to
remove unwanted solder if you accidentally create a bridge.
Tools Needed for Hack
Very fine-tipped soldering iron
Electronic solder (60% lead, 40% tin)
Small tip phillips screwdriver
Small blade screwdriver for pot. adjustment
Needle nose pliers
Diagonal cutters
Pulse generator or Servo driver
Step-by-Step
The following steps should be followed to convert the RC servo into a high quality, speed controlled, gearmotor drive:
1. Disassemble the servo. General instructions for doing this are covered in the continuous rotation hack.
If you intend to do both hacks to a servo, do only the mechanical modifications mentioned in the above
article, then continue below.
2. Replace the 5K servo position feedback pot. with either fixed (2.2K) resistors (poor to OK) or a 5K
trim pot (recommended).
(I chose to use a trimpot. There is some shift of the zero-speed pulse width with this change and the trim
pot. provides a convenient adjustment for this though the motor can also be stopped by not pulsing it.)
3. Either replace the 910K surface mount resistor in the speed control feedback path with a 220K240K resistor (cleanest) or add a 330K (orange,orange,yellow) shunt resistor (easiest) around it.
Be sure to insulate the longer lead to prevent contact with any intermediate pads on the bottom of
the circuit board. (I chose to add a 1/4W 330K shunt resistor since I'm not into surface mount
soldering yet. This resistor increases the speed sensor feedback by a factor of about four, which provides
full-range speed control.)
4. Replace the 0.47 uF capacitor in the pulse stretcher circuit with a 0.1 uF 10% ceramic capacitor.
(This capacitor decreases the gain of the error circuit by a factor of about four in order to balance the
effect of the previous mod and maintain servo stability. Don't use a low quality –20/+80% capacitor
here or you may have unpredictable results.)
5. Connect the servo to a servo driver (or pulse function generator), apply power, set the input pulse
width to 1.5 ms (50 Hz, 7.5% duty cycle), and adjust the new trimpot until the motor stops. If this
does not work, check the component values, wiring and solder connections.
6. Reassemble the servo case and gears in the reverse order of disassembly, being careful not to
pinch any wires between the case sections. (Don't forget to remove the limit-stop bump on the output
gear per the other hack if you haven't already done so).
Checkout
Once you have completed the specified modifications you are ready to test your servo. A great tool to have is a
test circuit that generates the servo pulses. The servo driver circuit mentioned above is a simple one-IC project
based on the 555 timer, and can be built on a small protoboard. It generates a manually-controllable 1-2 mS
pulse 50 times a second (50 Hz, 5-10% duty cycle) capable of driving a servo directly. Build it into a box with
a mating connectors for your servos, and you have a handy tool for working with RC servos now and in the
future.
With your servo connected to the servo driver or pulse function generator, you should be able to operate the
servo from complete stop to full speed in either direction smoothly and easilty over the 1-1.5 mS and 1.5-2 mS
(5-7.5% and 7.5-10% duty cycle) range. You are now ready to put it to work in your next mini robot.
Conclusion
I hope you find this modification useful for your purposes. The modified servo has excellent full range control
and very good low speed torque. The high speed torque however, is not so wonderful, but tolerable. The
modified servo tends to behave more like a voltage regulator than a well-tuned servo since the speed error will
now be proportional to speed and load. There are limits to what can be done to a RC servo without a major
circuit redesign. This modification accomplishes its goal, though not perfectly.
When subjected to this continuous rotation mod, the innocuous RC servo becomes a moderately priced, full
function wheel drive system for small robots, with a simple and easy microcontroller interface that can give
your robot the ability to move about with great dexterity. Since the general operating characteristics of most
RC servos are the same, this modification can probably be adapted to most RC servos with some adjustment of
the component values.
If you are interested in further reading on what makes RC servos tick, the following link provides more
technical information on other chips (the NE544 {older} and the M51660L) that are also used. Also an Internet
search using "RC servo" will produce an abundance of interesting and sometimes useful links.
Improving Servo Positioning Accuracy
David P. Anderson
[email protected]
I have documented a technique for improving the accuracy and repeatability of servo positioning by use of an
external reference potentiometer.
This problem originated when we were developing a two-axis head for a video camera mounted on our
remotely piloted vehicle. We wanted a vertical movement of 110 degrees, so the camera can look straight up,
straight ahead, and down forward about 20 degrees. This is doable with a standard R/C servo. We also wanted a
horizontal rotation axis of just over 360 degrees, so the head can rotate around left or right and see straight
behind itself.
We looked at R/C sailboat wench servos for the horizontal rotation, but they are pretty pricy. Besides, we have
lots of standard Futaba and Airtonics servos from our other hobby, R/C airplanes, laying around.
The first instantiation
was to gear up a
standard servo 1:3 by
putting a large spur gear
directly on the servo
output wheel, 36 teeth,
and a small gear attached
to the base of the camera
platform vertical axis, 12
teeth. This worked fine
to give us a bit more
than 360 degrees of
rotation with a standard
servo.
The problem with this approach is that when the
angular movement of the servo is geared up x3, the
positioning error is geared up x3 as well. This
means that the head/camera does not return to the
same position when the R/C transmitter sticks are
centered, depending on which direction it is turning
and how far. The whole thing was workable but
sloppy.
The solution to this problem was to use an external
pot to generate the feedback for the servo
positioning electronics. This same technique should
work with any servo driven scheme to increase the
positioning accuracy.
A little mini theory-of-ops might be useful here. I refer the interested reader to the excellent overview by Lee
Buse in the September 2000 SRS Encoder:
http://www.seattlerobotics.org/encoder/200009/S3003C.html
The position of the output wheel in a standard R/C style servo is dependent on two pulse streams, one of which
is the external control signal generated by a transmitter/receiver pair or a control computer, and the other
generated internally by the servo.
R/C Servo Control and Reference Signals:
The motor is driven in
whichever direction is
required to reduce the error
signal to 0, or very near 0.
The width of the internally
generated pulse is controlled
by a feedback potentiometer
attached to the output wheel
at the end of the servo motor
gear train. This is the pot that
is removed or disconnected in
the various servo-hack
schemes when used for
endless rotation to drive robot
wheels.
The servo electronics
compare the pulse width of
the incoming control signal
with the pulse width of the
internally generated signal. If the incoming signal is larger it drives the servo motor in one direction, and if it is
smaller it drives the motor in the opposite direction.
Normal R/C Servo Output Motor
and Feedback element:
These pots are typically a 5k linear
taper, or something similar. As the
motor drives the output wheel, it
turns the pot, which changes the
width of the internally generated
pulse, forcing it to match the width
of the control pulse. When the two
pulses are the same width, or very
close to the same width, the motor
is turned off.
This "very close to the same width" is the source of the servo dead zone. Most modern servos also vary the
motor speed such that the motor runs more slowly when the two pulse widths are close to the same, to prevent
"hunting" and servo chatter near the dead band, but still be able to drive at full speed when the pulses are very
different. Some robot builders have been able to exploit this feature to provide some limited variable robot
speeds from their hacked servos.
Our solution for increasing the positioning accuracy of the servo head
was to drive the head directly from the servo output and use an external
pot for the positioning feedback. Once the internal pot has been
disconnected and removed, the servo output can rotate endlessly until
the external pot is driven into range. The output and feedback pot can
then be geared up or down to whatever positioning accuracy is required.
For our camera platform, we attached an 80 tooth gear ring to the
outside of the platform base. We used a 20 tooth gear on a 10 turn pot,
so one full revolution of the platform mapped to 4 complete turns of the
pot, and 5 turns of the pot gave us the full range of the
servo movement. This way we are not gearing up the
servo position error x3 as before.
The construction
sequence is:
1. Open servo and
remove and/or disconnect
the feedback servo from
the output gear train.
2. Find where the three
wires from the pot
connect to the servo
printed circuit board. Unsolder the three wires and
solder in our own three
wire flat cable.
3. Re-assemble the servo,
enlarging the access hole
for the control wires to allow the new three-wire flat cable to pass though.
4. Select an appropriate multi-turn pot for your
application.
For the rotation we wanted, a 10 turn 10k pot
worked out exactly. Solder the three-wire flat
cable wires to the terminals on the external
multi-turn pot. Be sure to keep power, signal,
and ground in the right order.
5. Mechanically couple the multi-turn pot to
your output device :)
To test the servo, power it up and give it a nominal (1.5 milsec)control pulse. The motor should start running,
and the output shaft will rotate. You should be able to turn the external multi-turn pot with your fingers until the
motor slows and finally stops. Continuing to turn the pot should start the output shaft rotating in the opposite
direction, slowly at first, and then faster as you continue the rotation.
This is the setup we are currently using and it works just dandy. The robot head can rotate all the way around
about 15 degrees past backwards, and still reposition itself accurately when the controls are centered.
Because the feedback device is directly connected to the final output platform, this corrects for slop and
backlash in the driving mechanism that might
cause overshoot or undershoot. The servo
motor continues to drive until the final output
stage is in the correct position, irrespective of
slop in the gear train.
hope this is useful, happy roboting,
19 September 2000
Dallas, Texas
RCFS-V2
Radio Control FailSafe Version II
RCFS-V2 is a microcontroller based device that adds FailSafe and Glitch Filtering
features to nearly any PPM (AM/FM) radio control system. Despite its smaller size, it
offers higher performance than the original RCFS failsafe design.
Several years ago we introduced a microcontroller based R/C Failsafe project. It
installed inline with a model's servo and offered failsafe-like features to it. The design worked well, but the availability of
more powerful PIC microcontrollers has allowed us to create a more advanced design. This release is smaller, uses less
parts, and has exciting new software features.
Let's step back for a moment. There are differences of opinion about a R/C failsafe's role during an extended loss of radio
contact. Some modelers feel that all a failsafe device can do is just change the location of the crash. Others believe that
the ability to hold a model's attitude, or program in a reduced throttle setting, is helpful in such situations. In any event, we
wish to make it clear that using the RCFS-V2 device, or any other R/C FailSafe system, is at your risk.
Beyond the failsafe functions, the design offers other useful features. At the hardware level, it offers a robustly buffered
servo signal. Unlike the usual 1mA current that is offered by the typical receiver's decoder, RCFS-V2 delivers a low
impedance 20mA servo pulse. This healthy servo drive current can help reduce coupled noise problems that may occur
on long servo cable runs.
In addition, its sophisticated firmware can effectively mask short duration glitches. The glitch prevention features are
handled by a digital impulse filter that does a surprisingly good job. Intermittent glitch issues often haunt small electric
park flyer models since they are usually operated in harsh environments. This feature alone may provide a welcome
remedy to some installations.
The RCFS-V2 includes an optional low voltage detector. That's right, failsafe can be triggered if servo voltage becomes
too low for safe operation. Lastly, a bright LED indicates when the R/C signal has errors. It is a helpful troubleshooting
feature during those vital ground range tests.
Features of RCFS-V2:








Flexible Failsafe Modes (Idle, Hold, Preset).
Glitch Filtering with Servo Pulse Flywheeling.
Optional Low Voltage Failsafe.
Buffered Servo Signal (20mA drive).
1000 Step Pulse Resolution Provides Exceptional Pulse Fidelity.
Easy Range Testing: Status LED Indicates Servo Pulse Errors.
All Failsafe Features are User Programmable (Easy Pushbutton
Operation).
Designed for electric R/C models. Works with all 5V BEC voltage sources.
Hold Me
RCFS-V2 is installed between the R/C receiver and servo. It constantly analyzes the incoming servo pulses and looks for
trouble. Using a microcontroller, the pulses and framerate are checked to see if they fit within a allowable range, in a
template sort of fashion. If they are found to be acceptable then they are passed on to the servo.
If the servo's pulse width or framerate is invalid, the corrupted pulse is replaced with the last known good servo
information. In addition, if the servo pulse is valid, yet suspiciously out of context, the proprietary impulse filter will
determine if the pulse should be "repaired." This pulse substitution is maintained for a short time in a process called
Servo Pulse Flywheeling.
If the problem persists for more than one second then flywheeling is terminated and the FailSafe feature is enabled.
FailSafe can be set to hold the last valid position, move the servo to a preset position, or idle (disable) the servo pulse.
The latter is used with Electronic Speed Controls (ESC) or when you want to reduce servo currents to a minimum when
the RF signal is lost.
All the features are user-programmable. A tiny switch and LED status indicator are used to set the parameters you want. It
is as easy as pressing a button.
Timing is Everything
So, how does this magic really work? The servo signal is a simple digital pulse. It spends most of its time at a logic low
(0V). About every 20mS it goes logic high (3-5VDC) and then quickly goes low again. It is this tiny window of logic high
time, called the pulse width, that gets the attention of the servo.
Please refer to the drawing. The period labeled "A" is called the frame rate. In the example it is repeated every 20mS (50
times per second), which is quite typical for most AM or FM (PPM) R/C transmitters.
Modern servos define center as a 1.5mS pulse width, as shown by detail "B" in the drawing. Full servo rotation to one side
would require that this pulse width be reduced to 1.0mS. Full rotation to the other side would require the pulse width to
increase to 2.0mS.
In the eyes of RCFS, good servo pulses will be between 0.8mS and 2.2mS long. Even though a normal servo signal is
1.0mS to 2.0mS, some transmitters offer ATV settings that can extend the timing beyond that. The wider range taken by
RCFS allows compatibility with such radio systems.
When servo pulses do not fall within the allowed pulse range, or the framerate becomes suspicious, the signal is flagged
as "corrupt." When bad pulses are encountered during the flywheeling period, they are immediately substituted with the
last known good servo pulse value. This helps mask intermittent glitches. If the problem persists for more than a second
then RCFS-V2 will switch to a full FailSafe state. The user can set the failsafe mode as they see fit.
Less is the New More
Even though there are more features than before, the parts count is less. All it takes is an 8-pin PIC microcontroller,
capacitor, resistor, and LED. If you want the Low voltage detection then two more parts are needed. Shopping for these
parts is a breeze since they are all available at Digi-Key.
You will need a PIC12F683 chip programmer to "burn" the provided hex file's object code into the microcontroller. Be sure
to select the configuration fuses during chip burning as follows:
WDT: Disabled
MCLR: Disabled
Oscillator: IntRC I/O
Code Protection: Disable
EE Protection: Disable
FCM: Enable
BODEN0: = 1
BODEN1: = 1
Power Timer: Enable
IESO: Enable
The PIC's Hex file is designed to automatically instruct the programming hardware to chose these values. However, it is
always a good idea to check them for accuracy. Be sure to setup your programmer so that it does NOT overwrite the
factory stored OSCAL value! Please do not ask me how to do that -- I will not know how to operate your equipment.
If you have trouble burning the PIC, then please check your programmer. Whatever the fault, it is not a RC-CAM hex file
issue. The most common problem is that the user has forgotten to burn the PIC's configuration fuses, as described above.
By the way, unlike most of our other PIC projects, this one does not have Code Protection enabled. That means that you
can verify the PIC chip after programming. Please keep in mind that there are restrictions to using the hex file. Permission
requirements are found in the readme file that is provided with the hex data.
Board Construction:
Even though it is very simple, this project is only recommended to those that have electronic assembly experienced. If you
have successfully built any of the other RC-CAM Electronic Projects then you should have no problem with this one. Entry
level builders should plan on getting some hands-on help.
Below is the complete materials list:
DESCRIPTION
PIC12F683
.1uF Cap
150 ohm 1/8W Resistor
Bright LED
Push Button Switch
3-Pin Header
Servo Cable
Jumper Wire
REF
U1
C1
R1
LED1
S1
J2
J1
JP1
DIGIKEY P/N
PIC12F683-I/P-ND
1203PHCT-ND
150EBK-ND
404-1114-ND
EG2513-ND
A26510-40-ND
N/A
N/A
OPTIONAL LOW VOLTAGE DETECT PARTS
LM285-2-5 Voltage Ref IC D1
10K 1/8W Resistor
R2
296-9524-5-ND
10KEBK-ND
The RCFS-V2 board can be built using nearly any technique you wish.
Ours was built on a tiny piece of phenolic perfboard. Be sure that your
construction method is worthy of a model aircraft's environment.
Layout is not critical. Cap C1 should be installed with short leads to the
PIC. The circuit was point-to-point wired using 30 gauge insulated Kynar
wire. This wire is normally used for wirewrapping, but works fine with a
soldering iron. We recommend a temperature controlled iron (700° tip).
If the low voltage detect feature is not used then install the JP1 jumper wire
and omit R2 and D1. If low voltage detection is wanted, then omit JP1 and
install the two components.
The circuit can be hardwired with the servo's existing cable. However, we used a 3-Pin header for J2 and a short servo
cable on J1. Installation in the model plane is a plug-and-go sort of effort.
Check it Out
Simple mistakes can destroy electronic parts and may generally ruin your day, so check your work carefully. Do not install
the receiver battery until you have verified that the power leads are not shorted (use an ohmmeter). If all looks good, plug
the RCFS-V2 into a channel of your R/C receiver.
You may use your ESC/BEC or a standard 4.8V R/C battery for the receiver's power source. But, do NOT install the PIC
chip until you have verified that U1 pin-8 is ground and pin-1 has +4.5 to +5.5 VDC on it when power is applied. Remove
the battery BEFORE you install the PIC chip.
Now it's time to test your work. Just follow these three simple steps:
1. Turn on your transmitter and verify that the stick controls the servo as usual.
2. Turn off the transmitter. For a very short period the LED should blink, then turn on solid.
3. Turn on the transmitter and verify the LED immediately turns off.
Optional Low Voltage Feature
The optional low voltage feature should be used in limited circumstances. The feature is designed to invoke failsafe when
the servo voltage is under 3.8VDC. Servo control will be immediately restored once the voltage rises to about 4.2VDC.
The only expected application is on a throttle servo; perhaps you would like to idle the model's motor if the servo voltage
is bad (this can be used to warn you of trouble). In any case, use this feature with care.
User Configuration (Programming)
As mention earlier, the failsafe features are user programmable. Configuration is a breeze. Just follow these instructions.
1. Turn on the transmitter.
2. Press and hold the pushbutton switch while applying receiver power. Confirm the LED is flashing. Release the
3.
4.
5.
6.
7.
switch (LED will turn off).
Set the desired Failsafe mode as follows:
> Idle Mode: Press One (1) time.
> Hold Mode: Press Two (2) times. This provides the servo hold feature.
> Preset Mode: Press Three (3) times. This is popular for throttle servos.
Wait about five seconds until the LED begins to slowly flash. Now it is time to set the glitch filtering feature. You
have five seconds to respond.
> Filter Off: Do NOT press switch (do nothing).
> Filter On: Press One (1) Time. This is the recommended setting.
If you chose Idle or Hold Failsafe modes at step 3 then jump to step 7. Otherwise, move on to step 6.
Wait until you see the LED's Flash-Flash-pause pattern. Set the servo Preset position by moving the transmitter
stick. Once the servo is in the failsafe position you need, press the pushbutton switch.
Done. System is ready to use. This is a good time to test out your settings (turn off the transmitter and wait a
second or two). You may go back to step 1 to change your preferred settings at any time.
Blink Once for Yes
A review of the programmed user settings can be seen at any time. All you have to do is press the pushbutton during
normal operation (not during failsafe). A code will be blinked out:
> Idle Mode: Blink-Pause.
> Hold Mode: Blink-Blink-Pause.
> Preset Mode: Blink-Blink-Blink-Pause.
After the pause (about 3 secs) one more blink may be seen. It it is, then the Glitch Filter is enabled. Otherwise, if the extra
blink is missing, then the Glitch Filter is disabled.
Design Documents:
The technical details are available as file downloads. There is no charge for the information when used in a personal
(hobby) project. Commercial users must obtain written approval before use.
Please be aware that the information is copyright protected, so you are not authorized to republish it, distribute it, or sell it,
in any form. If you wish to share it, please do so only by providing a link to the RC-CAM site. Please respect this simple
request.
Schematic Files: PDF file of the RCFS-V2 circuitry. All major components are from http://www.digikey.com/.
Revision: Rev A, dated 04-05-2005
PIC Object Code: Firmware Hex files. You should occasionally check for updates.
Revision: V2.0, dated 04-05-2005.
The Small Print:
If you need a part then please consult the sources shown in the project (see schematics download). I do not work for, nor
represent, ANY supplier of the parts used in RCFS-V2. Any reference to a vendor is for your convenience and I do not
endorse or profit from any purchase that you make. You are free to use any parts source that you wish.
All information is provided as-is. I do not offer any warranty on its suitability. That means that if you build and use this
device, you will do so at your own risk. If you find documentation or software errors then please report them to me.
FeedBack:
I would enjoy hearing from anyone that uses the RCFS-V2. Please send me an email if you build it. Your comments and
suggestions are welcome.
Serial Wombat Servo Channel Mode
The Serial Wombat can control up to 12 servos on 12 different pins at a time.
Driving a servo with your Serial Wombat is easy! Just follow these simple steps:






Connect +5 volts and ground to your servo's power wires (often red and black)
Connect the servo control line to one of the Wombat's I/O pins
Pick a minimum and maximum pulse time for your servo. For starters, try 1ms minimum, and
2ms maximum
Initialize the servo pin using the two commands below. This will drive the servo to the commanded
position
Command the servo to position 0. If it doesn't go all the way to one side, lower the minimum pulse
width and try again
Command the servo to position 65535. If it doesn't go all the way to the other side, raise the variable
pulse (maximum - minimum) width and try again until you've tuned the system for your servo
Repeat the above steps for up to 11 more servos!
Message format:
Data
200
Sent to
the
Wombat:
Meaning:
Configure
Pin First
message
Pin #
17
Pin
Servo
Number to Control
be set to
Mode
Servo
Control
Minimum
Period
MSB
Minimum Variable
Period LSB Period
MSB
Variable
Public Data
Period LSB Buffer to
control
Position
The minimum pulse
length, in ticks (see
below for calculation)
The variable amount of The pin
time in pulse length (see whose
below for calculation) public data
will control
the servo
position
Servo
Position
MSB
Frames
between
updates
Reverse
0x55
Number of
frames to
wait
between
sending
pulses
0:
command
of zero
generates
minimum
pulse
Unused.
This message is echoed back by the Wombat.
Data
201
Sent to
the
Wombat:
Meaning:
Pin #
17
Configure Pin
Servo
Pin Second Number to Control
message
be set to
Mode
Servo
Control
Servo
Position
LSB
This sets the public data
buffer of the pin
controlling the servo.
This only matters if the
8th byte of the previous
message indicates the
current pin.
0:
command
of zero
generates
maximum
pulse
This message is echoed back by the Wombat.
The minimum and variable pulse widths are expressed in terms of the clock used to drive the system. This
allows the possiblity that the Wombat will be able to utilize an external crystal in future releases. Presently, the
Wombat is clocked using the internal 8Mhz oscillator. In order to calulate a width in ticks, use the following
equation:
Ticks = Pulse Width * Crystal Frequency
For example, for the Futaba S3003 described in the background section below, the minimum period would be
500us. In order to convert this to ticks, multiply .0005 by 8000000. The result is 4000. The variable time is the
difference between the longest and shortest pulse, 1750us for the S3003 above. In system ticks this is .00175 *
8000000, or 14000.
The servo channel mode reads a pin's public data buffer and adjusts the servo pulse accordingly. The channel
may read its own public data buffer, which is set by the host, or the public data buffer of another pin. This
allows the servo to respond to Wombat inputs with no assistance from the host. This would be useful if, for
example, the user wanted to control a servo with a joystick connected to one of the Wombat's analog inputs, or
with a rotary encoder attached to two input pins.
When the reverse option is set to 0, the Wombat will generate a minimum-length pulse when the public data
buffer is zero and a maximum length pulse when the public data buffer is 0xFFFF. Setting reverse to 1
The Wombat allows the host to configure how many frames to wait between sending pulses. For example, if a
new frame starts every 1 ms, and a 20ms update period is desired, then the host would configure the channel to
wait 19 frames between sending pulses.
Example:
Configure channel 16 to drive the Futaba S3003 servo described above based on a position commanded from
the host. Command the servo to move to the middle position. Assume the system is running a 1ms frame, and
that the servo should be updated every 20ms. Set the system to send longer pulses for bigger numbers. This
results in counterclockwise motion for increasing numbers on the S3003.
200 16 17 0x0FA0 0x36B0 16 ;
;
;
;
Set pin 16 to servo mode,
Minimum pulse 4000 ticks (0x0FA0)
Variable period 14000 ticks (0x36B0)
Read pin 16's data (this pin) for position
201 16 17 0x8000 19 0 0x55 ;
;
;
;
;
Second configuration message, pin 16 to servo mode
Set position to 0x8000 (middle pulse width)
19 frames (ms) between updates
0 = don't invert position command
last byte is unused
Background:
A servo is an integrated package which contains a motor, gears, and control circuitry. Servo Motors are
frequently used in model planes and cars, industrial robots, hobby robots, and anywhere that a precision
controlled angular output is needed. Most servos have only three wires, power (typically red) ground (typically
black) and a control line (typically yellow or white). Most servos are designed to operate on 4.8 to 6 volts.
The servo command protocol is very simple, but surprisingly tricky to implement on a microcontroller,
especially when multiple servos must be supported.. A high pulse is sent to the servo approximately every
20ms. The duration of the pulse instructs the servo to turn the motor to a particular angular position. Most
servos will rotate a total of 180 degrees. Typically, a 1500us pulse will place the servo in or near the center
position. The length of the pulse necessary to drive the servo 90 degrees to either side seems to vary according
to servo manufacturer or model. A search on the internet will reveal a wide variation of opinions about the
proper range of pulse length; various sites quote values from between 1250us to 1750us, all the way to 500us to
2500us. Manufacturer's web sites do not seem to have much information about the servo signal format either. In
fact, we haven't seen anywhere which even sets a standard regarding whether a longer pulse causes clockwise or
counter-clockwise movement.
In testing the Wombat we found that the times necessary to drive a servo through its full range did vary between
servo models and manufacturers. In order to accomodate as many servos as possible, the Servo channel mode
allows the host to configure three parameters describing the drive signal for the servo: the minimum pulse
width, the variable period of the pulse, and a reverse option. The Wombat's officially supported servo is the
Futaba S3003. This servo was chosen because of its low cost and common use. The S3003 is a servo which is
very commonly used in ready-to-run R/C kits. In testing with this servo we found that a pulse width of 500us
would drive it nearly all of the way clockwise. A pulse of 2250us would drive it nearly all of the way counterclockwise.
A servo requires a new pulse be sent approximately every 20ms. This is based on the fact that most servos are
actually analog circuits. The pulse is used to generate an analog voltage in the servo, which is then fed to a
sample-and-hold circuit. This voltage is compared to another voltage which is proportional to the servo's
position. A feedback control circuit then provides torque to move the servo until the voltage provided by the
servo position matches that provided by the sample-and-hold circuit. However, the sample-and-hold circuit may
drift over time, causing the servo to move from its commanded position. Therefore, a periodic refresh of this
sample-and-hold circuit keeps the servo very near its commanded position. The acutal requirements for refresh
rate vary by servo manufacturer and model, but are typically at least 20ms, and the period can typically vary a
couple of milliseconds from one pulse to the next without problem. When a servo is not being updated quickly
enough it may be observed to vibrate as the set position is changing between pulse updates. Some new servos
which use digital guts rather than the old analog circuits can hold a position indefinately from just one control
pulse.
The Wombat is based on the Microchip 18F4620 microcontroller. This controller has two pins, 16 and 17,
which have special circuitry designed to generate pulses. When one of these pins is used for servo mode, the
Wombat firmware can simply configure the hardware each time it wants to send a pulse, then move on to
servicing some other pin. Therefore, pins 16 and 17 are the best choices for servo control. However, in keeping
with the Wombat principles, all pins can provide servo control, but at a substantial cost to throughput and
system flexibility. When a pin other than 16 or 17 is used to control a servo the Wombat must provide
processing power to that pin during the entire time that the pulse is high. Therefore, the host should not
configure a pin other than 16 or 17 to servo control if a frame period shorter than the maximum possible servo
pulse is desired. In order to provide more deterministic behavior, the servo function will delay after completing
a pulse in order to make the execution time of every pulse-setting call to a non-hardware assisted channel the
same, regardless of the desired servo position. In order to provide the most accurate pulse possible, the Wombat
will cease processing all other tasks while the pulse is being generated. This means that incoming
communications from the RS-232 port may be lost if more than one character is recieved during the pulse time.
Therefore, it is recommended that the communications baud rate be sufficiently slow that the receipt of two
bytes of data cannot happen within the maximum time required by a pulse.
The Wombat can control up to 12 Futaba S3003 servos simultaneously. This can be achieved by configuring 12
pins, including pins 16 and 17, to servo control mode, and setting the frame period to 25ms (Our lab tests show
that the S3003 can go 25ms without a refresh). The hardware-assisted channels take almost no time to process.
The remaining ten software-only channels will take approximately 2.25ms each to execute, or about 22.5 ms.
The Wombat could control more servos if the maximum pulse length was shorter, or if the time between
refreshes was longer.