MPU6050 unstable values / drift

Hi everyone,

I'm having trouble with my MPU6050. I have it hooked up to an arduino uno (3.3V/GND/SDL->A5/SDA->A4/INT->2). It's integrated into my guitar, the point being to control my DAW and send MIDI CC messages.

I'm using the DMP for calculations of YPR.

Baud rate is set to 31250 in order to allow midi communication.

So far I am able to read values for all 3 axes, but there are a few problems:

  • The main problem is that sometimes (not systematically), the values slowly drift back to zero while the gyro hasn't moved. This problem seems to occur more often on the Pitch and Roll values.

  • Yaw is far more stable, however, my '0' seems to drift down with time (never up), making it quite unreliable also.

I'd like to signal that I do not observe the same drift when I'm looking at the values in serial.

I tested the same code on a different MPU6050 (to test whether or not the actual sensor was defective) and observed the same behavior.

Does anyone see anything in my code or setup that could explain this behavior?

Thanks a million!

MPU_6050_value_drift.ino (6.95 KB)

1 Like

For stable yaw values, a magnetometer or external yaw reference is required. The MPU-6050 has neither.

Gyros drift, and the drift rate depends on temperature. You can estimate the drift rate by averaging some samples when you know that the sensor is not rotating, and subtract the offsets from later readings.

For pitch and roll, only the accelerometer is required, but for those to be accurate the sensor must be held still. The gyro helps to correct for the inaccuracies when the sensor is moving, but is not perfect.

Here is working code to get pitch and roll from just the accelerometer (you may need to add pullups on the I2C SDA and SCL lines):

// minimal MPU-6050 tilt and roll (sjr)
// works perfectly with GY-521, pitch and roll signs agree with arrows on sensor module 7/2019
// tested with eBay Pro Mini, **no external pullups on SDA and SCL** (works with internal pullups!)
//
#include<Wire.h>
const int MPU_addr1 = 0x68;
float xa, ya, za, roll, pitch;

void setup() {

  Wire.begin();                                      //begin the wire communication
  Wire.beginTransmission(MPU_addr1);                 //begin, send the slave adress (in this case 68)
  Wire.write(0x6B);                                  //make the reset (place a 0 into the 6B register)
  Wire.write(0);
  Wire.endTransmission(true);                        //end the transmission
  Serial.begin(9600);
}

void loop() {

  Wire.beginTransmission(MPU_addr1);
  Wire.write(0x3B);
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr1, 6, true); //get six bytes accelerometer data

  xa = Wire.read() << 8 | Wire.read();
  ya = Wire.read() << 8 | Wire.read();
  za = Wire.read() << 8 | Wire.read();

  roll = atan2(ya , za) * 180.0 / PI;
  pitch = atan2(-xa , sqrt(ya * ya + za * za)) * 180.0 / PI;

  Serial.print("roll = ");
  Serial.print(roll,1);
  Serial.print(", pitch = ");
  Serial.println(pitch,1);
  delay(400);
}

Apparently if that sensor detects that its motionless it self-calibrates the gyro for you. So if you keep it moving constantly it can't do this and will inexorably drift.

MEMS accelerometers and rate-gyros are not precision devices in any sense. They are small, cheap - those are the selling points. Together with a magnetometer and barometer and GPS they will form a nice IMU system. Just the 6-axes should be able to work reasonably well as an IMU without meaningful yaw values, so long as vibration is low (vibration will confuse most of these sensors enough to make a difference, as the accelerometer averaging is disturbed).