[SOLVED] Need helpp Noob here.....MPU 6050

hi! so recently i bought a MPU 6050 and found a code to use it. i research about some code available about it and found out that it needs to be calibrated or to have an offset value.
i found a code that uses complementary filter to merge values from the MPU 6050.
but i cant figure out how to input my offset value. can somebody help me please....
thank you very much...
heres the code

[/*
 * MPU6050 to Arduino Compementary Angle Finder
 * 
 * This sketch calculates the angle of an MPU6050 relative to the ground using a complementary filter.
 * It is designed to be easy to understand and easy to use. 
 * 
 * The following are your pin connections for a GY-521 breakout board to Arduino UNO or NANO:
 * MPU6050  UNO/NANO
 * VCC      +5v
 * GND      GND (duh)
 * SCL      A5
 * SDA      A4
 * 
 * Of note: this sketch uses the "I2C Protocol," which allows the Arduino to access multiple pieces of data
 * on the MPU6050 with only two pins.  Way cooler than needing 7 pins for the 7 pieces of data you can get
 * from your MPU6050.  The two wires are a data wire and a clock wire. The "Wire.h" library does most of this 
 * communication between the Arduino and the MPU6050. It requires that the Arduino use the A5 adn A4 pins.
 * Other Arduinos (Arduini?) may use different pins for the I2C protocol, so look it up on the Arduino.cc website. 
 * The I2C protocol works this way like a conversation between the Arduino and the MPU.  It goes something like this:
 * Arduino: "Hey 0x68." (0x68 is the MPU's address)
 * MPU6050: "wat"
 * Arduino: "Gimme yer x acceleration data." (except Arduino is a computer, so it calls that data "0x3B"
 * MPU6050: "Ugh fine. 16980"
 * Arduino: "K stop now"
 * MPU6050: "K"
 * 
 */

#include<Wire.h>
const int MPU_addr=0x68;
double AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; //These will be the raw data from the MPU6050.
uint32_t timer; //it's a timer, saved as a big-ass unsigned int.  We use it to save times from the "micros()" command and subtract the present time in microseconds from the time stored in timer to calculate the time for each loop.
double compAngleX, compAngleY; //These are the angles in the complementary filter
#define degconvert 57.2957786 //there are like 57 degrees in a radian.



void setup() {
  // Set up MPU 6050:
  Wire.begin();
  #if ARDUINO >= 157
  Wire.setClock(400000UL); // Set I2C frequency to 400kHz
  #else
    TWBR = ((F_CPU / 400000UL) - 16) / 2; // Set I2C frequency to 400kHz
  #endif

  
  Wire.beginTransmission(MPU_addr);
  Wire.write(0x6B);  // PWR_MGMT_1 register
  Wire.write(0);     // set to zero (wakes up the MPU-6050)
  Wire.endTransmission(true);
  Serial.begin(115200);
  delay(100);

  //setup starting angle
  //1) collect the data
  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)

  //2) calculate pitch and roll
  double roll = atan2(AcY, AcZ)*degconvert;
  double pitch = atan2(-AcX, AcZ)*degconvert;

  //3) set the starting angle to this pitch and roll
  double gyroXangle = roll;
  double gyroYangle = pitch;
  double compAngleX = roll;
  double compAngleY = pitch;

  //start a timer
  timer = micros();
}

void loop() {
//Now begins the main loop. 
  //Collect raw data from the sensor.
  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)
  
  double dt = (double)(micros() - timer) / 1000000; //This line does three things: 1) stops the timer, 2)converts the timer's output to seconds from microseconds, 3)casts the value as a double saved to "dt".
  timer = micros(); //start the timer again so that we can calculate the next dt.

  //the next two lines calculate the orientation of the accelerometer relative to the earth and convert the output of atan2 from radians to degrees
  //We will use this data to correct any cumulative errors in the orientation that the gyroscope develops.
  double roll = atan2(AcY, AcZ)*degconvert;
  double pitch = atan2(-AcX, AcZ)*degconvert;

  //The gyroscope outputs angular velocities.  To convert these velocities from the raw data to deg/second, divide by 131.  
  //Notice, we're dividing by a double "131.0" instead of the int 131.
  double gyroXrate = GyX/131.0;
  double gyroYrate = GyY/131.0;

  //THE COMPLEMENTARY FILTER
  //This filter calculates the angle based MOSTLY on integrating the angular velocity to an angular displacement.
  //dt, recall, is the time between gathering data from the MPU6050.  We'll pretend that the 
  //angular velocity has remained constant over the time dt, and multiply angular velocity by 
  //time to get displacement.
  //The filter then adds a small correcting factor from the accelerometer ("roll" or "pitch"), so the gyroscope knows which way is down. 
  compAngleX = 0.99 * (compAngleX + gyroXrate * dt) + 0.01 * roll; // Calculate the angle using a Complimentary filter
  compAngleY = 0.99 * (compAngleY + gyroYrate * dt) + 0.01 * pitch; 
  
  //W00T print dat shit out, yo!
  Serial.print(compAngleX);Serial.print("\t");
  Serial.print(compAngleY);Serial.print("\n");

}]

