car using PID from centre line
Dependencies: FRDM-TFC mbed CBuffer XBEE mbed_angular_speed motor2 MMA8451Q
Fork of KL25Z_Camera_Test by
main.cpp@54:78854efeb1df, 2017-04-28 (annotated)
- Committer:
- FatCookies
- Date:
- Fri Apr 28 07:58:19 2017 +0000
- Revision:
- 54:78854efeb1df
- Parent:
- 52:af17b1a330f4
small param changes;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
maximusismax | 8:7c5e6b1e7aa5 | 1 | //Autonomous Car GDP controller |
maximusismax | 8:7c5e6b1e7aa5 | 2 | //Written by various group members |
maximusismax | 8:7c5e6b1e7aa5 | 3 | //Commented & cleaned up by Max/Adam |
maximusismax | 8:7c5e6b1e7aa5 | 4 | |
maximusismax | 8:7c5e6b1e7aa5 | 5 | //To-do |
maximusismax | 8:7c5e6b1e7aa5 | 6 | // -Change xbee transmission to non-blocking |
maximusismax | 8:7c5e6b1e7aa5 | 7 | // -Improve start/stop detection and resultant action (setting PID values?) |
maximusismax | 8:7c5e6b1e7aa5 | 8 | |
maximusismax | 8:7c5e6b1e7aa5 | 9 | #include <stdarg.h> |
maximusismax | 8:7c5e6b1e7aa5 | 10 | #include <stdio.h> |
maximusismax | 8:7c5e6b1e7aa5 | 11 | |
maximusismax | 0:566127ca8048 | 12 | #include "mbed.h" |
maximusismax | 0:566127ca8048 | 13 | #include "TFC.h" |
FatCookies | 4:4afa448c9cce | 14 | #include "XBEE.h" |
FatCookies | 9:aa2ce38dec6b | 15 | #include "angular_speed.h" |
FatCookies | 14:13085e161dd1 | 16 | #include "main.h" |
FatCookies | 12:da96e2f87465 | 17 | #include "motor.h" |
FatCookies | 45:3435bdd2d487 | 18 | #include "MMA8451Q.h" |
maximusismax | 8:7c5e6b1e7aa5 | 19 | |
FatCookies | 17:6ae90788cc2b | 20 | // Serial |
FatCookies | 17:6ae90788cc2b | 21 | #if USE_COMMS |
FatCookies | 17:6ae90788cc2b | 22 | Serial pc(PTD3,PTD2); |
FatCookies | 17:6ae90788cc2b | 23 | XBEE xb(&pc); |
FatCookies | 17:6ae90788cc2b | 24 | #endif |
FatCookies | 3:87a5122682fa | 25 | |
FatCookies | 17:6ae90788cc2b | 26 | // PID Timer |
FatCookies | 3:87a5122682fa | 27 | Timer t; |
FatCookies | 4:4afa448c9cce | 28 | |
FatCookies | 17:6ae90788cc2b | 29 | //Speed Sensors interupts and timers |
FatCookies | 9:aa2ce38dec6b | 30 | InterruptIn leftHallSensor(D0); |
FatCookies | 9:aa2ce38dec6b | 31 | InterruptIn rightHallSensor(D2); |
FatCookies | 9:aa2ce38dec6b | 32 | Timer t1; |
FatCookies | 9:aa2ce38dec6b | 33 | Timer t2; |
FatCookies | 9:aa2ce38dec6b | 34 | |
lh14g13 | 32:6829684f8c4d | 35 | //testing timer for laptimes |
FatCookies | 27:627d67e3b9b0 | 36 | Timer lapTimer; |
FatCookies | 16:81cdffd8c5d5 | 37 | |
FatCookies | 45:3435bdd2d487 | 38 | MMA8451Q acc(SDA, SCL, MMA8451_I2C_ADDRESS); |
FatCookies | 45:3435bdd2d487 | 39 | |
FatCookies | 45:3435bdd2d487 | 40 | |
FatCookies | 45:3435bdd2d487 | 41 | |
FatCookies | 45:3435bdd2d487 | 42 | int loop = 0; |
FatCookies | 45:3435bdd2d487 | 43 | float accc = 0.f; |
FatCookies | 21:0b69fada7c5f | 44 | |
maximusismax | 0:566127ca8048 | 45 | int main() { |
FatCookies | 45:3435bdd2d487 | 46 | |
maximusismax | 8:7c5e6b1e7aa5 | 47 | //Set up TFC driver stuff |
maximusismax | 0:566127ca8048 | 48 | TFC_Init(); |
FatCookies | 17:6ae90788cc2b | 49 | ALIGN_SERVO; |
FatCookies | 13:4e77264f254a | 50 | |
FatCookies | 17:6ae90788cc2b | 51 | #if USE_COMMS |
FatCookies | 17:6ae90788cc2b | 52 | //Setup baud rate for serial link, do not change! |
FatCookies | 17:6ae90788cc2b | 53 | pc.baud(BAUD_RATE); |
FatCookies | 17:6ae90788cc2b | 54 | #endif |
maximusismax | 0:566127ca8048 | 55 | |
maximusismax | 8:7c5e6b1e7aa5 | 56 | //Initialise/reset PID variables |
maximusismax | 8:7c5e6b1e7aa5 | 57 | initVariables(); |
FatCookies | 9:aa2ce38dec6b | 58 | initSpeedSensors(); |
FatCookies | 40:10e8e80af7da | 59 | |
FatCookies | 43:649473c5a12b | 60 | #if !(USE_COMMS) |
FatCookies | 43:649473c5a12b | 61 | buttonStartup(); |
FatCookies | 43:649473c5a12b | 62 | #endif |
FatCookies | 45:3435bdd2d487 | 63 | |
FatCookies | 12:da96e2f87465 | 64 | |
maximusismax | 0:566127ca8048 | 65 | while(1) { |
FatCookies | 3:87a5122682fa | 66 | |
FatCookies | 17:6ae90788cc2b | 67 | #if USE_COMMS |
FatCookies | 17:6ae90788cc2b | 68 | handleComms(); |
FatCookies | 17:6ae90788cc2b | 69 | #endif |
maximusismax | 8:7c5e6b1e7aa5 | 70 | |
maximusismax | 8:7c5e6b1e7aa5 | 71 | //If we have an image ready |
FatCookies | 13:4e77264f254a | 72 | if(TFC_LineScanImageReady>0) { |
FatCookies | 13:4e77264f254a | 73 | /* Find the bounds of the track and calculate how close we are to |
FatCookies | 13:4e77264f254a | 74 | * the centre */ |
FatCookies | 17:6ae90788cc2b | 75 | servo_pid.measured_value = findCentreValue(CLOSE_CAMERA, left, right); |
maximusismax | 8:7c5e6b1e7aa5 | 76 | |
FatCookies | 21:0b69fada7c5f | 77 | // Check if car is at the stop line |
FatCookies | 45:3435bdd2d487 | 78 | |
FatCookies | 54:78854efeb1df | 79 | /*if(loop % 10 == 0) { |
FatCookies | 45:3435bdd2d487 | 80 | accc = checkAcc(); |
FatCookies | 45:3435bdd2d487 | 81 | } |
FatCookies | 45:3435bdd2d487 | 82 | |
lh14g13 | 48:daa2a1900ada | 83 | if(accc < accTheshold) { |
FatCookies | 45:3435bdd2d487 | 84 | handleStartStop(); |
FatCookies | 45:3435bdd2d487 | 85 | } else { |
lh14g13 | 46:6806ea59ffed | 86 | //sendString("up %f", accc); |
FatCookies | 45:3435bdd2d487 | 87 | } |
FatCookies | 54:78854efeb1df | 88 | */ |
FatCookies | 45:3435bdd2d487 | 89 | |
FatCookies | 45:3435bdd2d487 | 90 | |
FatCookies | 45:3435bdd2d487 | 91 | |
FatCookies | 21:0b69fada7c5f | 92 | |
FatCookies | 27:627d67e3b9b0 | 93 | #if USE_COMMS |
FatCookies | 27:627d67e3b9b0 | 94 | // Send the line scan image over serial |
FatCookies | 27:627d67e3b9b0 | 95 | sendImage(); |
FatCookies | 27:627d67e3b9b0 | 96 | #endif |
FatCookies | 21:0b69fada7c5f | 97 | |
FatCookies | 21:0b69fada7c5f | 98 | |
FatCookies | 21:0b69fada7c5f | 99 | //Reset image ready flag |
FatCookies | 21:0b69fada7c5f | 100 | TFC_LineScanImageReady=0; |
lh14g13 | 19:65f0b6febc23 | 101 | |
FatCookies | 17:6ae90788cc2b | 102 | // Slow down, adjust PID values and enable differential before corners. |
FatCookies | 21:0b69fada7c5f | 103 | //handleCornering(); |
FatCookies | 17:6ae90788cc2b | 104 | |
FatCookies | 13:4e77264f254a | 105 | // Run the PID controllers and adjust steering/motor accordingly |
maximusismax | 8:7c5e6b1e7aa5 | 106 | PIDController(); |
maximusismax | 8:7c5e6b1e7aa5 | 107 | |
FatCookies | 21:0b69fada7c5f | 108 | |
FatCookies | 21:0b69fada7c5f | 109 | |
FatCookies | 21:0b69fada7c5f | 110 | |
FatCookies | 17:6ae90788cc2b | 111 | #if USE_COMMS |
FatCookies | 17:6ae90788cc2b | 112 | // Send the wheel speeds over serial |
FatCookies | 17:6ae90788cc2b | 113 | sendSpeeds(); |
FatCookies | 17:6ae90788cc2b | 114 | #endif |
FatCookies | 13:4e77264f254a | 115 | |
FatCookies | 21:0b69fada7c5f | 116 | |
maximusismax | 8:7c5e6b1e7aa5 | 117 | |
FatCookies | 45:3435bdd2d487 | 118 | //wait_ms(25); |
FatCookies | 21:0b69fada7c5f | 119 | |
maximusismax | 8:7c5e6b1e7aa5 | 120 | } |
maximusismax | 8:7c5e6b1e7aa5 | 121 | } |
maximusismax | 8:7c5e6b1e7aa5 | 122 | } |
maximusismax | 8:7c5e6b1e7aa5 | 123 | |
FatCookies | 40:10e8e80af7da | 124 | void buttonStartup() { |
FatCookies | 45:3435bdd2d487 | 125 | TFC_SetBatteryLED(led_values[b_pressed % 4]); |
FatCookies | 40:10e8e80af7da | 126 | while(1) { |
FatCookies | 45:3435bdd2d487 | 127 | //handleComms(); |
FatCookies | 45:3435bdd2d487 | 128 | |
FatCookies | 40:10e8e80af7da | 129 | // 2 bit is broken = max value is 13 |
FatCookies | 40:10e8e80af7da | 130 | uint8_t dip = TFC_GetDIP_Switch(); |
FatCookies | 40:10e8e80af7da | 131 | |
FatCookies | 40:10e8e80af7da | 132 | // 1 on press, 0 otherwise |
FatCookies | 40:10e8e80af7da | 133 | uint8_t button_a = TFC_ReadPushButton(0); |
FatCookies | 40:10e8e80af7da | 134 | uint8_t button_b = TFC_ReadPushButton(1); |
FatCookies | 40:10e8e80af7da | 135 | |
FatCookies | 40:10e8e80af7da | 136 | // -1 to 1, turning clockwise INCREASES value |
FatCookies | 40:10e8e80af7da | 137 | float pot_a = TFC_ReadPot(0); |
FatCookies | 40:10e8e80af7da | 138 | float pot_b = TFC_ReadPot(1); |
FatCookies | 40:10e8e80af7da | 139 | |
FatCookies | 45:3435bdd2d487 | 140 | if(button_b && !bDown) { |
FatCookies | 45:3435bdd2d487 | 141 | bDown = true; |
FatCookies | 45:3435bdd2d487 | 142 | continue; |
FatCookies | 45:3435bdd2d487 | 143 | } |
FatCookies | 45:3435bdd2d487 | 144 | if(!button_b && bDown) { |
FatCookies | 45:3435bdd2d487 | 145 | b_pressed++; |
FatCookies | 45:3435bdd2d487 | 146 | TFC_SetBatteryLED(led_values[b_pressed % 4]); |
FatCookies | 45:3435bdd2d487 | 147 | bDown = false; |
FatCookies | 45:3435bdd2d487 | 148 | continue; |
FatCookies | 45:3435bdd2d487 | 149 | } |
FatCookies | 45:3435bdd2d487 | 150 | |
FatCookies | 45:3435bdd2d487 | 151 | if(button_a && !aDown) { |
FatCookies | 45:3435bdd2d487 | 152 | aDown = true; |
FatCookies | 45:3435bdd2d487 | 153 | continue; |
FatCookies | 45:3435bdd2d487 | 154 | } |
FatCookies | 45:3435bdd2d487 | 155 | if(!button_a && aDown) { |
FatCookies | 45:3435bdd2d487 | 156 | |
FatCookies | 45:3435bdd2d487 | 157 | TFC_SetBatteryLED(0); |
FatCookies | 43:649473c5a12b | 158 | aDown = false; |
FatCookies | 43:649473c5a12b | 159 | |
FatCookies | 43:649473c5a12b | 160 | int choice = b_pressed % 4; |
FatCookies | 43:649473c5a12b | 161 | switch(choice) { |
FatCookies | 45:3435bdd2d487 | 162 | case 0: |
FatCookies | 43:649473c5a12b | 163 | initPID(&servo_pid, 2.2f, 0.6f, 0.f); |
lh14g13 | 50:1cfe1f975b0c | 164 | if(!torque){ |
FatCookies | 45:3435bdd2d487 | 165 | speed = 40; |
lh14g13 | 50:1cfe1f975b0c | 166 | } |
lh14g13 | 50:1cfe1f975b0c | 167 | else{ |
lh14g13 | 50:1cfe1f975b0c | 168 | speed = 0.4; |
lh14g13 | 50:1cfe1f975b0c | 169 | } |
lh14g13 | 47:6a58dcef714f | 170 | ed_tune = man_tuner; |
FatCookies | 43:649473c5a12b | 171 | break; |
FatCookies | 43:649473c5a12b | 172 | case 1: |
FatCookies | 43:649473c5a12b | 173 | initPID(&servo_pid, 2.2f, 0.6f, 0.f); |
lh14g13 | 50:1cfe1f975b0c | 174 | if(!torque){ |
lh14g13 | 47:6a58dcef714f | 175 | speed = 65; |
lh14g13 | 50:1cfe1f975b0c | 176 | } |
lh14g13 | 50:1cfe1f975b0c | 177 | else{ |
lh14g13 | 51:6a84fbc404c8 | 178 | speed = 0.6; |
lh14g13 | 50:1cfe1f975b0c | 179 | } |
lh14g13 | 47:6a58dcef714f | 180 | ed_tune = man_tuner; |
FatCookies | 43:649473c5a12b | 181 | break; |
FatCookies | 43:649473c5a12b | 182 | case 2: |
FatCookies | 43:649473c5a12b | 183 | initPID(&servo_pid, 2.2f, 0.6f, 0.f); |
lh14g13 | 50:1cfe1f975b0c | 184 | if(!torque){ |
lh14g13 | 47:6a58dcef714f | 185 | speed = 80; |
lh14g13 | 50:1cfe1f975b0c | 186 | } |
lh14g13 | 50:1cfe1f975b0c | 187 | else{ |
lh14g13 | 51:6a84fbc404c8 | 188 | speed= 0.8; |
lh14g13 | 50:1cfe1f975b0c | 189 | } |
lh14g13 | 47:6a58dcef714f | 190 | ed_tune = man_tuner; |
FatCookies | 43:649473c5a12b | 191 | break; |
FatCookies | 43:649473c5a12b | 192 | case 3: |
FatCookies | 43:649473c5a12b | 193 | initPID(&servo_pid, 2.2f, 0.6f, 0.f); |
lh14g13 | 47:6a58dcef714f | 194 | speed = 110; |
lh14g13 | 47:6a58dcef714f | 195 | ed_tune = man_tuner; |
FatCookies | 43:649473c5a12b | 196 | break; |
FatCookies | 45:3435bdd2d487 | 197 | } |
FatCookies | 45:3435bdd2d487 | 198 | |
FatCookies | 45:3435bdd2d487 | 199 | wait(2.f); |
FatCookies | 43:649473c5a12b | 200 | |
FatCookies | 45:3435bdd2d487 | 201 | ALIGN_SERVO; |
FatCookies | 45:3435bdd2d487 | 202 | right_motor_pid.desired_value=speed; |
FatCookies | 45:3435bdd2d487 | 203 | left_motor_pid.desired_value=speed; |
FatCookies | 45:3435bdd2d487 | 204 | TFC_HBRIDGE_ENABLE; |
FatCookies | 45:3435bdd2d487 | 205 | servo_pid.integral = 0; |
FatCookies | 45:3435bdd2d487 | 206 | //sendString("PID: %f %f %f speed:%f ed:%f",servo_pid.Kp, servo_pid.Ki, servo_pid.Kd, speed, ed_tune); |
FatCookies | 45:3435bdd2d487 | 207 | return; |
FatCookies | 43:649473c5a12b | 208 | } |
FatCookies | 43:649473c5a12b | 209 | |
FatCookies | 45:3435bdd2d487 | 210 | |
FatCookies | 40:10e8e80af7da | 211 | } |
FatCookies | 45:3435bdd2d487 | 212 | |
FatCookies | 45:3435bdd2d487 | 213 | } |
FatCookies | 40:10e8e80af7da | 214 | |
FatCookies | 45:3435bdd2d487 | 215 | |
FatCookies | 40:10e8e80af7da | 216 | |
FatCookies | 17:6ae90788cc2b | 217 | void initVariables() { |
FatCookies | 17:6ae90788cc2b | 218 | // Initialise three PID controllers for the servo and each wheel. |
oj3g13 | 34:3de7a19ccea3 | 219 | initPID(&servo_pid, 0.f, 0.f, 0.f); |
lh14g13 | 46:6806ea59ffed | 220 | initPID(&left_motor_pid, 0.01f, 0.f, 0.f); |
lh14g13 | 46:6806ea59ffed | 221 | initPID(&right_motor_pid, 0.01f, 0.f, 0.f); |
FatCookies | 17:6ae90788cc2b | 222 | |
lh14g13 | 19:65f0b6febc23 | 223 | right_motor_pid.desired_value=0; |
lh14g13 | 19:65f0b6febc23 | 224 | left_motor_pid.desired_value=0; |
lh14g13 | 19:65f0b6febc23 | 225 | |
lh14g13 | 19:65f0b6febc23 | 226 | // intialise the maximum speed interms of the angular speed. |
FatCookies | 17:6ae90788cc2b | 227 | valBufferIndex = 0; |
lh14g13 | 19:65f0b6febc23 | 228 | speed = 50; |
FatCookies | 13:4e77264f254a | 229 | |
FatCookies | 17:6ae90788cc2b | 230 | //Start stop |
FatCookies | 17:6ae90788cc2b | 231 | startstop = 0; |
FatCookies | 17:6ae90788cc2b | 232 | seen = false; |
FatCookies | 17:6ae90788cc2b | 233 | |
FatCookies | 17:6ae90788cc2b | 234 | // Turning |
FatCookies | 17:6ae90788cc2b | 235 | turning = 0; |
FatCookies | 17:6ae90788cc2b | 236 | keepTurning = 0; |
FatCookies | 17:6ae90788cc2b | 237 | slow = false; |
FatCookies | 20:ed954836d028 | 238 | |
FatCookies | 20:ed954836d028 | 239 | wL = 0; |
FatCookies | 20:ed954836d028 | 240 | wR = 0; |
FatCookies | 20:ed954836d028 | 241 | prevL = 0; |
FatCookies | 20:ed954836d028 | 242 | prevR = 0; |
maximusismax | 8:7c5e6b1e7aa5 | 243 | } |
maximusismax | 8:7c5e6b1e7aa5 | 244 | |
FatCookies | 13:4e77264f254a | 245 | void initPID(pid_instance* pid, float Kp, float Ki, float Kd) { |
FatCookies | 17:6ae90788cc2b | 246 | pid->Kp = Kp; |
FatCookies | 13:4e77264f254a | 247 | pid->Ki = Ki; |
FatCookies | 13:4e77264f254a | 248 | pid->Kd = Kd; |
FatCookies | 13:4e77264f254a | 249 | pid->dt = 0; |
FatCookies | 13:4e77264f254a | 250 | pid->p_error = 0; |
FatCookies | 13:4e77264f254a | 251 | pid->pid_error = 0; |
FatCookies | 13:4e77264f254a | 252 | pid->integral = 0; |
FatCookies | 13:4e77264f254a | 253 | pid->measured_value = 0; |
FatCookies | 13:4e77264f254a | 254 | pid->desired_value = 0; |
FatCookies | 13:4e77264f254a | 255 | pid->derivative = 0; |
FatCookies | 13:4e77264f254a | 256 | } |
FatCookies | 13:4e77264f254a | 257 | |
FatCookies | 29:b5b31256572b | 258 | bool leftSeen; |
FatCookies | 29:b5b31256572b | 259 | bool rightSeen; |
maximusismax | 31:1a06c9e1985e | 260 | |
maximusismax | 31:1a06c9e1985e | 261 | //Function which calcuates how far to the left/right of the centre of the track the car is |
maximusismax | 31:1a06c9e1985e | 262 | //Takes data from either camera, and passes some variables by reference, which will hold |
maximusismax | 31:1a06c9e1985e | 263 | //the indices holding the locations of the left and right edges of the track |
FatCookies | 17:6ae90788cc2b | 264 | inline float findCentreValue(volatile uint16_t * cam_data, uint8_t &l, uint8_t &r) { |
FatCookies | 17:6ae90788cc2b | 265 | |
maximusismax | 31:1a06c9e1985e | 266 | diff = 0; //Holds difference in intensity between consecutive pixels |
maximusismax | 31:1a06c9e1985e | 267 | prev = -1; //Holds index of last inspected pixel |
FatCookies | 29:b5b31256572b | 268 | |
maximusismax | 31:1a06c9e1985e | 269 | //Used for crossroads navigation, holds info on which edges of the track are observed |
FatCookies | 29:b5b31256572b | 270 | leftSeen = false; |
FatCookies | 29:b5b31256572b | 271 | rightSeen = false; |
maximusismax | 31:1a06c9e1985e | 272 | |
maximusismax | 31:1a06c9e1985e | 273 | //Starting in the middle index, step left, inspecting the the edge of the track |
oj3g13 | 34:3de7a19ccea3 | 274 | for(i = 63; i > 2; i--) { |
oj3g13 | 26:f3d770f3eda1 | 275 | curr_left = (uint8_t)(cam_data[i] >> 4) & 0xFF; |
FatCookies | 17:6ae90788cc2b | 276 | diff = prev - curr_left; |
maximusismax | 31:1a06c9e1985e | 277 | //Check incorporates a combination of looking at the difference in intensities |
maximusismax | 31:1a06c9e1985e | 278 | //and whether the pixels intensity is less than a threshold, corresponding to the black edge |
FatCookies | 17:6ae90788cc2b | 279 | if(abs(diff) >= CAM_DIFF && curr_left <= CAM_THRESHOLD && prev != -1) { |
maximusismax | 31:1a06c9e1985e | 280 | l = i; //Record the index where the edge is observed |
FatCookies | 29:b5b31256572b | 281 | leftSeen = true; |
FatCookies | 17:6ae90788cc2b | 282 | break; |
FatCookies | 17:6ae90788cc2b | 283 | } |
maximusismax | 31:1a06c9e1985e | 284 | prev = curr_left; //Update previous value for the loop |
FatCookies | 17:6ae90788cc2b | 285 | } |
maximusismax | 8:7c5e6b1e7aa5 | 286 | |
FatCookies | 17:6ae90788cc2b | 287 | prev = -1; |
maximusismax | 31:1a06c9e1985e | 288 | //As before, start in the middle but this time step rightwards in the image |
oj3g13 | 34:3de7a19ccea3 | 289 | for(i = 64; i < 126; i++) { |
oj3g13 | 26:f3d770f3eda1 | 290 | curr_right = (uint8_t)(cam_data[i] >> 4) & 0xFF; |
FatCookies | 17:6ae90788cc2b | 291 | int diff = prev - curr_right; |
FatCookies | 17:6ae90788cc2b | 292 | if(abs(diff) >= CAM_DIFF && curr_right <= CAM_THRESHOLD && prev != -1) { |
FatCookies | 17:6ae90788cc2b | 293 | r = i; |
FatCookies | 29:b5b31256572b | 294 | rightSeen = true; |
FatCookies | 17:6ae90788cc2b | 295 | break; |
FatCookies | 17:6ae90788cc2b | 296 | } |
FatCookies | 17:6ae90788cc2b | 297 | prev = curr_right; |
FatCookies | 17:6ae90788cc2b | 298 | } |
FatCookies | 17:6ae90788cc2b | 299 | |
maximusismax | 31:1a06c9e1985e | 300 | //If both edges are not visible, we are likely in a crossroads |
FatCookies | 29:b5b31256572b | 301 | if(!rightSeen && !leftSeen) { |
FatCookies | 43:649473c5a12b | 302 | #if USE_COMMS |
FatCookies | 43:649473c5a12b | 303 | sendString("lost edges"); |
FatCookies | 43:649473c5a12b | 304 | #endif |
maximusismax | 31:1a06c9e1985e | 305 | ALIGN_SERVO; //Straighten wheels so we go straight through the crossroads |
maximusismax | 31:1a06c9e1985e | 306 | servo_pid.integral = 0; |
oj3g13 | 34:3de7a19ccea3 | 307 | l=0;r=128; |
FatCookies | 29:b5b31256572b | 308 | } |
FatCookies | 29:b5b31256572b | 309 | |
maximusismax | 31:1a06c9e1985e | 310 | //Calculate how left/right from the centre line we are |
FatCookies | 17:6ae90788cc2b | 311 | return (64 - ((l+r)/2))/64.f; |
FatCookies | 13:4e77264f254a | 312 | } |
FatCookies | 13:4e77264f254a | 313 | |
maximusismax | 31:1a06c9e1985e | 314 | //Unused function currently |
maximusismax | 31:1a06c9e1985e | 315 | //Was used to establish whether we are in a corner, by inspecting a buffer of |
maximusismax | 31:1a06c9e1985e | 316 | //centre line values |
FatCookies | 17:6ae90788cc2b | 317 | inline void handleCornering() { |
FatCookies | 12:da96e2f87465 | 318 | |
maximusismax | 31:1a06c9e1985e | 319 | //Get current value of how left/right of centre line we are on the track |
FatCookies | 17:6ae90788cc2b | 320 | float lookaheadMeasuredValue = findCentreValue(LOOKAHEAD_CAMERA, farLeft, farRight); |
FatCookies | 15:ccde02f96449 | 321 | |
FatCookies | 13:4e77264f254a | 322 | measuredValBuffer[frame_counter % 64] = servo_pid.measured_value; |
FatCookies | 13:4e77264f254a | 323 | |
FatCookies | 13:4e77264f254a | 324 | int count = 0; |
FatCookies | 13:4e77264f254a | 325 | for(i = 0; i < 10; i++) { |
maximusismax | 31:1a06c9e1985e | 326 | //Step through the buffer, using modulus operator |
FatCookies | 13:4e77264f254a | 327 | float val = abs(measuredValBuffer[(frame_counter - i) % 64]); |
maximusismax | 31:1a06c9e1985e | 328 | if(val > 0.09) { //If the value exceeds a certain value (obtained experimentally), we are in a corner |
FatCookies | 13:4e77264f254a | 329 | count++; |
FatCookies | 13:4e77264f254a | 330 | } |
FatCookies | 13:4e77264f254a | 331 | } |
FatCookies | 12:da96e2f87465 | 332 | |
FatCookies | 29:b5b31256572b | 333 | /*if(!turning && abs(lookaheadMeasuredValue) > 0.11f){ |
FatCookies | 15:ccde02f96449 | 334 | TFC_SetMotorPWM(0.4,0.4); |
FatCookies | 15:ccde02f96449 | 335 | } |
FatCookies | 29:b5b31256572b | 336 | */ |
FatCookies | 15:ccde02f96449 | 337 | |
FatCookies | 29:b5b31256572b | 338 | if(false) { |
lh14g13 | 18:0095a3a8f8e4 | 339 | |
lh14g13 | 18:0095a3a8f8e4 | 340 | //default |
lh14g13 | 18:0095a3a8f8e4 | 341 | //TFC_SetMotorPWM(0.4,0.4); |
lh14g13 | 18:0095a3a8f8e4 | 342 | |
lh14g13 | 19:65f0b6febc23 | 343 | //dutyCycleCorner(speed,servo_pid.output); |
lh14g13 | 18:0095a3a8f8e4 | 344 | |
lh14g13 | 32:6829684f8c4d | 345 | |
lh14g13 | 18:0095a3a8f8e4 | 346 | //dutyCycleCorner(float cornerspeed, servo_pid.output); |
lh14g13 | 18:0095a3a8f8e4 | 347 | //dutyCycleCorner(speed, servo_pid.output); |
lh14g13 | 32:6829684f8c4d | 348 | // This activates the electronic differential so that it runs whilst cornering. |
lh14g13 | 32:6829684f8c4d | 349 | // this changes the desired desired speed of each of the wheels according to the angle of the servo. |
lh14g13 | 39:7b28ee39185d | 350 | sensorCorner(left_motor_pid.desired_value, right_motor_pid.desired_value , servo_pid.output, speed,ed_tune); |
FatCookies | 14:13085e161dd1 | 351 | } |
FatCookies | 14:13085e161dd1 | 352 | |
FatCookies | 29:b5b31256572b | 353 | /* |
FatCookies | 13:4e77264f254a | 354 | if(abs(servo_pid.measured_value) > 0.11f){ |
FatCookies | 15:ccde02f96449 | 355 | if(!turning) { |
FatCookies | 13:4e77264f254a | 356 | turning = 1; |
FatCookies | 13:4e77264f254a | 357 | } else { |
FatCookies | 13:4e77264f254a | 358 | turning++; |
FatCookies | 13:4e77264f254a | 359 | } |
FatCookies | 13:4e77264f254a | 360 | |
FatCookies | 13:4e77264f254a | 361 | } else { |
FatCookies | 13:4e77264f254a | 362 | if(turning) { |
FatCookies | 13:4e77264f254a | 363 | if(keepTurning == 0 || count > 6) { |
FatCookies | 13:4e77264f254a | 364 | keepTurning++; |
FatCookies | 13:4e77264f254a | 365 | } else { |
FatCookies | 15:ccde02f96449 | 366 | //sendString("stop turning turned=%d",turning); |
FatCookies | 13:4e77264f254a | 367 | keepTurning = 0; |
lh14g13 | 33:0fc789c09694 | 368 | turning = 0; |
lh14g13 | 33:0fc789c09694 | 369 | left_motor_pid.desired_value=speed; |
lh14g13 | 33:0fc789c09694 | 370 | right_motot_pid.desired_value=speed; |
FatCookies | 13:4e77264f254a | 371 | TFC_SetMotorPWM(speed,speed); |
FatCookies | 13:4e77264f254a | 372 | } |
FatCookies | 13:4e77264f254a | 373 | |
FatCookies | 13:4e77264f254a | 374 | } |
FatCookies | 13:4e77264f254a | 375 | } |
FatCookies | 29:b5b31256572b | 376 | */ |
FatCookies | 13:4e77264f254a | 377 | |
maximusismax | 8:7c5e6b1e7aa5 | 378 | } |
maximusismax | 8:7c5e6b1e7aa5 | 379 | |
maximusismax | 31:1a06c9e1985e | 380 | //Unused function currently |
maximusismax | 31:1a06c9e1985e | 381 | //Was used to estimate whether the stop marker was seen |
FatCookies | 17:6ae90788cc2b | 382 | inline float getLineEntropy() { |
FatCookies | 17:6ae90788cc2b | 383 | float entropy = 0; |
FatCookies | 17:6ae90788cc2b | 384 | float last = (int8_t)(CLOSE_CAMERA[0] >> 4) & 0xFF; |
FatCookies | 17:6ae90788cc2b | 385 | for(int i = 1; i < 128; i++) { |
FatCookies | 17:6ae90788cc2b | 386 | entropy += abs(last - ((int8_t)(CLOSE_CAMERA[i] >> 4) & 0xFF)); |
FatCookies | 17:6ae90788cc2b | 387 | } |
FatCookies | 17:6ae90788cc2b | 388 | return entropy; |
FatCookies | 17:6ae90788cc2b | 389 | } |
FatCookies | 17:6ae90788cc2b | 390 | |
FatCookies | 17:6ae90788cc2b | 391 | void handlePID(pid_instance *pid) { |
FatCookies | 17:6ae90788cc2b | 392 | pid->dt = t.read(); |
FatCookies | 17:6ae90788cc2b | 393 | pid->pid_error = pid->desired_value - pid->measured_value; |
FatCookies | 17:6ae90788cc2b | 394 | pid->integral = pid->integral + pid->pid_error * pid->dt; |
FatCookies | 17:6ae90788cc2b | 395 | pid->derivative = (pid->pid_error - pid->p_error) / pid->dt; |
FatCookies | 17:6ae90788cc2b | 396 | pid->output = pid->Kp * pid->pid_error + pid->Ki * pid->integral + pid->Kd * pid->derivative; |
FatCookies | 17:6ae90788cc2b | 397 | pid->p_error = pid->pid_error; |
FatCookies | 17:6ae90788cc2b | 398 | |
FatCookies | 17:6ae90788cc2b | 399 | if(pid->integral > 1.0f) { |
maximusismax | 31:1a06c9e1985e | 400 | pid->integral = 1.0f; |
FatCookies | 17:6ae90788cc2b | 401 | } |
FatCookies | 27:627d67e3b9b0 | 402 | if(pid->integral < -1.0f ) { |
FatCookies | 17:6ae90788cc2b | 403 | pid->integral = -1.0f; |
FatCookies | 17:6ae90788cc2b | 404 | } |
FatCookies | 17:6ae90788cc2b | 405 | } |
FatCookies | 17:6ae90788cc2b | 406 | |
lh14g13 | 19:65f0b6febc23 | 407 | |
FatCookies | 17:6ae90788cc2b | 408 | inline void PIDController() { |
FatCookies | 27:627d67e3b9b0 | 409 | // update motor measurements |
lh14g13 | 19:65f0b6febc23 | 410 | // Read the angular velocity of both wheels |
FatCookies | 27:627d67e3b9b0 | 411 | |
FatCookies | 27:627d67e3b9b0 | 412 | prevL = wL; |
FatCookies | 27:627d67e3b9b0 | 413 | prevR = wR; |
FatCookies | 27:627d67e3b9b0 | 414 | |
lh14g13 | 19:65f0b6febc23 | 415 | wL=Get_Speed(Time_L); |
lh14g13 | 19:65f0b6febc23 | 416 | wR=Get_Speed(Time_R); |
lh14g13 | 52:af17b1a330f4 | 417 | if(!torque){ |
FatCookies | 20:ed954836d028 | 418 | // Check if left wheel is slipping/giving an abnormal reading and ignore reading |
lh14g13 | 52:af17b1a330f4 | 419 | if(wL - prevL < 1.2/0.025) { //<3 magic numbers: 48....? |
lh14g13 | 52:af17b1a330f4 | 420 | left_motor_pid.measured_value = wL; |
lh14g13 | 52:af17b1a330f4 | 421 | } |
lh14g13 | 52:af17b1a330f4 | 422 | if(wR - prevR < 1.2/0.025) { |
lh14g13 | 52:af17b1a330f4 | 423 | right_motor_pid.measured_value = wR; |
lh14g13 | 52:af17b1a330f4 | 424 | } |
FatCookies | 20:ed954836d028 | 425 | } |
FatCookies | 21:0b69fada7c5f | 426 | |
FatCookies | 17:6ae90788cc2b | 427 | //PID Stuff! |
FatCookies | 17:6ae90788cc2b | 428 | t.start(); |
FatCookies | 17:6ae90788cc2b | 429 | handlePID(&servo_pid); |
oj3g13 | 35:e23354abf352 | 430 | //enables the ED |
lh14g13 | 51:6a84fbc404c8 | 431 | //sensorCorner(left_motor_pid.desired_value,right_motor_pid.desired_value, servo_pid.output,speed,ed_tune); |
lh14g13 | 52:af17b1a330f4 | 432 | if(!torque){ |
lh14g13 | 52:af17b1a330f4 | 433 | handlePID(&left_motor_pid); |
lh14g13 | 52:af17b1a330f4 | 434 | handlePID(&right_motor_pid); |
lh14g13 | 52:af17b1a330f4 | 435 | } |
FatCookies | 17:6ae90788cc2b | 436 | if((-1.0 <= servo_pid.output) && (servo_pid.output <= 1.0)) |
FatCookies | 17:6ae90788cc2b | 437 | { |
FatCookies | 17:6ae90788cc2b | 438 | TFC_SetServo(0, servo_pid.output); |
FatCookies | 17:6ae90788cc2b | 439 | } |
FatCookies | 17:6ae90788cc2b | 440 | else //Unhappy PID state |
FatCookies | 17:6ae90788cc2b | 441 | { |
FatCookies | 17:6ae90788cc2b | 442 | //sendString("out = %f p_err = %f", servo_pid.output, servo_pid.p_error); |
maximusismax | 31:1a06c9e1985e | 443 | //ALIGN_SERVO; |
maximusismax | 31:1a06c9e1985e | 444 | //Could cause the car to be travelling along one side of the track rather than in the middle |
FatCookies | 17:6ae90788cc2b | 445 | if(servo_pid.output >= 1.0f) { |
FatCookies | 17:6ae90788cc2b | 446 | TFC_SetServo(0, 0.9f); |
FatCookies | 17:6ae90788cc2b | 447 | servo_pid.output = 1.0f; |
FatCookies | 17:6ae90788cc2b | 448 | } else { |
FatCookies | 17:6ae90788cc2b | 449 | TFC_SetServo(0, -0.9f); |
FatCookies | 17:6ae90788cc2b | 450 | servo_pid.output = -1.0f; |
FatCookies | 17:6ae90788cc2b | 451 | } |
FatCookies | 17:6ae90788cc2b | 452 | } |
FatCookies | 17:6ae90788cc2b | 453 | |
lh14g13 | 42:4395ede5781e | 454 | // stops the motors from going into reverse and from being set to a value higher than 1. |
FatCookies | 20:ed954836d028 | 455 | if(left_motor_pid.output > 1.0f) { |
FatCookies | 20:ed954836d028 | 456 | left_motor_pid.output = 1.0f; |
lh14g13 | 19:65f0b6febc23 | 457 | } |
lh14g13 | 47:6a58dcef714f | 458 | /*if(left_motor_pid.output > 0.75f) { |
lh14g13 | 46:6806ea59ffed | 459 | left_motor_pid.output = 0.75f; |
lh14g13 | 47:6a58dcef714f | 460 | }*/ |
FatCookies | 29:b5b31256572b | 461 | if(left_motor_pid.output < 0.0f) { |
FatCookies | 27:627d67e3b9b0 | 462 | left_motor_pid.output = 0.0f; |
lh14g13 | 19:65f0b6febc23 | 463 | } |
lh14g13 | 19:65f0b6febc23 | 464 | |
FatCookies | 20:ed954836d028 | 465 | if(right_motor_pid.output > 1.0f) { |
FatCookies | 20:ed954836d028 | 466 | right_motor_pid.output = 1.0f; |
FatCookies | 20:ed954836d028 | 467 | } |
lh14g13 | 46:6806ea59ffed | 468 | |
lh14g13 | 47:6a58dcef714f | 469 | /*if(right_motor_pid.output > 0.75f) { |
lh14g13 | 46:6806ea59ffed | 470 | right_motor_pid.output = 0.75f; |
lh14g13 | 47:6a58dcef714f | 471 | }*/ |
FatCookies | 29:b5b31256572b | 472 | if(right_motor_pid.output < 0.0f) { |
FatCookies | 27:627d67e3b9b0 | 473 | right_motor_pid.output = 0.0f; |
FatCookies | 20:ed954836d028 | 474 | } |
lh14g13 | 51:6a84fbc404c8 | 475 | if(!torque){ |
FatCookies | 20:ed954836d028 | 476 | TFC_SetMotorPWM(left_motor_pid.output,right_motor_pid.output); |
lh14g13 | 51:6a84fbc404c8 | 477 | } |
lh14g13 | 51:6a84fbc404c8 | 478 | else{ |
lh14g13 | 52:af17b1a330f4 | 479 | dutyCycleCorner(speed,servo_pid.output,man_tuner); |
lh14g13 | 51:6a84fbc404c8 | 480 | } |
FatCookies | 17:6ae90788cc2b | 481 | t.stop(); |
FatCookies | 17:6ae90788cc2b | 482 | t.reset(); |
FatCookies | 17:6ae90788cc2b | 483 | t.start(); |
FatCookies | 17:6ae90788cc2b | 484 | } |
FatCookies | 17:6ae90788cc2b | 485 | |
FatCookies | 17:6ae90788cc2b | 486 | inline void handleStartStop() { |
maximusismax | 31:1a06c9e1985e | 487 | |
maximusismax | 31:1a06c9e1985e | 488 | //Function to detect the NXP cup stop marker |
maximusismax | 22:973b95478663 | 489 | |
maximusismax | 31:1a06c9e1985e | 490 | int slower = 0; //Only send a string every few frames |
maximusismax | 31:1a06c9e1985e | 491 | int difference = 0; //Holds the difference between intensities of consecutive pixels |
oj3g13 | 26:f3d770f3eda1 | 492 | int lastPixel, currentPixel, transitionsSeen; |
maximusismax | 22:973b95478663 | 493 | lastPixel = -1; |
maximusismax | 22:973b95478663 | 494 | transitionsSeen = 0; |
maximusismax | 31:1a06c9e1985e | 495 | //Starting near the left edge, step right, counting transitions. |
maximusismax | 31:1a06c9e1985e | 496 | //If there are several (exact value varies, best established experimentally), it is the marker |
maximusismax | 22:973b95478663 | 497 | for(int i = 30; i < 98; i++) { |
oj3g13 | 26:f3d770f3eda1 | 498 | currentPixel = (int)(CLOSE_CAMERA[i] >> 4) & 0xFF; |
maximusismax | 22:973b95478663 | 499 | difference = lastPixel - currentPixel; |
FatCookies | 27:627d67e3b9b0 | 500 | if(abs(difference) > 10 && lastPixel != -1){ //transition seen, increment counter |
maximusismax | 22:973b95478663 | 501 | transitionsSeen++; |
oj3g13 | 26:f3d770f3eda1 | 502 | i+=5; |
maximusismax | 22:973b95478663 | 503 | } |
maximusismax | 22:973b95478663 | 504 | lastPixel = currentPixel; |
maximusismax | 22:973b95478663 | 505 | } |
maximusismax | 31:1a06c9e1985e | 506 | //Was used to send an indication that the marker was seen, useful for debugging |
FatCookies | 45:3435bdd2d487 | 507 | //if (slower % 1000 == `0) { |
oj3g13 | 26:f3d770f3eda1 | 508 | //sendString("Transitions seen: %d", transitionsSeen); |
oj3g13 | 26:f3d770f3eda1 | 509 | //} |
maximusismax | 31:1a06c9e1985e | 510 | //slower++; |
oj3g13 | 26:f3d770f3eda1 | 511 | if(transitionsSeen >= 5) { |
maximusismax | 22:973b95478663 | 512 | //Stop the car! |
FatCookies | 43:649473c5a12b | 513 | #if USE_COMMS |
FatCookies | 45:3435bdd2d487 | 514 | //sendString("Start/stop seen"); |
FatCookies | 45:3435bdd2d487 | 515 | //lapTime(); |
FatCookies | 43:649473c5a12b | 516 | #endif |
oj3g13 | 26:f3d770f3eda1 | 517 | TFC_SetMotorPWM(0.f,0.f); |
oj3g13 | 26:f3d770f3eda1 | 518 | TFC_HBRIDGE_DISABLE; |
FatCookies | 43:649473c5a12b | 519 | |
oj3g13 | 26:f3d770f3eda1 | 520 | } |
FatCookies | 17:6ae90788cc2b | 521 | } |
FatCookies | 17:6ae90788cc2b | 522 | |
FatCookies | 45:3435bdd2d487 | 523 | float checkAcc() { |
lh14g13 | 48:daa2a1900ada | 524 | return abs(acc.getAccZ()); |
FatCookies | 45:3435bdd2d487 | 525 | } |
FatCookies | 45:3435bdd2d487 | 526 | |
FatCookies | 17:6ae90788cc2b | 527 | |
FatCookies | 17:6ae90788cc2b | 528 | inline void initSpeedSensors() { |
FatCookies | 17:6ae90788cc2b | 529 | t1.start(); |
FatCookies | 17:6ae90788cc2b | 530 | t2.start(); |
FatCookies | 17:6ae90788cc2b | 531 | |
FatCookies | 17:6ae90788cc2b | 532 | //Left and Right are defined looking at the rear of the car, in the direction the camera points at. |
FatCookies | 17:6ae90788cc2b | 533 | leftHallSensor.rise(&GetTime_L); |
FatCookies | 17:6ae90788cc2b | 534 | rightHallSensor.rise(&GetTime_R); |
FatCookies | 17:6ae90788cc2b | 535 | } |
FatCookies | 17:6ae90788cc2b | 536 | |
FatCookies | 17:6ae90788cc2b | 537 | void GetTime_L(){ |
FatCookies | 17:6ae90788cc2b | 538 | Time_L=t1.read_us(); |
FatCookies | 17:6ae90788cc2b | 539 | t1.reset(); |
FatCookies | 17:6ae90788cc2b | 540 | } |
FatCookies | 17:6ae90788cc2b | 541 | |
FatCookies | 17:6ae90788cc2b | 542 | void GetTime_R(){ |
FatCookies | 17:6ae90788cc2b | 543 | Time_R=t2.read_us(); |
FatCookies | 17:6ae90788cc2b | 544 | t2.reset(); |
FatCookies | 17:6ae90788cc2b | 545 | } |
FatCookies | 17:6ae90788cc2b | 546 | |
FatCookies | 17:6ae90788cc2b | 547 | #if USE_COMMS |
FatCookies | 17:6ae90788cc2b | 548 | void sendBattery() { |
FatCookies | 17:6ae90788cc2b | 549 | |
FatCookies | 17:6ae90788cc2b | 550 | if(frame_counter % 256 == 0) { |
FatCookies | 17:6ae90788cc2b | 551 | float level = TFC_ReadBatteryVoltage() * 6.25; |
FatCookies | 40:10e8e80af7da | 552 | pc.putc(BATTERY_LEVEL); |
FatCookies | 43:649473c5a12b | 553 | writeFloat(level); |
FatCookies | 17:6ae90788cc2b | 554 | } |
FatCookies | 17:6ae90788cc2b | 555 | } |
FatCookies | 17:6ae90788cc2b | 556 | |
FatCookies | 17:6ae90788cc2b | 557 | void sendString(const char *format, ...) { |
FatCookies | 17:6ae90788cc2b | 558 | va_list arg; |
FatCookies | 17:6ae90788cc2b | 559 | |
FatCookies | 40:10e8e80af7da | 560 | pc.putc(STATUS_STRING); |
FatCookies | 17:6ae90788cc2b | 561 | va_start (arg, format); |
FatCookies | 17:6ae90788cc2b | 562 | pc.vprintf(format,arg); |
FatCookies | 17:6ae90788cc2b | 563 | va_end (arg); |
FatCookies | 17:6ae90788cc2b | 564 | pc.putc(0); |
FatCookies | 17:6ae90788cc2b | 565 | } |
FatCookies | 17:6ae90788cc2b | 566 | |
maximusismax | 8:7c5e6b1e7aa5 | 567 | inline void sendImage() { |
maximusismax | 8:7c5e6b1e7aa5 | 568 | //Only send 1/3 of camera frames to GUI program |
maximusismax | 8:7c5e6b1e7aa5 | 569 | if((frame_counter % 3) == 0) { |
FatCookies | 40:10e8e80af7da | 570 | pc.putc(SEND_LINE); |
FatCookies | 15:ccde02f96449 | 571 | if(sendCam == 0) { |
FatCookies | 15:ccde02f96449 | 572 | for(i = 0; i < 128; i++) { |
FatCookies | 17:6ae90788cc2b | 573 | pc.putc((int8_t)(CLOSE_CAMERA[i] >> 4) & 0xFF); |
FatCookies | 15:ccde02f96449 | 574 | } |
FatCookies | 15:ccde02f96449 | 575 | } else { |
FatCookies | 15:ccde02f96449 | 576 | for(i = 0; i < 128; i++) { |
FatCookies | 17:6ae90788cc2b | 577 | pc.putc((int8_t)(LOOKAHEAD_CAMERA[i] >> 4) & 0xFF); |
FatCookies | 15:ccde02f96449 | 578 | } |
FatCookies | 15:ccde02f96449 | 579 | } |
FatCookies | 13:4e77264f254a | 580 | sendBattery(); |
FatCookies | 13:4e77264f254a | 581 | } |
FatCookies | 13:4e77264f254a | 582 | |
FatCookies | 13:4e77264f254a | 583 | frame_counter++; |
FatCookies | 13:4e77264f254a | 584 | } |
FatCookies | 13:4e77264f254a | 585 | |
FatCookies | 13:4e77264f254a | 586 | inline void sendSpeeds() { |
FatCookies | 43:649473c5a12b | 587 | pc.putc(SEND_SPEEDS); |
FatCookies | 43:649473c5a12b | 588 | writeFloat(wL * WHEEL_RADIUS); |
FatCookies | 43:649473c5a12b | 589 | writeFloat(wR * WHEEL_RADIUS); |
FatCookies | 43:649473c5a12b | 590 | } |
FatCookies | 14:13085e161dd1 | 591 | |
FatCookies | 43:649473c5a12b | 592 | void writeFloat(float f) { |
FatCookies | 43:649473c5a12b | 593 | byte_float_union._float = f; |
FatCookies | 27:627d67e3b9b0 | 594 | pc.putc(byte_float_union.bytes[0]); |
FatCookies | 27:627d67e3b9b0 | 595 | pc.putc(byte_float_union.bytes[1]); |
FatCookies | 27:627d67e3b9b0 | 596 | pc.putc(byte_float_union.bytes[2]); |
FatCookies | 27:627d67e3b9b0 | 597 | pc.putc(byte_float_union.bytes[3]); |
maximusismax | 8:7c5e6b1e7aa5 | 598 | } |
maximusismax | 8:7c5e6b1e7aa5 | 599 | |
FatCookies | 41:d74878640739 | 600 | float readFloat() { |
FatCookies | 41:d74878640739 | 601 | byte_float_union.bytes[0] = xb.cBuffer->read(); |
FatCookies | 41:d74878640739 | 602 | byte_float_union.bytes[1] = xb.cBuffer->read(); |
FatCookies | 41:d74878640739 | 603 | byte_float_union.bytes[2] = xb.cBuffer->read(); |
FatCookies | 41:d74878640739 | 604 | byte_float_union.bytes[3] = xb.cBuffer->read(); |
FatCookies | 41:d74878640739 | 605 | return byte_float_union._float; |
FatCookies | 41:d74878640739 | 606 | } |
FatCookies | 41:d74878640739 | 607 | |
FatCookies | 40:10e8e80af7da | 608 | // Listen for incoming commands from telemetry program and change car variables |
maximusismax | 8:7c5e6b1e7aa5 | 609 | inline void handleComms() { |
maximusismax | 8:7c5e6b1e7aa5 | 610 | if(curr_cmd != 0) { |
FatCookies | 4:4afa448c9cce | 611 | switch(curr_cmd) { |
FatCookies | 40:10e8e80af7da | 612 | // Change the PID values of the servo controller |
FatCookies | 40:10e8e80af7da | 613 | case CHANGE_PID: |
FatCookies | 20:ed954836d028 | 614 | if(xb.cBuffer->available() >= 12) { |
FatCookies | 20:ed954836d028 | 615 | |
FatCookies | 41:d74878640739 | 616 | servo_pid.Kp = readFloat(); |
FatCookies | 41:d74878640739 | 617 | servo_pid.Ki = readFloat(); |
FatCookies | 41:d74878640739 | 618 | servo_pid.Kd = readFloat(); |
FatCookies | 20:ed954836d028 | 619 | |
FatCookies | 20:ed954836d028 | 620 | sendString("pid= Kp: %f, Ki: %f, Kd: %f", servo_pid.Kp, servo_pid.Ki, servo_pid.Kd); |
maximusismax | 8:7c5e6b1e7aa5 | 621 | |
FatCookies | 4:4afa448c9cce | 622 | curr_cmd = 0; |
FatCookies | 4:4afa448c9cce | 623 | } |
FatCookies | 4:4afa448c9cce | 624 | break; |
FatCookies | 4:4afa448c9cce | 625 | |
FatCookies | 40:10e8e80af7da | 626 | // Set the maximum speed that the motor controllers should attempt to drive the car to |
FatCookies | 40:10e8e80af7da | 627 | case MAX_SPEED: |
FatCookies | 6:b0e160c51013 | 628 | if(xb.cBuffer->available() >= 1) { |
FatCookies | 4:4afa448c9cce | 629 | char a = xb.cBuffer->read(); |
FatCookies | 27:627d67e3b9b0 | 630 | speed = a; |
FatCookies | 13:4e77264f254a | 631 | sendString("s = %u %f",a, speed); |
FatCookies | 4:4afa448c9cce | 632 | curr_cmd = 0; |
FatCookies | 29:b5b31256572b | 633 | right_motor_pid.desired_value=speed; |
FatCookies | 29:b5b31256572b | 634 | left_motor_pid.desired_value=speed; |
FatCookies | 4:4afa448c9cce | 635 | } |
FatCookies | 4:4afa448c9cce | 636 | break; |
lh14g13 | 39:7b28ee39185d | 637 | |
FatCookies | 40:10e8e80af7da | 638 | // Change the electronic differential coefficient |
FatCookies | 40:10e8e80af7da | 639 | case CHANGE_ED: |
lh14g13 | 39:7b28ee39185d | 640 | if(xb.cBuffer->available() >= 4) { |
FatCookies | 41:d74878640739 | 641 | ed_tune = readFloat(); |
lh14g13 | 39:7b28ee39185d | 642 | curr_cmd = 0; |
lh14g13 | 39:7b28ee39185d | 643 | } |
lh14g13 | 39:7b28ee39185d | 644 | break; |
FatCookies | 4:4afa448c9cce | 645 | |
FatCookies | 4:4afa448c9cce | 646 | default: |
FatCookies | 13:4e77264f254a | 647 | // Unrecognised command |
FatCookies | 13:4e77264f254a | 648 | curr_cmd = 0; |
FatCookies | 4:4afa448c9cce | 649 | break; |
FatCookies | 4:4afa448c9cce | 650 | } |
FatCookies | 4:4afa448c9cce | 651 | } |
FatCookies | 4:4afa448c9cce | 652 | |
FatCookies | 6:b0e160c51013 | 653 | if(xb.cBuffer->available() > 0 && curr_cmd == 0) { |
FatCookies | 40:10e8e80af7da | 654 | |
FatCookies | 4:4afa448c9cce | 655 | char cmd = xb.cBuffer->read(); |
FatCookies | 40:10e8e80af7da | 656 | |
FatCookies | 40:10e8e80af7da | 657 | //Start car the car motors |
FatCookies | 40:10e8e80af7da | 658 | if(cmd == START) { |
FatCookies | 17:6ae90788cc2b | 659 | ALIGN_SERVO; |
FatCookies | 21:0b69fada7c5f | 660 | right_motor_pid.desired_value=speed; |
FatCookies | 21:0b69fada7c5f | 661 | left_motor_pid.desired_value=speed; |
FatCookies | 4:4afa448c9cce | 662 | TFC_HBRIDGE_ENABLE; |
FatCookies | 29:b5b31256572b | 663 | |
FatCookies | 21:0b69fada7c5f | 664 | |
FatCookies | 12:da96e2f87465 | 665 | servo_pid.integral = 0; |
FatCookies | 27:627d67e3b9b0 | 666 | lapTimer.start(); |
lh14g13 | 18:0095a3a8f8e4 | 667 | lapNo =0; |
FatCookies | 6:b0e160c51013 | 668 | |
FatCookies | 40:10e8e80af7da | 669 | // Stop the car motors |
FatCookies | 40:10e8e80af7da | 670 | } else if (cmd == STOP) { |
FatCookies | 4:4afa448c9cce | 671 | TFC_SetMotorPWM(0.0,0.0); |
lh14g13 | 19:65f0b6febc23 | 672 | right_motor_pid.desired_value=0; |
FatCookies | 21:0b69fada7c5f | 673 | right_motor_pid.measured_value = 0; |
FatCookies | 21:0b69fada7c5f | 674 | wR = 0; |
FatCookies | 21:0b69fada7c5f | 675 | prevR = 0; |
FatCookies | 21:0b69fada7c5f | 676 | |
lh14g13 | 19:65f0b6febc23 | 677 | left_motor_pid.desired_value=0; |
FatCookies | 21:0b69fada7c5f | 678 | left_motor_pid.measured_value = 0; |
FatCookies | 21:0b69fada7c5f | 679 | wL = 0; |
FatCookies | 21:0b69fada7c5f | 680 | prevL = 0; |
FatCookies | 21:0b69fada7c5f | 681 | |
FatCookies | 4:4afa448c9cce | 682 | TFC_HBRIDGE_DISABLE; |
lh14g13 | 18:0095a3a8f8e4 | 683 | endTest(); |
FatCookies | 40:10e8e80af7da | 684 | |
FatCookies | 40:10e8e80af7da | 685 | // Change the PID values of the servo controller |
FatCookies | 40:10e8e80af7da | 686 | } else if(cmd == CHANGE_PID) { |
FatCookies | 40:10e8e80af7da | 687 | curr_cmd = CHANGE_PID; |
FatCookies | 40:10e8e80af7da | 688 | |
FatCookies | 40:10e8e80af7da | 689 | // Set the maximum speed of the motor controllers |
FatCookies | 40:10e8e80af7da | 690 | } else if(cmd == MAX_SPEED) { |
FatCookies | 40:10e8e80af7da | 691 | curr_cmd = MAX_SPEED; |
FatCookies | 40:10e8e80af7da | 692 | |
FatCookies | 40:10e8e80af7da | 693 | // Switch the camera data that is sent over telemetry |
FatCookies | 40:10e8e80af7da | 694 | } else if(cmd == SWITCH_CAM) { |
FatCookies | 15:ccde02f96449 | 695 | sendCam = ~sendCam; |
FatCookies | 40:10e8e80af7da | 696 | |
FatCookies | 40:10e8e80af7da | 697 | // Modify the electronic differential coefficient |
FatCookies | 40:10e8e80af7da | 698 | } else if(cmd == CHANGE_ED) { |
FatCookies | 40:10e8e80af7da | 699 | curr_cmd = CHANGE_ED; |
FatCookies | 4:4afa448c9cce | 700 | } |
FatCookies | 4:4afa448c9cce | 701 | |
FatCookies | 4:4afa448c9cce | 702 | } |
maximusismax | 8:7c5e6b1e7aa5 | 703 | } |
lh14g13 | 18:0095a3a8f8e4 | 704 | |
lh14g13 | 18:0095a3a8f8e4 | 705 | float testSpeed(float speed) |
lh14g13 | 18:0095a3a8f8e4 | 706 | { |
lh14g13 | 18:0095a3a8f8e4 | 707 | // search: Speed Increase |
lh14g13 | 18:0095a3a8f8e4 | 708 | // every time the car sees the stop start the speed of the car will increase |
lh14g13 | 18:0095a3a8f8e4 | 709 | // this can occur on stop start trigger. |
lh14g13 | 18:0095a3a8f8e4 | 710 | // may need to send the speed back to the telemetry. |
lh14g13 | 18:0095a3a8f8e4 | 711 | if (speed>0.4) |
lh14g13 | 18:0095a3a8f8e4 | 712 | { |
lh14g13 | 18:0095a3a8f8e4 | 713 | speed+=0.05; |
lh14g13 | 18:0095a3a8f8e4 | 714 | } |
lh14g13 | 18:0095a3a8f8e4 | 715 | |
lh14g13 | 18:0095a3a8f8e4 | 716 | else |
lh14g13 | 18:0095a3a8f8e4 | 717 | { |
lh14g13 | 18:0095a3a8f8e4 | 718 | speed+=0.1; |
lh14g13 | 18:0095a3a8f8e4 | 719 | |
lh14g13 | 18:0095a3a8f8e4 | 720 | } |
lh14g13 | 18:0095a3a8f8e4 | 721 | |
lh14g13 | 18:0095a3a8f8e4 | 722 | |
lh14g13 | 18:0095a3a8f8e4 | 723 | sendString("s = %f", speed); |
lh14g13 | 18:0095a3a8f8e4 | 724 | return speed; |
lh14g13 | 18:0095a3a8f8e4 | 725 | |
lh14g13 | 18:0095a3a8f8e4 | 726 | } |
lh14g13 | 18:0095a3a8f8e4 | 727 | |
lh14g13 | 18:0095a3a8f8e4 | 728 | |
lh14g13 | 18:0095a3a8f8e4 | 729 | |
lh14g13 | 18:0095a3a8f8e4 | 730 | int lapTime() |
lh14g13 | 19:65f0b6febc23 | 731 | { |
lh14g13 | 18:0095a3a8f8e4 | 732 | // function which sends the lap time back to the telemetry. |
lh14g13 | 32:6829684f8c4d | 733 | //reads the timer |
FatCookies | 27:627d67e3b9b0 | 734 | float newTime= lapTimer.read(); |
lh14g13 | 18:0095a3a8f8e4 | 735 | lapNo += 1; |
lh14g13 | 18:0095a3a8f8e4 | 736 | float lapTime= newTime-oldTime; |
lh14g13 | 18:0095a3a8f8e4 | 737 | float avgTime= newTime/lapNo; |
lh14g13 | 32:6829684f8c4d | 738 | // this calulates the average lap time and the lap time. |
lh14g13 | 32:6829684f8c4d | 739 | //then sends the information back to the UI. |
lh14g13 | 19:65f0b6febc23 | 740 | sendString("For lap number: %d Lap Time: %f Avergae time: %f \n\r", lapNo,lapTime,avgTime); |
lh14g13 | 18:0095a3a8f8e4 | 741 | |
lh14g13 | 32:6829684f8c4d | 742 | |
lh14g13 | 18:0095a3a8f8e4 | 743 | return 0; |
lh14g13 | 18:0095a3a8f8e4 | 744 | } |
lh14g13 | 18:0095a3a8f8e4 | 745 | |
lh14g13 | 18:0095a3a8f8e4 | 746 | |
lh14g13 | 18:0095a3a8f8e4 | 747 | void endTest() |
lh14g13 | 18:0095a3a8f8e4 | 748 | {// This runs when the car has stopped, this should give the final elapsed time and othere things. this also stops the timer |
lh14g13 | 18:0095a3a8f8e4 | 749 | |
FatCookies | 27:627d67e3b9b0 | 750 | float time= lapTimer.read(); |
lh14g13 | 18:0095a3a8f8e4 | 751 | |
lh14g13 | 19:65f0b6febc23 | 752 | sendString("Laps done: %d Time elapsed: %f Average time: %f \n\r",lapNo, time,float (time/lapNo)); |
FatCookies | 27:627d67e3b9b0 | 753 | lapTimer.stop(); |
lh14g13 | 18:0095a3a8f8e4 | 754 | |
lh14g13 | 18:0095a3a8f8e4 | 755 | |
lh14g13 | 19:65f0b6febc23 | 756 | } |
lh14g13 | 33:0fc789c09694 | 757 | //motor controll specific(newfunction) |
lh14g13 | 18:0095a3a8f8e4 | 758 | |
lh14g13 | 18:0095a3a8f8e4 | 759 | |
lh14g13 | 18:0095a3a8f8e4 | 760 | |
lh14g13 | 18:0095a3a8f8e4 | 761 | |
FatCookies | 17:6ae90788cc2b | 762 | #endif |