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 
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.