Run_piggy:
hi! so recently i bought a MPU 6050 and found a code to use it. i research about some code available about it and found out that it needs to be calibrated or to have an offset value.
i found a code that uses complementary filter to merge values from the MPU 6050.
but i cant figure out how to input my offset value. can somebody help me please....
thank you very much...

I've been using the mpu6050 for several years and enjoy its features here is my successfully working code with at this moment I know of no known glitches :slight_smile:
Attached is the calibration code to generate the offsets for the gyro and accelerometer
look for the following lines of code near the top and replace them with the calibration values received from the program:

// supply your own gyro offsets here, scaled for min sensitivity use MPU6050_calibration.ino
//                       XA      YA      ZA      XG      YG      ZG
int MPUOffsets[6] = {  1136,    -44,   1047,     52,      5,     26};// Test Board

The code uses the mpu6050's microprocessor to calculate angles removing the load off of the UNO but the uno needs to know when the MPU6050 has completed the process before grabbing the data.
The MPU6050 stores the data in its FIFO buffer once every 10 microseconds or close to that. Then it pulses the int pin to let the UNO know it has data ready. At this time if the FIFO buffer is allowed to completely fill and overflow the data in the buffer will not be usable as there is no valid starting point to work with. My code resets the buffer to allow for the next instance to be correct.
The following code uses Jeff Rowberg library on github.com to handle most of the work.
I am using the MPU6050 to power my projects Youtube Video of Bot

Z

MPU-9255Cal.ino (48.2 KB)

MPU6050_Latest_code.ino (7.78 KB)

does this work on arduino mega 2560?
i tried uploading it but it says error in compiling in arduino mega 2560.
thanks.

What is the full error message ?
Have you got all the necessary libraries installed ?

Run_piggy:
does this work on arduino mega 2560?
i tried uploading it but it says error in compiling in arduino mega 2560.
thanks.

it should Just compiled the "MPU6050 latest code" for the mega2560 and had no errors. Please post error message

UKHeliBob:
What is the full error message ?
Have you got all the necessary libraries installed ?

thanks i a library was missing which why i got an error message.
thanks this was very helpfull

I was wondering is it possible to compare previous readings of the MPU6050 to the present to be able to determine the its difference. i actually need the data of how much angle did the MPU 6050 move. it would be awesome if it can also determine its direction if it was backward or forward by indicating its sign to + and - thank you so much for the advice

I was wondering is it possible to compare previous readings of the MPU6050 to the present to be able to determine the its difference

Of course it is.

start of loop()
  Read the values
  Compare them with the previous values and take action if required
  Save the current values as previous values
end of loop()

i tried it and it works but i notice that since the output is way too fast in sending value to the arduino it seem that the difference always becomes close to zero. Figured i could just get the average of Present and Previous reading of the sensor. would this solve the problem?

Run_piggy:
i tried it and it works but i notice that since the output is way too fast in sending value to the arduino it seem that the difference always becomes close to zero. Figured i could just get the average of Present and Previous reading of the sensor. would this solve the problem?

No.

The gyroscopes in the MPU-6050 don't measure angle, but angular velocity (degrees per second). If you want to use that to determine net angular displacement, you need to use some calculus to integrate the function.

Jiggy-Ninja:
No.

The gyroscopes in the MPU-6050 don't measure angle, but angular velocity (degrees per second). If you want to use that to determine net angular displacement, you need to use some calculus to integrate the function.

Thanks! kind sir can you show me how to do that. i really dont know the formula for that. i tried googling it but i don't understand the results.
thank you.

Integrating with discrete samples is easy. All you need to do to integrate is multiply your current sample by the time difference between the current sample and the previous sample.

In short:
Integrated value = sample * sample period

