Code used to generate IMU readings
Dependencies: MPU6050IMU TSL1401CL mbed
Diff: main.cpp
- Revision:
- 0:4856445a8db9
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Tue May 30 06:43:31 2017 +0000 @@ -0,0 +1,422 @@ +/* + * 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 "MPU6050.h" +#include "TSL1401CL.h" +#include "mbed.h" + +/***** Constants ******/ + +MPU6050 mpu6050; + +#define CAM_INTEGRATION_TIME 80 + +// Higher line threshold -> the sensor will only recognize larger changes in +// brightness as a line edge +#define LINE_THRESHOLD 3000 +#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.23 +#define TURN_SENS_INNER 1.5F +#define TURN_SENS_OUTER 0.5F + +// Defines data +#define LINE_HIST_SIZE 1000 +#define LINE_END_TIME 2500 + +// 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 +uint8_t line_hist[LINE_HIST_SIZE]; +int16_t accel_x[LINE_HIST_SIZE]; +int16_t accel_y[LINE_HIST_SIZE]; +int16_t accel_z[LINE_HIST_SIZE]; +int16_t gyro_x[LINE_HIST_SIZE]; +int16_t gyro_y[LINE_HIST_SIZE]; +int16_t gyro_z[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 (uint8_t a, uint8_t b, uint8_t c, uint8_t d); + +// Steers by linearly decreasing the inner wheel speed as the line moves from +// the center (unused in this program) +void steerStupid (int8_t line_pos); + +// Based on steerStupid; adds the ability for the inner wheel to rotate in +// reverse (unused in this program) +void steerPointTurns (int8_t line_pos); + +// Based on steerPointTurns; the outer wheel moves faster the farther the line +// is from center +void steerImprovedPointTurns (int8_t line_pos); + +int +main () +{ + /********** SENSOR SETUP **********/ + TSL1401CL cam (clk, si, adc); + cam.setIntegrationTime (CAM_INTEGRATION_TIME); + + int8_t line_pos = -1; + int8_t line_pos_previous = -1; + uint8_t line_lost_time = 0; + + hist_index = 0; + + i2c.frequency (400000); + + volatile bool imu_ready = false; + + wait_ms (100); + uint8_t whoami = mpu6050.readByte (MPU6050_ADDRESS, WHO_AM_I_MPU6050); + + if (whoami == 0x68) // WHO_AM_I should always be 0x68 + { + mpu6050.MPU6050SelfTest (SelfTest); + if (SelfTest[0] < 1.0f && SelfTest[1] < 1.0f && SelfTest[2] < 1.0f + && SelfTest[3] < 1.0f && SelfTest[4] < 1.0f && SelfTest[5] < 1.0f) + { + mpu6050.resetMPU6050 (); + mpu6050.calibrateMPU6050 (gyroBias, accelBias); + mpu6050.initMPU6050 (); + mpu6050.getAres (); + mpu6050.getGres (); + imu_ready = true; + } + } + else + { + setLEDs (1, 0, 1, 0); + wait_ms (1000); + } + // 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; + line_lost_time = 0; + if (imu_ready) + { + + if (mpu6050.readByte (MPU6050_ADDRESS, INT_STATUS) & 0x01) + { // check if data ready interrupt + mpu6050.readAccelData (accelCount); + // Read the x/y/z adc values + + accel_x[hist_index] = accelCount[0]; + accel_y[hist_index] = accelCount[1]; + accel_z[hist_index] = accelCount[2]; + + // Calculate the gyro value into actual degrees per + // second + + mpu6050.readGyroData (gyroCount); + + gyro_x[hist_index] = gyroCount[0]; + gyro_y[hist_index] = gyroCount[1]; + gyro_z[hist_index] = gyroCount[2]; + // Read the x/y/z ad values + // gyro_x = (float)gyroCount[0] * gRes + // - gyroBias[0]; // get actual gyro value, this + // // depends on scale being set + // gyro_y = (float)gyroCount[1] * gRes - gyroBias[1]; + // gyro_z = (float)gyroCount[2] * gRes - gyroBias[2]; + // pc.printf ("Gyro,%d,%d,%d\n", gyroCount[0], + // gyroCount[1], + // gyroCount[2]); + // + } + } + hist_index++; + + // Steer the vehicle + steerImprovedPointTurns (line_pos); + + line_pos_previous = line_pos; + } + else + { // Lost the line + // setLEDs (1, 1, 1, 1); + if (abs (line_pos_previous - TSL1401CL_PIXEL_COUNT / 2) + > TSL1401CL_PIXEL_COUNT / 4) + { + // Steer at maximum turn angle towards the last known line + // direction + if (line_pos_previous >= 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 + { + line_lost_time++; + if (line_lost_time >= LINE_END_TIME) + { + setLEDs (1, 0, 1, 0); + // Line end; transmit data to PC + m1_fwd.write (0); + m2_fwd.write (0); + // while (!pc.readable ()) + // ; + pc.printf ("----- Start line data -----\n"); + for (int i = 0; i <= hist_index; i++) + { + pc.printf ("Pos: %d\n", line_hist[i]); + float x, y, z; + x = (float)accel_x[i] * aRes - accelBias[0]; + y = (float)accel_y[i] * aRes - accelBias[1]; + z = (float)accel_z[i] * aRes - accelBias[2]; + pc.printf ("Acceleration,%f,%f,%f\n", x, y, z); + x = (float)gyro_x[i] * gRes - gyroBias[0]; + y = (float)gyro_y[i] * gRes - gyroBias[1]; + z = (float)gyro_z[i] * gRes - gyroBias[2]; + pc.printf ("Gyroscope,%f,%f,%f\n", x, y, z); + } + while (1) + ; + } + } + } + if (hist_index > LINE_HIST_SIZE) + { + setLEDs (1, 0, 0, 1); + + // Line end; transmit data to PC + m1_fwd.write (0); + m2_fwd.write (0); + // while (!pc.readable ()) + // ; + pc.printf ("----- Start line data -----\n"); + for (int i = 0; i <= hist_index; i++) + { + pc.printf ("Pos: %d\n", line_hist[i]); + float x, y, z; + x = (float)accel_x[i] * aRes - accelBias[0]; + y = (float)accel_y[i] * aRes - accelBias[1]; + z = (float)accel_z[i] * aRes - accelBias[2]; + pc.printf ("Acceleration,%f,%f,%f\n", x, y, z); + x = (float)gyro_x[i] * gRes - gyroBias[0]; + y = (float)gyro_y[i] * gRes - gyroBias[1]; + z = (float)gyro_z[i] * gRes - gyroBias[2]; + pc.printf ("Gyroscope,%f,%f,%f\n", x, y, z); + } + while (1) + ; + } + } +} + +float +max (float a, float b) +{ + if (a >= b) + return a; + return b; +} + +void +setLEDs (uint8_t a, uint8_t b, uint8_t c, uint8_t d) +{ + led1 = a; + led2 = b; + led3 = c; + led4 = d; +} + +void +steerStupid (int8_t line_pos) +{ + line_pos -= TSL1401CL_PIXEL_COUNT / 2; // Find offset from center + + if (line_pos < 0) + { + m1_fwd.write (SPEED_PWM); + m1_back.write (0); + m2_fwd.write (max (SPEED_PWM * (1.0F + + TURN_SENS_INNER * line_pos * 2.0F + / (float)TSL1401CL_PIXEL_COUNT), + 0)); + m2_back.write (0); + } + + if (line_pos >= 0) + { + m2_fwd.write (SPEED_PWM); + m2_back.write (0); + m1_fwd.write (max (SPEED_PWM * (1.0F + - TURN_SENS_INNER * line_pos * 2.0F + / (float)TSL1401CL_PIXEL_COUNT), + 0)); + m1_back.write (0); + } +} + +void +steerPointTurns (int8_t line_pos) +{ + line_pos -= TSL1401CL_PIXEL_COUNT / 2; // Find offset from center + + float pwm_outer = SPEED_PWM; + float pwm_inner = SPEED_PWM * (1.0F + - TURN_SENS_INNER * abs (line_pos) * 2.0F + / (float)TSL1401CL_PIXEL_COUNT); + + 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 +steerImprovedPointTurns (int8_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); + } + } +} \ No newline at end of file