asdfsaf
Dependencies: MPU6050-DMP-Ian mbed-rtos mbed
DMP.cpp
- Committer:
- majik
- Date:
- 2014-05-27
- Revision:
- 0:dceb852b19f3
File content as of revision 0:dceb852b19f3:
//Copied MPU6050.h and MPU6050.cpp from another library (otherwise MPU gets stuck randomly) /*** THIS IS THE BEST VERSION OF DMP CODE This code demonstrates how to access the MPU6050 IMU and fix the connection errors that occur, using a hardware hack. It requires two hardware fixes: A transistor (PTE5) and an extra GPIO pin (PTE23) connected to the SDA line. Error 1: The SDA line gets stuck on ground. Solution 1: Use the transistor to raise the SDA voltage off of ground. This resets the I2C bus. (line 71) Error 2: The SDA line gets stuck on 3.3V Solution 2: Use the GPIO line to pull the SDA voltage down a bit to reset the I2C bus. (line 96) (I am currently trying to find a software solution for the above hack) This code works for using the DMP. (See "DMP" for implementation that can do raw accel data) It appears all connection issues have been fixed. Next step: make code neater (in progress) LEARNED: Do not need the PTE23 line. Only fix necessary is the transistor (PTE5) ***/ #include "mbed.h" #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" #include "robot.h" //******* MPU DECLARATION THINGS *****************// int dmp_test =1; //if this is 0, get raw MPU values //if this is 1, get DMP values int16_t ax, ay, az; int16_t gx, gy, gz; //******* DMP things ****************// // MPU control/status vars bool dmpReady = false; // set true if DMP init was succesfful uint8_t mpuIntStatus; // holds interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer uint8_t MPU_CONNECTION; // orientation/motion vars Quaternion q; // [w,x,y,z] quaternion container VectorInt16 aa; // [x,y,z] accel sensor measurements VectorInt16 aaReal; // [x,y,z] gravity-free accel sensor measurements VectorInt16 aaWorld; // [x,y,z] world-frame accel sensor measurements VectorFloat gravity; // [x,y,z] gravity vector float euler[3]; // [psi,theta,phi] Euler angle container float ypr[3]; // [yaw,pitch,roll] yaw/pitch/roll container [rad]. Multiply by 180, divide by PI for [deg] InterruptIn checkpin(PTD7); //interrupt //*** Interrupt Detection Routine ***// volatile bool mpuInterrupt = false; //indicates whether interrupt pin has gone high void dmpDataReady(){ mpuInterrupt = true; } //****** END MPU DECLARATION ********************// int test_dmp(); //this wraps up the code req'd to start the DMP void start_dmp(MPU6050 mpu); //this will get the DMP ready void update_dmp(MPU6050 mpu); //call this frequently //*********************FUNCTIONS***************************************************************// int test_dmp(){ //returns 1 if ok (right now, it doesn't return at all if there is a problem /// This function tests the I2C port for the MPU6050 and resets it if it is not working //NOTE: when the I2C connection is not successful, calling initialize() will cause the board to freeze DigitalOut reset_pin(PTE5); //Transistor to pull up SDA line reset_pin = 0; //start the transistor in OFF mode //int count = 0; DigitalIn sample_1(PTE0); //(this pin will be used as the SDA pin when an MPU6050 object is declared int temp = sample_1; //Sample what is happening on the SDA line to guess what the solution is. myled = 1; //turn OFF LED. This will turn on again when the MPU is connected. //bt.baud(baudRate); DigitalOut reset_1(PTE0);//change the SDA pin to output. reset_1 = 0; if(temp == 1){ //if SDA line starts high, unstick by pulling it low bt.printf("\n\rSetting up I2C connection..."); reset_1 = 0; //SDA pin = low wait_ms(100); MPU6050 *mpu2 = new MPU6050; //create a temporary MPU connection for testing mpu2->reset(); //bt.baud(baudRate); while(mpu2->testConnection() == 0){ delete mpu2; //delete mpu2 so I can use PTE0 as a GPIO again bt.baud(baudRate); //you must reset baud rate whenever a new MPU6050 is declared DigitalOut sda_pinx(PTE0); sda_pinx = 0; //set this to 0 to pull the SDA line down from 3.3V reset_pin = 0; //make sure transistor = OFF bt.printf("\n\rRetry"); wait_ms(50); MPU6050 *mpu2 = new MPU6050; wait_ms(500); if(mpu2->testConnection() == 0) { reset_pin = 1; wait_ms(50); reset_pin = 0; } } delete mpu2; //free the memory allocated to mpu2 (this is important) }else{ bt.printf("\n\rSetting up I2C connection..."); reset_1 = 1; reset_pin = 1; wait_ms(20); reset_pin = 0; reset_1 = 0; wait_ms(20); } reset_pin = 0; DigitalIn not_used(PTE23); myled = 0; //turn ON LED return 1; } void start_dmp(MPU6050 mpu1){ //this will get the DMP ready //initialize device mpu1.reset(); bt.printf("\n\rInitializing I2C devices..."); devStatus = mpu1.dmpInitialize(); //insert gyro offsets here// Write a calibration algorithm in the future mpu1.setXGyroOffset(-31); //800/25=32 //-31 is the largest offset available mpu1.setYGyroOffset(-183/25); mpu1.setZGyroOffset(80/25); mpu1.setXAccelOffset(0); //the accel offsets don't do anything mpu1.setYAccelOffset(0); mpu1.setZAccelOffset(0); if(devStatus == 0){ //this means initialize was successful //turn on DMP bt.printf("\n\rEnabling DMP"); mpu1.setDMPEnabled(true); // enable interrupt detection bt.printf("Enabling interrupt detection (Arduino external interrupt 0)...\r\n"); checkpin.rise(&dmpDataReady); mpuIntStatus = mpu1.getIntStatus(); //set the DMP ready flag so main loop knows when it is ok to use bt.printf("DMP ready! Waiting for first interrupt"); dmpReady = true; //get expected DMP packet size packetSize = mpu1.dmpGetFIFOPacketSize(); }else{ bt.printf("\n\rDMP Initialization failed"); bt.printf("\t%d",devStatus); wait_ms(1000); } } void update_dmp(MPU6050 mpu1){ if (!dmpReady) return; //while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . //} // reset interrupt flag and get INT_STATUS byte //mpuInterrupt = false; //this resets the interrupt flag mpuIntStatus = mpu1.getIntStatus(); //get current FIFO count; fifoCount = mpu1.getFIFOCount(); //check for overflow (only happens if your code sucks) if((mpuIntStatus & 0x10) || fifoCount == 1024){ //reset so we can continue cleanly mpu1.resetFIFO(); bt.printf("\n\rFIFO overflow"); } else if (mpuIntStatus & 0x02){ //wait for correct available data length (should be very short) while (fifoCount < packetSize) fifoCount = mpu1.getFIFOCount(); //read a packet from FIFO mpu1.getFIFOBytes(fifoBuffer, packetSize); //track FIFO count here in the case there is > 1 packet available //(allows us to immediately read more w/o waiting for interrupt) fifoCount -= packetSize; mpu1.dmpGetQuaternion(&q,fifoBuffer); mpu1.dmpGetGravity(&gravity, &q); mpu1.dmpGetYawPitchRoll(ypr,&q,&gravity); #ifdef PRINT_GYR bt.printf("\n\rypr\t %f\t %f\t %f",ypr[0]*180/PI,ypr[1]*180/PI,ypr[2]*180/PI); #endif mpu1.dmpGetAccel(&aa, fifoBuffer); mpu1.dmpGetLinearAccel(&aaReal, &aa, &gravity); #ifdef PRINT_ACC bt.printf("\n\rareal\t%d\t%d\t%d",aaReal.x,aaReal.y,aaReal.z); #endif } }