James Heavey / Mbed 2 deprecated 3875_DISSERTATION

Dependencies:   mbed 3875_Individualproject

Committer:
jamesheavey
Date:
Mon Feb 24 04:51:39 2020 +0000
Revision:
10:691c02b352cb
Parent:
9:952586accbf9
Child:
11:c3299aca7d8f
Fix goal function, fix junction detector, make the invert path and return to start functions work, add interrupts

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jamesheavey 0:df5216b20861 1 #include "main.h"
jamesheavey 0:df5216b20861 2
jamesheavey 0:df5216b20861 3 // API
jamesheavey 0:df5216b20861 4 m3pi robot;
jamesheavey 0:df5216b20861 5
jamesheavey 0:df5216b20861 6 // LEDs
jamesheavey 0:df5216b20861 7 BusOut leds(LED4,LED3,LED2,LED1);
jamesheavey 0:df5216b20861 8
jamesheavey 0:df5216b20861 9 // Buttons
jamesheavey 0:df5216b20861 10 DigitalIn button_A(p18);
jamesheavey 0:df5216b20861 11 DigitalIn button_B(p17);
jamesheavey 0:df5216b20861 12 DigitalIn button_X(p21);
jamesheavey 0:df5216b20861 13 DigitalIn button_Y(p22);
jamesheavey 0:df5216b20861 14 DigitalIn button_enter(p24);
jamesheavey 0:df5216b20861 15 DigitalIn button_back(p23);
jamesheavey 0:df5216b20861 16
jamesheavey 0:df5216b20861 17 // Potentiometers
jamesheavey 0:df5216b20861 18 AnalogIn pot_P(p15);
jamesheavey 0:df5216b20861 19 AnalogIn pot_I(p16);
jamesheavey 0:df5216b20861 20 AnalogIn pot_D(p19);
jamesheavey 0:df5216b20861 21 AnalogIn pot_S(p20);
jamesheavey 0:df5216b20861 22
jamesheavey 0:df5216b20861 23 // Prototypes
jamesheavey 0:df5216b20861 24 void init();
jamesheavey 0:df5216b20861 25 void calibrate();
jamesheavey 10:691c02b352cb 26 void follow_line();
jamesheavey 7:7fefd782532d 27 char junction_detect();
jamesheavey 1:79219d0a33c8 28 void turn_selector( char turn );
jamesheavey 0:df5216b20861 29 void left();
jamesheavey 1:79219d0a33c8 30 void right();
jamesheavey 0:df5216b20861 31 void back();
jamesheavey 2:940e46e21353 32 void goal();
jamesheavey 2:940e46e21353 33 void simplify();
jamesheavey 10:691c02b352cb 34 void invert_path();
jamesheavey 0:df5216b20861 35
jamesheavey 0:df5216b20861 36 // Constants
jamesheavey 0:df5216b20861 37
jamesheavey 0:df5216b20861 38 const float A = 0.5; // 20
jamesheavey 0:df5216b20861 39 const float B = 1/10000; // 10000
jamesheavey 4:38c29dbc5953 40 const float C = 1.5; // 2/3
jamesheavey 0:df5216b20861 41
jamesheavey 5:ae417756235a 42 const int sens_thresh = 500; // replace the hard coded bits
jamesheavey 4:38c29dbc5953 43 const int turn_speed = 0.2;
jamesheavey 2:940e46e21353 44
jamesheavey 2:940e46e21353 45 // Global Variables
jamesheavey 2:940e46e21353 46
jamesheavey 2:940e46e21353 47 char path[100];
jamesheavey 10:691c02b352cb 48 char inv_path[100];
jamesheavey 2:940e46e21353 49 int path_length = 0;
jamesheavey 2:940e46e21353 50 unsigned int *sensor;
jamesheavey 3:a5e06482462e 51 float speed;
jamesheavey 10:691c02b352cb 52 float proportional = 0.0;
jamesheavey 10:691c02b352cb 53 float prev_proportional = 0.0;
jamesheavey 10:691c02b352cb 54 float integral = 0.0;
jamesheavey 10:691c02b352cb 55 float derivative = 0.0;
jamesheavey 2:940e46e21353 56
jamesheavey 2:940e46e21353 57 // Main
jamesheavey 2:940e46e21353 58
jamesheavey 0:df5216b20861 59 int main()
jamesheavey 0:df5216b20861 60 {
jamesheavey 0:df5216b20861 61 init();
jamesheavey 0:df5216b20861 62 calibrate();
jamesheavey 5:ae417756235a 63 speed = (pot_S*0.3)+0.2; // have it so max is 0.5 and min is 0.2
jamesheavey 0:df5216b20861 64
jamesheavey 0:df5216b20861 65 float dt = 1/50; // updating 50 times a second
jamesheavey 0:df5216b20861 66
jamesheavey 0:df5216b20861 67 while (1) {
jamesheavey 10:691c02b352cb 68
jamesheavey 10:691c02b352cb 69 follow_line();
jamesheavey 10:691c02b352cb 70
jamesheavey 10:691c02b352cb 71 char turn = junction_detect(); // rename this function something else
jamesheavey 10:691c02b352cb 72 turn_selector(turn);
jamesheavey 10:691c02b352cb 73 if ( turn != 'S' ) { // doesnt need 'S', also may not need 'R' as that is not technically a junction
jamesheavey 10:691c02b352cb 74 path[path_length] = turn;
jamesheavey 10:691c02b352cb 75 path_length ++;
jamesheavey 0:df5216b20861 76 }
jamesheavey 0:df5216b20861 77
jamesheavey 4:38c29dbc5953 78 simplify();
jamesheavey 4:38c29dbc5953 79
jamesheavey 4:38c29dbc5953 80 robot.lcd_clear();
jamesheavey 4:38c29dbc5953 81 robot.lcd_print(path,100);
jamesheavey 4:38c29dbc5953 82
jamesheavey 4:38c29dbc5953 83 //robot.display_data();
jamesheavey 0:df5216b20861 84
jamesheavey 0:df5216b20861 85 wait(dt);
jamesheavey 0:df5216b20861 86 }
jamesheavey 0:df5216b20861 87 }
jamesheavey 0:df5216b20861 88
jamesheavey 0:df5216b20861 89 void init()
jamesheavey 0:df5216b20861 90 {
jamesheavey 0:df5216b20861 91 robot.init();
jamesheavey 0:df5216b20861 92
jamesheavey 0:df5216b20861 93 button_A.mode(PullUp);
jamesheavey 0:df5216b20861 94 button_B.mode(PullUp);
jamesheavey 0:df5216b20861 95 button_X.mode(PullUp);
jamesheavey 0:df5216b20861 96 button_Y.mode(PullUp);
jamesheavey 0:df5216b20861 97 button_enter.mode(PullUp);
jamesheavey 0:df5216b20861 98 button_back.mode(PullUp);
jamesheavey 0:df5216b20861 99
jamesheavey 10:691c02b352cb 100 leds = 0b0000;
jamesheavey 0:df5216b20861 101 }
jamesheavey 0:df5216b20861 102
jamesheavey 0:df5216b20861 103 void calibrate()
jamesheavey 0:df5216b20861 104 {
jamesheavey 0:df5216b20861 105 leds = 0b1111;
jamesheavey 0:df5216b20861 106 robot.reset_calibration();
jamesheavey 0:df5216b20861 107
jamesheavey 0:df5216b20861 108 while (button_enter.read() == 1) {} // keep looping waiting for Enter to be pressed
jamesheavey 0:df5216b20861 109
jamesheavey 0:df5216b20861 110 wait(2.0); // small delay to allow hands to move away etc.
jamesheavey 0:df5216b20861 111
jamesheavey 0:df5216b20861 112 robot.auto_calibrate(); // run calibration routine
jamesheavey 0:df5216b20861 113 leds = 0b0000;
jamesheavey 0:df5216b20861 114 }
jamesheavey 0:df5216b20861 115
jamesheavey 10:691c02b352cb 116 void follow_line()
jamesheavey 0:df5216b20861 117 {
jamesheavey 10:691c02b352cb 118 robot.scan();
jamesheavey 10:691c02b352cb 119 sensor = robot.get_sensors(); // returns the current values of all the sensors from 0-1000
jamesheavey 10:691c02b352cb 120
jamesheavey 10:691c02b352cb 121 proportional = robot.read_line(); // returns a value between -1,1 (-1 = PC0 or further , -1 to -0.5 = PC1 (-0.5 is directly below PC1) , -0.5 to 0 = PC2 , 0 to 0.5 = PC3 , 0.5 to 1 and further = PC4)
jamesheavey 10:691c02b352cb 122 derivative = proportional - prev_proportional;
jamesheavey 10:691c02b352cb 123 integral += proportional;
jamesheavey 10:691c02b352cb 124 prev_proportional = proportional;
jamesheavey 10:691c02b352cb 125
jamesheavey 10:691c02b352cb 126 // calculate motor correction
jamesheavey 10:691c02b352cb 127 float motor_correction = proportional*A + integral*B + derivative*C;
jamesheavey 10:691c02b352cb 128
jamesheavey 10:691c02b352cb 129 // make sure the correction is never greater than the max speed as the motor will reverse
jamesheavey 10:691c02b352cb 130 if( motor_correction > speed ) {
jamesheavey 10:691c02b352cb 131 motor_correction = speed;
jamesheavey 10:691c02b352cb 132 }
jamesheavey 10:691c02b352cb 133 if( motor_correction < -speed ) {
jamesheavey 10:691c02b352cb 134 motor_correction = -speed;
jamesheavey 10:691c02b352cb 135 }
jamesheavey 0:df5216b20861 136
jamesheavey 10:691c02b352cb 137 if( proportional < 0 ) {
jamesheavey 10:691c02b352cb 138 robot.motors(speed+motor_correction,speed);
jamesheavey 10:691c02b352cb 139 } else {
jamesheavey 10:691c02b352cb 140 robot.motors(speed,speed-motor_correction);
jamesheavey 10:691c02b352cb 141 }
jamesheavey 1:79219d0a33c8 142 }
jamesheavey 0:df5216b20861 143
jamesheavey 7:7fefd782532d 144 char junction_detect()
jamesheavey 6:c10b367747a0 145 {
jamesheavey 7:7fefd782532d 146 bool left = false;
jamesheavey 6:c10b367747a0 147 bool right = false;
jamesheavey 7:7fefd782532d 148 bool straight = false;
jamesheavey 9:952586accbf9 149 bool goal = false;
jamesheavey 7:7fefd782532d 150
jamesheavey 7:7fefd782532d 151 if (sensor[0] > sens_thresh || sensor[4] > sens_thresh) {
jamesheavey 7:7fefd782532d 152 if (sensor[0] > sens_thresh) {
jamesheavey 7:7fefd782532d 153 left = true;
jamesheavey 7:7fefd782532d 154 while ( sensor[0] > sens_thresh && (sensor[1] > sens_thresh && sensor[2] > sens_thresh && sensor[3] > sens_thresh) ) {
jamesheavey 7:7fefd782532d 155 robot.forward(speed);
jamesheavey 7:7fefd782532d 156 robot.scan();
jamesheavey 7:7fefd782532d 157 if (sensor[4] > sens_thresh) {
jamesheavey 7:7fefd782532d 158 right = true;
jamesheavey 7:7fefd782532d 159 }
jamesheavey 7:7fefd782532d 160 }
jamesheavey 7:7fefd782532d 161
jamesheavey 9:952586accbf9 162 robot.scan();
jamesheavey 9:952586accbf9 163
jamesheavey 7:7fefd782532d 164 if ( sensor[0] > sens_thresh && (sensor[1] < sens_thresh && sensor[2] < sens_thresh && sensor[3] < sens_thresh) ) {
jamesheavey 7:7fefd782532d 165 if ( sensor[0] > sens_thresh && (sensor[1] < sens_thresh && sensor[2] < sens_thresh && sensor[3] < sens_thresh) ) {
jamesheavey 9:952586accbf9 166 goal = true;
jamesheavey 7:7fefd782532d 167 }
jamesheavey 7:7fefd782532d 168 }
jamesheavey 7:7fefd782532d 169
jamesheavey 9:952586accbf9 170 robot.scan();
jamesheavey 6:c10b367747a0 171
jamesheavey 7:7fefd782532d 172 if ( sensor[1] > sens_thresh || sensor[2] > sens_thresh || sensor[3] > sens_thresh ) {
jamesheavey 7:7fefd782532d 173 straight = true;
jamesheavey 7:7fefd782532d 174 }
jamesheavey 7:7fefd782532d 175 }
jamesheavey 7:7fefd782532d 176
jamesheavey 7:7fefd782532d 177 else if (sensor[4] > sens_thresh) {
jamesheavey 7:7fefd782532d 178 right = true;
jamesheavey 7:7fefd782532d 179 while ( sensor[4] > sens_thresh && (sensor[1] > sens_thresh && sensor[2] > sens_thresh && sensor[3] > sens_thresh) ) {
jamesheavey 7:7fefd782532d 180 robot.forward(speed);
jamesheavey 7:7fefd782532d 181 robot.scan();
jamesheavey 7:7fefd782532d 182 if (sensor[0] > sens_thresh) {
jamesheavey 7:7fefd782532d 183 left = true;
jamesheavey 7:7fefd782532d 184 }
jamesheavey 7:7fefd782532d 185 }
jamesheavey 7:7fefd782532d 186
jamesheavey 9:952586accbf9 187 robot.scan();
jamesheavey 9:952586accbf9 188
jamesheavey 7:7fefd782532d 189 if ( sensor[1] > sens_thresh || sensor[2] > sens_thresh || sensor[3] > sens_thresh ) {
jamesheavey 7:7fefd782532d 190 straight = true;
jamesheavey 7:7fefd782532d 191 }
jamesheavey 7:7fefd782532d 192 }
jamesheavey 7:7fefd782532d 193
jamesheavey 9:952586accbf9 194 } else if (sensor[1] < sens_thresh && sensor[2] < sens_thresh && sensor[3] < sens_thresh) {
jamesheavey 9:952586accbf9 195 return 'B';
jamesheavey 6:c10b367747a0 196 }
jamesheavey 7:7fefd782532d 197
jamesheavey 9:952586accbf9 198 if (goal) {
jamesheavey 9:952586accbf9 199 return 'G';
jamesheavey 9:952586accbf9 200 } else if (left) {
jamesheavey 9:952586accbf9 201 return 'L';
jamesheavey 9:952586accbf9 202 } else if (straight) {
jamesheavey 9:952586accbf9 203 return 'S';
jamesheavey 9:952586accbf9 204 } else if (right) {
jamesheavey 9:952586accbf9 205 return 'R';
jamesheavey 6:c10b367747a0 206 } else {
jamesheavey 9:952586accbf9 207 return 'S';
jamesheavey 9:952586accbf9 208 }
jamesheavey 6:c10b367747a0 209 }
jamesheavey 6:c10b367747a0 210
jamesheavey 0:df5216b20861 211
jamesheavey 1:79219d0a33c8 212 void turn_selector( char turn )
jamesheavey 1:79219d0a33c8 213 {
jamesheavey 1:79219d0a33c8 214 switch(turn) {
jamesheavey 5:ae417756235a 215 case 'G':
jamesheavey 5:ae417756235a 216 goal();
jamesheavey 1:79219d0a33c8 217 case 'L':
jamesheavey 1:79219d0a33c8 218 left();
jamesheavey 5:ae417756235a 219 break;
jamesheavey 1:79219d0a33c8 220 case 'S':
jamesheavey 1:79219d0a33c8 221 break;
jamesheavey 1:79219d0a33c8 222 case 'R':
jamesheavey 1:79219d0a33c8 223 right();
jamesheavey 5:ae417756235a 224 break;
jamesheavey 1:79219d0a33c8 225 case 'B':
jamesheavey 1:79219d0a33c8 226 back();
jamesheavey 5:ae417756235a 227 break;
jamesheavey 1:79219d0a33c8 228 }
jamesheavey 1:79219d0a33c8 229 }
jamesheavey 1:79219d0a33c8 230
jamesheavey 0:df5216b20861 231 void left()
jamesheavey 0:df5216b20861 232 {
jamesheavey 1:79219d0a33c8 233 leds = 0b1100;
jamesheavey 3:a5e06482462e 234
jamesheavey 3:a5e06482462e 235 while (sensor[0] > 500) { robot.scan(); }
jamesheavey 3:a5e06482462e 236
jamesheavey 0:df5216b20861 237 robot.spin_left(0.2);
jamesheavey 3:a5e06482462e 238 wait(0.1);
jamesheavey 3:a5e06482462e 239
jamesheavey 3:a5e06482462e 240 while (sensor[1] < 500) { robot.scan(); }
jamesheavey 3:a5e06482462e 241
jamesheavey 3:a5e06482462e 242 while (sensor[1] > 500) { robot.scan(); }
jamesheavey 1:79219d0a33c8 243 }
jamesheavey 1:79219d0a33c8 244
jamesheavey 1:79219d0a33c8 245 void right()
jamesheavey 1:79219d0a33c8 246 {
jamesheavey 1:79219d0a33c8 247 leds = 0b0011;
jamesheavey 5:ae417756235a 248
jamesheavey 3:a5e06482462e 249 while (sensor[4] > 500) { robot.scan(); }
jamesheavey 3:a5e06482462e 250
jamesheavey 1:79219d0a33c8 251 robot.spin_right(0.2);
jamesheavey 3:a5e06482462e 252 wait(0.1);
jamesheavey 3:a5e06482462e 253
jamesheavey 3:a5e06482462e 254 while (sensor[3] < 500) { robot.scan(); }
jamesheavey 3:a5e06482462e 255
jamesheavey 3:a5e06482462e 256 while (sensor[3] > 500) { robot.scan(); }
jamesheavey 0:df5216b20861 257 }
jamesheavey 0:df5216b20861 258
jamesheavey 0:df5216b20861 259 void back()
jamesheavey 0:df5216b20861 260 {
jamesheavey 1:79219d0a33c8 261 leds = 0b1111;
jamesheavey 5:ae417756235a 262 robot.reverse(speed);
jamesheavey 5:ae417756235a 263 wait(0.1);
jamesheavey 0:df5216b20861 264 robot.spin_right(0.2);
jamesheavey 3:a5e06482462e 265
jamesheavey 3:a5e06482462e 266 while (sensor[3] < 500) { robot.scan(); }
jamesheavey 3:a5e06482462e 267
jamesheavey 3:a5e06482462e 268 while (sensor[3] > 500) { robot.scan(); }
jamesheavey 0:df5216b20861 269 }
jamesheavey 1:79219d0a33c8 270
jamesheavey 2:940e46e21353 271 void simplify()
jamesheavey 1:79219d0a33c8 272 {
jamesheavey 2:940e46e21353 273 // check if the last one was a 'B'
jamesheavey 2:940e46e21353 274 // if it was, iterate over the last three turns and check the total angle change
jamesheavey 2:940e46e21353 275 // replace the three turns with the new single turn
jamesheavey 1:79219d0a33c8 276
jamesheavey 10:691c02b352cb 277 if( path[path_length-2] == 'B' && path_length >= 3) {
jamesheavey 10:691c02b352cb 278 int angle_change = 0;
jamesheavey 2:940e46e21353 279
jamesheavey 10:691c02b352cb 280 for (int i = 1; i <= 3; i++) {
jamesheavey 10:691c02b352cb 281 if (path[path_length - i] == 'L') { angle_change += 270; }
jamesheavey 10:691c02b352cb 282 else if (path[path_length - i] == 'R') { angle_change += 90; }
jamesheavey 10:691c02b352cb 283 else if (path[path_length - i] == 'B') { angle_change += 180; }
jamesheavey 4:38c29dbc5953 284 }
jamesheavey 4:38c29dbc5953 285
jamesheavey 4:38c29dbc5953 286 angle_change = angle_change % 360;
jamesheavey 4:38c29dbc5953 287
jamesheavey 4:38c29dbc5953 288 if (angle_change == 0) { path[path_length - 3] = 'S'; }
jamesheavey 4:38c29dbc5953 289 else if (angle_change == 90) { path[path_length - 3] = 'R'; }
jamesheavey 4:38c29dbc5953 290 else if (angle_change == 180) { path[path_length - 3] = 'B'; }
jamesheavey 4:38c29dbc5953 291 else if (angle_change == 270) { path[path_length - 3] = 'L'; }
jamesheavey 4:38c29dbc5953 292
jamesheavey 4:38c29dbc5953 293 for (int i = 1; i <= 2; i++) { path[path_length - i] = NULL; } // clear the other turns
jamesheavey 4:38c29dbc5953 294
jamesheavey 4:38c29dbc5953 295 path_length -= 2;
jamesheavey 2:940e46e21353 296 }
jamesheavey 5:ae417756235a 297 }
jamesheavey 5:ae417756235a 298
jamesheavey 10:691c02b352cb 299 void goal()
jamesheavey 10:691c02b352cb 300 {
jamesheavey 10:691c02b352cb 301 invert_path();
jamesheavey 10:691c02b352cb 302 int pointer = 0; //path_length - 1
jamesheavey 10:691c02b352cb 303
jamesheavey 10:691c02b352cb 304 robot.lcd_clear();
jamesheavey 10:691c02b352cb 305 robot.lcd_print(path,100);
jamesheavey 10:691c02b352cb 306
jamesheavey 10:691c02b352cb 307 robot.stop();
jamesheavey 10:691c02b352cb 308 while (button_enter.read() == 1) {} // keep looping waiting for Enter to be pressed
jamesheavey 10:691c02b352cb 309
jamesheavey 10:691c02b352cb 310 leds = 0b1001;
jamesheavey 10:691c02b352cb 311 wait(0.2);
jamesheavey 10:691c02b352cb 312 leds = 0b0110;
jamesheavey 10:691c02b352cb 313 wait(0.2);
jamesheavey 10:691c02b352cb 314 leds = 0b1001;
jamesheavey 10:691c02b352cb 315 wait(0.2);
jamesheavey 10:691c02b352cb 316 leds = 0b0110;
jamesheavey 10:691c02b352cb 317 wait(0.2);
jamesheavey 10:691c02b352cb 318
jamesheavey 10:691c02b352cb 319 //robot.reverse(speed);
jamesheavey 10:691c02b352cb 320 // back();
jamesheavey 10:691c02b352cb 321
jamesheavey 10:691c02b352cb 322 while(pointer <= path_length) {
jamesheavey 10:691c02b352cb 323 follow_line();
jamesheavey 10:691c02b352cb 324
jamesheavey 10:691c02b352cb 325 if (sensor[0] > sens_thresh || sensor[4] > sens_thresh) { // if junction found
jamesheavey 10:691c02b352cb 326 turn_selector(path[pointer]);
jamesheavey 10:691c02b352cb 327 if(path[pointer] == 'S') { // make this better
jamesheavey 10:691c02b352cb 328 robot.forward(speed);
jamesheavey 10:691c02b352cb 329 leds = 0b1010;
jamesheavey 10:691c02b352cb 330 wait(0.3);
jamesheavey 10:691c02b352cb 331 // while((sensor[0] > sens_thresh || sensor[4] > sens_thresh) { robot.scan(); }
jamesheavey 10:691c02b352cb 332 }
jamesheavey 10:691c02b352cb 333 pointer++;
jamesheavey 10:691c02b352cb 334 }
jamesheavey 5:ae417756235a 335 }
jamesheavey 10:691c02b352cb 336
jamesheavey 5:ae417756235a 337 robot.stop();
jamesheavey 5:ae417756235a 338 while(1) {
jamesheavey 5:ae417756235a 339 leds = 0b1000;
jamesheavey 5:ae417756235a 340 wait(0.2);
jamesheavey 5:ae417756235a 341 leds = 0b0100;
jamesheavey 5:ae417756235a 342 wait(0.2);
jamesheavey 5:ae417756235a 343 leds = 0b0010;
jamesheavey 5:ae417756235a 344 wait(0.2);
jamesheavey 5:ae417756235a 345 leds = 0b0001;
jamesheavey 5:ae417756235a 346 wait(0.2);
jamesheavey 5:ae417756235a 347 }
jamesheavey 5:ae417756235a 348 }
jamesheavey 5:ae417756235a 349
jamesheavey 10:691c02b352cb 350 void invert_path()
jamesheavey 5:ae417756235a 351 {
jamesheavey 10:691c02b352cb 352 // only call once then can use infinitely
jamesheavey 10:691c02b352cb 353 for( int i = 0; i <= path_length; i++ ){
jamesheavey 10:691c02b352cb 354 inv_path[i] = path[path_length-i];
jamesheavey 10:691c02b352cb 355 if( inv_path[i] == 'L' ) { inv_path[i] = 'R'; }
jamesheavey 10:691c02b352cb 356 if( inv_path[i] == 'R' ) { inv_path[i] = 'L'; }
jamesheavey 10:691c02b352cb 357 }
jamesheavey 5:ae417756235a 358 }