SSC-32 Open-Source Information: Description of SSC-32 Operation

 

The SSC-32 outputs are connected to shift registers, which are under control of an AVR ATMega8 processor running at 14.7456 MHz. Each shift register controls a bank of 8 outputs, numbered Bank 0 through Bank 3. Bank 0 contains outputs 0-7, Bank 1 contains outputs 8-15, etc. The shift registers are driven by the SPI (Serial Peripheral Interface) hardware of the ATMega8, clocked at the maximum rate of 7.3728 MHz. Every time the processor needs to change an output, it sends the byte representing an entire bank to the appropriate shift register. Using optimized assembly code, the processor is able to update the outputs as fast as every 1.5 microseconds.

The servo pulses are output one bank at a time. The 20 millisecond update period is divided as follows:

* 0.0 - 2.5 ms: Bank 0 pulses
* 2.5 - 5.0 ms: Bank 1 pulses
* 5.0 - 7.5 ms: Bank 2 pulses
* 7.5 - 10.0 ms: Bank 3 pulses
* 10.0 - 20.0 ms: no pulses

The pulse outputs are handled by an Interrupt Service Routine (ISR), so other processing can happen continuously in the background. An interrupt occurs at the beginning of a bank output interval to turn on all of the outputs that are enabled in the bank. Then, 8 more interrupts occur, one to turn off each output in the bank. If two or more edges occur very close together, they will be combined into the same interrupt. The process repeats every 20 milliseconds.

Received characters from the UART are also handled by an ISR, which places the characters into a queue for later processing. The background task removes received characters from the queue and acts upon them. As servo positions, speeds, and move times are received, they are collected into a table. When a carriage return character is received, the processor goes through the table and updates the servo target positions and speeds. The move speed for each servo is calculated so that all the servos start and end simultaneously. The following rules determine the speed of the move:

1. All servos involved in the move start and end at the same time.
2. If a speed is specified for a servo, that speed will not be exceeded during the move.
3. If a time is given for the move, then the move will take at least that long.
4. The move will be as fast as possible, without violating the first 3 rules.

In order to follow these rules, the processor looks at the current position, target position, and speed (if any) for each servo. The combination of the distance to be moved and the speed implies a time for the move, which will generally be different for each servo. In addition, there might be a time specified for the entire move. For the actual move time, the processor uses the longest time of all the times calculated. It then re-calculates the speed for each servo based on the actual move time. All of the calculations are performed using precision arithmetic, in order to minimize rounding errors.

In addition to handling received characters, the background task also updates the pulse widths for servos that are moving. It does this by adding a value to the pulse width every 20 milliseconds. This continues until the actual pulse width is equal to the target pulse width. The value added to the pulse width depends on the speed of the move; the higher the speed the faster the pulse width changes. The value added to the pulse width can be positive or negative, depending on whether the pulse width needs to increase or decrease.