Code for our FYDP -only one IMU works right now -RTOS is working
Embed:
(wiki syntax)
Show/hide line numbers
DMP.cpp
00001 //Copied MPU6050.h and MPU6050.cpp from another library (otherwise MPU gets stuck randomly) 00002 00003 /*** THIS IS THE BEST VERSION OF DMP CODE 00004 This code demonstrates how to access the MPU6050 IMU and fix the 00005 connection errors that occur, using a hardware hack. 00006 It requires two hardware fixes: A transistor (PTE5) and an extra GPIO pin (PTE23) connected 00007 to the SDA line. 00008 Error 1: The SDA line gets stuck on ground. 00009 Solution 1: Use the transistor to raise the SDA voltage off of ground. This resets the I2C bus. (line 71) 00010 Error 2: The SDA line gets stuck on 3.3V 00011 Solution 2: Use the GPIO line to pull the SDA voltage down a bit to reset the I2C bus. (line 96) 00012 (I am currently trying to find a software solution for the above hack) 00013 00014 This code works for using the DMP. (See "DMP" for implementation that can do raw accel data) 00015 It appears all connection issues have been fixed. 00016 Next step: make code neater (in progress) 00017 00018 LEARNED: Do not need the PTE23 line. Only fix necessary is the transistor (PTE5) 00019 ***/ 00020 00021 #include "mbed.h" 00022 #include "DMP.h" 00023 00024 00025 //******* MPU DECLARATION THINGS *****************// 00026 int dmp_test = 1; //if this is 0, get raw MPU values 00027 //if this is 1, get DMP values 00028 00029 int acc_offset[3]; //this saves the offset for acceleration 00030 00031 int16_t ax, ay, az; 00032 int16_t gx, gy, gz; 00033 00034 //******* DMP things ****************// 00035 // MPU control/status vars 00036 bool dmpReady = false; // set true if DMP init was succesfful 00037 uint8_t mpuIntStatus; // holds interrupt status byte from MPU 00038 uint8_t devStatus; // return status after each device operation (0 = success) 00039 uint16_t packetSize; // expected DMP packet size (default is 42 bytes) 00040 uint16_t fifoCount; // count of all bytes currently in FIFO 00041 uint8_t fifoBuffer[64]; // FIFO storage buffer 00042 bool dmpReady2 = false; // set true if DMP init was succesfful 00043 uint8_t mpuIntStatus2; // holds interrupt status byte from MPU 00044 uint8_t devStatus2; // return status after each device operation (0 = success) 00045 uint16_t packetSize2; // expected DMP packet size (default is 42 bytes) 00046 uint16_t fifoCount2; // count of all bytes currently in FIFO 00047 uint8_t fifoBuffer2[64]; // FIFO storage buffer 00048 00049 00050 00051 uint8_t MPU_CONNECTION; 00052 00053 // orientation/motion vars 00054 Quaternion q; // [w,x,y,z] quaternion container 00055 VectorInt16 aa; // [x,y,z] accel sensor measurements 00056 VectorInt16 aaReal; // [x,y,z] gravity-free accel sensor measurements 00057 VectorInt16 aaWorld; // [x,y,z] world-frame accel sensor measurements 00058 VectorFloat gravity; // [x,y,z] gravity vector 00059 float euler[3]; // [psi,theta,phi] Euler angle container 00060 float ypr[3]; // [yaw,pitch,roll] yaw/pitch/roll container [rad]. Multiply by 180, divide by PI for [deg] 00061 InterruptIn checkpin(PTD7); //interrupt 00062 InterruptIn checkpin2(PTD5); //PTD5 00063 //*** Interrupt Detection Routine ***// 00064 volatile bool mpuInterrupt = false; //indicates whether interrupt pin has gone high 00065 void dmpDataReady(){ 00066 mpuInterrupt = true; 00067 } 00068 volatile bool mpuInterrupt2 = false; //indicates whether interrupt pin has gone high 00069 void dmpDataReady2(){ 00070 mpuInterrupt2 = true; 00071 } 00072 00073 //****** END MPU DECLARATION ********************// 00074 00075 00076 int test_dmp(); //this wraps up the code req'd to start the DMP 00077 void start_dmp(MPU6050); //this will get the DMP ready 00078 void update_dmp(); //call this frequently 00079 00080 //*********************FUNCTIONS***************************************************************// 00081 int test_dmp(){ //returns 1 if ok (right now, it doesn't return at all if there is a problem 00082 imuSwitch = 1; 00083 LED_OFF; 00084 Thread::wait(100); 00085 00086 while(mpu.testConnection()==0) 00087 { 00088 imuSwitch = 0; 00089 Thread::wait(100); 00090 imuSwitch = 1; 00091 Thread::wait(100); 00092 bt.lock(); 00093 bt.printf("Stuck on IMU1"); 00094 bt.unlock(); 00095 } 00096 imuSwitch = 1; 00097 LED_ON //turn ON LED 00098 return 1; 00099 } 00100 int test_dmp2(){ //returns 1 if ok (right now, it doesn't return at all if there is a problem 00101 imu2Switch = 1; 00102 LED_OFF; 00103 Thread::wait(100); 00104 00105 while(mpu2.testConnection()==0) 00106 { 00107 imu2Switch = 0; 00108 Thread::wait(100); 00109 imu2Switch = 1; 00110 Thread::wait(100); 00111 bt.lock(); 00112 bt.printf("Stuck on IMU2"); 00113 bt.unlock(); 00114 } 00115 imu2Switch = 1; 00116 LED_ON //turn ON LED 00117 return 1; 00118 } 00119 00120 void start_dmp(MPU6050 mpu1){ //this will get the DMP ready 00121 //initialize device 00122 mpu1.reset(); 00123 DMP_DBG_MSG("\n\rInitializing I2C devices...") 00124 devStatus = mpu1.dmpInitialize(); 00125 //insert gyro offsets here// Write a calibration algorithm in the future 00126 mpu1.setXGyroOffset(0); //800/25=32 //-31 is the largest offset available 00127 mpu1.setYGyroOffset(0); 00128 mpu1.setZGyroOffset(0); 00129 mpu1.setXAccelOffset(0); //the accel offsets don't do anything 00130 mpu1.setYAccelOffset(0); 00131 mpu1.setZAccelOffset(0); 00132 00133 mpu1.setFullScaleGyroRange(MPU6050_GYRO_FS_2000); 00134 00135 if(devStatus == 0){ //this means initialize was successful 00136 //turn on DMP 00137 DMP_DBG_MSG("\n\rEnabling DMP") 00138 mpu1.setDMPEnabled(true); 00139 00140 // enable interrupt detection 00141 DMP_DBG_MSG("Enabling interrupt detection (Arduino external interrupt 0)...\r\n") 00142 checkpin.rise(&dmpDataReady); 00143 00144 mpuIntStatus = mpu1.getIntStatus(); 00145 00146 //set the DMP ready flag so main loop knows when it is ok to use 00147 DMP_DBG_MSG("DMP ready! Waiting for first interrupt") 00148 dmpReady = true; 00149 00150 //get expected DMP packet size 00151 packetSize = mpu1.dmpGetFIFOPacketSize(); 00152 }else{ 00153 DMP_DBG_MSG("\n\rDMP Initialization failed") 00154 DMP_DBG_MSG("\t%d",devStatus) 00155 Thread::wait(1000); 00156 } 00157 acc_offset[0]=0; 00158 acc_offset[1]=0; 00159 acc_offset[2]=0; 00160 mpu.setDLPFMode(MPU6050_DLPF_BW_42); 00161 } 00162 void start_dmp2(MPU6051 mpu1){ //this will get the DMP ready 00163 //initialize device 00164 mpu2.reset(); 00165 DMP_DBG_MSG("\n\rInitializing I2C devices...") 00166 devStatus2 = mpu2.dmpInitialize(); 00167 //insert gyro offsets here// Write a calibration algorithm in the future 00168 mpu2.setXGyroOffset(0); //800/25=32 //-31 is the largest offset available 00169 mpu2.setYGyroOffset(0); 00170 mpu2.setZGyroOffset(0); 00171 mpu2.setXAccelOffset(0); //the accel offsets don't do anything 00172 mpu2.setYAccelOffset(0); 00173 mpu2.setZAccelOffset(0); 00174 00175 mpu2.setFullScaleGyroRange(MPU6050_GYRO_FS_2000); 00176 00177 if(devStatus2 == 0){ //this means initialize was successful 00178 //turn on DMP 00179 DMP_DBG_MSG("\n\rEnabling DMP") 00180 mpu2.setDMPEnabled(true); 00181 00182 // enable interrupt detection 00183 DMP_DBG_MSG("Enabling interrupt detection (Arduino external interrupt 0)...\r\n") 00184 checkpin2.rise(&dmpDataReady2); 00185 00186 mpuIntStatus2 = mpu2.getIntStatus(); 00187 00188 //set the DMP ready flag so main loop knows when it is ok to use 00189 DMP_DBG_MSG("DMP ready! Waiting for first interrupt") 00190 dmpReady2 = true; 00191 00192 //get expected DMP packet size 00193 packetSize2 = mpu2.dmpGetFIFOPacketSize(); 00194 }else{ 00195 DMP_DBG_MSG("\n\rDMP Initialization failed") 00196 DMP_DBG_MSG("\t%d",devStatus2) 00197 Thread::wait(1000); 00198 } 00199 acc_offset[0]=0; 00200 acc_offset[1]=0; 00201 acc_offset[2]=0; 00202 mpu2.setDLPFMode(MPU6050_DLPF_BW_42); 00203 } 00204 00205 void update_dmp(){ 00206 if (!dmpReady) return; 00207 while (!mpuInterrupt && fifoCount < packetSize) { 00208 // other program behavior stuff here 00209 // if you are really paranoid you can frequently test in between other 00210 // stuff to see if mpuInterrupt is true, and if so, "break;" from the 00211 // while() loop to immediately process the MPU data 00212 // . 00213 } 00214 // reset interrupt flag and get INT_STATUS byte 00215 mpuInterrupt = false; //this resets the interrupt flag 00216 mpuIntStatus = mpu.getIntStatus(); 00217 00218 //get current FIFO count; 00219 fifoCount = mpu.getFIFOCount(); 00220 00221 //check for overflow (only happens if your code sucks) 00222 if((mpuIntStatus & 0x10) || fifoCount == 1024){ 00223 //reset so we can continue cleanly 00224 mpu.resetFIFO(); 00225 DMP_DBG_MSG("\n\rFIFO overflow") 00226 } else if (mpuIntStatus & 0x02){ 00227 int16_t x,y,z; 00228 //wait for correct available data length (should be very short) 00229 while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); 00230 00231 //read a packet from FIFO 00232 mpu.getFIFOBytes(fifoBuffer, packetSize); 00233 00234 //track FIFO count here in the case there is > 1 packet available 00235 //(allows us to immediately read more w/o waiting for interrupt) 00236 fifoCount -= packetSize; 00237 00238 mpu.dmpGetQuaternion(&q,fifoBuffer); 00239 imu_data.quat[0]=q.w; 00240 imu_data.quat[1]=q.x; 00241 imu_data.quat[2]=q.y; 00242 imu_data.quat[3]=q.z; 00243 mpu.dmpGetGravity(&gravity, &q); 00244 mpu.dmpGetYawPitchRoll(ypr,&q,&gravity); 00245 imu_data.ypr[0] = ypr[0]*180/M_PI;//MARK - this saves the yaw data so everyone can access it 00246 imu_data.ypr[1] = ypr[1]*180/M_PI; 00247 imu_data.ypr[2] = ypr[2]*180/M_PI; 00248 00249 mpu.getAcceleration(&x,&y,&z); 00250 imu_data.acc[0] = (x-acc_offset[0]) *9.81/16384; 00251 imu_data.acc[1] = (y-acc_offset[1]) *9.81/16384; 00252 imu_data.acc[2] = (z-acc_offset[2]) *9.81/16384; 00253 #ifdef PRINT_GYR 00254 DMP_DBG_MSG("\n\rypr\t %f\t %f\t %f",ypr[0]*180/PI,ypr[1]*180/PI,ypr[2]*180/PI) 00255 #endif 00256 00257 mpu.dmpGetAccel(&aa, fifoBuffer); 00258 mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity); 00259 #ifdef PRINT_ACC 00260 DMP_DBG_MSG("\n\rareal\t%d\t%d\t%d",aaReal.x,aaReal.y,aaReal.z) 00261 #endif 00262 //get rotations 00263 mpu.getMotion6(&x,&y,&z,&gx,&gy,&gz); 00264 float scale = 250/16384; 00265 imu_data.gyr[0] = gx*scale; 00266 imu_data.gyr[1] = gy*scale; 00267 imu_data.gyr[2] = gz*scale; 00268 00269 } 00270 } 00271 void update_dmp2(){ 00272 if (!dmpReady2) return; 00273 while (!mpuInterrupt2 && fifoCount2 < packetSize2) { 00274 // other program behavior stuff here 00275 // if you are really paranoid you can frequently test in between other 00276 // stuff to see if mpuInterrupt is true, and if so, "break;" from the 00277 // while() loop to immediately process the MPU data 00278 // . 00279 } 00280 // reset interrupt flag and get INT_STATUS byte 00281 mpuInterrupt2 = false; //this resets the interrupt flag 00282 mpuIntStatus2 = mpu2.getIntStatus(); 00283 00284 //get current FIFO count; 00285 fifoCount2 = mpu2.getFIFOCount(); 00286 00287 //check for overflow (only happens if your code sucks) 00288 if((mpuIntStatus2 & 0x10) || fifoCount2 == 1024){ 00289 //reset so we can continue cleanly 00290 mpu2.resetFIFO(); 00291 DMP_DBG_MSG("\n\rFIFO overflow") 00292 } else if (mpuIntStatus2 & 0x02){ 00293 int16_t x,y,z; 00294 //wait for correct available data length (should be very short) 00295 while (fifoCount2 < packetSize2) fifoCount2 = mpu2.getFIFOCount(); 00296 00297 //read a packet from FIFO 00298 mpu2.getFIFOBytes(fifoBuffer2, packetSize2); 00299 00300 //track FIFO count here in the case there is > 1 packet available 00301 //(allows us to immediately read more w/o waiting for interrupt) 00302 fifoCount2 -= packetSize2; 00303 00304 mpu2.dmpGetQuaternion(&q,fifoBuffer2); 00305 imu2_data.quat[0]=q.w; 00306 imu2_data.quat[1]=q.x; 00307 imu2_data.quat[2]=q.y; 00308 imu2_data.quat[3]=q.z; 00309 mpu2.dmpGetGravity(&gravity, &q); 00310 mpu2.dmpGetYawPitchRoll(ypr,&q,&gravity); 00311 imu2_data.ypr[0] = ypr[0]*180/M_PI;//MARK - this saves the yaw data so everyone can access it 00312 imu2_data.ypr[1] = ypr[1]*180/M_PI; 00313 imu2_data.ypr[2] = ypr[2]*180/M_PI; 00314 00315 mpu2.getAcceleration(&x,&y,&z); 00316 imu2_data.acc[0] = (x-acc_offset[0]) *9.81/16384; 00317 imu2_data.acc[1] = (y-acc_offset[1]) *9.81/16384; 00318 imu2_data.acc[2] = (z-acc_offset[2]) *9.81/16384; 00319 #ifdef PRINT_GYR 00320 DMP_DBG_MSG("\n\rypr\t %f\t %f\t %f",ypr[0]*180/PI,ypr[1]*180/PI,ypr[2]*180/PI) 00321 #endif 00322 00323 mpu2.dmpGetAccel(&aa, fifoBuffer2); 00324 mpu2.dmpGetLinearAccel(&aaReal, &aa, &gravity); 00325 #ifdef PRINT_ACC 00326 DMP_DBG_MSG("\n\rareal\t%d\t%d\t%d",aaReal.x,aaReal.y,aaReal.z) 00327 #endif 00328 //get rotations 00329 mpu2.getMotion6(&x,&y,&z,&gx,&gy,&gz); 00330 float scale = 250/16384; 00331 imu2_data.gyr[0] = gx*scale; 00332 imu2_data.gyr[1] = gy*scale; 00333 imu2_data.gyr[2] = gz*scale; 00334 00335 } 00336 } 00337 void update_acc() 00338 { 00339 int16_t x,y,z; 00340 mpu.getAcceleration(&x,&y,&z); 00341 imu_data.acc[0] = (x-acc_offset[0]) *9.81/16384; 00342 imu_data.acc[1] = (y-acc_offset[1]) *9.81/16384; 00343 imu_data.acc[2] = (z-acc_offset[2]) *9.81/16384; 00344 } 00345 void calibrate_1() //call this to calibrate the accelerometer 00346 { //in the future, modify the OFFSET REGISTERS to make the DMP converge faster 00347 //right now, I am only calculating the offset for the accelerometers 00348 int sum[3] = {0,0,0}; 00349 int i; 00350 int16_t x,y,z; 00351 00352 int count=0; 00353 int t_now = t.read_ms(); 00354 while((t.read_ms()-t_now) < 1000) //loop for one second 00355 { 00356 mpu.getAcceleration(&x,&y,&z); 00357 sum[0] += x; 00358 sum[1] += y; 00359 sum[2] += z; 00360 Thread::wait(5); 00361 count++; 00362 } 00363 for(i = 0; i<3; i++) 00364 acc_offset[i] = (sum[i]/count); 00365 //bt.printf("ACC_OFF:%d;%d;%d;",acc_offset[0],acc_offset[1],acc_offset[2]);//print the offset used by accelerometer 00366 }
Generated on Wed Jul 13 2022 10:32:23 by 1.7.2