R/C Servo Tester
Total Page:16
File Type:pdf, Size:1020Kb
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.
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.
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.
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 CPU to signal output_bit(SERIAL_TX,bit_test(data,7)); while (input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,6)); while (!input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,5)); while (input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,4)); while (!input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,3)); while (input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,2)); while (!input(SERIAL_CLK)); //wait for main CPU to signal output_bit(SERIAL_TX,bit_test(data,1)); while (input(SERIAL_CLK)); //wait for main CPU to signal 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); }
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 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. *********************************************************** 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 SERVO_CONTROL pin_B0 #define SERIAL_TX pin_B1 #define SERIAL_CLK pin_B2 #define GP2D02_VOUT pin_B3 #define GP2D02_VIN pin_B4 #define SWEEP_PATTERN 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 // 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 // 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 } 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 a Futaba S148 Servo Modify a Futaba S3003 Servo Modify a Kronos Robotics HRSERVO1 Servo Modify a Airtronics 94102 Servo Modify a Hitec HS-300 Servo Modify a 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, gear- motor 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 220K- 240K 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. Un- solder 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 REF DIGIKEY P/N PIC12F683 U1 PIC12F683-I/P-ND .1uF Cap C1 1203PHCT-ND 150 ohm 1/8W Resistor R1 150EBK-ND Bright LED LED1 404-1114-ND Push Button Switch S1 EG2513-ND 3-Pin Header J2 A26510-40-ND Servo Cable J1 N/A Jumper Wire JP1 N/A OPTIONAL LOW VOLTAGE DETECT PARTS LM285-2-5 Voltage Ref IC D1 296-9524-5-ND 10K 1/8W Resistor R2 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 switch (LED will turn off). 3. 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. 4. 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. 5. If you chose Idle or Hold Failsafe modes at step 3 then jump to step 7. Otherwise, move on to step 6. 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. 7. 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: 200 Pin # 17 Minimum Minimum Variable Variable Public Data Data Sent Period MSB Period LSB Period MSB Period LSB Buffer to to the control Wombat: Position Configure Pin Number Servo The minimum pulse The variable amount of The pin Pin First to be set to Control length, in ticks (see time in pulse length (see whose public message Servo Mode below for calculation) below for calculation) data will Meaning: Control control the servo position This message is echoed back by the Wombat. Data Sent 201 Pin # 17 Servo Servo Frames Reverse 0x55 to the Position Position between Wombat: MSB LSB updates Meaning: Configure Pin Number Servo This sets the public data Number of 0: command Unused. Pin Second to be set to Control buffer of the pin frames to of zero message Servo Mode controlling the servo. wait generates Control This only matters if the between minimum 8th byte of the previous sending pulse message indicates the pulses 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 counter- clockwise. 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.