50 Pounds of Robot Love

Introduction

Sensor Strategies

Mechanical Design

Electrical Design

Software Design

Gems of Wisdom

About the Team

Software Design

For our project, we used both the S12E128 and S12C32 microcontrollers.  The E128 handled all sensors and decision making and the C32 controlled all actuators.  The E128 gave commands to the C32 using a Serial Peripheral Interface (SPI) datalink.

E128 Pseudocode | C32 Pseudocode

E128 Code Listing |C32 Code Listing

E128 Pseudocode

E128 Main Module | SPI-Master Module | Tape Sensor Module | Beacon Sensor Module

E128 Main Module

Main:

                Init SPI

                Init Beacon Sensors

                Init Timers

                                Enable timers

                                Set prescale to highest resolution

                Init LEDs

                                Set DDRP to outputs

                                Set PTP LO– turn all LEDs off

                Init Tape Sensors

                Init Flash Sensor

 

1.       Wait for a flash                                                                 

2.       Turn clockwise in place                                                 

3.       Check for 50% duty cycle beacon                             

4.       Stop for 1 sec once pointing at ball dispenser

5.       Drive forward blindly for 1 sec

6.       Start checking tape sensors for line hit

7.       Once line is hit, decide which side of the game board we are on

8.       Keep driving forward until robot is approximately centered over tape

9.       Turn to get onto the line

10.   Begin PI controlled line following

11.   Continue until corner of tape

12.   Rotate in place to line up rear tape sensors with the line leading towards dispenser

13.   Use PI controlled line following in reverse

14.   Stop when next to dispenser / rear tape sensors hit a line

15.   Move forward until off that line, to give room for button presser

16.   Detach front bot

17.   Front bot drives along a curved path towards goal #3 based purely on board geometry

18.   Stop

19.   Turn in place to locate 90% duty cycle beacon

20.   Once found, use the difference in strength of signal from the beacon to each of the two analog beacon sensors to drive toward 90 % beacon

21.   Continue tracking for about 10 secs; until locked in above goal #3

22.   Begin to hit the dispenser button for 1 second every 1.5 seconds.

void InitializeLEDPorts():

                Set DDRP to all ouputs

                Set PTP LO– Turn LEDs off

void IssueCommand(unsigned char device, unsigned char command):

                Transfer the device byte through SPI

                Transfer the command byte through SPI

void FollowLine(theta0, x0, direction):

                Calculate elapsed time using TCNT

                Calculate theta decay, used to limit memory

                If on inside left tape, set x = 1

                If on inside right tape, set x = -1

                If on both inside tapes, set x = 0

                If on outside left tape, x = x*2

                If on outside right tape, x = x*2

 

                If driving backwards, check if rear tape sensors are on tape. If so, stop following

                Otherwise, calculate dv, the sum of controlled compensation for heading error and for lateral error.

                Determine the duty to set each the L and R motors

void DebugLEDx (char LEDs):

                Set PTP to the byte given

unsigned char MatchBeaconDutyBW (unsigned char eye, unsigned char duty, char HiBW, char LoBW):

                If the current duty on the desired eye is within the range of duty – LoBW and duty + highBW, return true.

void Detach(void):

                Send SPI device = DETACH, command  = START_UNLATCH

                Block for a couple seconds with a timer

                Send SPI device = DETACH, command  = STOP_UNLATCH

void InitializeFlash(void):

                Set DDRT to input for flash bit

void WaitForFlash(void):

                Wait until flash bit of PTT goes HI to return

 

SPI Master – E128 Module

void SPIM_InitializeSPI(void)

                Initialize baud rate 47 kHz (256 divisor)

                Use phase 3 clock

                Set E128 to Master

                Enable slave select

                Set to normal mode

                Enable SPI

unsigned char SPIM_TransferByte(unsigned char)

                Clear the SPIF flag if it is set

                Write byteOut to SPIDR

                Wait for byte to be received

                Return the received byte

 

Tape Sensor Module

Constants

OUTSIDE_RIGHT BIT3HI

INSIDE_RIGHT BIT2HI

INSIDE_LEFT BIT1HI

OUTSIDE_LEFT BIT0HI

ALL_TAPE (BIT0HI|BIT1HI|BIT2HI|BIT3HI)

