In this blog, we will learn about the MPU6050 sensor. It calculates the angle and motion values of the accelerometer and the gyroscope. With this, we will also see its wide application range.
Introduction
Have you ever wonder how your mobile screen adjusts automatically in a frame when you move your smartphone vertically or horizontally? We can achieve this task with the help of IMU(Inertial Measurement Unit) MPU6050. In this tutorial, we will talk about MPU6050 and its interfacing with Arduino. MPU6050 has been developed by InvenSense company. It is designed for obtaining values of accelerometer and gyroscope.
What is MPU6050?
MPU6050 is an IMU device that stands for Inertial Measurement Unit. It is a six-axis motion tracking device that calculates a three-axis accelerometer and three-axis gyroscope data. The biggest advantage of this board it comes with a digital motion processor. The significance of DMP(Digital motion processor) is, it performs very complex calculations/operations from its side, thus freeing up the microcontroller’s work. It provides motion data like roll, pitch, yaw, angles, landscape, and portrait sense, Etc.
It is very precise while converting analog data into digital data bits because it has 16 bits assigned for each channel. Digital Motion Processor or the DMP(Digital Matrix Processor) is an embedded processor that can reduce the host processor’s computational load by acquiring and processing data from Accelerometer, Gyroscope, and an external Magnetometer.
We will look towards some of its main features like:
- 3- axis gyroscope
- 3- axis accelerometer
- 16-bit ADC conversion for each channel
- 1024 bit FIFO buffer
- Digital output temperature sensor
- Integrated Digital Motion Processor
- Inbuilt temperature sensor
Pinout
- VCC: This pin is used to provide power(5v /3.3v)
- GND: As usual for providing 0v
- SDA: This pin is used for obtaining data serially from the sensor
- SCL: This pin is used for serial clock input
- XDA: This is used as an SDA for configuring and reading from an external sensor(Optional)
- XCL: This is used as an SCL for configuring and reading from external sensor (Optional)
- AD0: This is I2c slave address Bus, (least significant bit)
- INT: This one is an Interrupt pin for an indication of data ready
How does it Work?
How does the Accelerometer work?
An accelerometer works on the principle of the piezoelectric effect. Consider a cuboidal box with a ball inside it. If we move or tilt the box ball inside the box, it will fall on the box’s walls because of gravity. Similarly, IMU like MPU6050 also contains such MEMS (micro-electromechanical systems), which exactly work just like the cuboidal box with a ball inside it.
When the device/box is tilted, a ball inside the box falls upon the piezoelectric walls. Also, the analog data is captured from that wall’s channel and proceeds into digital data. It is often how an accelerometer works, and its output is so precise because it has 16-bit ADC present for every channel.
How does the Gyroscope work?
It works on the principle of Coriolis acceleration. Imagine that there's a fork-like structure that's in an exceedingly constant back-and-forth motion. Whenever you try to tilt this arrangement, the crystals experience a force within the direction of inclination. It often causes a result of the inertia of the moving fork. The crystals thus produce a current in consensus with the piezo effect, and the current is amplified.
Interfacing with the Arduino
As MPU6050 is an I2C communication device, the connections with the Arduino are pretty simple. The following circuit diagram will show you how the connections are made with Arduino.
Connections of MPU6050 with Arduino is as follows:
Arduino | MPU6050 |
---|---|
5v/3v | VCC |
GND | GND |
A5/ SCL pin | SCL |
A4/SDA pin | SDA |
pin 2 | INT |
Programming
To obtain the data from MPU6050, you will need to install the wire.h library.
You can download both the libraries from the following link:
From this code, we will get three basic parameters called Roll, Pitch, Yaw. Basically, what do these three things mean? When you are going through a car, you can measure its motion as forward, backward, left, and right. But, it will not be considered the same scenario when it comes to drones or flying vehicles. Flying control boards have different terminologies like yaw, pitch, and Rolls.
- The axis that runs front to the back of the drone is called the roll axis. The rotation around this axis is called roll motion.
- The axis that runs left to the right of the drone is called the pitch axis. The rotation around this axis is called pitch motion.
- The axis that runs top to the bottom of the drone is called the yaw axis. The rotation around this axis is called the yaw motion.
In the short words, we can say that,
- Rotation around the front-to-back axis is called roll.
- Rotation around the side-to-side axis is called pitch.
- Rotation around the vertical axis is called yaw.
For explaining the things, I will show you an image for a better understanding.
#include <Wire.h>
const int MPU = 0x68; // MPU6050 I2C address
float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;
float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;
float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;
float elapsedTime, currentTime, previousTime;
int c = 0;
void setup() {
Serial.begin(19200);
Wire.begin(); // Initialize comunication
Wire.beginTransmission(MPU); // Start communication with MPU6050 // MPU=0x68
Wire.write(0x6B); // Talk to the register 6B
Wire.write(0x00); // Make reset - place a 0 into the 6B register
Wire.endTransmission(true); //end the transmission
/*
// Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
Wire.beginTransmission(MPU);
Wire.write(0x1C); //Talk to the ACCEL_CONFIG register (1C hex)
Wire.write(0x10); //Set the register bits as 00010000 (+/- 8g full scale range)
Wire.endTransmission(true);
// Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
Wire.beginTransmission(MPU);
Wire.write(0x1B); // Talk to the GYRO_CONFIG register (1B hex)
Wire.write(0x10); // Set the register bits as 00010000 (1000deg/s full scale)
Wire.endTransmission(true);
delay(20);
*/
// Call this function if you need to get the IMU error values for your module
calculate_IMU_error();
delay(20);
}
void loop() {
// === Read acceleromter data === //
Wire.beginTransmission(MPU);
Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
//For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
// Calculating Roll and Pitch from the accelerometer data
accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI) - 0.58; // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) + 1.58; // AccErrorY ~(-1.58)
// === Read gyroscope data === //
previousTime = currentTime; // Previous time is stored before the actual time read
currentTime = millis(); // Current time actual time read
elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds
Wire.beginTransmission(MPU);
Wire.write(0x43); // Gyro data first register address 0x43
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true); // Read 4 registers total, each axis value is stored in 2 registers
GyroX = (Wire.read() << 8 | Wire.read()) / 131.0; // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
// Correct the outputs with the calculated error values
GyroX = GyroX + 0.56; // GyroErrorX ~(-0.56)
GyroY = GyroY - 2; // GyroErrorY ~(2)
GyroZ = GyroZ + 0.79; // GyroErrorZ ~ (-0.8)
// Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
gyroAngleX = gyroAngleX + GyroX * elapsedTime; // deg/s * s = deg
gyroAngleY = gyroAngleY + GyroY * elapsedTime;
yaw = yaw + GyroZ * elapsedTime;
// Complementary filter - combine acceleromter and gyro angle values
roll = 0.96 * gyroAngleX + 0.04 * accAngleX;
pitch = 0.96 * gyroAngleY + 0.04 * accAngleY;
// Print the values on the serial monitor
Serial.print(roll);
Serial.print("/");
Serial.print(pitch);
Serial.print("/");
Serial.println(yaw);
}
void calculate_IMU_error() {
// We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
// Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
// Read accelerometer values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x3B);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
// Sum all readings
AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
c++;
}
//Divide the sum by 200 to get the error value
AccErrorX = AccErrorX / 200;
AccErrorY = AccErrorY / 200;
c = 0;
// Read gyro values 200 times
while (c < 200) {
Wire.beginTransmission(MPU);
Wire.write(0x43);
Wire.endTransmission(false);
Wire.requestFrom(MPU, 6, true);
GyroX = Wire.read() << 8 | Wire.read();
GyroY = Wire.read() << 8 | Wire.read();
GyroZ = Wire.read() << 8 | Wire.read();
// Sum all readings
GyroErrorX = GyroErrorX + (GyroX / 131.0);
GyroErrorY = GyroErrorY + (GyroY / 131.0);
GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
c++;
}
//Divide the sum by 200 to get the error value
GyroErrorX = GyroErrorX / 200;
GyroErrorY = GyroErrorY / 200;
GyroErrorZ = GyroErrorZ / 200;
// Print the error values on the Serial Monitor
Serial.print("AccErrorX: ");
Serial.println(AccErrorX);
Serial.print("AccErrorY: ");
Serial.println(AccErrorY);
Serial.print("GyroErrorX: ");
Serial.println(GyroErrorX);
Serial.print("GyroErrorY: ");
Serial.println(GyroErrorY);
Serial.print("GyroErrorZ: ");
Serial.println(GyroErrorZ);
}
Output
From the above code, we have successfully got the Data Roll/ pitch/ Yaw.
Roll, pitch, yaw are the manipulated data obtained by gyroscopic angles of MPU6050. If you want to calculate basic accelerometer and gyroscopic values, you can receive them in some steps. For that, first, you have to install the library MPU6050_tockn.h.
After downloading this library, install the library with the following path.
Browse the library from its path directory. It is the process of adding the library to MPU6050. After including the library to Arduino IDE, you can select the code from the path.
Once the MPU-6050 library is added to Arduino IDE, we have a list of examples to choose from, like
- GetAllData
- GetAngle
Open code GetAllData.
#include <MPU6050_tockn.h>
#include <Wire.h>
MPU6050 mpu6050(Wire);
long timer = 0;
void setup() {
Serial.begin(9600);
Wire.begin();
mpu6050.begin();
mpu6050.calcGyroOffsets(true);
}
void loop() {
mpu6050.update();
if(millis() - timer > 1000){
Serial.println("=======================================================");
Serial.print("temp : ");Serial.println(mpu6050.getTemp());
Serial.print("accX : ");Serial.print(mpu6050.getAccX());
Serial.print("\taccY : ");Serial.print(mpu6050.getAccY());
Serial.print("\taccZ : ");Serial.println(mpu6050.getAccZ());
Serial.print("gyroX : ");Serial.print(mpu6050.getGyroX());
Serial.print("\tgyroY : ");Serial.print(mpu6050.getGyroY());
Serial.print("\tgyroZ : ");Serial.println(mpu6050.getGyroZ());
Serial.print("accAngleX : ");Serial.print(mpu6050.getAccAngleX());
Serial.print("\taccAngleY : ");Serial.println(mpu6050.getAccAngleY());
Serial.print("gyroAngleX : ");Serial.print(mpu6050.getGyroAngleX());
Serial.print("\tgyroAngleY : ");Serial.print(mpu6050.getGyroAngleY());
Serial.print("\tgyroAngleZ : ");Serial.println(mpu6050.getGyroAngleZ());
Serial.print("angleX : ");Serial.print(mpu6050.getAngleX());
Serial.print("\tangleY : ");Serial.print(mpu6050.getAngleY());
Serial.print("\tangleZ : ");Serial.println(mpu6050.getAngleZ());
Serial.println("=======================================================\n");
timer = millis();
}
}
Uploading this code into Arduino the MPU6050 will give you the values. You can see the output in the following image:
Output for Accelerometer and Gyroscope
You will get complete data of the accelerometer and gyroscope from the above output, including current temperature values.
Applications
Here are some applications of the MPU6050 sensor:
- 3D remoter controller
- In 3D mice controller
- In wearable health-tracking, fitness-tracking devices
- In drones and quadcopters, MPU6050 is used for position control.
- Used in controlling Robotic Arm
- Hand gesture control devices
- In Self-balancing robot
- In Humanoid robot for tilt, rotation, and balancing
- In smartphones for adjusting the frame
- Used in gimbals system for stabilization on drones
Final Words
In this tutorial, it has been concluded that the MPU6050 chip is a highly applicable device in many systems. It is used in wide applications and is considered the most crucial parameter of the system. Without this sensor, we can not make most of the complicated processes in robotics and the embedded fields. If you have any queries related to any doubt, you can drop them in the comment section.