Home Publications
Section 4 - System Controller PDF Print E-mail
Written by Michael   
Thursday, 11 June 2009 16:08

4.0 System Controller

4.1 Design

Due to the servos in the pan and tilt unit requiring defined signals to operate some form of digital controller was required. The system also called for some form of control to be possible from a host PC.

Initially experiments were carried out with a PIC microcontroller with a program written by Dr Jim Herd to drive the servo signals. The PIC would take 6bit commands and drive up to 4 servos. Commands came from a test program written in C++ which interfaced with the PIC through a USB Brick. The way the PIC software worked was, it would check which servo was addressed in the command and then delay between 1-2ms and then wait 18ms. The problem with this approach was that only one servo could be addressed at a time. Therefore there would be a slight delay between the pan servo finishing a move and the tilt servo starting a move. This produced a slow pan/tilt unit which was not acceptable. After upgrading a personal computer to the latest version of Microsoft Windows, Named Vista, it was discovered that the PC driver for the USB brick was not compatible with Vista. Other initiations of the brick were limited software support and only 16 control lines meant another solution was researched.

Through research of servo control methods, some prewritten Verilog code was located[xxi] which would drive the servos through an FPGA. This meant that two blocks could be created to drive the two servos simultaneously, and also a control system could be implemented on one piece of hardware. The Cyclone II FPGA was available within the department and this was chosen as the target for the control system.

The code required several modifications. The initial was that the clock speed in the code was originally 25MHz however the Cyclone II was configured to run at 50MHz. To change this, the value of clock divisions was changed from 98 to 195. The control to these blocks came from a serial module however this was changed so that desired position was input into the block and a strobe line to perform the move.

RC Servo Drive Module

Figure 19 - RC Servo Drive Module

Code was also found from the same source that implemented an RS232 decoder meaning characters could be sent from a controlling computer to the FPGA command unit. This code too required a small change, however this only needed the new data line to be brought outside the module so that the other blocks would know when a command had been received. The block was setup to receive at 115200 baud, 8bits, no parity and 1 stop bit.

4.2 Command Set

Since commands were transferred over the link using 8 bit commands, it was decided to use this as the command size for the controller, since it would avoid any complex systems to join received commands together. A simple 8 bit command set was devised, using bits 0 and 1 of the received data as the command code. The four options (00, 01, 10, 11) each having an assigned function. Initially command 01 and 10 set the pan and tilt servo positions respectively to the values in bits 2 to 7. This however only used 6bits of accuracy in servo positions, which wasn’t enough. Command 00 was therefore implemented with a sub-command being bits 2 & 3. The four combinations of the subcommand set the lower 4 bits and upper 4 bits of the pan and tilt servos. Meaning a pan move would take two commands to perform.

The command DoMove is used to make the servo drive blocks update their position from the desired position register. This means that you can make the servo perform the move once you have finished setting up the servo positions, since this requires multiple commands. The Command DoCommand is simple a waste time command whose only purpose is to create a second NewData pulse in the system to perform the command previously set.

To set the x (pan) servo to position would mean 10010111 sending commands 01110000 and 10010100.


4.3 Circuit Schematic

Complete Schematic of Controller

Figure 20 – Complete Schematic of Controller

 

The inputs of the circuit are the RS232 transmit and receive lines (trans and recei above) which provide the inputs into the serial decoder block. The other input is the clock of 50MHz, required to synchronise the circuit and also decode the time dependant serial signals. The serial decoder module has the ability to return data on the serial bus however this is not implemented in the circuit at the present time. The main outputs are the X and Y servo signal lines, the modulation data output (to modulator) and the modulator enable line. The values of the X and Y servos are output to a string of LEDs on the Cyclone II board for debugging.

4.4 Operation of Blocks

4.4.1 Serial Module

 

Purpose:

Takes the raw digital stream from the UART chip and converts the serial data to parallel (8bits). Also signals when new data has been received.

Inputs:

· RxD

· Clk

· GPin

® Receive line from the UART chip

® Clock line to time the operation

® Data to be transmitted when data received (Not Used)

Outputs:

· Txd

· GPout

· NewData

® Transmit line from the UART chip (Not Used)

® Data received in parallel format

® Flag to signal that new data has been received

Block was prewritten[xxii] and uses two other Verilog files, called async_transmitter and async_receiver. These are the files that contain the main code that strip out the data for transmitting and receiving data on the serial port. It is essential these two files are in the same folder as the SerialModule file. To function correctly the files need to know the speed of the serial port (baud rate) and also the clock speed of the chip. The baud rate and clock speed is set inside the files as parameters. The operation of the async files is not discussed here but is available at the reference above. The SerialModule simply waits for data to be received and transmits a response back. In the circuit the response is always 0 as its not implemented. A slight modification was made to bring the NewData line outside the module.

