Help! MPU6050 to read from 0 - 360 degrees

Hello everyone. I need to measure X and Y axis using MPU6050 (accelerometer + gyro) from 0 - 360 degrees. But the problem is that the value of these angles starts from 0 then reaches 90, then starts to decrease again to reach 0. what i. need to do is to have this value in the range of zero to 360 (positive) not from zero to 90 as it is now Do anyone have any idea??

The program used "MPU6050_DMP6" is from the example of the library in the link below. Library: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050

As the comments in that sketch say:

// Also note that yaw/pitch/roll angles suffer from gimbal lock (for
// more info, see: http://en.wikipedia.org/wiki/Gimbal_lock)
#define OUTPUT_READABLE_YAWPITCHROLL

Did you read about the problem of gimbal lock?

If you want 360° orientation you might need to learn how to use Quaternions.

This code works great!!!

Wiring:

You must hook up the INT to pin 2 on your Arduino!

Use the Library found at i2cdevlib/Arduino/MPU6050 at master · jrowberg/i2cdevlib · GitHub
Run The MPU6050_calibration.ino (attached below) and follow the instructions in the serial monitor: set it to 115200 baud
You will get the Calibration for your MPU6050. Every MPU6050 is different!

Look for these lines of code in the MPU6050_Latest_code.ino sketch:

// supply your own gyro offsets here, scaled for min sensitivity use MPU6050_calibration.ino
// -4232  -706  1729  173 -94 37
//                       XA      YA      ZA      XG      YG      ZG
int MPUOffsets[6] = {  -4232,  -706,   1729,    173,    -94,     37};

put your offsets you got from the calibration here.

Note: I have custom Debug Print Macros These are basically enhanced Serial.print() for displaying information.

#define DPRINTSTIMER(t)    for (static unsigned long SpamTimer; (unsigned long)(millis() - SpamTimer) >= (t); SpamTimer = millis()) // Spam Timer
#define  DPRINTSFN(StrSize,Name,...) {char S[StrSize];Serial.print("\t");Serial.print(Name);Serial.print(" "); Serial.print(dtostrf((float)__VA_ARGS__ ,S));}//StringSize,Name,Variable,Spaces,Percision   <<< Prints floats as a formated string with description
#define DPRINTLN(...)      Serial.println(__VA_ARGS__) // Simple Println()

In the function MPUMath() I am calculating the Yaw, Pitch and Roll angles that you are looking for.
Note: The MPUMath triggers by interrupt (pin 2) about every 10 milliseconds. your loop() code can’t have delays more than 8~9 ms or the FIFO(First in First out) buffer in the MPU6050 will become corrupted and your readings will fail. avoid using delay() in the loop at all costs. look up “Blink without delay” to learn how to do this.

void MPUMath() {
  mpu.dmpGetQuaternion(&q, fifoBuffer);
  mpu.dmpGetGravity(&gravity, &q);
  mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  Yaw = (ypr[0] * 180.0 / M_PI);
  Pitch = (ypr[1] *  180.0 / M_PI);
  Roll = (ypr[2] *  180.0 / M_PI);
  DPRINTSTIMER(100) {
    DPRINTSFN(15, "\tYaw:", Yaw, 6, 1); // \t is the tab character // fancy Serial.Print
    DPRINTSFN(15, "\tPitch:", Pitch, 6, 1); // how to use DPRINTSFN() 15: USING 15 CHARACTERS MAX for the number to string conversion, "\tPitch": displayed name, Pitch: Floating point value to display, 6: using 6 characters in the conversion, 1: trim the float to 1 decimal place
    DPRINTSFN(15, "\tRoll:", Roll, 6, 1); //DPRINTSFN() Will display any floating point number with simple and space everything nicely
    DPRINTLN(); // Simple New Line
  }
}

