Two MPU 6050 drift

Hi,

I'm doing a project in which I have two evaluate the data from two IMUs, MPU 6050, connected at the same Arduino board. I got a problem because even with calibration, so the evaluation of the offsets, I continuously get an increasing (or decreasing value).

For example:

New Line

9600 baud

Angle X1: -0.00°, Angle Y1: -0.00°, Angle Z1: -0.00°, Angle X2: -0.00°, Angle Y2: 0.00°, Angle Z2: 0.00°

Angle X1: -0.02°, Angle Y1: 0.01°, Angle Z1: -0.00°, Angle X2: -0.01°, Angle Y2: 0.01°, Angle Z2: -0.01°

Angle X1: -0.03°, Angle Y1: 0.02°, Angle Z1: -0.00°, Angle X2: -0.02°, Angle Y2: 0.01°, Angle Z2: -0.02°

Angle X1: -0.04°, Angle Y1: 0.04°, Angle Z1: -0.01°, Angle X2: -0.03°, Angle Y2: 0.01°, Angle Z2: -0.03°

Angle X1: -0.06°, Angle Y1: 0.05°, Angle Z1: -0.01°, Angle X2: -0.04°, Angle Y2: 0.01°, Angle Z2: -0.03°

Angle X1: -0.07°, Angle Y1: 0.07°, Angle Z1: -0.01°, Angle X2: -0.05°, Angle Y2: 0.01°, Angle Z2: -0.04°

Angle X1: -0.08°, Angle Y1: 0.08°, Angle Z1: -0.01°, Angle X2: -0.05°, Angle Y2: 0.01°, Angle Z2: -0.05°

Angle X1: -0.10°, Angle Y1: 0.10°, Angle Z1: -0.01°, Angle X2: -0.06°, Angle Y2: 0.01°, Angle Z2: -0.06°

Here there is my code, with the offsets evaluated with calibration.

#include <Wire.h>

const int MPU_addr_1 = 0x68; // I2C address of the first MPU-6050
const int MPU_addr_2 = 0x69; // I2C address of the second MPU-6050

int16_t AcX1, AcY1, AcZ1, Tmp1, GyroX1, GyroY1, GyroZ1;
int16_t AcX2, AcY2, AcZ2, Tmp2, GyroX2, GyroY2, GyroZ2;

float angleX1 = 0, angleY1 = 0, angleZ1 = 0;
float angleX2 = 0, angleY2 = 0, angleZ2 = 0;
float gforceX1, gforceY1, gforceZ1, gforceX2, gforceY2, gforceZ2;

// Offsets for the two IMUs
int16_t offset1[6] = {-1124, 311, 1556, 37, 17, 59};
int16_t offset2[6] = {-163, -921, 1100, 77, -100, -12};

void setup() {
  Wire.begin();

  // Setup for MPU-6050 1
  Wire.beginTransmission(MPU_addr_1);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  // Setup for MPU-6050 2
  Wire.beginTransmission(MPU_addr_2);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);

  Serial.begin(9600);
}

void loop() {
  // Read data from MPU-6050 1
  Wire.beginTransmission(MPU_addr_1);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr_1, 14, true); // request a total of 14 registers
  AcX1 = Wire.read() << 8 | Wire.read();
  AcY1 = Wire.read() << 8 | Wire.read();
  AcZ1 = Wire.read() << 8 | Wire.read();
  Tmp1 = Wire.read() << 8 | Wire.read();
  GyroX1 = Wire.read() << 8 | Wire.read();
  GyroY1 = Wire.read() << 8 | Wire.read();
  GyroZ1 = Wire.read() << 8 | Wire.read();

  // Read data from MPU-6050 2
  Wire.beginTransmission(MPU_addr_2);
  Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_addr_2, 14, true); // request a total of 14 registers
  AcX2 = Wire.read() << 8 | Wire.read();
  AcY2 = Wire.read() << 8 | Wire.read();
  AcZ2 = Wire.read() << 8 | Wire.read();
  Tmp2 = Wire.read() << 8 | Wire.read();
  GyroX2 = Wire.read() << 8 | Wire.read();
  GyroY2 = Wire.read() << 8 | Wire.read();
  GyroZ2 = Wire.read() << 8 | Wire.read();

  // Apply offsets
  AcX1 -= offset1[0];
  AcY1 -= offset1[1];
  AcZ1 -= offset1[2];
  GyroX1 -= offset1[3];
  GyroY1 -= offset1[4];
  GyroZ1 -= offset1[5];

  AcX2 -= offset2[0];
  AcY2 -= offset2[1];
  AcZ2 -= offset2[2];
  GyroX2 -= offset2[3];
  GyroY2 -= offset2[4];
  GyroZ2 -= offset2[5];

  float dt = 0.005; // Sample time (adjust as needed)

  // Evaluation of the angles
  angleX1 += (GyroX1 / 131.0) * dt;
  angleY1 += (GyroY1 / 131.0) * dt;
  angleZ1 += (GyroZ1 / 131.0) * dt;

  angleX2 += (GyroX2 / 131.0) * dt;
  angleY2 += (GyroY2 / 131.0) * dt;
  angleZ2 += (GyroZ2 / 131.0) * dt;

  // Evaluation of the gForces
  gforceX1 = AcX1 / 16384.0;
  gforceY1 = AcY1 / 16384.0;
  gforceZ1 = AcZ1 / 16384.0;

  gforceX2 = AcX2 / 16384.0;
  gforceY2 = AcY2 / 16384.0;
  gforceZ2 = AcZ2 / 16384.0;

  Serial.print("Angle X1: ");
  Serial.print(angleX1);
  Serial.print("°, Angle Y1: ");
  Serial.print(angleY1);
  Serial.print("°, Angle Z1: ");
  Serial.print(angleZ1);
  Serial.print("°, Angle X2: ");
  Serial.print(angleX2);
  Serial.print("°, Angle Y2: ");
  Serial.print(angleY2);
  Serial.print("°, Angle Z2: ");
  Serial.print(angleZ2);
  Serial.println("°");

  delay(5); // Adjust the delay as needed
}

Can you help me understanding and solving this problem?
Thanks

Gyro drift is always a problem, and it is temperature dependent. Calibration constants vary with both time and temperature.

You will never be able to eliminate gyro drift completely, especially with the long obsolete MPU-6050. It was discontinued years ago, so you undoubtedly have a cheap clone or counterfeit.

Those are the sensors given to me for this project. Are there any other sensors like these that are more precise and that doesn't cost so much?

The ISM330DHCX greatly outperforms the MPU-6050.

Otherwise, do the MPU-6050 calibration at startup, to minimize temperature and time effects.

Make sure the angle integration is correct. What you posted is not correct. The timing is not correct, and it has a useless delay. Why bother to read the acceleration values if you don't use them?

Can I connect two of them to the same Arduino board?

Can you help me understanding the errors?
Thank you very much for your time

Yes, you can connect two to the same Arduino. See Adafruit's getting started guide, and the data sheet.

Correct the integration by eliminating unnecessary sensor reads and calculations, eliminate the delay, and measure the loop time.

Keep in mind that the resulting angles are not Euler angles, representing sensor orientation.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.