WRCE TSD / Mbed 2 deprecated BNOser_servo

Dependencies:   mbed BNO055_fusion

Committer:
pmmccorkell
Date:
Wed Sep 18 11:14:10 2019 +0000
Revision:
0:6e9da949a2a3
last known code of land UAV

Who changed what in which revision?

UserRevisionLine numberNew contents of line
pmmccorkell 0:6e9da949a2a3 1 #include "mbed.h"
pmmccorkell 0:6e9da949a2a3 2 #include "BNO055.h"
pmmccorkell 0:6e9da949a2a3 3
pmmccorkell 0:6e9da949a2a3 4 Serial pc(USBTX, USBRX);
pmmccorkell 0:6e9da949a2a3 5 I2C i2c(p9,p10);
pmmccorkell 0:6e9da949a2a3 6 DigitalOut pwr_on(p30);
pmmccorkell 0:6e9da949a2a3 7 BNO055 imu(i2c,p26);
pmmccorkell 0:6e9da949a2a3 8 //DigitalOut led1(LED1);
pmmccorkell 0:6e9da949a2a3 9
pmmccorkell 0:6e9da949a2a3 10 //instantiate global ready to 0
pmmccorkell 0:6e9da949a2a3 11 uint32_t ready = 0x00000000;
pmmccorkell 0:6e9da949a2a3 12
pmmccorkell 0:6e9da949a2a3 13 BNO055_ID_INF_TypeDef bno055_id_inf;
pmmccorkell 0:6e9da949a2a3 14 BNO055_EULER_TypeDef euler_angles;
pmmccorkell 0:6e9da949a2a3 15 //BNO055_QUATERNION_TypeDef quaternion;
pmmccorkell 0:6e9da949a2a3 16 //BNO055_LIN_ACC_TypeDef linear_acc;
pmmccorkell 0:6e9da949a2a3 17 BNO055_GRAVITY_TypeDef gravity;
pmmccorkell 0:6e9da949a2a3 18 //BNO055_TEMPERATURE_TypeDef chip_temp;
pmmccorkell 0:6e9da949a2a3 19
pmmccorkell 0:6e9da949a2a3 20 // Instantiate motor driver PWM pins, duty cycle, and period
pmmccorkell 0:6e9da949a2a3 21 double stop_pw=.0015;
pmmccorkell 0:6e9da949a2a3 22 //double fwd_pw=.0018;
pmmccorkell 0:6e9da949a2a3 23 //double rev_pw=.0012;
pmmccorkell 0:6e9da949a2a3 24 PwmOut RH_motor(p23);
pmmccorkell 0:6e9da949a2a3 25 PwmOut Lfwd(p21); // left forward
pmmccorkell 0:6e9da949a2a3 26 PwmOut Lrev(p22); // left reverse
pmmccorkell 0:6e9da949a2a3 27 PwmOut Rfwd(p24); // right forward
pmmccorkell 0:6e9da949a2a3 28 PwmOut Rrev(p25); // right reverse
pmmccorkell 0:6e9da949a2a3 29 float dutycycle=0.40;
pmmccorkell 0:6e9da949a2a3 30
pmmccorkell 0:6e9da949a2a3 31
pmmccorkell 0:6e9da949a2a3 32 //Lazy... don't want to track these down everywhere
pmmccorkell 0:6e9da949a2a3 33 //Standard servo rate -> 50Hz
pmmccorkell 0:6e9da949a2a3 34 double servo_freq=50;
pmmccorkell 0:6e9da949a2a3 35 double servo_period=(1/servo_freq);
pmmccorkell 0:6e9da949a2a3 36 //25us per data sheet Blue Robotics BESC-R1
pmmccorkell 0:6e9da949a2a3 37 double esc_step=(25/1000000);
pmmccorkell 0:6e9da949a2a3 38 //400Hz update frequency per data sheet
pmmccorkell 0:6e9da949a2a3 39 int esc_freq=400;
pmmccorkell 0:6e9da949a2a3 40 double esc_time_ms=(1000/esc_freq);
pmmccorkell 0:6e9da949a2a3 41 //1.1-1.9ms pw per data sheet
pmmccorkell 0:6e9da949a2a3 42 double esc_range=.0004;
pmmccorkell 0:6e9da949a2a3 43 //natural #
pmmccorkell 0:6e9da949a2a3 44 double e=2.71828;
pmmccorkell 0:6e9da949a2a3 45
pmmccorkell 0:6e9da949a2a3 46
pmmccorkell 0:6e9da949a2a3 47
pmmccorkell 0:6e9da949a2a3 48
pmmccorkell 0:6e9da949a2a3 49 //Data function pulls data from BNO and sends over serial
pmmccorkell 0:6e9da949a2a3 50 //Accepts unsigned 32bit key word (k) that RasPi will use as trigger
pmmccorkell 0:6e9da949a2a3 51 uint16_t data(uint32_t k) {
pmmccorkell 0:6e9da949a2a3 52 //Instantiate status array of 6 32-bit words.
pmmccorkell 0:6e9da949a2a3 53 //First 16 bits of each 32-bit word are Identifiers for RasPi to correctly assign the trailing 16 bits of data.
pmmccorkell 0:6e9da949a2a3 54 uint32_t status[6]={0};
pmmccorkell 0:6e9da949a2a3 55
pmmccorkell 0:6e9da949a2a3 56 //word 0: Key
pmmccorkell 0:6e9da949a2a3 57 //Used to ensure Pi and Mbed are on same page.
pmmccorkell 0:6e9da949a2a3 58 status[0]=k;
pmmccorkell 0:6e9da949a2a3 59
pmmccorkell 0:6e9da949a2a3 60 //word 1: Status information.
pmmccorkell 0:6e9da949a2a3 61 //0xffff acts as prefix to identify Status for RasPi.
pmmccorkell 0:6e9da949a2a3 62 //Last 3 bits (from right) are current position (POS[0-7]). See BNO datasheet.
pmmccorkell 0:6e9da949a2a3 63 //4th bit (from right) is RH turn motors enabled.
pmmccorkell 0:6e9da949a2a3 64 //5th bit (from right) is LH turn motors enabled.
pmmccorkell 0:6e9da949a2a3 65 status[1]=ready;
pmmccorkell 0:6e9da949a2a3 66
pmmccorkell 0:6e9da949a2a3 67 //word 2: Calibration.
pmmccorkell 0:6e9da949a2a3 68 //0xc000 acts as prefix to identify Cal for RasPi.
pmmccorkell 0:6e9da949a2a3 69 status[2]=0xc0000000+imu.read_calib_status();
pmmccorkell 0:6e9da949a2a3 70
pmmccorkell 0:6e9da949a2a3 71 //Get Euler data from BNO.
pmmccorkell 0:6e9da949a2a3 72 imu.get_Euler_Angles(&euler_angles);
pmmccorkell 0:6e9da949a2a3 73
pmmccorkell 0:6e9da949a2a3 74 //word 3 is Heading.
pmmccorkell 0:6e9da949a2a3 75 //0xc100 acts as prefix to identify Heading for RasPi.
pmmccorkell 0:6e9da949a2a3 76 uint16_t h = euler_angles.h;
pmmccorkell 0:6e9da949a2a3 77 status[3]=0xc1000000+h;
pmmccorkell 0:6e9da949a2a3 78
pmmccorkell 0:6e9da949a2a3 79 //Offset calculation: 360*16bit resolution = 5760 -> converted to hex = 0x1680
pmmccorkell 0:6e9da949a2a3 80 int offset=0x1680;
pmmccorkell 0:6e9da949a2a3 81
pmmccorkell 0:6e9da949a2a3 82 //word 4 is Roll.
pmmccorkell 0:6e9da949a2a3 83 //0xc300 acts as prefix to identify Roll for RasPi.
pmmccorkell 0:6e9da949a2a3 84 //BNO sends Roll and Pitch as +/- 180deg. Add offset of 360deg to avoid dealing with signed ints over serial.
pmmccorkell 0:6e9da949a2a3 85 uint16_t r = offset + euler_angles.r;
pmmccorkell 0:6e9da949a2a3 86 status[4]=0xc3000000+r;
pmmccorkell 0:6e9da949a2a3 87
pmmccorkell 0:6e9da949a2a3 88 //word 5 is Pitch.
pmmccorkell 0:6e9da949a2a3 89 //0xc500 acts as prefix to identify Pitch for RasPi.
pmmccorkell 0:6e9da949a2a3 90 //BNO sends Roll and Pitch as +/- 180deg. Add offset of 360deg to avoid dealing with signed ints over serial.
pmmccorkell 0:6e9da949a2a3 91 uint16_t p = offset + euler_angles.p;
pmmccorkell 0:6e9da949a2a3 92 status[5]=0xc5000000+p;
pmmccorkell 0:6e9da949a2a3 93
pmmccorkell 0:6e9da949a2a3 94 //For loop iterates through Status array to transmit 6 32-bit words over Serial with "\n" appended for Python in RasPi.
pmmccorkell 0:6e9da949a2a3 95 int i;
pmmccorkell 0:6e9da949a2a3 96 int l=(sizeof(status)/sizeof(uint32_t))-1;
pmmccorkell 0:6e9da949a2a3 97 for (i=0; i<=l; i++) {
pmmccorkell 0:6e9da949a2a3 98 pc.printf("%x\n", status[i]);
pmmccorkell 0:6e9da949a2a3 99 }
pmmccorkell 0:6e9da949a2a3 100
pmmccorkell 0:6e9da949a2a3 101 //return heading
pmmccorkell 0:6e9da949a2a3 102 return h;
pmmccorkell 0:6e9da949a2a3 103 }
pmmccorkell 0:6e9da949a2a3 104
pmmccorkell 0:6e9da949a2a3 105 //Function to setup motor PWM for right turn
pmmccorkell 0:6e9da949a2a3 106 void TurnRight() {
pmmccorkell 0:6e9da949a2a3 107 //mask off other bits and set Rmotor status to on
pmmccorkell 0:6e9da949a2a3 108 ready=(ready & 0xfffffff7) + 0x8;
pmmccorkell 0:6e9da949a2a3 109 // pc.printf("Turning Right\r\n");
pmmccorkell 0:6e9da949a2a3 110 Rfwd.write(dutycycle);
pmmccorkell 0:6e9da949a2a3 111 Lrev.write(dutycycle);
pmmccorkell 0:6e9da949a2a3 112 }
pmmccorkell 0:6e9da949a2a3 113
pmmccorkell 0:6e9da949a2a3 114 //Function to setup motor PWM for left turn
pmmccorkell 0:6e9da949a2a3 115 void TurnLeft() {
pmmccorkell 0:6e9da949a2a3 116 //mask off other bits and set Lmotor status to on
pmmccorkell 0:6e9da949a2a3 117 ready=(ready & 0xffffffef) + 0x10;
pmmccorkell 0:6e9da949a2a3 118 // pc.printf("Turning Left\r\n");
pmmccorkell 0:6e9da949a2a3 119 Lfwd.write(dutycycle);
pmmccorkell 0:6e9da949a2a3 120 Rrev.write(dutycycle);
pmmccorkell 0:6e9da949a2a3 121 }
pmmccorkell 0:6e9da949a2a3 122
pmmccorkell 0:6e9da949a2a3 123 //Function to stop all motors
pmmccorkell 0:6e9da949a2a3 124 void Stop_motors() {
pmmccorkell 0:6e9da949a2a3 125 //Set PW on all PWM pins to 0
pmmccorkell 0:6e9da949a2a3 126 Lfwd.write(0);
pmmccorkell 0:6e9da949a2a3 127 Lrev.write(0);
pmmccorkell 0:6e9da949a2a3 128 Rfwd.write(0);
pmmccorkell 0:6e9da949a2a3 129 Rrev.write(0);
pmmccorkell 0:6e9da949a2a3 130 //zero out Lm and Rm status bits
pmmccorkell 0:6e9da949a2a3 131 ready=(ready & 0xffffffe7);
pmmccorkell 0:6e9da949a2a3 132 }
pmmccorkell 0:6e9da949a2a3 133
pmmccorkell 0:6e9da949a2a3 134 //The sigmoid curve for logistic function.
pmmccorkell 0:6e9da949a2a3 135 //Used for continuous PWM and softstart / softstop near end points.
pmmccorkell 0:6e9da949a2a3 136 double Sigmoid(double Ymax, double m, double x0, double x) {
pmmccorkell 0:6e9da949a2a3 137 // double Logistic_func=(Ymax/(1+(e^((-1*m)*(x-x0)))));
pmmccorkell 0:6e9da949a2a3 138 double exponent=((-1*m)*(x-x0));
pmmccorkell 0:6e9da949a2a3 139 double power=pow(e,exponent);
pmmccorkell 0:6e9da949a2a3 140 double Logistic_func=Ymax/(1+power);
pmmccorkell 0:6e9da949a2a3 141 // pc.printf("exp: %f, power:%f, ret: %f\r\n",exponent,power,Logistic_func);
pmmccorkell 0:6e9da949a2a3 142 return Logistic_func;
pmmccorkell 0:6e9da949a2a3 143 }
pmmccorkell 0:6e9da949a2a3 144
pmmccorkell 0:6e9da949a2a3 145 //Function to control RH motor
pmmccorkell 0:6e9da949a2a3 146 void RH_motor_cntrl(double target_pw) {
pmmccorkell 0:6e9da949a2a3 147 double step_pw=.00005;
pmmccorkell 0:6e9da949a2a3 148 double current_pw=(RH_motor.read()*.02);
pmmccorkell 0:6e9da949a2a3 149 double diff_pw=abs(target_pw-current_pw);
pmmccorkell 0:6e9da949a2a3 150 //Time we want to take to get from 1.5 to [1.9 or 1.1]
pmmccorkell 0:6e9da949a2a3 151 // double Delay=0.5; //500ms
pmmccorkell 0:6e9da949a2a3 152 //Total # of steps / resolution of ESC
pmmccorkell 0:6e9da949a2a3 153 // double Steps=((.0019-.0015)/esc_step);
pmmccorkell 0:6e9da949a2a3 154 //Center of sigmoid curve
pmmccorkell 0:6e9da949a2a3 155 double Center=.1; //100ms -> ramp up within 200ms
pmmccorkell 0:6e9da949a2a3 156 //slope at Center
pmmccorkell 0:6e9da949a2a3 157 double Slope=50; //rate of ramp up
pmmccorkell 0:6e9da949a2a3 158 double time_count=0; //total time in while loop
pmmccorkell 0:6e9da949a2a3 159 double dwell_time=0.001; //time to wait between while loop
pmmccorkell 0:6e9da949a2a3 160 double tolerance_pw=.000045; //45us
pmmccorkell 0:6e9da949a2a3 161 double dir=0;
pmmccorkell 0:6e9da949a2a3 162 while(diff_pw>tolerance_pw) {
pmmccorkell 0:6e9da949a2a3 163 current_pw=(RH_motor.read()*.02);
pmmccorkell 0:6e9da949a2a3 164 diff_pw=abs(target_pw-current_pw);
pmmccorkell 0:6e9da949a2a3 165 if ((target_pw-current_pw)>=0) {
pmmccorkell 0:6e9da949a2a3 166 dir=(1);
pmmccorkell 0:6e9da949a2a3 167 //RH moving fwd
pmmccorkell 0:6e9da949a2a3 168 // ready=(ready & 0xfffffff7) + 0x8;
pmmccorkell 0:6e9da949a2a3 169 }
pmmccorkell 0:6e9da949a2a3 170 if ((target_pw-current_pw)<0) {
pmmccorkell 0:6e9da949a2a3 171 dir=(-1);
pmmccorkell 0:6e9da949a2a3 172 //RH moving rev
pmmccorkell 0:6e9da949a2a3 173 // ready=(ready & 0xffffffef) + 0x10;
pmmccorkell 0:6e9da949a2a3 174 }
pmmccorkell 0:6e9da949a2a3 175 double factor=Sigmoid(1,Slope,Center,time_count);
pmmccorkell 0:6e9da949a2a3 176 //double new_pw=stop_pw+(diff_pw*factor);
pmmccorkell 0:6e9da949a2a3 177 double new_pw;
pmmccorkell 0:6e9da949a2a3 178 double speed_pw=step_pw+(diff_pw*factor);
pmmccorkell 0:6e9da949a2a3 179 if (dir==1) new_pw=current_pw+speed_pw;
pmmccorkell 0:6e9da949a2a3 180 //new_pw=current_pw+.0000025;
pmmccorkell 0:6e9da949a2a3 181 if (dir==-1) new_pw=current_pw-speed_pw;
pmmccorkell 0:6e9da949a2a3 182 //new_pw=current_pw-.0000025;
pmmccorkell 0:6e9da949a2a3 183 pc.printf("diff: %f, factor: %f\r\n",diff_pw,factor);
pmmccorkell 0:6e9da949a2a3 184 pc.printf("pw: %f, speed: %f, offset: %f\r\n",current_pw,speed_pw,step_pw);
pmmccorkell 0:6e9da949a2a3 185 RH_motor.pulsewidth(new_pw);
pmmccorkell 0:6e9da949a2a3 186 wait_ms(dwell_time);
pmmccorkell 0:6e9da949a2a3 187 time_count+=dwell_time;
pmmccorkell 0:6e9da949a2a3 188 }
pmmccorkell 0:6e9da949a2a3 189 RH_motor.pulsewidth(target_pw);
pmmccorkell 0:6e9da949a2a3 190 //zero out Lm and Rm status bits
pmmccorkell 0:6e9da949a2a3 191 // ready=(ready & 0xffffffe7);
pmmccorkell 0:6e9da949a2a3 192 }
pmmccorkell 0:6e9da949a2a3 193
pmmccorkell 0:6e9da949a2a3 194 //Function to handle motor logic
pmmccorkell 0:6e9da949a2a3 195 void motors(int desired_heading) {
pmmccorkell 0:6e9da949a2a3 196 //Pull heading from BNO and correct for 16bit/deg resolution.
pmmccorkell 0:6e9da949a2a3 197 double current_heading=((data(0x1234abcd))/0x10);
pmmccorkell 0:6e9da949a2a3 198 //Set acceptable tolerance in deg, for heading accuracy.
pmmccorkell 0:6e9da949a2a3 199 double tolerance = 3.0;
pmmccorkell 0:6e9da949a2a3 200 //The natural #
pmmccorkell 0:6e9da949a2a3 201
pmmccorkell 0:6e9da949a2a3 202 //Error handling. Only continue for 0-360 range.
pmmccorkell 0:6e9da949a2a3 203 if (desired_heading>=0 and desired_heading<=360) {
pmmccorkell 0:6e9da949a2a3 204 //Calculate how far to turn in degrees.
pmmccorkell 0:6e9da949a2a3 205 double diff = abs(desired_heading-(current_heading));
pmmccorkell 0:6e9da949a2a3 206 //Correct for 360-0 edge cases if 'diff'erence is greater than 180.
pmmccorkell 0:6e9da949a2a3 207 //Change direction and recalculate for accurate 'tolerance' comparison.
pmmccorkell 0:6e9da949a2a3 208 if (diff>180) {
pmmccorkell 0:6e9da949a2a3 209 if (desired_heading>180) diff=((current_heading+180)-(desired_heading-180));
pmmccorkell 0:6e9da949a2a3 210 if (current_heading>180) diff=((desired_heading+180)-(current_heading-180));
pmmccorkell 0:6e9da949a2a3 211 }
pmmccorkell 0:6e9da949a2a3 212 while (diff > tolerance) {
pmmccorkell 0:6e9da949a2a3 213 double dir=1;
pmmccorkell 0:6e9da949a2a3 214 double speed=0;
pmmccorkell 0:6e9da949a2a3 215 current_heading=((data(0x1234abcd))/0x10);
pmmccorkell 0:6e9da949a2a3 216 diff=abs((desired_heading)-(current_heading));
pmmccorkell 0:6e9da949a2a3 217 //Sigmoid data
pmmccorkell 0:6e9da949a2a3 218 double center=15; //deg
pmmccorkell 0:6e9da949a2a3 219 double slope=0.5; //rate of change
pmmccorkell 0:6e9da949a2a3 220 if (diff>180) {
pmmccorkell 0:6e9da949a2a3 221 dir=(-1);
pmmccorkell 0:6e9da949a2a3 222 if (desired_heading>180) diff=((current_heading+180)-(desired_heading-180));
pmmccorkell 0:6e9da949a2a3 223 if (current_heading>180) diff=((desired_heading+180)-(current_heading-180));
pmmccorkell 0:6e9da949a2a3 224 }
pmmccorkell 0:6e9da949a2a3 225 if ((desired_heading-current_heading)<0) dir=(dir*-1);
pmmccorkell 0:6e9da949a2a3 226 speed=Sigmoid(esc_range,slope,center,diff);
pmmccorkell 0:6e9da949a2a3 227 if (dir==1) {
pmmccorkell 0:6e9da949a2a3 228 RH_motor_cntrl(stop_pw+speed);
pmmccorkell 0:6e9da949a2a3 229 TurnRight();
pmmccorkell 0:6e9da949a2a3 230 }
pmmccorkell 0:6e9da949a2a3 231 if (dir==-1) {
pmmccorkell 0:6e9da949a2a3 232 RH_motor_cntrl(stop_pw-speed);
pmmccorkell 0:6e9da949a2a3 233 TurnLeft();
pmmccorkell 0:6e9da949a2a3 234 }
pmmccorkell 0:6e9da949a2a3 235 wait_ms(20);
pmmccorkell 0:6e9da949a2a3 236 }
pmmccorkell 0:6e9da949a2a3 237 // pc.printf("heading: %i, diff: %i\r\n",current_heading,diff);
pmmccorkell 0:6e9da949a2a3 238 }
pmmccorkell 0:6e9da949a2a3 239 }
pmmccorkell 0:6e9da949a2a3 240
pmmccorkell 0:6e9da949a2a3 241 void maintain(int desired_heading) {
pmmccorkell 0:6e9da949a2a3 242 while(1) {
pmmccorkell 0:6e9da949a2a3 243 motors(desired_heading);
pmmccorkell 0:6e9da949a2a3 244 wait_ms(20);
pmmccorkell 0:6e9da949a2a3 245 }
pmmccorkell 0:6e9da949a2a3 246 }
pmmccorkell 0:6e9da949a2a3 247
pmmccorkell 0:6e9da949a2a3 248 //Function to accept desired position, program BNO,
pmmccorkell 0:6e9da949a2a3 249 // and update ready word by masking non-position bits
pmmccorkell 0:6e9da949a2a3 250 // and adding the new position to position bits
pmmccorkell 0:6e9da949a2a3 251 void switch_pos(int position) {
pmmccorkell 0:6e9da949a2a3 252 if (position>=0 and position<8) {
pmmccorkell 0:6e9da949a2a3 253 switch (position) {
pmmccorkell 0:6e9da949a2a3 254 case 1:
pmmccorkell 0:6e9da949a2a3 255 imu.set_mounting_position(MT_P1);
pmmccorkell 0:6e9da949a2a3 256 ready=((ready & 0xfffffff8)+0x1);
pmmccorkell 0:6e9da949a2a3 257 break;
pmmccorkell 0:6e9da949a2a3 258 case 2:
pmmccorkell 0:6e9da949a2a3 259 imu.set_mounting_position(MT_P2);
pmmccorkell 0:6e9da949a2a3 260 ready=((ready & 0xfffffff8)+0x2);
pmmccorkell 0:6e9da949a2a3 261 break;
pmmccorkell 0:6e9da949a2a3 262 case 3:
pmmccorkell 0:6e9da949a2a3 263 imu.set_mounting_position(MT_P3);
pmmccorkell 0:6e9da949a2a3 264 ready=((ready & 0xfffffff8)+0x3);
pmmccorkell 0:6e9da949a2a3 265 break;
pmmccorkell 0:6e9da949a2a3 266 case 4:
pmmccorkell 0:6e9da949a2a3 267 imu.set_mounting_position(MT_P4);
pmmccorkell 0:6e9da949a2a3 268 ready=((ready & 0xfffffff8)+0x4);
pmmccorkell 0:6e9da949a2a3 269 break;
pmmccorkell 0:6e9da949a2a3 270 case 5:
pmmccorkell 0:6e9da949a2a3 271 imu.set_mounting_position(MT_P5);
pmmccorkell 0:6e9da949a2a3 272 ready=((ready & 0xfffffff8)+0x5);
pmmccorkell 0:6e9da949a2a3 273 break;
pmmccorkell 0:6e9da949a2a3 274 case 6:
pmmccorkell 0:6e9da949a2a3 275 imu.set_mounting_position(MT_P6);
pmmccorkell 0:6e9da949a2a3 276 ready=((ready & 0xfffffff8)+0x6);
pmmccorkell 0:6e9da949a2a3 277 break;
pmmccorkell 0:6e9da949a2a3 278 case 7:
pmmccorkell 0:6e9da949a2a3 279 imu.set_mounting_position(MT_P7);
pmmccorkell 0:6e9da949a2a3 280 ready=((ready & 0xfffffff8)+0x7);
pmmccorkell 0:6e9da949a2a3 281 break;
pmmccorkell 0:6e9da949a2a3 282 case 0:
pmmccorkell 0:6e9da949a2a3 283 default:
pmmccorkell 0:6e9da949a2a3 284 imu.set_mounting_position(MT_P0);
pmmccorkell 0:6e9da949a2a3 285 ready=((ready & 0xfffffff8));
pmmccorkell 0:6e9da949a2a3 286 break;
pmmccorkell 0:6e9da949a2a3 287 }
pmmccorkell 0:6e9da949a2a3 288 }
pmmccorkell 0:6e9da949a2a3 289 }
pmmccorkell 0:6e9da949a2a3 290
pmmccorkell 0:6e9da949a2a3 291 //Commands function handles Serial input, checks for correct syntax, and calls appropriate function(s) to execute commands.
pmmccorkell 0:6e9da949a2a3 292 void commands() {
pmmccorkell 0:6e9da949a2a3 293 //Instantiate input char array to buffer Serial input.
pmmccorkell 0:6e9da949a2a3 294 char input[1000];
pmmccorkell 0:6e9da949a2a3 295 //check_pos char array used to filter Position commands.
pmmccorkell 0:6e9da949a2a3 296 char check_pos[5]="pos:";
pmmccorkell 0:6e9da949a2a3 297 //check_hea char array used to filter Go to Heading commands.
pmmccorkell 0:6e9da949a2a3 298 char check_hea[5]="hea:";
pmmccorkell 0:6e9da949a2a3 299 //check_mnt char array used to filter Maintain Heading commands.
pmmccorkell 0:6e9da949a2a3 300 char check_mnt[5]="mnt:";
pmmccorkell 0:6e9da949a2a3 301
pmmccorkell 0:6e9da949a2a3 302 //While loop reads Serial input into input buffer.
pmmccorkell 0:6e9da949a2a3 303 int i=0;
pmmccorkell 0:6e9da949a2a3 304 while (pc.readable()) {
pmmccorkell 0:6e9da949a2a3 305 input[i]=pc.getc();
pmmccorkell 0:6e9da949a2a3 306 // pc.printf("read char %c to %i\r\n",input[i], i);
pmmccorkell 0:6e9da949a2a3 307 i++;
pmmccorkell 0:6e9da949a2a3 308 }
pmmccorkell 0:6e9da949a2a3 309
pmmccorkell 0:6e9da949a2a3 310 //Only continue if input buffer has 7 entries, otherwise ignore input buffer.
pmmccorkell 0:6e9da949a2a3 311 //All commands from RasPi shall come in a format of 7 characters "abc:xyz"
pmmccorkell 0:6e9da949a2a3 312 // where 'abc' is an identifying string and 'xyz' is a decimal number.
pmmccorkell 0:6e9da949a2a3 313 if (i==7) {
pmmccorkell 0:6e9da949a2a3 314 // pc.printf("checking 0-%c, 1-%c, 2-%c, 3-%c, 4-%c \r\n",check_pos[0],check_pos[1],check_pos[2],check_pos[3],check_pos[4]);
pmmccorkell 0:6e9da949a2a3 315
pmmccorkell 0:6e9da949a2a3 316 //Instantiate counters that will be used to verify known commands.
pmmccorkell 0:6e9da949a2a3 317 int verified_pos=0;
pmmccorkell 0:6e9da949a2a3 318 int verified_hea=0;
pmmccorkell 0:6e9da949a2a3 319 int verified_mnt=0;
pmmccorkell 0:6e9da949a2a3 320
pmmccorkell 0:6e9da949a2a3 321 //While loop checks first 4 characters of input buffer and attempts to match
pmmccorkell 0:6e9da949a2a3 322 // against known commands.
pmmccorkell 0:6e9da949a2a3 323 int q=0;
pmmccorkell 0:6e9da949a2a3 324 while (q<4) {
pmmccorkell 0:6e9da949a2a3 325 //Increment verified_pos if a match is found between Serial input buffer
pmmccorkell 0:6e9da949a2a3 326 // and Position command format.
pmmccorkell 0:6e9da949a2a3 327 if (input[q]==check_pos[q]) {
pmmccorkell 0:6e9da949a2a3 328 verified_pos++;
pmmccorkell 0:6e9da949a2a3 329 // pc.printf("verified for pos %c at %i\r\n",input[q],q);
pmmccorkell 0:6e9da949a2a3 330 }
pmmccorkell 0:6e9da949a2a3 331
pmmccorkell 0:6e9da949a2a3 332 //Increment verified_hea if a match is found between Serial input buffer
pmmccorkell 0:6e9da949a2a3 333 // and Heading command format.
pmmccorkell 0:6e9da949a2a3 334 if (input[q]==check_hea[q]) {
pmmccorkell 0:6e9da949a2a3 335 // pc.printf("verified for hea %c at %i\r\n",input[q],q);
pmmccorkell 0:6e9da949a2a3 336 verified_hea++;
pmmccorkell 0:6e9da949a2a3 337 }
pmmccorkell 0:6e9da949a2a3 338
pmmccorkell 0:6e9da949a2a3 339 if (input[q]==check_mnt[q]) {
pmmccorkell 0:6e9da949a2a3 340 verified_mnt++;
pmmccorkell 0:6e9da949a2a3 341 }
pmmccorkell 0:6e9da949a2a3 342 q++;
pmmccorkell 0:6e9da949a2a3 343 }
pmmccorkell 0:6e9da949a2a3 344
pmmccorkell 0:6e9da949a2a3 345 //If first 4 characters from Serial input buffer match Position command format,
pmmccorkell 0:6e9da949a2a3 346 // execute "switch_pos" function.
pmmccorkell 0:6e9da949a2a3 347 if (verified_pos==4) {
pmmccorkell 0:6e9da949a2a3 348 int change=(input[6]-'0');
pmmccorkell 0:6e9da949a2a3 349 switch_pos(change);
pmmccorkell 0:6e9da949a2a3 350 }
pmmccorkell 0:6e9da949a2a3 351
pmmccorkell 0:6e9da949a2a3 352 //If first 4 characters from Serial input buffer match Heading command format,
pmmccorkell 0:6e9da949a2a3 353 // execute "motors" function.
pmmccorkell 0:6e9da949a2a3 354 if (verified_hea==4) {
pmmccorkell 0:6e9da949a2a3 355 //Correct for ascii '0', and reform 3digit decimal number
pmmccorkell 0:6e9da949a2a3 356 int hea100=(input[4]-'0');
pmmccorkell 0:6e9da949a2a3 357 int hea10=(input[5]-'0');
pmmccorkell 0:6e9da949a2a3 358 int hea1=(input[6]-'0');
pmmccorkell 0:6e9da949a2a3 359 int hea=(hea100*100)+(hea10*10)+(hea1*1);
pmmccorkell 0:6e9da949a2a3 360 // pc.printf("heading: %i\r\n",hea);
pmmccorkell 0:6e9da949a2a3 361 motors(hea);
pmmccorkell 0:6e9da949a2a3 362 //zero out ready status for LH and RH motors
pmmccorkell 0:6e9da949a2a3 363 ready=(ready & 0xffffffe7);
pmmccorkell 0:6e9da949a2a3 364 Stop_motors();
pmmccorkell 0:6e9da949a2a3 365 RH_motor_cntrl(stop_pw);
pmmccorkell 0:6e9da949a2a3 366 }
pmmccorkell 0:6e9da949a2a3 367
pmmccorkell 0:6e9da949a2a3 368 if (verified_mnt==4) {
pmmccorkell 0:6e9da949a2a3 369 int mnt100=(input[4]-'0');
pmmccorkell 0:6e9da949a2a3 370 int mnt10=(input[5]-'0');
pmmccorkell 0:6e9da949a2a3 371 int mnt1=(input[6]-'0');
pmmccorkell 0:6e9da949a2a3 372 int mnt=(mnt100*100)+(mnt10*10)+(mnt1*1);
pmmccorkell 0:6e9da949a2a3 373 maintain(mnt);
pmmccorkell 0:6e9da949a2a3 374 RH_motor_cntrl(stop_pw);
pmmccorkell 0:6e9da949a2a3 375 //zero out ready status for LH and RH motors
pmmccorkell 0:6e9da949a2a3 376 ready=(ready & 0xffffffe7);
pmmccorkell 0:6e9da949a2a3 377 }
pmmccorkell 0:6e9da949a2a3 378 }
pmmccorkell 0:6e9da949a2a3 379 }
pmmccorkell 0:6e9da949a2a3 380
pmmccorkell 0:6e9da949a2a3 381 int main() {
pmmccorkell 0:6e9da949a2a3 382 //engage plaidspeed
pmmccorkell 0:6e9da949a2a3 383 pc.baud(115200);
pmmccorkell 0:6e9da949a2a3 384 // imu.set_mounting_position(MT_P3);
pmmccorkell 0:6e9da949a2a3 385 RH_motor.period(.02);
pmmccorkell 0:6e9da949a2a3 386 RH_motor.pulsewidth(stop_pw);
pmmccorkell 0:6e9da949a2a3 387
pmmccorkell 0:6e9da949a2a3 388 //If not ready, reset BNO.
pmmccorkell 0:6e9da949a2a3 389 while (imu.chip_ready() == 0) {
pmmccorkell 0:6e9da949a2a3 390 do {
pmmccorkell 0:6e9da949a2a3 391 pc.printf("resetting BNO\r\n");
pmmccorkell 0:6e9da949a2a3 392 pwr_on=0;
pmmccorkell 0:6e9da949a2a3 393 wait_ms(100);
pmmccorkell 0:6e9da949a2a3 394 pwr_on=1;
pmmccorkell 0:6e9da949a2a3 395 wait_ms(50);
pmmccorkell 0:6e9da949a2a3 396 } while(imu.reset());
pmmccorkell 0:6e9da949a2a3 397 }
pmmccorkell 0:6e9da949a2a3 398 wait_ms(20);
pmmccorkell 0:6e9da949a2a3 399
pmmccorkell 0:6e9da949a2a3 400 //If BNO is ready, set ready status indication
pmmccorkell 0:6e9da949a2a3 401 if (imu.chip_ready()) {
pmmccorkell 0:6e9da949a2a3 402 ready=0xffff0000;
pmmccorkell 0:6e9da949a2a3 403 }
pmmccorkell 0:6e9da949a2a3 404 // uint32_t keyver=intake(ready);
pmmccorkell 0:6e9da949a2a3 405
pmmccorkell 0:6e9da949a2a3 406 //Look for serial input commands and send to 'commands' function.
pmmccorkell 0:6e9da949a2a3 407 //If no serial input commands, stream data.
pmmccorkell 0:6e9da949a2a3 408 while(1) {
pmmccorkell 0:6e9da949a2a3 409 if (pc.readable()) commands();
pmmccorkell 0:6e9da949a2a3 410 else data(0x1234abcd);
pmmccorkell 0:6e9da949a2a3 411 wait_ms(20);
pmmccorkell 0:6e9da949a2a3 412 }
pmmccorkell 0:6e9da949a2a3 413 }
pmmccorkell 0:6e9da949a2a3 414