
To ensure my Dedicated Servo Controller worked and was stable, I made a Servo "Ranger" program. It's a dual purpose design (discussed later) that allows the user to control 8 servos via two potentiometers.
One potentiometer selects the servo, and the other sets the position. While there are 8 servos to choose from, there is a 9th mode which displays both the total number of packets sent and the total number of errors that have occurred. An error occurs if the value "1" is not returned from the Dedicated Servo Controller after a packet has been transmitted.
Any number of possibilities could result in a packet validation error, such as:
Most of the above possibilities will result in ambiguous UART data being received. Before the Dedicated Controller will update servo positions, the entire packet must pass a checksum. Each servo position is XORd together, then compared with the pre-calculated checksim. A failure will result in the controller sending back a "0" (which simply means 'bad packet'). If the packet passes the validation, then a "1" is returned ('good packet').
This project was really a dual purpose. As the name suggests (Servo Ranger), the program allows full control of a servo to "test" deflection angles. This is handy for discovering both the limitations and any linearization errors a servo may have. This is probably the long term role for this little board, so the project was named after it.
What does the rest of this article have to do with the Servo Ranger? The ranger checks every packet transmission and ensures the Dedicated Controller returns a "1". Any failures are clocked and displayed in mode 9 (as mentioned earlier). The project was not intended for long term use, rather for a real life crunch test on the dedicated controller, hence the open-board design below. I left it running for a couple of hours to see how stable the program was - Here's a picture after that time:

As shown in the picture, over 900,000 packets have been transmitted. There were no errors recorded in that time frame, nor has there been an error in the 12+ hours I thought I would leave it on for.
A brief video of the project in operation:
(video of project not uploaded as yet)
And the source code itself. Note the use of the potentiometers - my new favorite way to do business!
Device = 18F2620 Clock = 32 Config OSC = INTIO67, MCLRE = OFF #option LCD_DATA = PORTB.0 #option LCD_RS = PORTB.4 #option LCD_EN = PORTB.5 Include "IntOSC8PLL.bas" Include "USART.bas" Include "ADC.bas" Include "CONVERT.bas" Include "LCD.bas" // define valid servo range Const Servo_Min = 600 Const Servo_Max = 2400 Const InitialPosition = 1000 Dim Servo(8) As Word, curServo As Word, curPosition As Word, Errors As Byte, TotalErrors As LongWord, TotalPackets As LongWord, ScreenRefresh As Boolean // function that samples the Mode potentiometer and returns the desired decoded value Function GetServoIndex() As Word Dim Segments, i As Byte Result = ADC.ReadMedian(1) // split the 10 bit ADC resolution into known segments for the array Segments = 1023 / 9 // determine where the ADC result lies throughout the segments & return the desired array value i = 0 Repeat If Result <= ((i+1) * Segments) Then Break EndIf Inc(i) Until i = 8 Result = i End Function Function GetServoPosition() As Word Dim tmpLongWord As LongWord Result = ADC.ReadMedian(0) tmpLongWord = Result * (Servo_Max-Servo_Min) Result = tmpLongWord / 1023 + Servo_Min End Function Sub RefreshLCD() LCD.WriteAt(1,1,"S: E: ") LCD.WriteAt(2,1,"Pos: ") ScreenRefresh = False End Sub Sub SendServoPositions() Dim CRC As Word Dim i As Byte // send header USART.Write(255,255) // send each servo position For i = 0 To 7 USART.WriteByte(Servo(i).byte0) USART.WriteByte(Servo(i).byte1) Next // calculate and send CRC CRC = 0 For i = 0 To 7 CRC = CRC Xor Servo(i) Next USART.WriteWord(CRC) Inc(TotalPackets) If TotalPackets = 1000000 Then TotalPackets = 0 EndIf End Sub // update all 8 servo positions Sub InitialiseServos() Dim i As Byte For i = 0 To 7 Servo(i) = InitialPosition Next End Sub Sub CheckControls() curServo = GetServoIndex If curServo 8 Then curPosition = GetServoPosition Servo(curServo) = curPosition EndIf End Sub Sub UpdateDisplay() If curServo 8 Then If ScreenRefresh Then RefreshLCD EndIf LCD.WriteAt(1,3,DecToStr(curServo,1)) LCD.WriteAt(2,5,DecToStr(curPosition,4)) LCD.WriteAt(1,7,DecToStr(Errors,2)) Else ScreenRefresh = True LCD.WriteAt(1,1,"P:",DecToStr(TotalPackets,6)) LCD.WriteAt(2,1,"E:",DecToStr(TotalErrors,6)) EndIf End Sub Sub CheckForConfirmation() If Not USART.WaitForTimeout(1,5) Then Inc(Errors) If Errors = 100 Then Errors = 0 EndIf Inc(TotalErrors) If TotalErrors = 1000000 Then TotalErrors = 0 EndIf EndIf End Sub // Enable PLL OSCTUNE.6 = 1 // initialize program USART.SetBaudrate(br38400) ADCON1 = %00001101 ADCON2 = %10101111 LCD.WriteAt(1,1,"Servo ") LCD.WriteAt(2,1," Ranger") DelayMS(2000) LCD.WriteAt(1,1,"By ") LCD.WriteAt(2,1," Mitchy") DelayMS(2000) LCD.Cls InitialiseServos Errors = 0 TotalErrors = 0 TotalPackets = 0 RefreshLCD // main program loop While True CheckControls SendServoPositions CheckForConfirmation UpdateDisplay Wend
Download the Swordfish program and Gerber files here: Servo Ranger Source Files
Thoughts comments and feedback are more then welcome.