I have bought MPU-6050 a month ago for a project, I have got a hang I2C protocol and register maps of MPU. I have learnt how to get raw values of accelerometer and gyroscope. What I needed for my project is roll and pitch angles and acceleration in x,y,z axes. I have tried some algorithms as shown below:
First I saw a code which uses only raw accelerometer values to get roll and pitch. Here is a small snippet of that code:
x=(AcX)/16384;
y=(AcY)/16384;
z=(AcZ)/16384;
roll = (atan2(y, z)+PI)*57.295779513082320876798154814105;
pitch = (atan2(x , z)+PI)*57.295779513082320876798154814105;
As you can see this uses principle of angle between two vectors, the angles were pretty accurate. But the problem with this code is that as the sensor moves in a particular direction without changing the roll or pitch they still seemed to change (The roll and pitch values are dependent on accel values).
Next, I saw about using Complementary Filter my code:
#include<Wire.h>
const int MPU_addr=0x68, dt=20;
float AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
float xa,ya,za,xg,yg,zg;
float gan_x = 0 ,gan_y = 0,aan_x = 0,aan_y = 0, anx = 0, any = 0, gain =0.95;
int xao = -521 ,yao = 1073 ,zao = 1724 ,xgo = 94 ,ygo =31 ,zgo = 60; //offset values
void setup()
{
Serial.begin(115200);
Wire.begin();
Wire.beginTransmission(MPU_addr);
Wire.write(0x1A);
Wire.write(0b00000110);
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x1B);
Wire.write(0b00000000);
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x1C);
Wire.write(0b00000000);
Wire.endTransmission(true);
Wire.beginTransmission(MPU_addr);
Wire.write(0x6B);
Wire.write(0b00000000);
Wire.endTransmission(true);
}
void loop()
{
Wire.beginTransmission(MPU_addr);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU_addr,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
xa = (AcX-xao)/16384; //sensitivity adjusting
ya = (AcY-yao)/16384;
za = (AcZ-zao)/16384;
xg = (GyX-xgo)/131;
yg = (GyY-ygo)/131;
zg = (GyZ-zgo)/131;
gan_x = dt * xg + anx; // integrating
gan_y = dt * yg + any;
aan_x = (atan2(ya,za)+PI)*57.295779513082320876798154814105;
aan_y = (atan2(xa,za)+PI)*57.295779513082320876798154814105;
anx = (gain) * gan_x + (1-gain) * aan_x; // filtering
any = (gain) * gan_y + (1-gain) * aan_y;
//Serial.print(" | GyX = ");
Serial.print(gan_x);
Serial.print(" ");
//Serial.print(" | GyY = ");
Serial.println(gan_y);
}
This code gives good gyroscope values in terms of angular velocity but I want it in degrees is there any way to change those gyro values to degrees(like in first case)?
I saw Jeff Rowberg's library and I can't seem understand all of the code. Can anyone please provide any reference material explaining the functions present in i2cdevlib.h (Ex: mpu.dmpInitialize(), mpu.setDMPEnabled() etc) it would be a lot of help.
I also would like to know if there are any other alternative IMUs (Gyro+accel) other than MPU6050 which are more of an open source than 6050 (in terms of accessing DMP which seems to be main drawback for MPU) and easier to work with.
I am using Arduino Nano.
-Thank you in advance