Austin Community College initial line follower program for Freescale car. This is based upon the FRDM-TFC code at mbed.org.

Dependencies:   mbed

Fork of FRDM-TFC by Eli Hughes

Austin Community College - Initial Specs for FRDM-TFC line following car.

This uses the fine library by ELI HUGHES.

Our goal here is to provide the simplest line-follower as a quick car checkout.

First, we limit the run duration for the car, so that you can catch it, if necessary. Right DIP switch (4) sets run time. 0 => 5 sec, 1 => 10 sec.

We provide simple speed selection with the other three DIP switches. I recommend 001 as the slowest real speed, (000 is stop, of course). DIP switches 1 2 3 make a 3 bit speed. 1 is msb, 3 is lsb

The car won't start until you press and release the driver's side PB. Left PB (TFC_PUSH_BUTTON_1) is permissive GO on release using left 3 DIPs for speed 0-7.

The car will stop when the passenger side PB is pressed. Right PB is STOP - TFC_PUSH_BUTTON_0

TFC_Ticker[3] is our run time counter. Like the Code Warrior edition, we use msec tickers.

Left (Driver side) trim pot 1 can be used to trim static steering servo Right trim pot 0 can be used to offset line camera

Back LED reflects drive motor status. The top three are not currently used.

Committer:
knalty
Date:
Mon Nov 11 03:04:42 2013 +0000
Revision:
5:9d36b4c896e1
Parent:
4:8a4a3fc59e57
Initial Line Following Code, Nov 10, 2013

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emh203 3:23cce037011f 1 #include "mbed.h"
emh203 3:23cce037011f 2 #include "TFC.h"
emh203 3:23cce037011f 3
knalty 5:9d36b4c896e1 4
knalty 5:9d36b4c896e1 5 /* Austin Community College Initial Specs
knalty 5:9d36b4c896e1 6
knalty 5:9d36b4c896e1 7 Left (Driver side) trimpot 1 can be used to trim static steering servo
knalty 5:9d36b4c896e1 8
knalty 5:9d36b4c896e1 9 Right trimpot 0 can be used to offset line camera
knalty 5:9d36b4c896e1 10
knalty 5:9d36b4c896e1 11 Left PB (TFC_PUSH_BUTTON_1) is permissive GO using left 3 DIPs for speed 0-7
emh203 3:23cce037011f 12
knalty 5:9d36b4c896e1 13 Right DIP switch (4) sets run time. 0 => 5 sec, 1 => 10 sec.
knalty 5:9d36b4c896e1 14 DIP switches 1 2 3 make a 3 bit speed. 1 is msb, 3 is lsb
knalty 5:9d36b4c896e1 15 TFC_Ticker[3] is our run time counter
knalty 5:9d36b4c896e1 16
knalty 5:9d36b4c896e1 17 Right PB is STOP and CENTER_SERVO. TFC_PUSH_BUTTON_0
emh203 3:23cce037011f 18
knalty 5:9d36b4c896e1 19 Back LED reflects drive motor status
knalty 5:9d36b4c896e1 20
knalty 5:9d36b4c896e1 21 */
knalty 5:9d36b4c896e1 22
knalty 5:9d36b4c896e1 23
knalty 5:9d36b4c896e1 24 //This ticker code is used to maintain compability with the Codewarrior version of the sample.
knalty 5:9d36b4c896e1 25 // This code uses an MBED Ticker for background timing.
knalty 5:9d36b4c896e1 26
emh203 3:23cce037011f 27 //This ticker code is used to maintain compability with the Codewarrior version of the sample. This code uses an MBED Ticker for background timing.
emh203 3:23cce037011f 28
emh203 3:23cce037011f 29 #define NUM_TFC_TICKERS 4
emh203 3:23cce037011f 30
emh203 3:23cce037011f 31 Ticker TFC_TickerObj;
emh203 3:23cce037011f 32
emh203 3:23cce037011f 33 volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
emh203 3:23cce037011f 34
emh203 3:23cce037011f 35 void TFC_TickerUpdate()
emh203 3:23cce037011f 36 {
emh203 3:23cce037011f 37 int i;
emh203 3:23cce037011f 38
emh203 3:23cce037011f 39 for(i=0; i<NUM_TFC_TICKERS; i++)
emh203 3:23cce037011f 40 {
emh203 3:23cce037011f 41 if(TFC_Ticker[i]<0xFFFFFFFF)
emh203 3:23cce037011f 42 {
emh203 3:23cce037011f 43 TFC_Ticker[i]++;
emh203 3:23cce037011f 44 }
emh203 3:23cce037011f 45 }
emh203 3:23cce037011f 46 }
emh203 3:23cce037011f 47
emh203 3:23cce037011f 48
emh203 3:23cce037011f 49
emh203 3:23cce037011f 50
emh203 3:23cce037011f 51
knalty 5:9d36b4c896e1 52 int main(void)
knalty 5:9d36b4c896e1 53 {
knalty 5:9d36b4c896e1 54 uint32_t i=0;
knalty 5:9d36b4c896e1 55 uint32_t MaxRunTime;
knalty 5:9d36b4c896e1 56 uint8_t Motor_ON;
knalty 5:9d36b4c896e1 57 float Motor_Speed;
knalty 5:9d36b4c896e1 58 float Servo_Position; // -1.0 .. +1.0
knalty 5:9d36b4c896e1 59 float Servo_Offset; // -1.0 to +1.0
knalty 5:9d36b4c896e1 60 float Camera_Offset;
knalty 5:9d36b4c896e1 61 uint8_t Start_PB_Pressed; // flag to detect release of Start_PB
knalty 5:9d36b4c896e1 62 uint8_t DIP_Speed;
knalty 5:9d36b4c896e1 63 uint8_t scratch;
knalty 5:9d36b4c896e1 64 uint16_t Current_Location;
knalty 5:9d36b4c896e1 65 uint16_t Current_Min;
knalty 5:9d36b4c896e1 66 float DarkSpot;
knalty 5:9d36b4c896e1 67
knalty 5:9d36b4c896e1 68 // Initialization
knalty 5:9d36b4c896e1 69
knalty 5:9d36b4c896e1 70 TFC_Init();
knalty 5:9d36b4c896e1 71 TFC_TickerObj.attach_us(&TFC_TickerUpdate,1000);
knalty 5:9d36b4c896e1 72
knalty 5:9d36b4c896e1 73 TFC_HBRIDGE_DISABLE; // Explicitly turn off motor
knalty 5:9d36b4c896e1 74 TFC_SetMotorPWM(0.0, 0.0 ); // Explicitly zero motor setpoints
knalty 5:9d36b4c896e1 75 TFC_SetServo(0, 0.0); // Explicitly center steering servo
knalty 5:9d36b4c896e1 76 Motor_ON = 0;
knalty 5:9d36b4c896e1 77 Motor_Speed = 0;
knalty 5:9d36b4c896e1 78 Start_PB_Pressed = 0;
knalty 5:9d36b4c896e1 79 Servo_Position = 0.0;
knalty 5:9d36b4c896e1 80 TFC_BAT_LED0_OFF;
knalty 5:9d36b4c896e1 81 TFC_BAT_LED1_OFF;
knalty 5:9d36b4c896e1 82 TFC_BAT_LED2_OFF;
knalty 5:9d36b4c896e1 83 TFC_BAT_LED3_OFF;
knalty 5:9d36b4c896e1 84 DIP_Speed = 0;
knalty 5:9d36b4c896e1 85 TFC_Ticker[3] = 0; // clear run timer
knalty 5:9d36b4c896e1 86
knalty 5:9d36b4c896e1 87 // Main Event Loop
knalty 5:9d36b4c896e1 88
knalty 5:9d36b4c896e1 89 for(;;)
knalty 5:9d36b4c896e1 90 {
knalty 5:9d36b4c896e1 91
knalty 5:9d36b4c896e1 92 //TFC_Task coordinates with communications and periodic interrupt routines
knalty 5:9d36b4c896e1 93
knalty 5:9d36b4c896e1 94 // TFC_Task();
knalty 5:9d36b4c896e1 95
knalty 5:9d36b4c896e1 96 // check for stop button pressed
knalty 5:9d36b4c896e1 97
knalty 5:9d36b4c896e1 98 if (TFC_PUSH_BUTTON_0_PRESSED)
knalty 5:9d36b4c896e1 99 {
knalty 5:9d36b4c896e1 100 TFC_HBRIDGE_DISABLE; // Explicitly turn off motor
knalty 5:9d36b4c896e1 101 TFC_SetMotorPWM(0.0, 0.0 ); // Explicitly zero motor setpoints
knalty 5:9d36b4c896e1 102 TFC_SetServo(0, 0.0); // Explicitly center steering servo
knalty 5:9d36b4c896e1 103 Motor_ON = 0;
knalty 5:9d36b4c896e1 104 Motor_Speed = 0.0;
knalty 5:9d36b4c896e1 105 Start_PB_Pressed = 0;
knalty 5:9d36b4c896e1 106 Servo_Position = 0.0;
knalty 5:9d36b4c896e1 107 TFC_BAT_LED0_OFF; // turn off motor power indicator LED
knalty 5:9d36b4c896e1 108 TFC_BAT_LED1_OFF;
knalty 5:9d36b4c896e1 109 TFC_BAT_LED2_OFF;
knalty 5:9d36b4c896e1 110 TFC_BAT_LED3_OFF;
knalty 5:9d36b4c896e1 111
knalty 5:9d36b4c896e1 112 }
knalty 5:9d36b4c896e1 113
knalty 5:9d36b4c896e1 114 // read trimpots to establish servo and camera offsets
knalty 5:9d36b4c896e1 115
knalty 5:9d36b4c896e1 116 Camera_Offset = TFC_ReadPot(0); // returns -1.0 to 1.0
knalty 5:9d36b4c896e1 117 Servo_Offset = TFC_ReadPot(1); // returns -1.0 to 1.0
knalty 5:9d36b4c896e1 118
knalty 5:9d36b4c896e1 119 // read SW4 and update MaxRunTime
knalty 5:9d36b4c896e1 120
knalty 5:9d36b4c896e1 121 if (TFC_GetDIP_Switch() & 8) MaxRunTime = 10000; else MaxRunTime = 5000; // 10 sec, or 5 sec
knalty 5:9d36b4c896e1 122
knalty 5:9d36b4c896e1 123 // check run status, and turn off motors if run time exceeded
knalty 5:9d36b4c896e1 124
knalty 5:9d36b4c896e1 125 if (Motor_ON == 0) TFC_Ticker[3] = 0; // clear run timer
knalty 5:9d36b4c896e1 126 else if(TFC_Ticker[3] > MaxRunTime)
knalty 5:9d36b4c896e1 127 {
knalty 5:9d36b4c896e1 128 TFC_HBRIDGE_DISABLE; // Explicitly turn off motor
knalty 5:9d36b4c896e1 129 TFC_SetMotorPWM(0.0, 0.0 ); // Explicitly zero motor setpoints
knalty 5:9d36b4c896e1 130 TFC_SetServo(0, 0.0); // Explicitly center steering servo
knalty 5:9d36b4c896e1 131 Motor_ON = 0;
knalty 5:9d36b4c896e1 132 Motor_Speed = 0.0;
knalty 5:9d36b4c896e1 133 Start_PB_Pressed = 0;
knalty 5:9d36b4c896e1 134 Servo_Position = 0.0;
knalty 5:9d36b4c896e1 135 TFC_BAT_LED0_OFF; // turn off motor power indicator LED
knalty 5:9d36b4c896e1 136 TFC_BAT_LED1_OFF;
knalty 5:9d36b4c896e1 137 TFC_BAT_LED2_OFF;
knalty 5:9d36b4c896e1 138 TFC_BAT_LED3_OFF;
knalty 5:9d36b4c896e1 139 }
knalty 5:9d36b4c896e1 140
knalty 5:9d36b4c896e1 141 //check for the start button (1) pressed, then released.
knalty 5:9d36b4c896e1 142
knalty 5:9d36b4c896e1 143 if (TFC_PUSH_BUTTON_1_PRESSED) Start_PB_Pressed = 1;
knalty 5:9d36b4c896e1 144 if ((!TFC_PUSH_BUTTON_1_PRESSED) & (Start_PB_Pressed)) // Falling edge detected
knalty 5:9d36b4c896e1 145 {
knalty 5:9d36b4c896e1 146 TFC_BAT_LED0_ON; // turn on back LED
knalty 5:9d36b4c896e1 147 scratch = TFC_GetDIP_Switch(); // read DIP switches for initial speed
knalty 5:9d36b4c896e1 148 DIP_Speed = 0;
knalty 5:9d36b4c896e1 149 if (scratch & 1) DIP_Speed += 4; // SW1
knalty 5:9d36b4c896e1 150 if (scratch & 2) DIP_Speed += 2; // SW2
knalty 5:9d36b4c896e1 151 if (scratch & 4) DIP_Speed += 1; // SW3
knalty 5:9d36b4c896e1 152 Motor_Speed = 0.125*DIP_Speed; // scale 0..7 to 0.0 .. 0.875
knalty 5:9d36b4c896e1 153
knalty 5:9d36b4c896e1 154 Motor_ON = 1; // set flag used by run duration logic
knalty 5:9d36b4c896e1 155 TFC_SetMotorPWM(Motor_Speed, Motor_Speed); // acts like Motor_Speed is zero
knalty 5:9d36b4c896e1 156 TFC_HBRIDGE_ENABLE; // enable motors
knalty 5:9d36b4c896e1 157 }
knalty 5:9d36b4c896e1 158
knalty 5:9d36b4c896e1 159 // scan through the camera array, and find smallest value in the zone 32..96
knalty 5:9d36b4c896e1 160
knalty 5:9d36b4c896e1 161 if(Motor_ON)
knalty 5:9d36b4c896e1 162 {
knalty 5:9d36b4c896e1 163 Current_Min = TFC_LineScanImage0[32]; // TFC_LineScanImage0
knalty 5:9d36b4c896e1 164 Current_Location = 32;
knalty 5:9d36b4c896e1 165 for (i=32;i<96;i++)
knalty 5:9d36b4c896e1 166 {
knalty 5:9d36b4c896e1 167 if(TFC_LineScanImage0[i] < Current_Min)
knalty 5:9d36b4c896e1 168 {
knalty 5:9d36b4c896e1 169 Current_Min = TFC_LineScanImage0[i];
knalty 5:9d36b4c896e1 170 Current_Location = i;
knalty 5:9d36b4c896e1 171 }
emh203 3:23cce037011f 172 }
knalty 5:9d36b4c896e1 173
knalty 5:9d36b4c896e1 174 DarkSpot = (64.0 - Current_Location)*0.02; // gain will need to be played with.
knalty 5:9d36b4c896e1 175
knalty 5:9d36b4c896e1 176 Servo_Position = DarkSpot + Servo_Offset + Camera_Offset;
knalty 5:9d36b4c896e1 177 TFC_SetServo(0,Servo_Position);
knalty 5:9d36b4c896e1 178 }
knalty 5:9d36b4c896e1 179
emh203 3:23cce037011f 180 }
emh203 3:23cce037011f 181 }