alternatly you might want other information from the DMP (Digital Motion Processing) available from the MPU6050

            // display quaternion values in easy matrix form: w x y z
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            Serial.print("quat\t");
            Serial.print(q.w);
            Serial.print("\t");
            Serial.print(q.x);
            Serial.print("\t");
            Serial.print(q.y);
            Serial.print("\t");
            Serial.println(q.z);
 
            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetEuler(euler, &q);
            Serial.print("euler\t");
            Serial.print(euler[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(euler[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(euler[2] * 180/M_PI);


            // display Euler angles in degrees
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print("ypr\t");
            Serial.print(ypr[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(ypr[1] * 180/M_PI);
            Serial.print("\t");
            Serial.println(ypr[2] * 180/M_PI);


            // display real acceleration, adjusted to remove gravity
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            Serial.print("areal\t");
            Serial.print(aaReal.x);
            Serial.print("\t");
            Serial.print(aaReal.y);
            Serial.print("\t");
            Serial.println(aaReal.z);
 

            // display initial world-frame acceleration, adjusted to remove gravity
            // and rotated based on known orientation from quaternion
            mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetAccel(&aa, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetLinearAccel(&aaReal, &aa, &gravity);
            mpu.dmpGetLinearAccelInWorld(&aaWorld, &aaReal, &q);
            Serial.print("aworld\t");
            Serial.print(aaWorld.x);
            Serial.print("\t");
            Serial.print(aaWorld.y);
            Serial.print("\t");
            Serial.println(aaWorld.z);


            // display quaternion values in InvenSense Teapot demo format:
            teapotPacket[2] = fifoBuffer[0];
            teapotPacket[3] = fifoBuffer[1];
            teapotPacket[4] = fifoBuffer[4];
            teapotPacket[5] = fifoBuffer[5];
            teapotPacket[6] = fifoBuffer[8];
            teapotPacket[7] = fifoBuffer[9];
            teapotPacket[8] = fifoBuffer[12];
            teapotPacket[9] = fifoBuffer[13];
            Serial.write(teapotPacket, 14);
            teapotPacket[11]++; // packetCount, loops at 0xFF on purpose

MPU6050_Latest_code.ino (7.4 KB)

MPU6050_calibration.ino (7.64 KB)

I did the calibration and use your MPU6050_Latest_code.ino on Arduino Micro and serial monitor output is

i2cSetup MPU6050Connect Enabling DMP... Enabling interrupt detection (Arduino external interrupt pin 2 on the Uno)... mpu.getInterruptDrive= 0 Setup complete

How can I output the accurate measuring of angle in serial monitor? I just want to print it with LCD like a box angle measuring device.. Sorry beginner. Btw. thanks for helping!

robert_james: I did the calibration and use your MPU6050_Latest_code.ino on Arduino Micro and serial monitor output is

i2cSetup MPU6050Connect Enabling DMP... Enabling interrupt detection (Arduino external interrupt pin 2 on the Uno)... mpu.getInterruptDrive= 0 Setup complete

How can I output the accurate measuring of angle in serial monitor? I just want to print it with LCD like a box angle measuring device.. Sorry beginner. Btw. thanks for helping!

The MPUMath() routine calculates the angles from the MPU and displays them. I removed the macros and put what the macros do in normal code:

void MPUMath() {
  mpu.dmpGetQuaternion(&q, fifoBuffer);
  mpu.dmpGetGravity(&gravity, &q);
  mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  Yaw = (ypr[0] * 180.0 / M_PI);
  Pitch = (ypr[1] *  180.0 / M_PI);
  Roll = (ypr[2] *  180.0 / M_PI);
  static unsigned long SpamTimer;
  if ( (unsigned long)(millis() - SpamTimer) >= (100)){
    SpamTimer = millis();
    char S[15];
    Serial.print("\t");
    Serial.print(Yaw);
    Serial.print(" ");
    Serial.print(dtostrf((float) Yaw, 6, 1,S));
    Serial.print("\t");
    Serial.print(Pitch);
    Serial.print(" ");
    Serial.print(dtostrf((float) Pitch, 6, 1,S));
    Serial.print("\t");
    Serial.print(Roll);
    Serial.print(" ");
    Serial.print(dtostrf((float) Roll, 6, 1,S));
    Serial.println(); // Simple New Line
  }
}

I think your problem isn't the display of code. Your serial output was 100% correct up to the point when data should be ready to retrieve data from the MPU6050. The question I have is with pin 2: Do you have a wire attached from pin 2 on the Arduino Micro to the INT pin on the MPU6050?

How you can tell if the INT (MPU6050 interrupt pin) is triggering the Arduino Micro is with an LED attached to pin 13 (usually the onboard LED) will be ON (it blinks every 10ms) and it fails off. If the LED is off then your wiring isn't connected properly.

I just do the MPU6050_calibration.ino and run MPU6050_Latest_code.ino

Based on the link below INT pin is on Pin 0 / RX https://www.arduino.cc/en/Reference/AttachInterrupt

SDA and SCL are on Pin 2 and 3 https://www.google.com.ph/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=0ahUKEwiEpuDh3LTRAhVGtJQKHfFqCS0QjRwIBw&url=https%3A%2F%2Fwww.arduino.cc%2Fen%2FMain%2FarduinoBoardMicro&psig=AFQjCNHGJq3-lmYqx5y7lqyxfhgMrlLMDA&ust=1484039679427635

The Pin 13 LED doesn't blink And the display at serial monitor ends when the setup is complete.

I really appreciate your help. Thanks!

robert_james: I just do the MPU6050_calibration.ino and run MPU6050_Latest_code.ino

Based on the link below INT pin is on Pin 0 / RX https://www.arduino.cc/en/Reference/AttachInterrupt

SDA and SCL are on Pin 2 and 3 https://www.google.com.ph/url?sa=i&rct=j&q=&esrc=s&source=images&cd=&cad=rja&uact=8&ved=0ahUKEwiEpuDh3LTRAhVGtJQKHfFqCS0QjRwIBw&url=https%3A%2F%2Fwww.arduino.cc%2Fen%2FMain%2FarduinoBoardMicro&psig=AFQjCNHGJq3-lmYqx5y7lqyxfhgMrlLMDA&ust=1484039679427635

The Pin 13 LED doesn't blink And the display at serial monitor ends when the setup is complete.

I really appreciate your help. Thanks!

:) Thats right you are using a different chip than the atmega328p I didn't realize that the ATmega32U4 uses pins 2&3 for i2c communications From the Arduino Micro Page:

External Interrupts: 0(RX), 1(TX), 2, 3 and 7. These pins can be configured to trigger an interrupt on a low value, a rising or falling edge, or a change in value. See the attachInterrupt() function for details.

It looks like you will have to use interrupt on pin 7 for the MPU6050 INT connection. on line 112 of the MPU6050_Latest_code make the following change

 attachInterrupt(0, dmpDataReady, RISING); //pin 2 on the Uno
 to
 attachInterrupt(digitalPinToInterrupt(7), dmpDataReady, RISING); //pin 7 on the Micro

Now connect the MPU6050 INT pin to the Arduino Micro Pin7


What we are doing with this is using the MPU6050's micro processor to calculate our angles for us. the MPU6050 takes about 10 microseconds to do this. When the calculated data is ready it triggers a pulse that the interrupt pin ( micro pin 7) sees and knows now it can ask the MPU6050 for the calculated values.

you will need to have SDA and SCL are on Pin 2 and 3 connected and now int on pin 7 I hope this works now :)

thanks it works..

but the problem is it is measuring only up to 180 then reducing back to 0.. and a randon negative values appearing..

how can it make to 0 - 360 then back again to 0 (positive value) just like: https://www.youtube.com/watch?v=U7lf_E79j7Q (i have tried the program but doesn't work) https://drive.google.com/file/d/0B5lyA67pJIcWUU5BamlMZkVXLTA/view (In this program how i can change the interrupt pin?)

much appreciated..

The MPU6050 Math formula returns Radians (What are Radians?) and I do the math to convert it to degrees

void MPUMath() {
  mpu.dmpGetQuaternion(&q, fifoBuffer);
  mpu.dmpGetGravity(&gravity, &q);
  mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
  Yaw = (ypr[0] * 180.0 / M_PI); // Converts Radians to degrees
  Pitch = (ypr[1] *  180.0 / M_PI);// Converts Radians to degrees
  Roll = (ypr[2] *  180.0 / M_PI);// Converts Radians to degrees
  DPRINTSTIMER(100) {
    DPRINTSFN(15, "\tYaw:", Yaw, 6, 1);
    DPRINTSFN(15, "\tPitch:", Pitch, 6, 1);
    DPRINTSFN(15, "\tRoll:", Roll, 6, 1);
    DPRINTLN();
  }
}

You could shift it to only show positive numbers by simply adding 180°

  Yaw = (ypr[0] * 180.0 / M_PI) +180; // Converts Radians to degrees
  Pitch = (ypr[1] *  180.0 / M_PI) +180;// Converts Radians to degrees
  Roll = (ypr[2] *  180.0 / M_PI) +180;// Converts Radians to degrees

https://drive.google.com/file/d/0B5lyA67pJIcWUU5BamlMZkVXLTA/view (In this program how i can change the interrupt pin?)

The example code from your link reads raw data and the UNO does all the calculations. Since the MPU6050 is only handing angle change rates you will not need the interrupt pin. It should work but I haven't needed to calculate from raw angle rates to angles in quite a while once I started using the MPU6050 so troubleshooting this code would be difficult for me. My math skills lack in the raw calculations.

Z

Raw calculation Code from Robert_james post https://drive.google.com/file/d/0B5lyA67pJIcWUU5BamlMZkVXLTA/view : Z

Is it possible to combine the program for angle measuring and angle calibration? Just like i have option to calibrate first before measuring or directly measure...

robert_james: Is it possible to combine the program for angle measuring and angle calibration? Just like i have option to calibrate first before measuring or directly measure...

Once your MPU is calibrated you wouldn't need to get the calibration numbers again. I've tried to combine them but the Calibration routine requires quite a bit of memory and so I have not succeeded in combining them.

How can I combine programs both are using I2c? I am using LCD i2c as a interface.. LCD I2C

// lcd_I2C_test 
#include 
#include 

#define I2C_ADDR    0x27
#define BACKLIGHT_PIN     3
#define En_pin  2
#define Rw_pin  1
#define Rs_pin  0
#define D4_pin  4
#define D5_pin  5
#define D6_pin  6
#define D7_pin  7
LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,BACKLIGHT_PIN,POSITIVE);

int loopCount = 0;

void setup()
{
 // Switch on the backlight
 pinMode ( BACKLIGHT_PIN, OUTPUT );
 digitalWrite ( BACKLIGHT_PIN, LOW );

 lcd.begin(20,4);               // initialize the lcd 

 lcd.home ();                   // go home
 lcd.print("Hello, ARDUINO ");  
 lcd.setCursor ( 0, 1 );        // go to the next line
 lcd.print ("     WORLD!  ");      
}

void loop()
{
 lcd.clear();                // clear LCD screen
 delay(200);
 lcd.print("Hello, ARDUINO "); 
 lcd.setCursor ( 0, 1 );        // go to the next line
 delay(200);
 lcd.print ("    WORLD!  ");      
 delay(500);
 lcd.setCursor ( 0, 1 );        // go to the next line
 lcd.print (loopCount++);
 blink2();
 delay(500);  
}

void blink2(){
 static byte lastState ;
 pinMode ( 13, OUTPUT );
 if (lastState != HIGH){
   digitalWrite ( 13, HIGH ); 
   lastState = HIGH;
 }
 else {
   digitalWrite ( 13, LOW ); 
   lastState = LOW;
 }
}

LCD and MPU6050 are both using SDA and SCL pin..

robert_james: How can I combine programs both are using I2c? I am using LCD i2c as a interface.. LCD I2C

// lcd_I2C_test 
#include 
#include 

define I2C_ADDR    0x27

define BACKLIGHT_PIN     3

define En_pin  2

define Rw_pin  1

define Rs_pin  0

define D4_pin  4

define D5_pin  5

define D6_pin  6

define D7_pin  7

LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin,Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin,BACKLIGHT_PIN,POSITIVE);

int loopCount = 0;

void setup() { // Switch on the backlight pinMode ( BACKLIGHT_PIN, OUTPUT ); digitalWrite ( BACKLIGHT_PIN, LOW );

lcd.begin(20,4);               // initialize the lcd

lcd.home ();                   // go home lcd.print("Hello, ARDUINO ");   lcd.setCursor ( 0, 1 );        // go to the next line lcd.print ("     WORLD!  ");       }

void loop() { lcd.clear();                // clear LCD screen delay(200); lcd.print("Hello, ARDUINO "); lcd.setCursor ( 0, 1 );        // go to the next line delay(200); lcd.print ("    WORLD!  ");       delay(500); lcd.setCursor ( 0, 1 );        // go to the next line lcd.print (loopCount++); blink2(); delay(500);   }

void blink2(){ static byte lastState ; pinMode ( 13, OUTPUT ); if (lastState != HIGH){   digitalWrite ( 13, HIGH );   lastState = HIGH; } else {   digitalWrite ( 13, LOW );   lastState = LOW; } }




LCD and MPU6050 are both using SDA and SCL pin..

MPU6050 and LCD i2c have different addresses on the i2c buss so you can combine the programs. You will probably need to look at both libraries to see if they try to create duplicate declarations of the same or similar functions. This may be easy and they work great together or you bay have your work cut out for you. Produce some code and share it both your successes and struggles. I don't have the LCDi2c display but we as a community share our talents to help others and we may be able to resolve issues you run into. Thanks for joining us :) Z

All the same no one really answered the question.

robert_james: Hello everyone. I need to measure X and Y axis using MPU6050 (accelerometer + gyro) from 0 - 360 degrees. But the problem is that the value of these angles starts from 0 then reaches 90, then starts to decrease again to reach 0. what i. need to do is to have this value in the range of zero to 360 (positive) not from zero to 90 as it is now Do anyone have any idea??

The program used "MPU6050_DMP6" is from the example of the library in the link below. Library: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050

To answer your original question Have you tried all the angle calculation functions your library provides? I know the dmpGetYawPitchRoll() uses gravity to measure pitch and roll so you are seeing angle to gravity (which works great for balancing bots). The dmpGetEuler() is closer to your request it is calculated relative to the object rather than the world. the dmpGetEuler returns radians so you still need to convert them to degrees.

Degrees = (radians * 180.0 / M_PI);
uint8_t MPU6050::dmpGetanAccel(int32_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = (((uint32_t)packet[28] << 24) | ((uint32_t)packet[29] << 16) | ((uint32_t)packet[30] << 8) | packet[31]);
    data[1] = (((uint32_t)packet[32] << 24) | ((uint32_t)packet[33] << 16) | ((uint32_t)packet[34] << 8) | packet[35]);
    data[2] = (((uint32_t)packet[36] << 24) | ((uint32_t)packet[37] << 16) | ((uint32_t)packet[38] << 8) | packet[39]);
    return 0;
}
uint8_t MPU6050::dmpGetAccel(int16_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = (packet[28] << 8) | packet[29];
    data[1] = (packet[32] << 8) | packet[33];
    data[2] = (packet[36] << 8) | packet[37];
    return 0;
}
uint8_t MPU6050::dmpGetAccel(VectorInt16 *v, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    v -> x = (packet[28] << 8) | packet[29];
    v -> y = (packet[32] << 8) | packet[33];
    v -> z = (packet[36] << 8) | packet[37];
    return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int32_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = (((uint32_t)packet[0] << 24) | ((uint32_t)packet[1] << 16) | ((uint32_t)packet[2] << 8) | packet[3]);
    data[1] = (((uint32_t)packet[4] << 24) | ((uint32_t)packet[5] << 16) | ((uint32_t)packet[6] << 8) | packet[7]);
    data[2] = (((uint32_t)packet[8] << 24) | ((uint32_t)packet[9] << 16) | ((uint32_t)packet[10] << 8) | packet[11]);
    data[3] = (((uint32_t)packet[12] << 24) | ((uint32_t)packet[13] << 16) | ((uint32_t)packet[14] << 8) | packet[15]);
    return 0;
}
uint8_t MPU6050::dmpGetQuaternion(int16_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = ((packet[0] << 8) | packet[1]);
    data[1] = ((packet[4] << 8) | packet[5]);
    data[2] = ((packet[8] << 8) | packet[9]);
    data[3] = ((packet[12] << 8) | packet[13]);
    return 0;
}
uint8_t MPU6050::dmpGetQuaternion(Quaternion *q, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    int16_t qI[4];
    uint8_t status = dmpGetQuaternion(qI, packet);
    if (status == 0) {
        q -> w = (float)qI[0] / 16384.0f;
        q -> x = (float)qI[1] / 16384.0f;
        q -> y = (float)qI[2] / 16384.0f;
        q -> z = (float)qI[3] / 16384.0f;
        return 0;
    }
    return status; // int16 return value, indicates error if this line is reached
}
// uint8_t MPU6050::dmpGet6AxisQuaternion(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetRelativeQuaternion(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGyro(int32_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = (((uint32_t)packet[16] << 24) | ((uint32_t)packet[17] << 16) | ((uint32_t)packet[18] << 8) | packet[19]);
    data[1] = (((uint32_t)packet[20] << 24) | ((uint32_t)packet[21] << 16) | ((uint32_t)packet[22] << 8) | packet[23]);
    data[2] = (((uint32_t)packet[24] << 24) | ((uint32_t)packet[25] << 16) | ((uint32_t)packet[26] << 8) | packet[27]);
    return 0;
}
uint8_t MPU6050::dmpGetGyro(int16_t *data, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    data[0] = (packet[16] << 8) | packet[17];
    data[1] = (packet[20] << 8) | packet[21];
    data[2] = (packet[24] << 8) | packet[25];
    return 0;
}
uint8_t MPU6050::dmpGetGyro(VectorInt16 *v, const uint8_t* packet) {
    // TODO: accommodate different arrangements of sent data (ONLY default supported now)
    if (packet == 0) packet = dmpPacketBuffer;
    v -> x = (packet[16] << 8) | packet[17];
    v -> y = (packet[20] << 8) | packet[21];
    v -> z = (packet[24] << 8) | packet[25];
    return 0;
}
// uint8_t MPU6050::dmpSetLinearAccelFilterCoefficient(float coef);
// uint8_t MPU6050::dmpGetLinearAccel(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccel(VectorInt16 *v, VectorInt16 *vRaw, VectorFloat *gravity) {
    // get rid of the gravity component (+1g = +8192 in standard DMP FIFO packet, sensitivity is 2g)
    v -> x = vRaw -> x - gravity -> x*8192;
    v -> y = vRaw -> y - gravity -> y*8192;
    v -> z = vRaw -> z - gravity -> z*8192;
    return 0;
}
// uint8_t MPU6050::dmpGetLinearAccelInWorld(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetLinearAccelInWorld(VectorInt16 *v, VectorInt16 *vReal, Quaternion *q) {
    // rotate measured 3D acceleration vector into original state
    // frame of reference based on orientation quaternion
    memcpy(v, vReal, sizeof(VectorInt16));
    v -> rotate(q);
    return 0;
}
// uint8_t MPU6050::dmpGetGyroAndAccelSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGyroSensor(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetControlData(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetTemperature(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetGravity(long *data, const uint8_t* packet);
uint8_t MPU6050::dmpGetGravity(VectorFloat *v, Quaternion *q) {
    v -> x = 2 * (q -> x*q -> z - q -> w*q -> y);
    v -> y = 2 * (q -> w*q -> x + q -> y*q -> z);
    v -> z = q -> w*q -> w - q -> x*q -> x - q -> y*q -> y + q -> z*q -> z;
    return 0;
}
// uint8_t MPU6050::dmpGetUnquantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetQuantizedAccel(long *data, const uint8_t* packet);
// uint8_t MPU6050::dmpGetExternalSensorData(long *data, int size, const uint8_t* packet);
// uint8_t MPU6050::dmpGetEIS(long *data, const uint8_t* packet);

uint8_t MPU6050::dmpGetEuler(float *data, Quaternion *q) {
    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);   // psi
    data[1] = -asin(2*q -> x*q -> z + 2*q -> w*q -> y);                              // theta
    data[2] = atan2(2*q -> y*q -> z - 2*q -> w*q -> x, 2*q -> w*q -> w + 2*q -> z*q -> z - 1);   // phi
    return 0;
}
uint8_t MPU6050::dmpGetYawPitchRoll(float *data, Quaternion *q, VectorFloat *gravity) {
    // yaw: (about Z axis)
    data[0] = atan2(2*q -> x*q -> y - 2*q -> w*q -> z, 2*q -> w*q -> w + 2*q -> x*q -> x - 1);
    // pitch: (nose up/down, about Y axis)
    data[1] = atan(gravity -> x / sqrt(gravity -> y*gravity -> y + gravity -> z*gravity -> z));
    // roll: (tilt left/right, about X axis)
    data[2] = atan(gravity -> y / sqrt(gravity -> x*gravity -> x + gravity -> z*gravity -> z));
    return 0;
}

Hello I'am using the MPU6050_Latest_code.ino, but with me it shows the value roll and pitch only from 0 -90 / 90 - 0. What do I need to change, to get values from 0-180 / 180-0 ?

Greetings Gorbi

Gorbi5: Hello I'am using the MPU6050_Latest_code.ino, but with me it shows the value roll and pitch only from 0 -90 / 90 - 0. What do I need to change, to get values from 0-180 / 180-0 ?

Greetings Gorbi

Zero being flat. Correct? Try subtracting 90 from the value. Let me know if this works. I don't have my test board setup to confirm

No, it does not work. The value starts only at 90 and goes to 180 and then to 90 again. I changed the following code:

// ================================================================ // === MPU Math === // ================================================================ float Yaw, Pitch, Roll; void MPUMath() { mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Yaw = (ypr[0] * 180.0 / M_PI*)-90; Pitch = (ypr[1] * 180.0 / M_PI)-90; Roll = (ypr[2] * 180.0 / M_PI)-90*; DPRINTSTIMER(100) { DPRINTSFN(15, "\tYaw:", Yaw, 6, 1); DPRINTSFN(15, "\tPitch:", Pitch, 6, 1); DPRINTSFN(15, "\tRoll:", Roll, 6, 1); DPRINTLN(); } }

The source for the conversion is found here. (Attached)
I’m not efficient at this math.
I know the results are in radians and I’m converting this to degrees.
I believe The roll and pitch use the accelerometer primarily.

Z

helper_3dmath.h (7.99 KB)

Gorbi5,

What was the final result that you used to solve your problem ?