4.4.2 Servo Driver

Purpose:

Takes a desired position and sets up a pulse to drive a servo motor.

Inputs:

· DesiredPos

· Clk

· Change

® The desired position of the servo (8bits)

® Clock

® Update the servo position to the desired position

Outputs:

· RCservo_pulse

· Position

® Pulse stream to servo control line

® Current position of the servo

Again block was prewritten and needed modification. A full listing and description is available from the sourcexxi. The pulse length varies between 1ms + (position*3.9uS), the tick count is used to generate the 3.9uS delay. This required modification to work under the 50Mhz clock. The parameter ClockDiv was set to 196 and the pulse count register was extended to prevent it overflowing. The RS232 part of the code was removed and the perform change signal was implemented. The position data was brought inside and out the module as a number of registers.

4.4.3 Command Decoder

Purpose:

Decodes commands received on serial port and performs the desired action on the outputs.

Inputs:

· CommIn

· Clk

· DataAv

® The 8 bit input command received from serial block

® Clock

® Flag that new data has been receiver (From Serial)

Outputs:

· LaserEn

· Xpos

· Ypos

· DoMove

· ModData

· ModEnable

® Former LaserEn line, Now Output3

® Desired position of X (pan) servo

® Desired position of Y (tilt) servo

® Signal to move servos to desired position

® 6bit data to modulate by PIC

® Line to enable the pic modulator

The function of this block is to take the 8 bits that have been output from the SerialModule and strip out the command bits to determine which command is being addressed from Table 2 above. It performs this on the rising edge of the DataAv line from the SerialModule.

The way it performs this is by using a number of multiple nested switch-case statements. The first (outermost) switch determines what bits 1 and 0 are. If they are 00 (8bit servo position) then it uses another switch to determine which nibble of which servo is being addressed using bits 3 and 2 of the original CommIn data. The command ‘other commands’ also uses a nested switch statement. The concept is best illustrated in the pseudo code on the next page.

During the development stage it was discovered that the commands wouldn’t decode properly, in fact what would happen was that it would take a second command to perform the action of the first and then the third would perform the action of the second. This is believed to be a problem with the timing of the commands, and likely caused when the multiple commands execute at once. To solve this problem a wasted command was used which performed no action. Other methods were also employed to solve this such as a state machine which extended the length of the DataAv signal from the SerialModule to 5 clock periods. This implementation works and is available on the attached CD, “xyservo3” project. Since time was limited, it was not possible to develop this version further and the simpler implementation of the extra command was used.

 

4.5 Command Decoder Pseudocode

7654|32|10 <- Bit Number
CommIn = xxxx|xx|xx

On positive edge of NewData signal… Do the following

If (bit1 & bit0 is 00) Command is 8bit servo positions so check next 2 bits…

If (bit3 & bit2 is 00) set lower 4 bits of desired X position to (bit7 to 4)

If (bit3 & bit2 is 01) set upper 4 bits of desired X position to (bit7 to 4)

If (bit3 & bit2 is 10) set lower 4 bits of desired Y position to (bit7 to 4)

If (bit3 & bit2 is 11) set lower 4 bits of desired Y position to (bit7 to 4)

If (bit1 & bit0 is 01) Command is move both servos (6bits)…..

Set Upper 6 bits of desired X & Y position to (bit 7 to 2)

If (bit1 & bit0 is 10) Command is set modulator data (6bits)…..

Set Upper 6 bits of desired X & Y position to (bit 7 to 2)

If (bit1 & bit0 is 11) Command is another command so check remaining 6bits…..

If (bit7 to 2 is 000000) set output3 to be LOW

If (bit7 to 2 is 000001) set output3 to be HIGH

If (bit7 to 2 is 000010) add one to the desired X servo position

If (bit7 to 2 is 000011) subtract one from the desired X servo position

If (bit7 to 2 is 000100) subtract one from the desired Y servo position

If (bit7 to 2 is 000101) add one to the desired Y servo position

If (bit7 to 2 is 000110) set modulator enable line to be LOW

If (bit7 to 2 is 000111) set modulator enable line to be LOW

If (bit7 to 2 is 111110) Do nothing

If (bit7 to 2 is 111111) Set servo position to desired position

End


4.6 Test Program

4.6 1 GUI

 

In order to verify the operation of the controller and test the commands, a test program was designed in Borland C++ Builder. With this program all the commands could be sent over the serial link to the controller.

Test Program GUI

Figure 21 - Test Program GUI

 

