Wednesday, 6 April 2011

Servo board controller - parallel not serial

Many moons ago, we put together a multiple channel servo controller which generated a lot of interest on YouTube.

As part of the newly-relaunched NerdClub website, it made sense to write a few posts about how the all-new 20 channel controller works. Kits will be made available to anyone who just wants to get their hands on a working servo board, without the need to puzzle out all the clever code.

For this board, we're using the trusty old PIC 18F4550 microcontroller. You can use the lower-voltage 18LF version of this chip too, but we're sticking with the 5V version (see schematics later on).

Many people have asked how we managed to get beyond the theoretical limit of 8 servos on a 20ms pulse. For anyone not familiar with servo control, the way a servo works is it receives a signal of between 1ms and 2ms in duration (1ms = extreme left position, 2ms = extreme right). This signal has to be repeated every 20ms.



In practice, a servo signal is usually between 0.8ms and 2.4ms in length. Allowing for up to 2.5ms per servo, and repeating each signal every 20ms, this means we can send 20/2.5 = 8 signals one after the other, before having to return to the first servo to repeat the whole process all over again.



This is where we challenged the assumption that the servo signals have to all be sent serially (one after the other). We took the "parallel" approach - we turn on all servo pins at the same time, then compare the current time (in milliseconds) from the on signal start, to an array of "off values". Every time the current timer exceeds the "off value", the corresponding output pin is turned off.

Let's say we've an array of three off values:
servooff[1]=1000
servooff[2]=1500
servooff[3]=2000

We turn on all three servo pins at the same time, and start a timer running.
During the main code loop, we compare the current running timer value (converted into milliseconds) against each of the three off values. When the running timer exceeds 1000, we send servo pin one low (turn off the servo signal). This is the same as a 1ms servo signal (which sets servo one to the extreme left position). After the timer exceeds 1500 (1.5ms) servo pin 2 goes low (servo two is set to the mid-position) and after the running timer exceeds 2000 (2ms) servo pin 3 goes low (setting servo three to the extreme right position).

Because the signals need to repeat every 20ms, we now have 18ms of hanging around before we reset the running timer and turn on all servo pins again.
(in fact, these 18ms are used for other processing such as receiving and processing user input, getting data from an SPI eeprom chip and so on).

Using this "parallel" method of processing the servo signals, we can have many more than just eight servos. We stopped at 20 because our PIC microcontroller has 40 pins - 4 are used for power and USB, 5 for SPI clocking an eeprom chip, a few push-button inputs, serial comms (send and receive) and we decided to leave a couple of spares.


Parallel method of controlling servo signals - all are turned on at the same time, and switched off at different times (between 0.8ms and 2.4ms after being switched on).