Gyroscope of MPU6050

Hello everyone,

I’m using the MPU-6050 and the Arduino platform to measure the rotation of a certain object.

I noticed that the MPU6050 can only measure the gyro rates while placed horizontally on a flat surface with the z axis running vertically.
If I place the MPU 6050 differently, so that the x axis runs vertically to measure another rotation, it doesn’t show the correct values like it did while rotation around the z axis.
From my „non-professional“ point of view it basically seems like the z axis being the „main“ axis for rotation.
I was wondering if there is a possible modification in the code to show the correct values in every axis?

void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

  void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

    // wait for MPU interrupt or extra packet(s) available
    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;
    mpuIntStatus = mpu.getIntStatus();

    // get current FIFO count
    fifoCount = mpu.getFIFOCount();

    // check for overflow (this should never happen unless our code is too inefficient)
    if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));

    // otherwise, check for DMP data ready interrupt (this should happen frequently)
    } else if (mpuIntStatus & 0x02) {
        // wait for correct available data length, should be a VERY short wait
        while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

        // read a packet from FIFO
        mpu.getFIFOBytes(fifoBuffer, packetSize);
        
        // track FIFO count here in case there is > 1 packet available
        // (this lets us immediately read more without waiting for an interrupt)
        fifoCount -= packetSize;

        #ifdef OUTPUT_READABLE_QUATERNION
            // 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);
        #endif

        #ifdef OUTPUT_READABLE_EULER
            // 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);
        #endif

        #ifdef OUTPUT_READABLE_YAWPITCHROLL
            // 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);
        #endif

        #ifdef OUTPUT_READABLE_REALACCEL
            // 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);
        #endif

        #ifdef OUTPUT_READABLE_WORLDACCEL
            // 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);
        #endif
    
        #ifdef OUTPUT_TEAPOT
            // 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
        #endif

        // blink LED to indicate activity
        blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);

        Serial.print(zahler1);
        zahler1 = zahler1 +1;

// ===   SD CARD

        String dataString = "";
        dataString += String(zahler1);
        dataString += ",";
        dataString += String(ypr[0] * 180/M_PI);
        dataString += ",";
        dataString += String(ypr[1] * 180/M_PI);
        dataString += ",";
        dataString += String(ypr[2] * 180/M_PI);
        dataString += ",";
        dataString += String(aaReal.x);
        dataString += ",";
        dataString += String(aaReal.y);
        dataString += ",";
        dataString += String(aaReal.z);

The initial set up is taken from this side:

AFAIK the gyro reads rotation rates on all its own three axes, as referenced from it's own position, regardless of orientation.

If you turn it 90 degrees around X, it's Z axis becomes horizontal and Y vertical, do not expect it to show your room (absolute) reference axis. If you want that, it must be translated by you in code.

Thanks for your answer!

So assuming I want an absolute reference axis or better three absolute reference axis, so the MPU 6050 can identify the new position in a room, how can I change this in my code below?

The MPU 6050 cannot give you absolute orientation in 3 dimensions, because there is no "yaw" reference. You need to add a magnetometer or other North reference for that.

So am I right to say that basically the MPU 6050 by itself can't identify the absolute three dimension orientation in a room?

And if I turn it 90 degrees around X, it can't identify that the Y axis is now running vertically and therefore the new yaw reference? And that's why I'm getting incorrect values?

Thanks in advance for your help

Student1234:
So am I right to say that basically the MPU 6050 by itself can't identify the absolute three dimension orientation in a room?

You are right and nobody claimed otherwise.

And if I turn it 90 degrees around X, it can't identify that the Y axis is now running vertically and therefore the new yaw reference?

well, if-you're sure it doesnt accelerate (no rotation or acceleration, just uniform speed), its XYZ accelerometer will tell you exactly which way is up.

And that's why I'm getting incorrect values?

Thanks in advance for your help

The values are correct from its own reference, incorrect is expecting an absolute positioning/orientation from it.

Your program with or without in-build DMP could compute an approximative position change from a known starting point, but that will be accurate for seconds or minutes and subjected to drift.

To make corrections from drift you need to measure another vector direction that reliably doesn't move with the sensor itself, like the earth magnetic field. That's why the newer 9150 and 9250 have magnetometers too.

So assuming I want an absolute reference axis or better three absolute reference axis, so the MPU 6050 can identify the new position in a room, how can I change this in my code below?

Think of it like driving blind in a car. You have information about wheel diameters and how much they turned, and when/how much the steering wheel steered, this information updated 100 times per second.

You can compute an approximate current orientation and position from these informations but the more you move the less accurate this approximation gets.
You then add a compass, to know at least where are you going towards, and can have better precision for tasks like "go 100 miles south then another 10 west" but there are inaccuracies issues with wheel diameters not being precisely known.

An accelerometer is worst, it allows you to approximate speed changes, but can't tell absolute speed. orientation-wise, accelerometer to tell you where is up + compass to tell you where is up + gyro to tell you you don't spin too fast to compromise accelerometer output you can get an idea where is up, north, and all other directions. But absolute position... will drift anyway.

If you want to dig into math and how to do it, you can check code for robot drones and airplanes that use 6050, 9150 and so on. Hint: google Ardupilot.

Thanks for the car example. I think I got the idea what you are talking about.

One last question, I do get the exact values (plot shows 90 degrees on the z gyrometer) of the rotation when the MPU6050 is placed horizontally on a flat surface the z axis running vertically and turned 90 degree around z axis while not moving in x and y axis.
Despite your great explanations I don't exactly understand this

I don't understand your code, it has too loop() functions that open (that's really strange) and otherwise no begining and no end.
I assume it's a part of an example from a library you use. What's that library?