BACK_LEFT BIT4HI

BACK_MIDDLE BIT5HI

BACK_RIGHT BIT6HI

TAPE_PORT PTU

TAPE_PORT_DD DDRU

BACK_LEFT_CUTOFF 550

BACK_MID_CUTOFF 550

BACK_RIGHT_CUTOFF 550

 

void TS_InitializeTapeSensors(void)

                Set DDRU to input for tape sensors

                Initialize AD

unsigned char TS_GetTape(void)

                Return the which of the tape sensors are HI.

unsigned char TS_GetBackTape(void)

Return which analog values for the rear tape sensors are above the defined cutoffs

unsigned int TS_GetAnalogValue(char)

                Return the requested analog value

 

Beacon Sensor Module

Constants

                PERIOD_CHANGE_MAX 25

                N_HISTORY 10

void BS_OpenEyes(void)

                Init timer

                                Enable timer

                                Set to 187.5 kHz clock

                                Capture rising edges on IC4,6

                                Capture falling edges on IC5,7

                Init interrupts

                Init history

                                Set DutyHistory to all zeros

                Init AD

char BS_GetDuty(char)

                If there hasn’t been an update in 1 ms, assume the beacon is lost

                Otherwise, return either DutyLeft or DutyRight as desired

char BS_NewDutyArrived(char)

                Return true if a new duty for this sensor has been received

void BS_NewDutyHandled(char)

                Clear new duty flag for this sensor

unsigned int BS_GetAnalog(char)

                Return the analog signal strength associated with this sensor

 

void interrupt _Vec_tim0ch4 Chan1HI(void)

                Save current time as last low time

                Log change in this channel          

                Clear interrupt flag

 

void interrupt _Vec_tim0ch5 Chan1LO(void)

                Save current time as last high time

                Calculate duty from difference in last hi and last lo time

                Take the time average of the last 10 duty readings

                Log new duty received

Clear the interrupt flag

 

void interrupt _Vec_tim0ch6 Chan2HI(void)

                Save current time as last low time

                Log change in this channel          

                Clear interrupt flag

 

void interrupt _Vec_tim0ch7 Chan2LO(void)

                Save current time as last high time

                Calculate duty from difference in last hi and last lo time

                Take the time average of the last 10 duty readings

                Log new duty received

Clear the interrupt flag

C32 Pseudocode

C32 Main Module | Detach Module | DriveMotor Module | SPI Constants | SPI-Slave Module | Switch Motor Module

C32 Main Module

Main:

                Initialize SPI

                Initialize Drive Motor

                Initialize Detach Motor

                Initialize Switch Motor

                Enable Interrupts

               

                Repeat Forever:

                                Handle switch motor timer expire

                                Handle new SPI data

                                                If received byte is a device

                                                                Set current device to designated device

                                                                Available devices:

                                                                                DRIVE – Sets L/R motor directions to preset PWM

                                                                                DRIVE_LEFT_FORWARD – Sets L CW PWM

                                                                                DRIVE_LEFT_REVERSE  - Sets L CCW PWM

                                                                                DRIVE_RIGHT_FORWARD – Sets R CCW PWM

                                                                                DRIVE_RIGHT_REVERSE – Sets R CW PWM

                                                                                DETACH – Runs Detach motor CW

                                                                                RELOAD – Runs Switch motor back and forth

                                                If received byte is a command

                                                                Handle the command for the current device

                                                               

Private Functions:

                void DriveCommand:

                                Takes SPI command byte for device = DRIVE

                                Available commands:

                                                TURN_LEFT

                                                TURN_RIGHT

                                                DRIVE_STRAIGHT

                                                STOP

                                                REVERSE

                void DriveLeftForwardCommand:

                                Takes SPI command byte for device = DRIVE_LEFT_FORWARD

                                Available commands

                                                Sets Left PWM: DM_SetPWM_Left(command)

                void DriveLeftReverseCommand:

                                Takes SPI command byte for device = DRIVE_LEFT_REVERSE

                                Available commands

                                                Sets Left PWM: DM_SetPWM_Left(-command)

                void DriveRightForwardCommand:

                                Takes SPI command byte for device = DRIVE_RIGHT_FORWARD

                                Available commands

                                                Sets Left PWM: DM_SetPWM_Right(command)

                void DriveRightReverseCommand:

                                Takes SPI command byte for device = DRIVE_RIGHT_REVERSE

                                Available commands

                                                Sets Left PWM: DM_SetPWM_Right(-command)

                void DetachCommand:

                                Takes SPI command byte for device = DETACH

                                Available commands

                                                START_UNLATCH

                                                STOP_UNLATCH

                void ReloadCommand:

                                Takes any command for device = RELOAD as PRESS_BUTTON     

 

 