Integrated value = sample * sample period

Pretty sure you need some summing somewhere.

Oops, well, just do a running sum of all the "integrated values" calculated. Easy fix.

gfvalvo:
Pretty sure you need some summing somewhere.

Understatement of the day.

Also tongue-twister.

Integrated value += sample * sample period

i'm kinda confuse in summing..
so as the sample is being integrated to get the final angular displacement i need to do a summation of all the integrated values?

Run_piggy:
i'm kinda confuse in summing..
so as the sample is being integrated to get the final angular displacement i need to do a summation of all the integrated values?

No. When using a complimentary filter with a gyro, you only need to integrate over the current sample period, so you don't need to add the results of any other sample period.

To prove it, below is a fully working test sketch I'm made for a self-stabilizing altimeter for an Arduino RC plane. Within the sketch, I use a complimentary filter (with an MPU9250).

#include <Wire.h>
#include <FaBo9Axis_MPU9250.h>
#include <Servo.h>

#define M_PI 3.14159265359

FaBo9Axis fabo_9axis;

float offsetax = 0;
float offsetay = 0;
float ax, ay, az;
float gx, gy, gz;
float integrated_gx = 0;
float scaled_gx = 0;
float integrated_gy = 0;
float scaled_gy = 0;
float angleRoll = 0;
float anglePitch = 0;
float A_ = 0.7;
float dt = 0.01;
float angleRollAcc = 0;
float anglePitchAcc = 0;
byte gyroSensitivity = 131; //16 bit ADC with +-250dps --> sensitivity = 2^16 / 500 = 131

double currentTime = millis();
double timeBench = currentTime;
double samplePeriod = 10;  //sample period in ms

Servo horizontal;
Servo vertical;



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

  if (fabo_9axis.begin()) {
    Serial.println("configured FaBo 9Axis I2C Brick");
  } else {
    Serial.println("device error");
    while (1);
  }

  horizontal.attach(52);
  vertical.attach(53);

  horizontal.write(90);
  vertical.write(90);
}



void loop()
{  
  //prime the timer
  currentTime = millis();

  //execute once per sample time-period
  if ((currentTime - timeBench) >= samplePeriod)
  {
    //reset timer
    timeBench = currentTime;

    //get data
    fabo_9axis.readAccelXYZ(&ax, &ay, &az);
    fabo_9axis.readGyroXYZ(&gx, &gy, &gz);

    //remove offset
    ax = ax - offsetax;
    ay = ay - offsetay;

    //scale by sensitivity
    scaled_gx = gx / gyroSensitivity;
    scaled_gx = gy / gyroSensitivity;

    //integrate gyro readings
    integrated_gx = scaled_gx * dt;
    integrated_gx = scaled_gx * dt;

    angleRollAcc = -atan2(ax, sqrt((ay*ay) + (az*az))) * 180 / M_PI;
    anglePitchAcc = atan2(ay, sqrt((ax*ax) + (az*az))) * 180 / M_PI;

    angleRoll = A_ * (angleRoll + integrated_gx) + (1 - A_) * (angleRollAcc);
    anglePitch = A_ * (anglePitch + integrated_gx) + (1 - A_) * (anglePitchAcc);

    //print for debugging////
    /*Serial.print("angleRoll: ");
    Serial.print(angleRoll);
    Serial.print(" anglePitch: ");
    Serial.print(anglePitch);
    Serial.println();*/
    /////////////////////////

    /*Serial.print("angleRoll: ");
    Serial.print((byte)map(angleRoll,-90,90,0,180));
    Serial.print(" anglePitch: ");
    Serial.println((byte)map(anglePitch,-90,90,180,0));*/

    horizontal.write(map(angleRoll,-90,90,0,180));
    vertical.write(map(anglePitch,-90,90,0,180));
  }
}

Run_piggy:
i'm kinda confuse in summing..
so as the sample is being integrated to get the final angular displacement i need to do a summation of all the integrated values?

Oh, wait. I thought you were asking about integrating when using the complimentary filter. BUT since you are trying to find the total offset, then YES, you need to use

Integrated value += sample * sample period

as Jiggy-Ninja stated.

Run_piggy:
i'm kinda confuse in summing..
so as the sample is being integrated to get the final angular displacement i need to do a summation of all the integrated values?

The summation IS the integration. Actually, an approximation of integration. It becomes integration when, in the limit, the time period (aka dt) approaches zero.