Programming for Shadow Robot control for smart phone mapping application.
Dependencies: Motor LSM9DS1_Library_cal mbed Servo
main.cpp@3:ce743dbbd4a5, 2016-12-07 (annotated)
- Committer:
- greiner218
- Date:
- Wed Dec 07 22:29:35 2016 +0000
- Revision:
- 3:ce743dbbd4a5
- Parent:
- 2:64585b8d8404
- Child:
- 4:bc55afdd43de
Added some position tracking
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
greiner218 | 0:616fbf21a20e | 1 | #include "mbed.h" |
greiner218 | 0:616fbf21a20e | 2 | #include "Motor.h" |
greiner218 | 1:8638bdaf172b | 3 | #include "Servo.h" |
greiner218 | 1:8638bdaf172b | 4 | #include "LSM9DS1.h" |
greiner218 | 3:ce743dbbd4a5 | 5 | #include <math.h> |
greiner218 | 3:ce743dbbd4a5 | 6 | |
greiner218 | 3:ce743dbbd4a5 | 7 | #define PI 3.14159 |
greiner218 | 3:ce743dbbd4a5 | 8 | #define DECLINATION -4.94 |
greiner218 | 3:ce743dbbd4a5 | 9 | #define DIST_FACTOR 0.107475 //cm/tick Conversion between a tick from Hall effect sensor and linear distance. |
greiner218 | 3:ce743dbbd4a5 | 10 | //Approximately 190 ticks for a full wheel rotation. |
greiner218 | 3:ce743dbbd4a5 | 11 | //Approximately 6.5cm wheel diameter |
greiner218 | 3:ce743dbbd4a5 | 12 | //pi*diameter (cm) / 190(ticks) |
greiner218 | 3:ce743dbbd4a5 | 13 | volatile float heading; |
greiner218 | 3:ce743dbbd4a5 | 14 | void getHeading(float ax, float ay, float az, float mx, float my, float mz); |
greiner218 | 3:ce743dbbd4a5 | 15 | float PI_cont(float err); |
greiner218 | 0:616fbf21a20e | 16 | |
greiner218 | 1:8638bdaf172b | 17 | //MOTOR PINS |
greiner218 | 1:8638bdaf172b | 18 | Motor rwheel(p22, p18, p17); // pwmA, fwd / Ain2, rev / Ain1 |
greiner218 | 1:8638bdaf172b | 19 | Motor lwheel(p23, p15, p16); // pwmB, fwd / Bin2, rev / |
greiner218 | 1:8638bdaf172b | 20 | //BLUETOOTH PINS |
greiner218 | 1:8638bdaf172b | 21 | Serial bt(p28,p27); |
greiner218 | 1:8638bdaf172b | 22 | //LEFT SONAR |
greiner218 | 1:8638bdaf172b | 23 | DigitalOut triggerL(p14); |
greiner218 | 1:8638bdaf172b | 24 | DigitalIn echoL(p12); |
greiner218 | 1:8638bdaf172b | 25 | //RIGHT SONAR |
greiner218 | 1:8638bdaf172b | 26 | DigitalOut triggerR(p13); |
greiner218 | 1:8638bdaf172b | 27 | DigitalIn echoR(p11); |
greiner218 | 3:ce743dbbd4a5 | 28 | int correction = 0; //Used to adjust software delay for sonar measurement |
greiner218 | 3:ce743dbbd4a5 | 29 | Timer sonar; |
greiner218 | 3:ce743dbbd4a5 | 30 | |
greiner218 | 1:8638bdaf172b | 31 | //SERVO PINS |
greiner218 | 1:8638bdaf172b | 32 | Servo angle(p21); |
greiner218 | 1:8638bdaf172b | 33 | //IMU PINS |
greiner218 | 2:64585b8d8404 | 34 | LSM9DS1 imu(p9, p10, 0xD6, 0x3C); |
greiner218 | 3:ce743dbbd4a5 | 35 | Ticker nav; |
greiner218 | 3:ce743dbbd4a5 | 36 | float posX = 0; |
greiner218 | 3:ce743dbbd4a5 | 37 | float posY = 0; |
greiner218 | 3:ce743dbbd4a5 | 38 | int tickDistL = 0; |
greiner218 | 3:ce743dbbd4a5 | 39 | int tickDistR = 0; |
greiner218 | 1:8638bdaf172b | 40 | |
greiner218 | 1:8638bdaf172b | 41 | Serial pc(USBTX, USBRX); |
greiner218 | 0:616fbf21a20e | 42 | Timer timestamp; |
greiner218 | 3:ce743dbbd4a5 | 43 | |
greiner218 | 1:8638bdaf172b | 44 | // Set up Hall-effect control |
greiner218 | 2:64585b8d8404 | 45 | InterruptIn EncR(p25); |
greiner218 | 2:64585b8d8404 | 46 | InterruptIn EncL(p24); |
greiner218 | 1:8638bdaf172b | 47 | int ticksR = 0; // Encoder wheel state change counts |
greiner218 | 1:8638bdaf172b | 48 | int ticksL = 0; |
greiner218 | 1:8638bdaf172b | 49 | float speedL = 0; //PWM speed setting for left wheel (scaled between 0 and 1) |
greiner218 | 1:8638bdaf172b | 50 | float speedR = 0; //Same for right wheel |
greiner218 | 2:64585b8d8404 | 51 | int dirL = 1; //1 for fwd, -1 for reverse |
greiner218 | 2:64585b8d8404 | 52 | int dirR = 1; //1 for fwd, -1 for reverse |
greiner218 | 1:8638bdaf172b | 53 | Ticker Sampler; //Interrupt Routine to sample encoder ticks. |
greiner218 | 2:64585b8d8404 | 54 | int tracking = 0; //Flag used to indicate right wheel correction |
greiner218 | 1:8638bdaf172b | 55 | |
greiner218 | 3:ce743dbbd4a5 | 56 | //PI controller |
greiner218 | 3:ce743dbbd4a5 | 57 | //global variables |
greiner218 | 3:ce743dbbd4a5 | 58 | float kp=12.0f; |
greiner218 | 3:ce743dbbd4a5 | 59 | float ki=4.0f; |
greiner218 | 3:ce743dbbd4a5 | 60 | float kd=1.0f; |
greiner218 | 3:ce743dbbd4a5 | 61 | float P=0; |
greiner218 | 3:ce743dbbd4a5 | 62 | float I=0; |
greiner218 | 3:ce743dbbd4a5 | 63 | float D=0; |
greiner218 | 3:ce743dbbd4a5 | 64 | float dt=0.1f; |
greiner218 | 3:ce743dbbd4a5 | 65 | float out=0.0f; |
greiner218 | 3:ce743dbbd4a5 | 66 | float max=0.5f; |
greiner218 | 3:ce743dbbd4a5 | 67 | float min=-0.5f; |
greiner218 | 3:ce743dbbd4a5 | 68 | float prerr=0.0f; |
greiner218 | 3:ce743dbbd4a5 | 69 | |
greiner218 | 1:8638bdaf172b | 70 | //Sample encoders and find error on right wheel. Assume Left wheel is always correct speed. |
greiner218 | 1:8638bdaf172b | 71 | void sampleEncoder() |
greiner218 | 1:8638bdaf172b | 72 | { |
greiner218 | 2:64585b8d8404 | 73 | float E; // Error between the 2 wheel speeds |
greiner218 | 2:64585b8d8404 | 74 | if(tracking) { //Right wheel "tracks" left wheel if enabled. |
greiner218 | 1:8638bdaf172b | 75 | |
greiner218 | 1:8638bdaf172b | 76 | E = ticksL - ticksR; //Find error |
greiner218 | 2:64585b8d8404 | 77 | //E = (ticksL+1)/(ticksR+1); |
greiner218 | 2:64585b8d8404 | 78 | if (dirL == 1) |
greiner218 | 2:64585b8d8404 | 79 | { |
greiner218 | 2:64585b8d8404 | 80 | speedR = speedR + float(E) / 255.0f; //Assign a scaled increment to the right wheel based on error |
greiner218 | 2:64585b8d8404 | 81 | //speedR = E*speedR; |
greiner218 | 2:64585b8d8404 | 82 | if (speedR < 0) speedR = 0; |
greiner218 | 2:64585b8d8404 | 83 | } |
greiner218 | 2:64585b8d8404 | 84 | else if (dirL == -1) |
greiner218 | 2:64585b8d8404 | 85 | { |
greiner218 | 2:64585b8d8404 | 86 | speedR = speedR - float(E) / 255.0f; //Assign a scaled increment to the right wheel based on error |
greiner218 | 2:64585b8d8404 | 87 | //speedR = E*speedR; |
greiner218 | 2:64585b8d8404 | 88 | if (speedR > 0) speedR = 0; |
greiner218 | 2:64585b8d8404 | 89 | } |
greiner218 | 1:8638bdaf172b | 90 | rwheel.speed(speedR); |
greiner218 | 1:8638bdaf172b | 91 | } |
greiner218 | 2:64585b8d8404 | 92 | //pc.printf("tickL: %i tickR: %i Error: %i\n\r ",ticksL, ticksR, ticksL - ticksR); |
greiner218 | 1:8638bdaf172b | 93 | ticksR = 0; //Restart the counters |
greiner218 | 1:8638bdaf172b | 94 | ticksL = 0; |
greiner218 | 1:8638bdaf172b | 95 | } |
greiner218 | 0:616fbf21a20e | 96 | |
greiner218 | 3:ce743dbbd4a5 | 97 | void getHeading(float ax, float ay, float az, float mx, float my, float mz) |
greiner218 | 3:ce743dbbd4a5 | 98 | { |
greiner218 | 3:ce743dbbd4a5 | 99 | float roll = atan2(ay, az); |
greiner218 | 3:ce743dbbd4a5 | 100 | float pitch = atan2(-ax, sqrt(ay * ay + az * az)); |
greiner218 | 3:ce743dbbd4a5 | 101 | // touchy trig stuff to use arctan to get compass heading (scale is 0..360) |
greiner218 | 3:ce743dbbd4a5 | 102 | mx = -mx; |
greiner218 | 3:ce743dbbd4a5 | 103 | if (my == 0.0) |
greiner218 | 3:ce743dbbd4a5 | 104 | heading = (mx < 0.0) ? 180.0 : 0.0; |
greiner218 | 3:ce743dbbd4a5 | 105 | else |
greiner218 | 3:ce743dbbd4a5 | 106 | heading = atan2(mx, my)*360.0/(2.0*PI); |
greiner218 | 3:ce743dbbd4a5 | 107 | //pc.printf("heading atan=%f \n\r",heading); |
greiner218 | 3:ce743dbbd4a5 | 108 | heading -= DECLINATION; //correct for geo location |
greiner218 | 3:ce743dbbd4a5 | 109 | if(heading>180.0) heading = heading - 360.0; |
greiner218 | 3:ce743dbbd4a5 | 110 | else if(heading<-180.0) heading = 360.0 + heading; |
greiner218 | 3:ce743dbbd4a5 | 111 | else if(heading<0.0) heading = 360.0 + heading; |
greiner218 | 3:ce743dbbd4a5 | 112 | } |
greiner218 | 3:ce743dbbd4a5 | 113 | |
greiner218 | 3:ce743dbbd4a5 | 114 | float PI_cont(float err) |
greiner218 | 3:ce743dbbd4a5 | 115 | { |
greiner218 | 3:ce743dbbd4a5 | 116 | float Pout=kp*err; |
greiner218 | 3:ce743dbbd4a5 | 117 | P=Pout; |
greiner218 | 3:ce743dbbd4a5 | 118 | //pc.printf("P is: %f \n\r",P); |
greiner218 | 3:ce743dbbd4a5 | 119 | |
greiner218 | 3:ce743dbbd4a5 | 120 | float Iout=Iout+err*dt; |
greiner218 | 3:ce743dbbd4a5 | 121 | I=ki*Iout; |
greiner218 | 3:ce743dbbd4a5 | 122 | //pc.printf("I is: %f \n\r",I); |
greiner218 | 3:ce743dbbd4a5 | 123 | |
greiner218 | 3:ce743dbbd4a5 | 124 | float Dout = (err - prerr)/dt; |
greiner218 | 3:ce743dbbd4a5 | 125 | D=kd*Dout; |
greiner218 | 3:ce743dbbd4a5 | 126 | |
greiner218 | 3:ce743dbbd4a5 | 127 | out=P+I+D; |
greiner218 | 3:ce743dbbd4a5 | 128 | |
greiner218 | 3:ce743dbbd4a5 | 129 | prerr=err; |
greiner218 | 3:ce743dbbd4a5 | 130 | |
greiner218 | 3:ce743dbbd4a5 | 131 | //pc.printf("out is: %f \n\r",out); // basically pwm out |
greiner218 | 3:ce743dbbd4a5 | 132 | if (out>max)out=max; |
greiner218 | 3:ce743dbbd4a5 | 133 | else if (out<min)out=min; |
greiner218 | 3:ce743dbbd4a5 | 134 | return out; |
greiner218 | 3:ce743dbbd4a5 | 135 | } |
greiner218 | 3:ce743dbbd4a5 | 136 | |
greiner218 | 3:ce743dbbd4a5 | 137 | void turn(float angle) |
greiner218 | 3:ce743dbbd4a5 | 138 | { |
greiner218 | 3:ce743dbbd4a5 | 139 | float s =0.05;//speed by which the robot should turn |
greiner218 | 3:ce743dbbd4a5 | 140 | while(!imu.magAvailable(X_AXIS)); |
greiner218 | 3:ce743dbbd4a5 | 141 | imu.readMag(); |
greiner218 | 3:ce743dbbd4a5 | 142 | while(!imu.accelAvailable()); |
greiner218 | 3:ce743dbbd4a5 | 143 | imu.readAccel(); |
greiner218 | 3:ce743dbbd4a5 | 144 | while(!imu.gyroAvailable()); |
greiner218 | 3:ce743dbbd4a5 | 145 | imu.readGyro(); |
greiner218 | 3:ce743dbbd4a5 | 146 | getHeading(imu.calcAccel(imu.ax), imu.calcAccel(imu.ay), imu.calcAccel(imu.az), imu.calcMag(imu.mx), |
greiner218 | 3:ce743dbbd4a5 | 147 | imu.calcMag(imu.my), imu.calcMag(imu.mz)); |
greiner218 | 3:ce743dbbd4a5 | 148 | float PV = heading;//the original heading |
greiner218 | 3:ce743dbbd4a5 | 149 | float SP = heading - angle;//the new required heading |
greiner218 | 3:ce743dbbd4a5 | 150 | if(SP>=360){//reseting after 360 degrees to 0 |
greiner218 | 3:ce743dbbd4a5 | 151 | SP = SP-360; |
greiner218 | 3:ce743dbbd4a5 | 152 | } |
greiner218 | 3:ce743dbbd4a5 | 153 | pc.printf("PV: %f\n",PV); |
greiner218 | 3:ce743dbbd4a5 | 154 | pc.printf("SV: %f\n",SP); |
greiner218 | 3:ce743dbbd4a5 | 155 | wait(2); |
greiner218 | 3:ce743dbbd4a5 | 156 | //pc.printf("required: %f\n",requiredHeading); |
greiner218 | 3:ce743dbbd4a5 | 157 | float error = angle; |
greiner218 | 3:ce743dbbd4a5 | 158 | pc.printf("error: %f\n",error); |
greiner218 | 3:ce743dbbd4a5 | 159 | int reached = 0; |
greiner218 | 3:ce743dbbd4a5 | 160 | while(reached ==0){ |
greiner218 | 3:ce743dbbd4a5 | 161 | |
greiner218 | 3:ce743dbbd4a5 | 162 | while(!imu.magAvailable(ALL_AXIS)); |
greiner218 | 3:ce743dbbd4a5 | 163 | imu.readMag(); |
greiner218 | 3:ce743dbbd4a5 | 164 | getHeading(imu.calcAccel(imu.ax), imu.calcAccel(imu.ay), imu.calcAccel(imu.az), imu.calcMag(imu.mx), |
greiner218 | 3:ce743dbbd4a5 | 165 | imu.calcMag(imu.my), imu.calcMag(imu.mz)); |
greiner218 | 3:ce743dbbd4a5 | 166 | PV = heading;//calculate the current heading |
greiner218 | 3:ce743dbbd4a5 | 167 | |
greiner218 | 3:ce743dbbd4a5 | 168 | error=(PV-SP)/360;//find error between current heading and required heading |
greiner218 | 3:ce743dbbd4a5 | 169 | float correction=PI_cont(error);//correction to motor speed |
greiner218 | 3:ce743dbbd4a5 | 170 | if (error> 1.5/360 || error<-1.5/360) { //an error limit of 1.5 degrees allowed.. checking if the robot needs to turn more |
greiner218 | 3:ce743dbbd4a5 | 171 | rwheel.speed((s+correction)/2); |
greiner218 | 3:ce743dbbd4a5 | 172 | lwheel.speed((s-correction)/2); |
greiner218 | 3:ce743dbbd4a5 | 173 | pc.printf("error in 1st if: %f\n\r",error); |
greiner218 | 3:ce743dbbd4a5 | 174 | pc.printf("error in 1st if: %f\n\r",error); |
greiner218 | 3:ce743dbbd4a5 | 175 | } |
greiner218 | 3:ce743dbbd4a5 | 176 | else if (error>=-1.5/360 && error<=1.5/360) { //within within satisfying angular range |
greiner218 | 3:ce743dbbd4a5 | 177 | rwheel.speed(0); |
greiner218 | 3:ce743dbbd4a5 | 178 | lwheel.speed(0);//stop moving and exit the loop |
greiner218 | 3:ce743dbbd4a5 | 179 | pc.printf("error in 2nd if: %f\n\r",error); |
greiner218 | 3:ce743dbbd4a5 | 180 | break; |
greiner218 | 3:ce743dbbd4a5 | 181 | } |
greiner218 | 3:ce743dbbd4a5 | 182 | wait(0.01); |
greiner218 | 3:ce743dbbd4a5 | 183 | } |
greiner218 | 3:ce743dbbd4a5 | 184 | |
greiner218 | 3:ce743dbbd4a5 | 185 | rwheel.speed(0); |
greiner218 | 3:ce743dbbd4a5 | 186 | lwheel.speed(0); |
greiner218 | 3:ce743dbbd4a5 | 187 | } |
greiner218 | 3:ce743dbbd4a5 | 188 | |
greiner218 | 3:ce743dbbd4a5 | 189 | |
greiner218 | 3:ce743dbbd4a5 | 190 | void sendCmd(char cmd, float arg) |
greiner218 | 3:ce743dbbd4a5 | 191 | { |
greiner218 | 3:ce743dbbd4a5 | 192 | unsigned char c[sizeof arg]; |
greiner218 | 3:ce743dbbd4a5 | 193 | memcpy(c, &arg, sizeof arg); |
greiner218 | 3:ce743dbbd4a5 | 194 | bt.putc('!'); |
greiner218 | 3:ce743dbbd4a5 | 195 | bt.putc(cmd); |
greiner218 | 3:ce743dbbd4a5 | 196 | bt.putc(c[0]); |
greiner218 | 3:ce743dbbd4a5 | 197 | bt.putc(c[1]); |
greiner218 | 3:ce743dbbd4a5 | 198 | bt.putc(c[2]); |
greiner218 | 3:ce743dbbd4a5 | 199 | bt.putc(c[3]); |
greiner218 | 3:ce743dbbd4a5 | 200 | |
greiner218 | 3:ce743dbbd4a5 | 201 | } |
greiner218 | 3:ce743dbbd4a5 | 202 | |
greiner218 | 1:8638bdaf172b | 203 | int ping(int i) |
greiner218 | 1:8638bdaf172b | 204 | { |
greiner218 | 3:ce743dbbd4a5 | 205 | float distance = 0; |
greiner218 | 1:8638bdaf172b | 206 | switch(i) |
greiner218 | 1:8638bdaf172b | 207 | { |
greiner218 | 1:8638bdaf172b | 208 | |
greiner218 | 1:8638bdaf172b | 209 | case(1): //Ping Left Sonar |
greiner218 | 1:8638bdaf172b | 210 | // trigger sonar to send a ping |
greiner218 | 3:ce743dbbd4a5 | 211 | pc.printf("Pinging sonar 1...\n\r"); |
greiner218 | 1:8638bdaf172b | 212 | triggerL = 1; |
greiner218 | 1:8638bdaf172b | 213 | sonar.reset(); |
greiner218 | 3:ce743dbbd4a5 | 214 | //wait_us(10.0); |
greiner218 | 1:8638bdaf172b | 215 | //wait for echo high |
greiner218 | 1:8638bdaf172b | 216 | while (echoL==0) {}; |
greiner218 | 1:8638bdaf172b | 217 | //echo high, so start timer |
greiner218 | 1:8638bdaf172b | 218 | sonar.start(); |
greiner218 | 3:ce743dbbd4a5 | 219 | triggerL = 0; |
greiner218 | 1:8638bdaf172b | 220 | //wait for echo low |
greiner218 | 1:8638bdaf172b | 221 | while (echoL==1) {}; |
greiner218 | 1:8638bdaf172b | 222 | //stop timer and read value |
greiner218 | 1:8638bdaf172b | 223 | sonar.stop(); |
greiner218 | 1:8638bdaf172b | 224 | //subtract software overhead timer delay and scale to cm |
greiner218 | 1:8638bdaf172b | 225 | distance = (sonar.read_us()-correction)/58.0; |
greiner218 | 3:ce743dbbd4a5 | 226 | pc.printf("Got distance %f cm back.\n\r", distance); |
greiner218 | 1:8638bdaf172b | 227 | //wait so that any echo(s) return before sending another ping |
greiner218 | 1:8638bdaf172b | 228 | wait(0.015); |
greiner218 | 1:8638bdaf172b | 229 | break; |
greiner218 | 1:8638bdaf172b | 230 | case(2): //Ping Right Sonar |
greiner218 | 1:8638bdaf172b | 231 | // trigger sonar to send a ping |
greiner218 | 3:ce743dbbd4a5 | 232 | pc.printf("Pinging sonar 2...\n\r"); |
greiner218 | 1:8638bdaf172b | 233 | triggerR = 1; |
greiner218 | 1:8638bdaf172b | 234 | sonar.reset(); |
greiner218 | 3:ce743dbbd4a5 | 235 | //wait_us(10.0); |
greiner218 | 1:8638bdaf172b | 236 | //wait for echo high |
greiner218 | 1:8638bdaf172b | 237 | while (echoR==0) {}; |
greiner218 | 1:8638bdaf172b | 238 | //echo high, so start timer |
greiner218 | 1:8638bdaf172b | 239 | sonar.start(); |
greiner218 | 3:ce743dbbd4a5 | 240 | triggerR = 0; |
greiner218 | 1:8638bdaf172b | 241 | //wait for echo low |
greiner218 | 1:8638bdaf172b | 242 | while (echoR==1) {}; |
greiner218 | 1:8638bdaf172b | 243 | //stop timer and read value |
greiner218 | 1:8638bdaf172b | 244 | sonar.stop(); |
greiner218 | 1:8638bdaf172b | 245 | //subtract software overhead timer delay and scale to cm |
greiner218 | 1:8638bdaf172b | 246 | distance = (sonar.read_us()-correction)/58.0; |
greiner218 | 3:ce743dbbd4a5 | 247 | pc.printf("Got distance %f cm back.\n\r", distance); |
greiner218 | 1:8638bdaf172b | 248 | //wait so that any echo(s) return before sending another ping |
greiner218 | 1:8638bdaf172b | 249 | wait(0.015); |
greiner218 | 1:8638bdaf172b | 250 | break; |
greiner218 | 1:8638bdaf172b | 251 | default: |
greiner218 | 1:8638bdaf172b | 252 | break; |
greiner218 | 3:ce743dbbd4a5 | 253 | } |
greiner218 | 3:ce743dbbd4a5 | 254 | return distance; |
greiner218 | 3:ce743dbbd4a5 | 255 | } |
greiner218 | 3:ce743dbbd4a5 | 256 | |
greiner218 | 3:ce743dbbd4a5 | 257 | void sweep() |
greiner218 | 3:ce743dbbd4a5 | 258 | { |
greiner218 | 3:ce743dbbd4a5 | 259 | int dL = 0; |
greiner218 | 3:ce743dbbd4a5 | 260 | int dR = 0; |
greiner218 | 3:ce743dbbd4a5 | 261 | if (angle <=0.5) //Set to min angle and execute forward sweep. |
greiner218 | 3:ce743dbbd4a5 | 262 | { |
greiner218 | 3:ce743dbbd4a5 | 263 | angle = 0; |
greiner218 | 3:ce743dbbd4a5 | 264 | wait(.5); |
greiner218 | 3:ce743dbbd4a5 | 265 | while( angle >= 0 && angle < 1) |
greiner218 | 3:ce743dbbd4a5 | 266 | { |
greiner218 | 3:ce743dbbd4a5 | 267 | dL = ping(1); |
greiner218 | 3:ce743dbbd4a5 | 268 | dR = ping(2); |
greiner218 | 3:ce743dbbd4a5 | 269 | sendCmd('D',dL); |
greiner218 | 3:ce743dbbd4a5 | 270 | sendCmd('D',dR); |
greiner218 | 3:ce743dbbd4a5 | 271 | angle = angle + 0.05; |
greiner218 | 3:ce743dbbd4a5 | 272 | } |
greiner218 | 3:ce743dbbd4a5 | 273 | angle = 1; |
greiner218 | 1:8638bdaf172b | 274 | } |
greiner218 | 3:ce743dbbd4a5 | 275 | else if (angle > 0.5) //Set to max angle and execute backward sweep. |
greiner218 | 3:ce743dbbd4a5 | 276 | { |
greiner218 | 3:ce743dbbd4a5 | 277 | angle = 1; |
greiner218 | 3:ce743dbbd4a5 | 278 | wait(.5); |
greiner218 | 3:ce743dbbd4a5 | 279 | while( angle > 0 && angle <= 1) |
greiner218 | 3:ce743dbbd4a5 | 280 | { |
greiner218 | 3:ce743dbbd4a5 | 281 | dL = ping(1); |
greiner218 | 3:ce743dbbd4a5 | 282 | dR = ping(2); |
greiner218 | 3:ce743dbbd4a5 | 283 | sendCmd('D',dL); |
greiner218 | 3:ce743dbbd4a5 | 284 | sendCmd('D',dR); |
greiner218 | 3:ce743dbbd4a5 | 285 | angle = angle - 0.05; |
greiner218 | 3:ce743dbbd4a5 | 286 | } |
greiner218 | 3:ce743dbbd4a5 | 287 | angle = 0; |
greiner218 | 3:ce743dbbd4a5 | 288 | } |
greiner218 | 3:ce743dbbd4a5 | 289 | } |
greiner218 | 3:ce743dbbd4a5 | 290 | |
greiner218 | 3:ce743dbbd4a5 | 291 | void updatePos() |
greiner218 | 3:ce743dbbd4a5 | 292 | { |
greiner218 | 3:ce743dbbd4a5 | 293 | float deltaX; |
greiner218 | 3:ce743dbbd4a5 | 294 | float deltaY; |
greiner218 | 3:ce743dbbd4a5 | 295 | float dist; |
greiner218 | 3:ce743dbbd4a5 | 296 | while(!imu.magAvailable(X_AXIS)); |
greiner218 | 3:ce743dbbd4a5 | 297 | imu.readMag(); |
greiner218 | 3:ce743dbbd4a5 | 298 | while(!imu.accelAvailable()); |
greiner218 | 3:ce743dbbd4a5 | 299 | imu.readAccel(); |
greiner218 | 3:ce743dbbd4a5 | 300 | while(!imu.gyroAvailable()); |
greiner218 | 3:ce743dbbd4a5 | 301 | imu.readGyro(); |
greiner218 | 3:ce743dbbd4a5 | 302 | getHeading(imu.calcAccel(imu.ax), imu.calcAccel(imu.ay), imu.calcAccel(imu.az), imu.calcMag(imu.mx), |
greiner218 | 3:ce743dbbd4a5 | 303 | imu.calcMag(imu.my), imu.calcMag(imu.mz)); |
greiner218 | 3:ce743dbbd4a5 | 304 | dist = (tickDistR + tickDistL)/2.0f*DIST_FACTOR; //Average the ticks and convert to linear distance. |
greiner218 | 3:ce743dbbd4a5 | 305 | pc.printf("Magnetic Heading: %f degress ",heading); |
greiner218 | 3:ce743dbbd4a5 | 306 | pc.printf("L ticks: %d R ticks: %d ",tickDistL, tickDistR); |
greiner218 | 3:ce743dbbd4a5 | 307 | tickDistR = 0;//Reset the ticks. |
greiner218 | 3:ce743dbbd4a5 | 308 | tickDistL = 0; |
greiner218 | 3:ce743dbbd4a5 | 309 | deltaX = dist*(float)sin((double)heading*PI/180.0f); //Do trig. |
greiner218 | 3:ce743dbbd4a5 | 310 | deltaY = dist*(float)cos((double)heading*PI/180.0f); |
greiner218 | 3:ce743dbbd4a5 | 311 | posX = posX + deltaX; |
greiner218 | 3:ce743dbbd4a5 | 312 | posY = posY + deltaY; |
greiner218 | 3:ce743dbbd4a5 | 313 | pc.printf("deltaX: %f deltaY: %f ",deltaX,deltaY); |
greiner218 | 3:ce743dbbd4a5 | 314 | pc.printf("posX: %f posY:%f \n\r",posX,posY); |
greiner218 | 1:8638bdaf172b | 315 | } |
greiner218 | 1:8638bdaf172b | 316 | |
greiner218 | 2:64585b8d8404 | 317 | void incTicksR() |
greiner218 | 2:64585b8d8404 | 318 | { |
greiner218 | 2:64585b8d8404 | 319 | ticksR++; |
greiner218 | 3:ce743dbbd4a5 | 320 | tickDistR++; |
greiner218 | 2:64585b8d8404 | 321 | } |
greiner218 | 2:64585b8d8404 | 322 | |
greiner218 | 2:64585b8d8404 | 323 | void incTicksL() |
greiner218 | 2:64585b8d8404 | 324 | { |
greiner218 | 2:64585b8d8404 | 325 | ticksL++; |
greiner218 | 3:ce743dbbd4a5 | 326 | tickDistL++; |
greiner218 | 2:64585b8d8404 | 327 | } |
greiner218 | 2:64585b8d8404 | 328 | |
greiner218 | 0:616fbf21a20e | 329 | int main() |
greiner218 | 0:616fbf21a20e | 330 | { |
greiner218 | 2:64585b8d8404 | 331 | char cmd; |
greiner218 | 0:616fbf21a20e | 332 | timestamp.start(); |
greiner218 | 2:64585b8d8404 | 333 | angle = 0.0f; |
greiner218 | 3:ce743dbbd4a5 | 334 | //Calibrate the IMU |
greiner218 | 3:ce743dbbd4a5 | 335 | if (!imu.begin()) { |
greiner218 | 3:ce743dbbd4a5 | 336 | pc.printf("Failed to communicate with LSM9DS1.\n"); |
greiner218 | 3:ce743dbbd4a5 | 337 | } |
greiner218 | 3:ce743dbbd4a5 | 338 | imu.calibrate(); |
greiner218 | 3:ce743dbbd4a5 | 339 | imu.calibrateMag(0); |
greiner218 | 1:8638bdaf172b | 340 | // Initialize hall-effect control |
greiner218 | 2:64585b8d8404 | 341 | Sampler.attach(&sampleEncoder, 0.2); //Sampler uses sampleEncoder function every 200ms |
greiner218 | 1:8638bdaf172b | 342 | EncL.mode(PullUp); // Use internal pullups |
greiner218 | 1:8638bdaf172b | 343 | EncR.mode(PullUp); |
greiner218 | 2:64585b8d8404 | 344 | EncR.rise(&incTicksR); |
greiner218 | 2:64585b8d8404 | 345 | EncL.rise(&incTicksL); |
greiner218 | 3:ce743dbbd4a5 | 346 | nav.attach(&updatePos,1);//Update X,Y,H every second |
greiner218 | 2:64585b8d8404 | 347 | while(1) |
greiner218 | 2:64585b8d8404 | 348 | { |
greiner218 | 2:64585b8d8404 | 349 | //Check if char is ready to be read and put into command buffer; |
greiner218 | 2:64585b8d8404 | 350 | if(bt.getc() =='!') |
greiner218 | 2:64585b8d8404 | 351 | { |
greiner218 | 2:64585b8d8404 | 352 | cmd = bt.getc(); |
greiner218 | 2:64585b8d8404 | 353 | switch (cmd) |
greiner218 | 2:64585b8d8404 | 354 | { |
greiner218 | 2:64585b8d8404 | 355 | case 'B': |
greiner218 | 2:64585b8d8404 | 356 | pc.printf("Got Command B!\n\r"); |
greiner218 | 2:64585b8d8404 | 357 | break; |
greiner218 | 2:64585b8d8404 | 358 | |
greiner218 | 2:64585b8d8404 | 359 | case 'S': //Stop moving |
greiner218 | 2:64585b8d8404 | 360 | pc.printf("Got Command STOP!\n\r"); |
greiner218 | 2:64585b8d8404 | 361 | tracking = 0; //Turn off wheel feedback updates |
greiner218 | 2:64585b8d8404 | 362 | speedL = 0; |
greiner218 | 2:64585b8d8404 | 363 | speedR = 0; |
greiner218 | 2:64585b8d8404 | 364 | lwheel.speed(0); |
greiner218 | 2:64585b8d8404 | 365 | rwheel.speed(0); |
greiner218 | 2:64585b8d8404 | 366 | break; |
greiner218 | 2:64585b8d8404 | 367 | |
greiner218 | 2:64585b8d8404 | 368 | case 'F': //Forward |
greiner218 | 2:64585b8d8404 | 369 | pc.printf("Got Command FORWARD!\n\r"); |
greiner218 | 2:64585b8d8404 | 370 | dirL = 1; |
greiner218 | 2:64585b8d8404 | 371 | dirR = 1; |
greiner218 | 2:64585b8d8404 | 372 | speedL = 0.9f; |
greiner218 | 2:64585b8d8404 | 373 | speedR = 0.9f; |
greiner218 | 2:64585b8d8404 | 374 | rwheel.speed(speedR); |
greiner218 | 2:64585b8d8404 | 375 | lwheel.speed(speedL); |
greiner218 | 2:64585b8d8404 | 376 | tracking = 1; //Turn on wheel feedback updates |
greiner218 | 3:ce743dbbd4a5 | 377 | tickDistL = 0; //Reset the distance ticks. |
greiner218 | 3:ce743dbbd4a5 | 378 | tickDistR = 0; |
greiner218 | 2:64585b8d8404 | 379 | break; |
greiner218 | 2:64585b8d8404 | 380 | |
greiner218 | 2:64585b8d8404 | 381 | case 'R': //Reverse |
greiner218 | 2:64585b8d8404 | 382 | pc.printf("Got Command REVERSE!\n\r"); |
greiner218 | 2:64585b8d8404 | 383 | dirL = -1; |
greiner218 | 2:64585b8d8404 | 384 | dirR = -1; |
greiner218 | 2:64585b8d8404 | 385 | speedL = -0.9f; |
greiner218 | 2:64585b8d8404 | 386 | speedR = -0.9f; |
greiner218 | 2:64585b8d8404 | 387 | rwheel.speed(speedR); |
greiner218 | 2:64585b8d8404 | 388 | lwheel.speed(speedL); |
greiner218 | 2:64585b8d8404 | 389 | tracking = 1; |
greiner218 | 3:ce743dbbd4a5 | 390 | tickDistL = 0; //Reset the distance ticks. |
greiner218 | 3:ce743dbbd4a5 | 391 | tickDistR = 0; |
greiner218 | 3:ce743dbbd4a5 | 392 | break; |
greiner218 | 3:ce743dbbd4a5 | 393 | |
greiner218 | 3:ce743dbbd4a5 | 394 | case 'P': //Sweep |
greiner218 | 3:ce743dbbd4a5 | 395 | pc.printf("Got Command SWEEP!\n\r"); |
greiner218 | 3:ce743dbbd4a5 | 396 | sweep(); |
greiner218 | 2:64585b8d8404 | 397 | break; |
greiner218 | 2:64585b8d8404 | 398 | |
greiner218 | 2:64585b8d8404 | 399 | default: |
greiner218 | 2:64585b8d8404 | 400 | pc.printf("Unknown Command!\n\r"); |
greiner218 | 2:64585b8d8404 | 401 | break; |
greiner218 | 2:64585b8d8404 | 402 | |
greiner218 | 1:8638bdaf172b | 403 | } |
greiner218 | 1:8638bdaf172b | 404 | } |
greiner218 | 0:616fbf21a20e | 405 | } |
greiner218 | 0:616fbf21a20e | 406 | } |