Detach Module

Constants:

LATCH                   PTT

UNLATCH                            BIT2HI

LATCH_STOP      ~UNLATCH

LATCHING_TIMER           0

UNLATCH_TIME               250        

Interface Functions:

                void D_Initialize()

                                Set DDRT to UNLATCH

                                Set LATCH to LATCH_STOP so robot is in one piece

                void D_Transform()

                                Set LATCH to UNLATCH—pull the latch pin high, driving the latching motor.

                void D_StopMotor()

                                Set LATCH to LATCH_STOP– pulls that pin low, stopping the motor.

 

 

DriveMotor Module

Constants:

Clock_Scale_Value 128      // post scaler.   3 MHz / (128*2)

Total_Period_Value 100                // clock cycles per PWM period

MS *750

 

RAMMING_SPEED 30

REVERSE_SPEED -30

 

INSIDE_TURNING_SPEED -30

OUTSIDE_TURNING_SPEED 30

ON 1

OFF 0

 

DIR PTAD

LEFT_FORWARD BIT0LO

RIGHT_FORWARD BIT1LO

LEFT_BACKWARD BIT0HI

RIGHT_BACKWARD BIT1HI

 

Interface Functions:

void DM_Initialize(void)

                Init AD0 and AD1 to output

                Init PWM to Clock_Scale_Value

                Stop the drive motor

void DM_UpdateMotors(char, char)

                Sets left and right duty cycles

void DM_TurnRight(void)

                Sets left to OUTSIDE_TURNING_SPEED

                Sets right to INSIDE_TURNING_SPEED

void DM_TurnLeft(void)

                Sets right to OUTSIDE_TURNING_SPEED

                Sets left to INSIDE_TURNING_SPEED

void DM_DriveStraight(void)

                Sets left and right to RAMMING_SPEED

void DM_Stop(void)

                Sets left and right to zero

void DM_Reverse(void)

                Sets left and right to REVERSE_SPEED

void DM_SetPWM_Left(char)

                Sets the left duty

void DM_SetPWM_Right(char)

                                Sets the right duty

 

 

SPI Constants Module – Shared C32 and E128

                Contains bit designations for devices and their respective commands.

               

 

SPI Slave Module – C32

Module Level Vars:

                unsigned char newData is true if new data has been received

                unsigned char byteIn stores the received byte

Interface Functions:

void SPIS_InitializeSPI(void)

                Init baud rate, clock phase, slave select

                Enable interrupts

                Enable SPI

                Read SPISR and write SPIDR

unsigned char SPIS_IsNewData(void)

                returns newData to indicate whether or not new data has been received

void SPIS_ClearDataFlag(void)

                sets newData to false to indicate that data has been handled

unsigned char SPIS_ReadByte(void)

                returns the stored byte

 

Switch Motor Module

Interface Functions:

void SM_Initialize(void)

                Enables PWM chan 3

                Sets PWM polarity to 1

                Sets PWM clock to 187.5 kHz, then post-scaled

                Ties PWM to T3

                Sets switch motor off

                Inits a 4ms timer                                              

void SM_UpdateMotor(char)

                Sets the motor duty cycle

char SM_NeedsAttention(void)

                Indicates timer expired

void SM_StartPressing(void)

                Sets state to WAS_PRESSING

                Clears expired timer

                Starts new timer

                Updates motor to forward à stalls pressing the button for 1 sec

void SM_BackOff(void)

                Sets state to WAS_REVERSING

                Clears expired timer

                Starts new timer

                Updates motor to reverse à stalls pressing against robot for 50 ms

void SM_Wait(void)

                Released motor

                Sets state to WAS_WAITING

                Clear timer

                Starts new 3 sec timer