Contents
About MPU-6050
MPU-6050 is a chip manufactured by Invensense which combines 3 axis accelerometer and 3 axis gyroscope with an on-board digital motion processor. It also includes a embedded temperature sensor and an on chip oscillator. It is very accurate and consist of analogue to digital conversion hardware for each channel thereby capturing x,y,z channels at the same time. The arduino can be interfaced with I2C bus.
3-axis Gyroscope
The MPU-6050 consist of a 3 axis gyroscope which can detect rotational velocity along the x,y,z axis with micro electro mechanical system technology (MEMS).
- When the sensor is rotated along any axis a vibration is produced due to Coriolis effect which is detected by the MEMS.
- 16-bit ADC is used to digitize voltage to sample each axis.
- +/- 250, +/- 500, +/- 1000, +/- 2000 are the full scale range of output.
- Angular velocity is measured along each axis in degree per second unit.
3-axis Accelerometer
The MPU-6050 consist of a 3 axis accelerometer which can detect angle of tilt or inclination along the x,y,z axis with micro electro mechanical system technology (MEMS).
- Acceleration along the axes deflects the moving mass which in turn unbalances the differential capacitor which is detected with electro mechanical system technology (MEMS). Output amplitude is proportional to acceleration.
- 16-bit ADC is used to digitize the values.
- +/- 2g, +/- 4g, +/- 8g, +/- 16g are the full scale range of output.
- In normal position that is when the device is placed on a flat surface the values are 0g on x axis, 0g on y axis and +1 on z axis.
On chip temperature sensor
The output from the temperature sensor is digitized by ADC and can be read off the sensor data register.
Digital motion processor (DMP)
The embedded digital motion processor is used to do computations on the sensor data. The values can be read off the dmp registers.
The raw values can be directly read of the accelerometer and gyroscope registers by the arduino. The MPU-6050 chip also includes a 1024 byte FIFO buffer where data can be placed and read off. The MPU-6050 always acts as a slave when connected to the Arduino with SDA and SCL pins connected to the I2C bus. But it also has its own auxiliary I2C controller which enables it to act as master to another device like a magnetometer. The on-board DMP can be programmed with firmware to do complex calculations with the sensor values.
The AD0 selects between I2C addresses 0x68 and 0x69 enabling 2 of these sensors to be connected in the same project. Most breakout boards either have a pull down or pull up resistor to keep default at high or low.
GY-521 breakout board
Pinout
- VCC (the GY-521 board has a onboard voltage regulator therefore either 5v or 3.3v can be connected.)
- GND (Ground pin)
- SCL (Serial clock line for I2C)
- SDA (Serial Data Line for I2C)
- XDA (Auxiliary data)
- XCL (Auxiliary clock)
- AD0 (when this pin set to low the I2C address of the board will be 0x68, when it is set to high the I2C address will be 0x69)
- INT (Interrupt digital output)
Connections
Schematic
Connection Diagram
The connections are given as follows:
- VCC to any 5v out pin of Arduino Uno.
- GND to any ground pin of Arduino Uno.
- SDA to A4 pin of Arduino Uno.
- SCL to A5 pin of Arduino Uno.
Pitch and Roll Calculation
Roll is the rotation around x-axis and pitch is the rotation along y-axis.
Both are calculated using the equation below:
The result is in radians. ( It can be converted to degrees by multiplying by 180 and dividing by pi)
Program
#include <Wire.h> //library allows communication with I2C / TWI devices #include <math.h> //library includes mathematical functions const int MPU=0x68; //I2C address of the MPU-6050 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ; //16-bit integers int AcXcal,AcYcal,AcZcal,GyXcal,GyYcal,GyZcal,tcal; //calibration variables double t,tx,tf,pitch,roll; void setup() { Wire.begin(); //initiate wire library and I2C Wire.beginTransmission(MPU); //begin transmission to I2C slave device Wire.write(0x6B); // PWR_MGMT_1 register Wire.write(0); // set to zero (wakes up the MPU-6050) Wire.endTransmission(true); //ends transmission to I2C slave device Serial.begin(9600); //serial communication at 9600 bauds } void loop() { Wire.beginTransmission(MPU); //begin transmission to I2C slave device Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H) Wire.endTransmission(false); //restarts transmission to I2C slave device Wire.requestFrom(MPU,14,true); //request 14 registers in total //Acceleration data correction AcXcal = -950; AcYcal = -300; AcZcal = 0; //Temperature correction tcal = -1600; //Gyro correction GyXcal = 480; GyYcal = 170; GyZcal = 210; //read accelerometer data 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) //read temperature data Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) 0x42 (TEMP_OUT_L) //read gyroscope data 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) //temperature calculation tx = Tmp + tcal; t = tx/340 + 36.53; //equation for temperature in degrees C from datasheet tf = (t * 9/5) + 32; //fahrenheit //get pitch/roll getAngle(AcX,AcY,AcZ); //printing values to serial port Serial.print("Angle: "); Serial.print("Pitch = "); Serial.print(pitch); Serial.print(" Roll = "); Serial.println(roll); Serial.print("Accelerometer: "); Serial.print("X = "); Serial.print(AcX + AcXcal); Serial.print(" Y = "); Serial.print(AcY + AcYcal); Serial.print(" Z = "); Serial.println(AcZ + AcZcal); Serial.print("Temperature in celsius = "); Serial.print(t); Serial.print(" fahrenheit = "); Serial.println(tf); Serial.print("Gyroscope: "); Serial.print("X = "); Serial.print(GyX + GyXcal); Serial.print(" Y = "); Serial.print(GyY + GyYcal); Serial.print(" Z = "); Serial.println(GyZ + GyZcal); delay(1000); } //function to convert accelerometer values into pitch and roll void getAngle(int Ax,int Ay,int Az) { double x = Ax; double y = Ay; double z = Az; pitch = atan(x/sqrt((y*y) + (z*z))); //pitch calculation roll = atan(y/sqrt((x*x) + (z*z))); //roll calculation //converting radians into degrees pitch = pitch * (180.0/3.14); roll = roll * (180.0/3.14) ; }
Output
The output can be read from the serial port of Arduino using the serial monitor.
Video
Any doubts or suggestions? Comment below.