MPU6050 With Arduino

Introduction

Have you ever wonder how your mobile screen adjusts automatically in a frame when you move your smartphone vertically or horizontally, this is achieved by a gyroscope sensor. Hello Friends, today we will talk about MPU6050 and its interfacing with Arduino. MPU6050 has been developed by InvenSense company. It is made for obtaining values of accelerometer and gyroscope.

What is MPU6050

MPU6050 is a chip including 6 axis gyroscope and accelerometer. The MPU-6050 consists of a 3 axis accelerometer that can detect the angle of tilt or inclination along the x,y, z-axis with micro electro mechanical system technology (MEMS). Mpu6050 is an IMU sensor that contains MEMS(Micro-electromechanical system) 3 axis accelerometer and 3 axis gyroscope.

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 computational load from the host processor, like an Arduino, 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
  • Inbuild temperature sensor

Pinout:

  • VCC: This pin is used to provide power(5v /3.3v) with respect to ground
  • 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 the ball inside in it, after we move or tilt the box the ball inside the box will fall on the walls of the box because of gravity. In an exceedingly very similar way, IMU like MPU6050 also contains such MEMS (micro-electromechanical systems ) which exactly work just like the cuboidal box with the ball inside it when the device tilted the ball inside the box falls upon the piezoelectric walls and also the analog data is captured from that channel of the wall and proceed into a digital one. This 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. it’s held in situ using piezoelectric crystals. Whenever you are trying to tilt this arrangement, the crystals experience a force within the direction of inclination. this is often caused a result of the inertia of the moving fork. The crystals thus produce a current in consensus with the piezo effect, and this current is amplified.

Interfacing with the Arduino

As MPU6050 is an I2C communication device, so its connections with the Arduino is pretty simple, the following circuit diagram will show you how the connections are been made with Arduino.

Connections of MPU6050 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 3 basic parameters called Roll, Pitch, Yaw.

What is Roll Pitch & Yaw?

  • 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

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 is 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 important parameter of the system. Without this sensor, we can not make most of the complicated processes in robotics as well as the embedded field. If you have any queries related to any doubt you can drop them in the comment section. See you in the next session.