Made code public
Dependencies: MPU6050IMU_1 TSL1401CL_1 mbed
main.cpp
- Committer:
- yxyang
- Date:
- 2017-05-30
- Revision:
- 0:ba0a5e86259f
File content as of revision 0:ba0a5e86259f:
/* * A sample path following program for the Zumy board. * Author: Galen Savidge * * Behavior: * Zumy follows the edge of the line until no line is found for LINE_END_TIME * cycles. Line position is recorded every frame as an 8 bit unsigned int. The * general area of the line is shown on the 4 LEDs on the mbed board. If a line * is not found all 4 LEDs are turned on. The Zumy stops and ine position data * is output to serial once the end of the track is reached. */ #include "TSL1401CL.h" #include "mbed.h" /***** Constants ******/ #define CAM_INTEGRATION_TIME 80 // Higher line threshold -> the sensor will only recognize larger changes in // brightness as a line edge #define LINE_THRESHOLD 000 #define LINE_PRECISION 2 #define LINE_CROP_AMOUNT 4 // These constants define the base pwm across the motors and how much the // controller // adjusts based on position of the line relative to the sensor #define SPEED_PWM 0.25 #define TURN_SENS_INNER 1.5F #define TURN_SENS_OUTER 0.5F // Defines data #define LINE_HIST_SIZE 12000 #define RETRACT_START_TIME 50 #define LINE_END_TIME 1000 #define SMOOTHING_FACTOR 0.5 // Sensor pins #define clk p16 #define si p17 #define adc p18 // Motors -- As labelled on the Zumy mbed board PwmOut m1_fwd (p21); PwmOut m1_back (p22); PwmOut m2_fwd (p23); PwmOut m2_back (p24); // LEDs DigitalOut led1 (LED1); DigitalOut led2 (LED2); DigitalOut led3 (LED3); DigitalOut led4 (LED4); // USB serial Serial pc (USBTX, USBRX); // Data storage uint16_t line_hist[LINE_HIST_SIZE]; uint16_t hist_index; /***** Helper functions *****/ float max (float a, float b); // Sets the 4 LEDS on the mbed board to the four given binary values void setLEDs (uint16_t a, uint16_t b, uint16_t c, uint16_t d); // Based on steerPointTurns; the outer wheel moves faster the farther the line // is from center void steerImprovedPointTurns (int16_t line_pos); void steerImprovedPointTurnsBackward (int16_t line_pos); int main () { /********** SENSOR SETUP **********/ TSL1401CL cam (clk, si, adc); cam.setIntegrationTime (CAM_INTEGRATION_TIME); int16_t line_pos = -1; int16_t line_pos_previous = -1; int16_t steer_pos = -1; uint16_t line_lost_time = 0; hist_index = 0; // Read garbage data while (!cam.integrationReady ()) ; cam.read (); while (1) { /***** Read line sensor *****/ while (!cam.integrationReady ()) ; // Wait for integration cam.read (); /***** Line following loop *****/ line_pos = cam.findLineEdge (LINE_THRESHOLD, LINE_PRECISION, LINE_CROP_AMOUNT); if (line_pos != -1) { // On the line // Set LEDs based on the position of the line if (line_pos < (TSL1401CL_PIXEL_COUNT - 2 * LINE_CROP_AMOUNT) / 4) { setLEDs (1, 0, 0, 0); } else if (line_pos < (TSL1401CL_PIXEL_COUNT - 2 * LINE_CROP_AMOUNT) / 2) { setLEDs (0, 1, 0, 0); } else if (line_pos < (TSL1401CL_PIXEL_COUNT - 2 * LINE_CROP_AMOUNT) * 3 / 4) { setLEDs (0, 0, 1, 0); } else { setLEDs (0, 0, 0, 1); } // Record the line position line_hist[hist_index] = line_pos; hist_index++; line_lost_time = 0; if (steer_pos == -1) { steer_pos = line_pos; } else { steer_pos = line_pos * (1 - SMOOTHING_FACTOR) + steer_pos * SMOOTHING_FACTOR; } // Steer the vehicle steerImprovedPointTurns (steer_pos); line_pos_previous = line_pos; } else { // Lost the line line_lost_time++; if (line_lost_time >= LINE_END_TIME) { // Line end; transmit data to PC setLEDs (1, 1, 1, 1); m1_fwd.write (0); m2_fwd.write (0); m1_back.write (0); m2_back.write (0); while (!pc.readable ()) ; pc.printf ("----- Start line data -----\n"); for (int i = 0; i <= hist_index; i++) { pc.printf ("%d\n", line_hist[i]); } while (1) ; } else if (abs (steer_pos - TSL1401CL_PIXEL_COUNT / 2) > TSL1401CL_PIXEL_COUNT / 4) { setLEDs (1, 0, 0, 1); // Steer at maximum turn angle towards the last known line // direction if (steer_pos >= TSL1401CL_PIXEL_COUNT / 2) { steerImprovedPointTurns (TSL1401CL_PIXEL_COUNT - 1 - LINE_CROP_AMOUNT); // line_hist[hist_index] = TSL1401CL_PIXEL_COUNT - 1 - // LINE_CROP_AMOUNT; } else { steerImprovedPointTurns (LINE_CROP_AMOUNT); // line_hist[hist_index] = LINE_CROP_AMOUNT; } } else if (line_lost_time > RETRACT_START_TIME) { setLEDs (0, 1, 1, 0); steerImprovedPointTurnsBackward (TSL1401CL_PIXEL_COUNT / 2); wait_ms (50); } else { setLEDs (0, 0, 0, 0); } line_hist[hist_index] = 0; hist_index++; } if (hist_index > LINE_HIST_SIZE) { hist_index = 0; } } } float max (float a, float b) { if (a >= b) return a; return b; } void setLEDs (uint16_t a, uint16_t b, uint16_t c, uint16_t d) { led1 = a; led2 = b; led3 = c; led4 = d; } void steerImprovedPointTurns (int16_t line_pos) { line_pos -= TSL1401CL_PIXEL_COUNT / 2; // Find offset from center // Find desired motor voltages based on the controller float pwm_outer = SPEED_PWM * (1.0F + TURN_SENS_OUTER * abs (line_pos) * 2.0F / (float)TSL1401CL_PIXEL_COUNT); float pwm_inner = SPEED_PWM * (1.0F - TURN_SENS_INNER * abs (line_pos) * 2.0F / (float)TSL1401CL_PIXEL_COUNT); // Write to the appropriate PWM pins if (line_pos < 0) { m1_fwd.write (pwm_outer); m1_back.write (0); if (pwm_inner >= 0) { m2_fwd.write (pwm_inner); m2_back.write (0); } else { m2_fwd.write (0); m2_back.write (pwm_inner * -1.0F); } } if (line_pos >= 0) { m2_fwd.write (pwm_outer); m2_back.write (0); if (pwm_inner >= 0) { m1_fwd.write (pwm_inner); m1_back.write (0); } else { m1_fwd.write (0); m1_back.write (pwm_inner * -1.0F); } } } void steerImprovedPointTurnsBackward (int16_t line_pos) { line_pos -= TSL1401CL_PIXEL_COUNT / 2; // Find offset from center // Find desired motor voltages based on the controller float pwm_outer = SPEED_PWM * (1.0F + TURN_SENS_OUTER * abs (line_pos) * 2.0F / (float)TSL1401CL_PIXEL_COUNT); float pwm_inner = SPEED_PWM * (1.0F - TURN_SENS_INNER * abs (line_pos) * 2.0F / (float)TSL1401CL_PIXEL_COUNT); // Write to the appropriate PWM pins if (line_pos < 0) { m1_back.write (pwm_outer); m1_fwd.write (0); if (pwm_inner >= 0) { m2_back.write (pwm_inner); m2_fwd.write (0); } else { m2_back.write (0); m2_fwd.write (pwm_inner * -1.0F); } } if (line_pos >= 0) { m2_back.write (pwm_outer); m2_fwd.write (0); if (pwm_inner >= 0) { m1_back.write (pwm_inner); m1_fwd.write (0); } else { m1_back.write (0); m1_fwd.write (pwm_inner * -1.0F); } } }