Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "mbed.h"
- #include "TFC.h"
- #define DEBUG_ENABLED 0
- #define DERIVATIVE_DEBUG_ENABLED 0
- #define TAOS_CLK_LENGTH_DEBUG 0
- // ############################################################################################################################
- // Turning parameters
- // ############################################################################################################################
- #define SERVO_FACTOR 1.000 // overall sensitivity of servo -- high value -> maximum servo
- #define SERVO_DIFFERENCE 0.000 // turn when desired value differs more than this -- low value=update more often
- #define SERVO_TICKER_COUNT 0.000 // wait time between adjusting the servo (10.0 = 20mS = minimum
- #define DIFFERENTIAL_TURN_FACTOR 0.600 // 0.0 - 1.0 -- how much slower the inside wheel should go? -- high value=faster
- #define MOTOR_REDUCTION_FACTOR 0.100 // 0.0 - 1.0 -- how much slower should hard turns go? -- high value=faster
- #define MAX_TURN_SPEED 0.650 // all speeds will turn at same rate unless coded differently -- high value=faster
- #define MAX_SERVO 0.70 // maximum value
- #define MAX_SERVO_NEGATIVE -0.70 // negative maximum value
- // ############################################################################################################################
- // Image parsing parameters
- // ############################################################################################################################
- #define LIGHTING_CALIBRATION_TIME 200
- #define TICKER_UPDATE_COUNT 200 // was 2000 - 2mS
- #define TOTAL_PIXELS 128 // total pixels in image
- #define PIXELS_TO_MASK 4 // # pixels to disregard at each end of the image (at least 2!)
- #define CENTER_LINE_WIDTH_MINIMUM 5 // minimum pixel width for center line
- #define CENTER_LINE_WIDTH_MAXIMUM 15 // maximum pixel width for center line
- #define FINISH_LINE_WIDTH_MINIMUM 30 // minimum pixel width for finish line
- #define FINISH_LINE_WIDTH_MAXIMUM 40 // maximum pixel width for finish line
- #define HYSTERESIS_START_FACTOR 6.00 // 6x average of all derivatives - start counting as a line when >
- #define HYSTERESIS_STOP_FACTOR 1.25 // 1.5x average of all derivatives - stop counting as a line when <
- // ############################################################################################################################
- #define MIDDLE_OF_TRACK 63.5 // pixel count for the center of the track
- // ############################################################################################################################
- // for accelerometer code
- // ############################################################################################################################
- #define REG_WHO_AM_I 0x0D
- #define REG_CTRL_REG_1 0x2A
- #define REG_OUT_X_MSB 0x01
- #define REG_OUT_Y_MSB 0x03
- #define REG_OUT_Z_MSB 0x05
- #define UINT14_MAX 16383
- #define MMA8451_I2C_ADDRESS (0x1d<<1)
- #include "MMA8451Q.h"
- #include "MMA8451Q.hpp"
- // ############################################################################################################################
- //This macro is to maintain compatibility with Codewarrior version of the sample. This version uses the MBED libraries for serial port access
- Serial PC(USBTX,USBRX);
- #define TERMINAL_PRINTF PC.printf
- //This ticker code is used to maintain compability with the Codewarrior version of the sample. This code uses an MBED Ticker for background timing.
- #define NUM_TFC_TICKERS 4
- Ticker TFC_TickerObj;
- volatile uint32_t TFC_Ticker[NUM_TFC_TICKERS];
- //accelerometer
- MMA8451Q acc(PTE25, PTE24, MMA8451_I2C_ADDRESS);
- bool findDerivative();
- volatile float centerLine=-1;
- volatile int transitionCount=-1;
- volatile int stopMarkerCount=-1;
- volatile int dipSwitchValue=0;
- volatile float straitawaySpeed=0.0;
- volatile float turnSpeed=0.0;
- volatile float speedMultiplier=0.0;
- volatile float leftTurnMultiplier=0.0;
- volatile float rightTurnMultiplier=0.0;
- volatile float currentServoValue=0.0;
- volatile float appliedServoValue=0.0;
- volatile bool hbridgeEnabled=false;
- volatile bool lineIdentified=false;
- volatile bool finishMarkerIdentfied=false;
- volatile bool lineFound=false;
- volatile uint16_t * myCurrentImage;
- volatile float tickerScale;
- volatile float relativeOffsetFromCenter;
- volatile float differentialSpeedAdjustment;
- volatile float turnSpeedAdjustment;
- volatile bool button_A_Pressed=false;
- volatile bool button_B_Pressed=false;
- volatile float maxThreshold;
- volatile float minThreshold;
- volatile uint16_t averageOfDerivatives = 0;
- extern uint8_t LineScanWorkingBuffer;
- volatile uint8_t TAOS_Pulse_Width=50; //original value was 50
- volatile uint32_t lightingCalibrationTime=0;
- volatile float servoDifferenceFactor;
- volatile float servoMultiplier;
- //volatile float accelerometerX;
- //volatile float accelerometerY;
- //volatile float accelerometerZ;
- //volatile int flat=0; //flat=0, uphill=1, downhill=2
- void TFC_TickerUpdate()
- {
- int i;
- for(i=0; i<NUM_TFC_TICKERS; i++)
- {
- if(TFC_Ticker[i]<0xFFFFFFFF)
- {
- TFC_Ticker[i]++;
- }
- }
- }
- int main()
- {
- uint32_t i,j,t = 0;
- PC.baud(115200);
- tickerScale = 2000.0 / (float)TICKER_UPDATE_COUNT;
- TFC_TickerObj.attach_us(&TFC_TickerUpdate, TICKER_UPDATE_COUNT);
- TFC_Init();
- //all lights on to show calibration of lighting in progress
- TFC_BAT_LED0_ON;
- TFC_BAT_LED1_ON;
- TFC_BAT_LED2_ON;
- TFC_BAT_LED3_ON;
- #if DERIVATIVE_DEBUG_ENABLED
- lightingCalibrationTime = LIGHTING_CALIBRATION_TIME;
- #endif
- while (lightingCalibrationTime < LIGHTING_CALIBRATION_TIME) {
- if (findDerivative()) {
- lightingCalibrationTime++;
- TFC_BAT_LED2_ON;
- }
- }
- #if TAOS_CLK_LENGTH_DEBUG
- TERMINAL_PRINTF("TAOS_Pulse_Width=%d\r\n", TAOS_Pulse_Width);
- #endif
- //all lights on to show calibration of lighting has completed
- TFC_BAT_LED0_OFF;
- TFC_BAT_LED1_OFF;
- TFC_BAT_LED2_OFF;
- TFC_BAT_LED3_OFF;
- while (!TFC_PUSH_BUTTON_0_PRESSED); //wait here button A is pressed.
- while (TFC_PUSH_BUTTON_0_PRESSED); //debounce button A.
- // *******************************************
- // * Set the speed multipliers if in race mode
- // *******************************************
- turnSpeed = MAX_TURN_SPEED;
- switch(dipSwitchValue = TFC_GetDIP_Switch()) {
- case 8:
- straitawaySpeed = 0.700;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 9:
- straitawaySpeed = 0.760;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 10:
- straitawaySpeed = 0.800;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 11:
- straitawaySpeed = 0.840;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 12:
- straitawaySpeed = 0.880;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 13:
- straitawaySpeed = 0.920;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 14:
- straitawaySpeed = 0.960;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- case 15:
- straitawaySpeed = 1.000;
- //turnSpeed = (MAX_TURN_SPEED > straitawaySpeed) ? straitawaySpeed : MAX_TURN_SPEED;
- if (hbridgeEnabled == false) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- break;
- default:
- straitawaySpeed = 0.0;
- turnSpeed = 0.0;
- leftTurnMultiplier = 0.0;
- rightTurnMultiplier = 0.0;;
- if (hbridgeEnabled == true) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_DISABLE;
- hbridgeEnabled = false;
- }
- break;
- }
- while (1) {
- if (TFC_PUSH_BUTTON_0_PRESSED) { //use this button to start the state machine
- button_A_Pressed = true; //set the start flag
- button_B_Pressed = false; //clear the stop flag
- }
- if (TFC_PUSH_BUTTON_1_PRESSED) { //use this button to reset the state machine
- button_A_Pressed = false; //clear the start flag
- button_B_Pressed = true; //set the stop flag
- }
- if ((button_A_Pressed == false) || (button_B_Pressed == true)) {
- if (TFC_Ticker[0] > (int)(SERVO_TICKER_COUNT * tickerScale)) { //20mS target when 10
- TFC_SetServo(0.0);
- TFC_Ticker[0] = 0;
- }
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- if (hbridgeEnabled == true) {
- TFC_HBRIDGE_DISABLE;
- hbridgeEnabled = false;
- }
- }
- else {
- //accelerometerX = abs(acc.getAccX());
- //accelerometerY = abs(acc.getAccY());
- //accelerometerZ = acc.getAccZ();
- //if (accelerometerZ > 0.95) {
- // flat = 0;
- //}
- //else if ((flat < 2) && (accelerometerZ <= 0.95)) {
- // flat++; //do nothing first 2 passes in case it is just bumps
- //}
- //else if ((flat >= 2) && (accelerometerZ <= 0.95)) {
- // //goose the motors here - going uphill
- // wait_ms(100);
- // //slow the motors here - going downhill
- // wait_ms(250);
- // flat = 0; // expect to be going flat after going uphill and then downhill
- //}
- //else {
- // flat = 0; // now going downhill
- //}
- #if DEBUG_ENABLED
- TERMINAL_PRINTF("%7.3f\r\n", accelerometerZ);
- wait_ms(1000);
- #endif
- if (hbridgeEnabled == false) {
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- switch(dipSwitchValue) {
- // **************************************************************
- // * Demo mode 0 & unknown mode just tests the switches and LED's
- // **************************************************************
- default:
- case 0:
- if (TFC_PUSH_BUTTON_0_PRESSED) {
- TFC_BAT_LED0_ON;
- }
- else {
- TFC_BAT_LED0_OFF;
- }
- if (TFC_PUSH_BUTTON_1_PRESSED) {
- TFC_BAT_LED3_ON;
- }
- else {
- TFC_BAT_LED3_OFF;
- }
- //turn these LEDs off for demo mode 0
- TFC_BAT_LED1_OFF;
- TFC_BAT_LED2_OFF;
- break;
- // ************************************************************************
- // * Demo mode 1 will just move the servos with the on-board potentiometers
- // ************************************************************************
- case 1:
- if (TFC_Ticker[0] > (int)(20.0 * tickerScale)) {
- TFC_Ticker[0] = 0; //reset the Ticker
- //Every 20 mSeconds, update the Servos
- TFC_SetServo(TFC_ReadPot(0));
- }
- //Let's put a pattern on the LEDs
- if (TFC_Ticker[1] > (int)(125.0 * tickerScale)) {
- TFC_Ticker[1] = 0;
- t++;
- if (t>4) {
- t=0;
- }
- TFC_SetBatteryLED_Level(t);
- }
- if (hbridgeEnabled == true) {
- TFC_SetMotorPWM(0,0); //Make sure motors are off
- TFC_HBRIDGE_DISABLE;
- hbridgeEnabled = false;
- }
- break;
- // *******************************************************
- // * Demo Mode 2 will use the Pots to make the motors move
- // *******************************************************
- case 2 :
- if (hbridgeEnabled == false) {
- TFC_HBRIDGE_ENABLE;
- hbridgeEnabled = true;
- }
- TFC_SetMotorPWM(TFC_ReadPot(0),TFC_ReadPot(1));
- //Let's put a pattern on the LEDs
- if (TFC_Ticker[1] > (int)(125.0 * tickerScale)) {
- TFC_Ticker[1] = 0;
- t++;
- if (t>4) {
- t=0;
- }
- TFC_SetBatteryLED_Level(t);
- }
- break;
- // *************************************************************************************************************
- // * Demo Mode 3 will be in Freescale Garage Mode. It will beam data from the Camera to the Labview Application
- // *************************************************************************************************************
- case 3 :
- if (TFC_LineScanImageReady) {
- TERMINAL_PRINTF("\r\n");
- TERMINAL_PRINTF("L:");
- //Let's put a pattern on the LEDs
- if (TFC_Ticker[1] > (int)(125.0 * tickerScale)) {
- TFC_Ticker[1] = 0;
- t++;
- if (t>4) {
- t=0;
- }
- }
- // camera 1
- myCurrentImage = TFC_LineScanImage0;
- TFC_LineScanImageReady = 0; //only use images newer than the one I have now
- for (i=0; i<8; i++) {
- for (j=0; j<16; j++) {
- TERMINAL_PRINTF("%04d",myCurrentImage[(i*16)+j]);
- if ((i==7) && (j==15)) {
- TERMINAL_PRINTF("\r\n");
- }
- else {
- TERMINAL_PRINTF(",");
- }
- wait_ms(10);
- }
- }
- }
- break;
- // *************************************************************************************************************
- // * Demo Mode 4 will be in Freescale Garage Mode. It counts the line transitions seen by the camera
- // *************************************************************************************************************
- case 4:
- if (findDerivative()) {
- // camera 1
- switch (transitionCount) {
- case 0: TFC_BAT_LED1_OFF; TFC_BAT_LED0_OFF; break;
- case 1: TFC_BAT_LED1_OFF; TFC_BAT_LED0_ON; break;
- case 2: TFC_BAT_LED1_ON; TFC_BAT_LED0_OFF; break;
- case 3: TFC_BAT_LED1_ON; TFC_BAT_LED0_ON; break;
- default: TFC_BAT_LED1_OFF; TFC_BAT_LED0_OFF; break;
- }
- }
- break;
- // ***************************************************************************************
- // * Race modes 8-15 will have the car naviagate at varioud speeds (8-slowest, 15-fastest)
- // ***************************************************************************************
- case 8:
- case 9:
- case 10:
- case 11:
- case 12:
- case 13:
- case 14:
- case 15:
- if (findDerivative()) { //Update the track position if a new image is available
- #if DEBUG_ENABLED
- TERMINAL_PRINTF("centerLine=%4.1f, lineIdentified=%d, finishMarkerIdentfied=%d\n", centerLine, lineIdentified, finishMarkerIdentfied);
- #endif
- switch ((int)(centerLine + 0.5)) {
- case 0: case 1: case 2: case 3: //hard right
- case 4: case 5: case 6: case 7:
- case 8: case 9: case 10: case 11:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 12: case 13: case 14: case 15:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 16: case 17: case 18: case 19: // hard right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 20: case 21: case 22: case 23:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.95;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 24: case 25: case 26: case 27: // hard right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.90;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 28: case 29: case 30: case 31:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.85;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 32: case 33: case 34: case 35: // hard right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.80;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 36: case 37: case 38: case 39:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.70;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 40: case 41: case 42: case 43: // medium right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.60;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 44: case 45: case 46: case 47:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.50;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.20)) ? 0.60 : (straitawaySpeed - 0.20);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.40)) ? 0.30 : (straitawaySpeed - 0.40);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 48: case 49: case 50: case 51: // soft right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.40;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.15)) ? 0.60 : (straitawaySpeed - 0.15);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.30)) ? 0.30 : (straitawaySpeed - 0.30);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 52: case 53: case 54: case 55:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.30;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.10))? 0.60 : (straitawaySpeed - 0.010);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.20))? 0.30 : (straitawaySpeed - 0.20);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 56: case 57: case 58: case 59: // very soft right
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.20;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.05))? 0.60 :(straitawaySpeed - 0.05);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.10))? 0.30 :(straitawaySpeed - 0.10);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 60: case 61: case 62:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.10;
- leftTurnMultiplier = (0.60 > (straitawaySpeed - 0.025))? 0.60 : (straitawaySpeed - 0.025);
- rightTurnMultiplier = (0.30 > (straitawaySpeed - 0.05)) ? 0.30 : (straitawaySpeed - 0.05);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- default:
- case 63: case 64:
- currentServoValue = 0.0;
- rightTurnMultiplier = straitawaySpeed;
- leftTurnMultiplier = straitawaySpeed;
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 65: case 66: case 67:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.10;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.05)) ? 0.30 : (straitawaySpeed - 0.05);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.025))? 0.60 : (straitawaySpeed - 0.025);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 68: case 69: case 70: case 71: // very soft left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.20;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.10)) ? 0.30 : (straitawaySpeed - 0.10);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.05)) ? 0.60 : (straitawaySpeed - 0.05);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 72: case 73: case 74: case 75:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.30;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.20)) ? 0.30 : (straitawaySpeed - 0.20);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.10)) ? 0.60 : (straitawaySpeed - 0.10);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 76: case 77: case 78: case 79: // soft left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.40;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.30)) ? 0.30 : (straitawaySpeed - 0.30);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.15)) ? 0.60 : (straitawaySpeed - 0.15);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 80: case 81: case 82: case 83:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.50;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.40)) ? 0.30 : (straitawaySpeed - 0.40);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.20)) ? 0.60 : (straitawaySpeed - 0.20);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 84: case 85: case 86: case 87: // medium left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.60;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 88: case 89: case 90: case 91:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.70;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 92: case 93: case 94: case 95: // hard left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.80;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 96: case 97: case 98: case 99:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.85;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 100: case 101: case 102: case 103: // hard left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.90;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 104: case 105: case 106: case 107:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR * 0.95;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 108: case 109: case 110: case 111: // hard left
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 112: case 113: case 114: case 115:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- case 116: case 117: case 118: case 119: // hard left
- case 120: case 121: case 122: case 123: // hard left
- case 124: case 125: case 126: case 127:
- currentServoValue = relativeOffsetFromCenter * MAX_SERVO * SERVO_FACTOR;
- leftTurnMultiplier = (0.30 > (straitawaySpeed - 0.50)) ? 0.30 : (straitawaySpeed - 0.50);
- rightTurnMultiplier = (0.60 > (straitawaySpeed - 0.25)) ? 0.60 : (straitawaySpeed - 0.25);
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- break;
- }
- #if DEBUG_ENABLED
- TERMINAL_PRINTF("currentServoValue=%f, speedMultiplier=%f, leftTurnMultiplier=%f, rightTurnMultiplier=%f\n", currentServoValue, speedMultiplier, leftTurnMultiplier, rightTurnMultiplier);
- #endif
- }
- switch (transitionCount) {
- case 0: TFC_BAT_LED1_OFF; TFC_BAT_LED0_OFF; break;
- case 1: TFC_BAT_LED1_OFF; TFC_BAT_LED0_ON; break;
- case 2: TFC_BAT_LED1_ON; TFC_BAT_LED0_OFF; break;
- case 3: TFC_BAT_LED1_ON; TFC_BAT_LED0_ON; break;
- default: TFC_BAT_LED1_OFF; TFC_BAT_LED0_OFF; break;
- }
- if ((lineIdentified == true) && (finishMarkerIdentfied == false) && TFC_ServoTicker) {
- appliedServoValue = currentServoValue;
- TFC_SetServo(appliedServoValue);
- TFC_ServoTicker = 0;
- }
- else if (finishMarkerIdentfied == true) {
- //shut everything down if multiple lines are found or if I'm lost
- TFC_SetServo(0.0);
- TFC_SetMotorPWM(0.0, 0.0); // crossing start/finish so stop
- TFC_HBRIDGE_DISABLE;
- hbridgeEnabled = false;
- }
- else if (lineIdentified == false) {
- if (leftTurnMultiplier > 0.0001) {
- leftTurnMultiplier -= 0.0001;
- }
- else if (leftTurnMultiplier < -0.0001) {
- leftTurnMultiplier += 0.0001;
- }
- else {
- leftTurnMultiplier = 0.0;
- }
- if (rightTurnMultiplier > 0.0001) {
- rightTurnMultiplier -= 0.0001;
- }
- else if (rightTurnMultiplier < -0.0001) {
- rightTurnMultiplier += 0.001;
- }
- else {
- rightTurnMultiplier = 0.0;
- }
- TFC_SetMotorPWM(leftTurnMultiplier, (-1.0 * rightTurnMultiplier));
- }
- break;
- }
- }
- }
- }
- bool findDerivative() { //use divided difference method to obtain approxmation of second derivative - accelaration of change
- volatile uint8_t i;
- volatile uint8_t transitionWidth;
- volatile uint8_t countOfDerivatives = 0;
- volatile uint8_t lineDetected[TOTAL_PIXELS];
- volatile uint16_t firstTransitionValue;
- volatile uint16_t secondTransitionValue;
- volatile uint32_t sumOfDerivatives = 0;
- volatile uint16_t startOfSecondTransition;
- volatile uint16_t derivativeValues[TOTAL_PIXELS];
- volatile bool firstTransitionFound;
- volatile uint16_t * workingImagePtr;
- volatile uint16_t currentPixel;
- volatile uint16_t * derivativeValuesPtr;
- volatile uint8_t * previousPreviousLineDetectedPtr;
- volatile uint8_t * previousLineDetectedPtr;
- volatile uint8_t * currentLineDetectedPtr;
- volatile uint8_t * nextLineDetectedPtr;
- volatile uint8_t * nextNextLineDetectedPtr;
- volatile uint16_t * previousPixelPtr;
- volatile uint16_t * currentPixelPtr;
- volatile uint16_t * nextPixelPtr;
- volatile uint16_t maximumPixelValue;
- volatile uint16_t localImageBuffer[128];
- volatile uint16_t * myLocalImage;
- if (!TFC_LineScanImageReady) {
- lineFound = false;
- transitionCount = stopMarkerCount = firstTransitionValue = secondTransitionValue = 0;
- return(false);
- }
- TFC_BAT_LED2_ON;
- TFC_LineScanImageReady = 0;
- //make a copy of the image buffer before it is over-run
- for (i=0, myCurrentImage=TFC_LineScanImage0, myLocalImage=localImageBuffer; i<128; i++, myLocalImage++, myCurrentImage++) {
- *myLocalImage = *myCurrentImage;
- }
- myCurrentImage = localImageBuffer;
- transitionCount = stopMarkerCount = firstTransitionValue = secondTransitionValue = 0;
- //lower masked range now contains first valid pixel count
- for (i=0, workingImagePtr=myCurrentImage, currentPixel=myCurrentImage[PIXELS_TO_MASK], derivativeValuesPtr=&(derivativeValues[0]), currentLineDetectedPtr=&(lineDetected[0]);
- i<PIXELS_TO_MASK;
- i++) {
- *workingImagePtr++ = currentPixel; // tail values = first value of consequence
- *derivativeValuesPtr++ = 0;
- *currentLineDetectedPtr++ = 0;
- }
- //upper masked range now contains last valid pixel count
- for (i=(TOTAL_PIXELS-PIXELS_TO_MASK+1), workingImagePtr=&(myCurrentImage[TOTAL_PIXELS-PIXELS_TO_MASK+1]), currentPixel=myCurrentImage[TOTAL_PIXELS-PIXELS_TO_MASK], derivativeValuesPtr=&(derivativeValues[TOTAL_PIXELS-PIXELS_TO_MASK+1]), currentLineDetectedPtr=&(lineDetected[TOTAL_PIXELS-PIXELS_TO_MASK+1]);
- i<PIXELS_TO_MASK;
- i++) {
- *workingImagePtr++ = currentPixel; // tail values = first value of consequence
- *derivativeValuesPtr++ = 0;
- *currentLineDetectedPtr++ = 0;
- }
- if (lightingCalibrationTime < LIGHTING_CALIBRATION_TIME) { //time to average the lighting
- sumOfDerivatives = 0;
- countOfDerivatives = 0;
- maximumPixelValue = 0;
- //look at i-1 & i+1 - first check will only determine thresholds
- for (i=PIXELS_TO_MASK, lineFound=false, derivativeValuesPtr=&(derivativeValues[PIXELS_TO_MASK]), previousPixelPtr=&(myCurrentImage[PIXELS_TO_MASK-1]), currentPixelPtr=&(myCurrentImage[PIXELS_TO_MASK]), nextPixelPtr=&(myCurrentImage[PIXELS_TO_MASK+1]);
- i<(TOTAL_PIXELS-PIXELS_TO_MASK);
- i++, derivativeValuesPtr++, nextPixelPtr++, currentPixelPtr++, previousPixelPtr++) {
- *derivativeValuesPtr = abs((int)((*nextPixelPtr + *currentPixelPtr)-(*previousPixelPtr << 1)));
- sumOfDerivatives += *derivativeValuesPtr;
- countOfDerivatives++;
- if (*currentPixelPtr > maximumPixelValue) {
- maximumPixelValue = *currentPixelPtr; //find maximum pixel value to adjust camera exposure time
- }
- }
- averageOfDerivatives = (sumOfDerivatives / countOfDerivatives);
- maxThreshold = (HYSTERESIS_START_FACTOR * (float)averageOfDerivatives);
- minThreshold = (HYSTERESIS_STOP_FACTOR * (float)averageOfDerivatives);
- if ((maximumPixelValue > 4080) && (TAOS_Pulse_Width > 25)) { //target an maximum pixel value of between 3500 & 4080 to set exposure time
- TAOS_Pulse_Width--;
- }
- else if ((maximumPixelValue < 3500) && (TAOS_Pulse_Width < 250)) { //target an maximum pixel value of between 3500 & 4080 to set exposure time
- TAOS_Pulse_Width++;
- }
- }
- //look at i-1 & i+1 - subsequent checks will determine line placement
- for (i=PIXELS_TO_MASK, lineFound=false, derivativeValuesPtr=&(derivativeValues[PIXELS_TO_MASK]), previousPixelPtr=&(myCurrentImage[PIXELS_TO_MASK-1]), currentPixelPtr=&(myCurrentImage[PIXELS_TO_MASK]), nextPixelPtr=&(myCurrentImage[PIXELS_TO_MASK+1]), currentLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK]);
- i<(TOTAL_PIXELS-PIXELS_TO_MASK);
- i++, derivativeValuesPtr++, nextPixelPtr++, currentPixelPtr++, previousPixelPtr++, currentLineDetectedPtr++) {
- *derivativeValuesPtr = abs((int)((*nextPixelPtr + *currentPixelPtr)-(*previousPixelPtr << 1)));
- if (lineFound == false) {
- if (*derivativeValuesPtr > maxThreshold) {
- lineFound = true;
- *currentLineDetectedPtr = 1;
- }
- else {
- lineFound = false;
- *currentLineDetectedPtr = 0;
- }
- }
- else {
- if (*derivativeValuesPtr > minThreshold) {
- lineFound = true;
- *currentLineDetectedPtr = 1;
- }
- else {
- lineFound = false;
- *currentLineDetectedPtr = 0;
- }
- }
- }
- //join lines for glitch filtering when not in demo mode
- for (i=PIXELS_TO_MASK,
- previousPreviousLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK-2]),
- previousLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK-1]),
- currentLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK]),
- nextLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK+1]),
- nextNextLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK+2]);
- i<(TOTAL_PIXELS-PIXELS_TO_MASK);
- i++,
- previousPreviousLineDetectedPtr++,
- previousLineDetectedPtr++,
- currentLineDetectedPtr++,
- nextLineDetectedPtr++,
- nextNextLineDetectedPtr++) {
- if (*previousLineDetectedPtr && *nextLineDetectedPtr) {
- *currentLineDetectedPtr = 1;
- }
- if (*previousLineDetectedPtr && *nextNextLineDetectedPtr) {
- *currentLineDetectedPtr = 1;
- }
- if (*previousPreviousLineDetectedPtr && *nextLineDetectedPtr) {
- *currentLineDetectedPtr = 1;
- }
- }
- #if DERIVATIVE_DEBUG_ENABLED
- TERMINAL_PRINTF("%02d: ",LineScanWorkingBuffer);
- for (i=0, currentLineDetectedPtr=&(lineDetected[0]); i<TOTAL_PIXELS; i++,currentLineDetectedPtr++) {
- TERMINAL_PRINTF("%d",*currentLineDetectedPtr);
- }
- TERMINAL_PRINTF("\r\n");
- wait_ms(100);
- #endif
- lineIdentified = false;
- firstTransitionFound = false;
- //count the transitions found - should be at least 2
- for (i=PIXELS_TO_MASK, currentLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK]), previousLineDetectedPtr=&(lineDetected[PIXELS_TO_MASK-1]);
- i<(TOTAL_PIXELS-PIXELS_TO_MASK);
- i++, currentLineDetectedPtr++, previousLineDetectedPtr++) {
- if (firstTransitionFound == false) { // still in the white area
- if (!(*previousLineDetectedPtr) && *currentLineDetectedPtr){ // transition starting
- firstTransitionValue = i;
- firstTransitionFound = true; // now look for falling edge
- }
- }
- else {
- if (!(*previousLineDetectedPtr) && *currentLineDetectedPtr){ // transition starting
- startOfSecondTransition = i; // start of the second tansition - save in case nothing
- while ((i<TOTAL_PIXELS) && *currentLineDetectedPtr) {
- i++;
- currentLineDetectedPtr++;
- previousLineDetectedPtr++;
- }
- secondTransitionValue = (i - 1);
- transitionWidth = secondTransitionValue - firstTransitionValue;
- if ((transitionWidth >= CENTER_LINE_WIDTH_MINIMUM) && // Am I looking at the line?
- (transitionWidth <= CENTER_LINE_WIDTH_MAXIMUM)) {
- centerLine = (float)(firstTransitionValue + secondTransitionValue) / 2.0;
- firstTransitionFound = false;
- lineIdentified = true;
- transitionCount++;
- }
- else if ((transitionWidth >= FINISH_LINE_WIDTH_MINIMUM) && // Am I looking at one of the start markers?
- (transitionWidth <= FINISH_LINE_WIDTH_MAXIMUM)) {
- firstTransitionFound = false;
- stopMarkerCount++;
- transitionCount++;
- }
- else { // Apparently looking at nothing important - shift the looking glass
- firstTransitionValue = startOfSecondTransition;
- }
- }
- }
- }
- if (stopMarkerCount == 2) {
- finishMarkerIdentfied = true; // found the start/stop line
- }
- if (lineIdentified) {
- relativeOffsetFromCenter = (MIDDLE_OF_TRACK - centerLine)/MIDDLE_OF_TRACK;
- differentialSpeedAdjustment = abs(relativeOffsetFromCenter) * DIFFERENTIAL_TURN_FACTOR;
- turnSpeedAdjustment = abs(relativeOffsetFromCenter) * MOTOR_REDUCTION_FACTOR;
- #if DERIVATIVE_DEBUG_ENABLED
- TERMINAL_PRINTF("relativeOffsetFromCenter=%7.3f, differentialSpeedAdjustment=%7.3f, turnSpeedAdjustment=%7.3f\r\n", relativeOffsetFromCenter, differentialSpeedAdjustment, turnSpeedAdjustment);
- wait_ms(500);
- #endif
- }
- TFC_BAT_LED2_OFF;
- return(true);
- }
Advertisement
Add Comment
Please, Sign In to add comment