|
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
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
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
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
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
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
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
Contains bit designations
for devices and their respective commands.
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
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
|