!NOTE! This is out of date. These controllers have been replaced. I'll update the page when the design becomes final.
Requirements: Schematic
PWMGen code
Feedback module code
I2C Slave library (roughly a C port of AN734 lifted from the CCS forums)


The servos require a pulse from 1ms to 2ms for 90 degree operation. This pulse is to be repeated roughly every 20ms. Further rotation, upto about 180 is available on some servos and the window expands to something on the order of 600us to 2.5us but is dependant upon the particular servo.

I used a microchip PIC16F88 running at 20Mhz to generate the pulses. Chose that one because of its hardware I2C slave support and because they are cheap and versatile (bought a bunch of them, using them for lots of other stuff).

to In order to get a very high resolution and smooth signal generation, I'm going to let the software worry about the translation from my internal counts to the position during a calibration phase.

I take 6 16 bit position values and sort them. Next subtract one from the next such that each value now represents the count from one to the next. Set all the pins high and start counting down to zero for each servo/value. Once 0 is hit, set its cooresponding pin low and move to the next servo.


The NetMedia boards got me going on the idea that I could use a current sense circuit to produce some meaningful data about how hard each servo is working. Thier boards work but do so way too slowly for my purposes. The also had a nifty feature of setting a servos position value to 0 which would turn off the pulse train to that servo. I lifted that for my design as well. (This happens to be a nasty bug in their boards. If you have any of them set to 0, you get what appears to be random noise communicating with the board). They way thier boards work is to take put a low side current shunt resistor in series with each of the servos and take a slow A/D reading off each one to determine the current draw of each channel.

Now I don't know if the reason they did it so slowly was because they misunderstood the way the servos are working or if they were just using a slow chip (they rubbed the number off). In fact the way the servos seem to operate is in an all on or all off manner. But the duration that the motor is pulsed on for is a function of the error between the actual and desired positions.

So, I designed my circuit to take fast readings on each channel comparing the result to a threshold and timing how long each line is above the threshold. What I get back is a reasonably good feel for the error. I plan to do more extensive testing to determine linearity, figure actual position possibilities, and even put it into a sympathetic mode, following external forces, but haven't gotten there yet.

One major drawback to this method (instead of cracking the servo open and tapping the internal pot) is that we don't know the direction of the error. We know the motor is working because it's in the wrong position, we know how hard it's working, but we don't know which way it's moving. One of the random servos I used happened to exhibit a behavior that would allow that determination via this method, but the ones that came with the kit do not. Perhaps yours will show the same behavior, namely a larger current draw in one direction that the other. I plan to try to recreate this data via software.


After trying a bunch of things, I settled on I2C. There are currently 3 controllers, but I may want to add more as some point. I needed a fast method of communication that could be easily daisy chained and expanded. My bit rate on I2C is approaching 800Khz, but the actual throughput with delays for interrupt latency drops to about 150kbps. Which is good enough.

Having just started looking at the 18 chips, I've stumbled across CAN. Haven't explored it yet, but will if I end up rebuilding these things.


If your are going to try to build one of these or are just curious, the resistors R6 and R7 are evenly matched for a 50% voltage divider. 2.5V is the lowest allowable VREF+ on this chip so that's what I feed it. R0-R5 are .03 omh 1/4watt resistors. OHMITE 605HR030 (these things are fragile, order a bunch of extras). If your servos are significantly lower power than mine, you'll need to use a higher ohm resistor to get into the reliably detectable range for the PIC's ADC.

After showing this thing to a buddy who knows infinitely more about electronics than I do, he pointed out a flaw. The amount of current I'm putting into the analog inputs of the feedback pic should be limited via a resistor. However, I managed to just squeak by on the tolerances so I don't need to scrap my first printed PCBs!