Development Board: Servo "Ranger"

servo_motor_dc

Overview

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.

 

Circumstances that could lead to errors

Any number of possibilities could result in a packet validation error, such as:

  • Noise on UART interface.
  • Dedicated Servo Controller doing something else during a packet reception.
  • Noise generated from Servo operation.
  • Slow/buggy code (such as incorrect context saving).

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').

 

The "Ranger"

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:

Servo_Ranger

Over 900,000 packets (P) have been sent - a single error (E) is yet to occur.

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)

 

Swordfish Program

 

And the source code itself. Note the use of the potentiometers - my new favorite way to do business!

Swordfish Program: Servo "Range Finder"
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.

Forum Activity

Member Access