Once of the main features of the program is the grey square. By clicking activate scan, the user can move the mouse over the area to move the head to any position within the 8bit range of the servos. To send this data requires four 8 bit commands.

Using the slider bar in the middle a value can be sent to the PIC microcontroller which is modulated into a RC5 command as the data bits. The Enable and Disable buttons simple enable and disable the modulation line. The Out3 button is used to turn output 3 on the FPGA on or off. This was originally used to turn the laser on and off in initial development, however when the method was switched to IR, the line in the wiring had to be used for the IR circuit.

The X and Y servo positions can be set roughly to any value within the range of travel to a resolution of 6 bits. This operation is performed in a single 8 bit command. The move left, right, up and down buttons all simply add or subtract 1 from the current coordinate position.

Since the program was used on multiple systems using different COM ports, initially upon starting up, the program attempts to open COM port 1. If this is unsuccessful then it attempts to open COM port 2. If this again is unsuccessful an error message is displayed. A Fully commented listing of the program is available on the attached CD. The main functions and operation is discussed below.

4.6.2 Main Functions

 

FormLoad

This is the function that runs when the program is first opened. The purpose of this function is to open the COM port at the specified speed. First it tries to open COM1, if this is unavailable, it opens COM2.

SendCommand

This command takes an integer value passed to it and converts it to a char and then writes this char to the serial port. It is converted to a char as these are 8 bits and is what the serial port writing function requires. After the command has been written the DoCommand value is sent. No check is made if the value passed is greater than the max (255) however this will produce an error when the program attempts to cast a number greater than 255 (Maximum value of a char).

ModData

This function sets up the modulation data command using a modulation value that is passed to it, and then writes this value to the serial port. The modulation value is shifted 4 bit places to the left and then 2 (10bin­) is added to it for the command number. A DoCommand then follows. The FPGA then outputs this value to the PIC.

Move

The purpose of this function is to move both servos to a 6 bit position (0 to 63). The function sets up the command and sends it, followed by a MoveServos command to actually perform the move. The position value is shifted 4 bit places to the left and then 1 (01bin­) is added to it for the command number.

MoveAccurately

This function sends 5 commands on the serial port to move the servos to a specified position with 8 bit accuracy. To do this is sends the 4 nibbles of the two 8bit positions (X&Y) one by one by setting up the commands using bit shifting and addition of the command numbers. See command table or commented code for further information.

 

Example of X position = 10010111, Upper Nibble = 1001, Lower Nibble = 0111.

Upper 4 bits of X position command = 0100 = 4 decimal
Lower 4 bits of X position command = 0000 = 0 decimal

1st command to send: shift upper nibble (1001) four places to the left = 1001 0000

now add command value (0100 for upper) = 1001 0100
now send command.

2nd command to send: shift lower nibble (0111) four places to the left = 0111 0000

now add command value (0000 for upper) = 0111 0000
now send command.
Now send MoveServos command.

ScanButtonClick

This function is executed when the user clicks on the button which says “Activate Scan” or “Deactivate Scan” depending upon the current state. Its purpose is to either enable or disable the automatic movement which occurs when the user pans their mouse over the grey scan area shape.

ScanAreaMouseMove

This is the function that is called every time the user hovers the mouse over the scan area. The function is passed the coordinates of the mouse relative to the shapes top left corner as X and Y. The shape has been deliberately set to 255 pixels high and 255 wide, the same as the number of positions possible with the servos. This means every pixel uniquely defines a coordinate position possible with the pan and tilt head. Since the origin of the shape is top left, and the origin of the servos is the top right, the x-position is calculated at 255-X. The function, if activated will perform a servo move to position ( (255-X) , (Y) ) and update the caption below the shape to display the current position.

ModValueBarChange

This function is called when the Modulation Value slider bar changes value. This function simply updates the label below showing which value has been selected.

AutoMoveButtonClick

This function is called when the AutoMove button is clicked. Its function is to enable or disable the automatic movement of the servos depending upon the position of the slider. When disabled the user needs to click the Move servos button. Clicking the button inverts the current state.

XYPosBarChange

This function is called when the XY Position slider bar changes value. If automove is enabled then it automatically sends the move command to the servos to move both servos to a rough 6 bit position.

Rest of ButtonClick functions

The remaining functions are all functions called when a button is clicked. They set the modulation value, enable/disable the modulation, move both servos, move a servo one position, enable/disable the output3 and exit the program. See program for more information.

 


Last Updated on Friday, 17 July 2009 20:43
 
User Rating: / 0
PoorBest      
Copyright © 2012 Michael-Jones.name. All Rights Reserved.