Wrong angles using MPU6500

Hello, i use MPU6500 to read values from Gyro and Acc so i can combine them to angles. The purpose of it to create PID in the future, but for now i have problems reading those values. I use MPU6050_light library. When i try to apply Complimentary Filter to it and for example i turn the MPU for 90 degrees, for some reason it shows me only 20. I tried a couple of ways to reduce noises and etc but i give up. If somebody can help me to understand what it can be?

#include <Wire.h>
#include <MPU6050_light.h>

MPU6050 mpu(Wire);

unsigned long timer;
float dt;

float roll, pitch;        // Filtered angles
float alpha = 0.96;       // Complementary filter coefficient (0..1)

void setup() {
  Serial.begin(115200);
  Wire.begin();

  if (mpu.begin() != 0) {
    Serial.println("MPU6050 initialization failed");
    while (1);
  }

  Serial.println("Calibrating, please keep the MPU6050 still...");
  delay(2000);
  mpu.calcOffsets();
  Serial.println("Calibration complete!");

  timer = millis();
}

void loop() {
  mpu.update();

  dt = (millis() - timer) / 1000.0; // Time difference in seconds
  timer = millis();

  // Angles from accelerometer (in degrees)
  float rollAcc = atan2(mpu.getAccY(), mpu.getAccZ()) * 180 / PI;
  float pitchAcc = atan2(-mpu.getAccX(), sqrt(mpu.getAccY()*mpu.getAccY() + mpu.getAccZ()*mpu.getAccZ())) * 180 / PI;

  // Integrate gyroscope data (degrees per second * dt = degrees)
  roll += mpu.getGyroX() * dt;
  pitch += mpu.getGyroY() * dt;

  // Apply complementary filter
  roll = alpha * roll + (1 - alpha) * rollAcc;
  pitch = alpha * pitch + (1 - alpha) * pitchAcc;

  Serial.print("Roll: ");
  Serial.print(roll, 2);
  Serial.print(" | Pitch: ");
  Serial.println(pitch, 2);

  delay(10);
}

Update. For example using Arduino Nano Connect RP2040 gives me quite good numbers and i don't have any problem with angles. Using inbuilt Gyro and Acc inside of RP2040

Show the output, post it in code tags.
Maybe us ms instead of secs?

Ok, this is stable position without any moving:

16:21:01.974 -> Roll: 0.04 | Pitch: 0.01

16:21:01.974 -> Roll: 0.04 | Pitch: 0.01

16:21:02.007 -> Roll: 0.05 | Pitch: 0.02

16:21:02.007 -> Roll: 0.06 | Pitch: 0.03

16:21:02.045 -> Roll: 0.06 | Pitch: 0.04

16:21:02.045 -> Roll: 0.06 | Pitch: 0.06

16:21:02.045 -> Roll: 0.06 | Pitch: 0.05

16:21:02.083 -> Roll: 0.06 | Pitch: 0.05

16:21:02.083 -> Roll: 0.07 | Pitch: 0.05

16:21:02.116 -> Roll: 0.06 | Pitch: 0.04

16:21:02.116 -> Roll: 0.04 | Pitch: 0.04

16:21:02.116 -> Roll: 0.05 | Pitch: 0.03

And this is i flip the board on 90 degrees:

16:21:55.962 -> Roll: -1.18 | Pitch: 29.21

16:21:55.962 -> Roll: -1.19 | Pitch: 29.23

16:21:55.962 -> Roll: -1.19 | Pitch: 29.24

16:21:56.002 -> Roll: -1.19 | Pitch: 29.25

16:21:56.002 -> Roll: -1.20 | Pitch: 29.24

16:21:56.034 -> Roll: -1.20 | Pitch: 29.23

16:21:56.034 -> Roll: -1.20 | Pitch: 29.25

16:21:56.034 -> Roll: -1.20 | Pitch: 29.26

16:21:56.077 -> Roll: -1.19 | Pitch: 29.24

16:21:56.077 -> Roll: -1.19 | Pitch: 29.23

16:21:56.077 -> Roll: -1.19 | Pitch: 29.24

In that case you get exact angles from the accelerations while integration of rotation speed runs away even with the smallest offsets. A Kalman filter may help a bit.

Newer MCU are praised for higher precision.

Probably correct, you have mixed float with int variables, you need to deal with that in the math you are using else the values will be truncated or overflow. Look at the mpu6050 library examples for guidance.

i try different libraries examples and different libraries but they all work on mpu6050, i barely can find something with 6500 to make it work. This is kind of strange i though mpu6050 and mpu6500 should use the same chip\protocol\controlling

But thank you, i will try more

Your problem isn't the library, your basic math and use of the programming language is incorrect.
Use the Adafruit_MPU6050 library and the basic_readings example in that library.
If you need to manipulate the data fields, print out every intermediate result and check for accuracy. Do not mix float and int if possible and if you must, use a cast. If you use an int constant like 180, make it a float by writing 180.0. I am not sure if it matters or makes a difference to specify it as 180.0000 or just 180.0.

The MPU6050_light library doesn't work as you expect because the accelerometer calibration is incorrect.

You can calculate reasonable tilt or pitch/roll angles from the raw accelerometer data alone, following this approach: https://wiki.dfrobot.com/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing

Example for MPU-6050;

// minimal MPU-6050 pitch and roll (sjr). Works with MPU-9250 as well.
// Tested with GY-521, pitch and roll signs agree with arrows on sensor module 7/2019
//
// Tested with 3.3V eBay Pro Mini with no external pullups on I2C bus (worked with internal pullups)
// Add 4.7K pullup resistors to 3.3V if required. A4 = SDA, A5 = SCL

#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);  //send starting register address, accelerometer high byte
  Wire.endTransmission(false); //restart for read
  Wire.requestFrom(MPU_addr1, 6); //get six bytes accelerometer data
  int t = Wire.read();
  xa = (t << 8) | Wire.read();
  t = Wire.read();
  ya = (t << 8) | Wire.read();
  t = Wire.read();
  za = (t << 8) | Wire.read();
// formula from https://wiki.dfrobot.com/How_to_Use_a_Three-Axis_Accelerometer_for_Tilt_Sensing
  roll = atan2(ya , za) * 180.0 / PI;
  pitch = atan2(-xa , sqrt(ya * ya + za * za)) * 180.0 / PI; //account for roll already applied

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

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