MPU-6050 GY-521 6-axis accelerometer gyroscope

I’m experimenting with several accelerometer/gyroscope sensors for different purposes, from robotics, drone equilibrium, vibration control, building oscilations, to seismicity.

In this case we are using the the MPU-6050 6-axis accelerometer/gyroscope.

Some of its features are I2C Digital-output of 6 or 9-axis MotionFusion data in rotation matrix, quaternion, Euler Angle, or raw data format. This may be very convenient depending on the use and algebraic model of the data being processed. For example some drone software may either prefer matrix or quaternion representation to feed its internal coordinates engine. Input Voltage: 2.3 – 3.4V.  Tri-Axis angular rate sensor (gyro) with a sensitivity up to 131 LSBs/dps and a full-scale range of ±250, ±500, ±1000, and ±2000dps. Tri-Axis accelerometer with a programmable full scale range of ±2g, ±4g, ±8g and ±16g. Digital Motion Processing™ (DMP™) engine offloads complex MotionFusion, sensor timing synchronization and gesture detection.

There are several implementations of sensor modules with different features and caveats. See here.

Connect your sensor board with Arduino UNO as shown. This is actually an I2C connection. This assumes that your board has I2C hardware.

Arduino UNO with hardware I2C and MPU-6050

For software I2C connection see some other examples.

Load the following code to your Arduino IDE:

// MPU-6050 Short Example Sketch
 // By Arduino User JohnChi
 // August 17, 2014
 // Public Domain
 #include
 const int MPU_addr=0x68; // I2C address of the MPU-6050
 int16_t AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
 void setup(){
 Wire.begin();
 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(9600);
 Serial.println("Starting MPU6050 Enrique Latorres");
 }
 void loop(){
 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)
 Serial.print("AcX = "); Serial.print(AcX);
 Serial.print(" | AcY = "); Serial.print(AcY);
 Serial.print(" | AcZ = "); Serial.print(AcZ);
 Serial.print(" | Tmp = "); Serial.print(Tmp/340.00+36.53); //equation for temperature in degrees C from datasheet
 Serial.print(" | GyX = "); Serial.print(GyX);
 Serial.print(" | GyY = "); Serial.print(GyY);
 Serial.print(" | GyZ = "); Serial.println(GyZ);
 delay(333);
 }

Compile and load to your Arduino board. Open the serial Monitor to see the results.

Starting MPU6050 Enrique Latorres
 AcX = 13344 | AcY = -1156 | AcZ = 9028 | Tmp = 20.06 | GyX = -64 | GyY = 20 | GyZ = -9
 AcX = 13336 | AcY = -1116 | AcZ = 9284 | Tmp = 20.06 | GyX = -65 | GyY = 43 | GyZ = -44
 AcX = 13476 | AcY = -1048 | AcZ = 9144 | Tmp = 19.97 | GyX = -93 | GyY = 43 | GyZ = -32
 AcX = 13276 | AcY = -1164 | AcZ = 9160 | Tmp = 20.11 | GyX = -77 | GyY = 31 | GyZ = -36
 AcX = 13268 | AcY = -1136 | AcZ = 9208 | Tmp = 20.06 | GyX = -76 | GyY = 51 | GyZ = -65
 AcX = 13408 | AcY = -1016 | AcZ = 9212 | Tmp = 20.06 | GyX = -85 | GyY = 34 | GyZ = -51
 AcX = 13484 | AcY = -1172 | AcZ = 9136 | Tmp = 20.11 | GyX = -18 | GyY = 30 | GyZ = -26
 AcX = 13420 | AcY = -1144 | AcZ = 9124 | Tmp = 20.11 | GyX = -79 | GyY = 74 | GyZ = -37

After a simple shaking we see that it is working in 2g range and 32767 is top of scale. For all six axis the working range is -32768, +32767. That is 16384 is 1g. So what AcX, AcY and AcZ are reading is the orthogonal projection of earth gravity to each of the axis. If you place the sensor in an horizontal stand it will get something near 16384 plus minus some noise.

Also computing something like √((13344 ÷ 16384) ² + (- 1156 ÷ 16384) ² + (9028 ÷ 16384) ² )= 0.9858707387 ~ = 1,0 g = 9.80665 m/s2 Notice gravity may vary according different  factors and places on Earth. Also this equipment reads raw data without calibration.

Another example using Rowberg’s Library.

// I2C device class (I2Cdev) demonstration Arduino sketch for MPU6050 class
 // mofdified from example by Jeff Rowberg
 #include "I2Cdev.h"
 #include "MPU6050.h"
 #include "Wire.h"
 MPU6050 accelgyro(0X68); //default address I2C is 0x68
 //declare variables
 int16_t ax, ay, az;
 int16_t gx, gy, gz;
 int16_t temp;
 float temp_MPU;
 #define LED_PIN 13
 bool blinkState = false;
 void setup() {
 Wire.begin();
 Serial.begin(38400);
 Serial.println("Initializing I2C devices...");
 accelgyro.initialize();
 Serial.println("Testing device connections...");
 Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
 // change accel/gyro offset values to zero
 accelgyro.setXGyroOffset(0);
 accelgyro.setYGyroOffset(0);
 accelgyro.setZGyroOffset(0);
 // configure Arduino LED for
 pinMode(LED_PIN, OUTPUT);
 Serial.println("MPU-6050 example - Enrique Latorres");
 Serial.print("ax"); Serial.print("t");
 Serial.print("ay"); Serial.print("t");
 Serial.print("az"); Serial.print("t");
 Serial.print("temp"); Serial.print("t");
 Serial.print("gx"); Serial.print("t");
 Serial.print("gy"); Serial.print("t");
 Serial.println("gz");
 }
void loop() {
// read raw accel/gyro measurements from device
//accelgyro.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
accelgyro.getAcceleration(&ax, &ay, &az);
accelgyro.getRotation(&gx, &gy, &gz);
temp=accelgyro.getTemperature();
// display tab-separated accel/gyro x/y/z values
Serial.print(ax); Serial.print("t");
Serial.print(ay); Serial.print("t");
Serial.print(az); Serial.print("t");
//convert integer to temperature in centigrades Celsius
//https://www.i2cdevlib.com/forums/topic/53-mpu-6050-temperature-compensation/
temp_MPU=float(temp)/340+36.53;
Serial.print(temp_MPU); Serial.print("t");
Serial.print(gx); Serial.print("t");
Serial.print(gy); Serial.print("t");
Serial.println(gz);
// blink LED to indicate activity
blinkState = !blinkState;
delay(300); //just slow down a little bit
digitalWrite(LED_PIN, blinkState);
}

Compiling and Loading the program gets the following result on Serial Monitor.

MPU-6050 example - Enrique Latorres
 ax ay az temp gx gy gz
 12016 -2038 10648 20.95 61 -21 46
 12030 -1838 10594 20.96 -102 -23 -115
 12046 -1712 10550 20.95 -102 23 -97
 11990 -1978 10640 20.93 32 62 85
 12040 -1848 10616 20.97 -114 15 -105
 11972 -1852 10642 20.94 -27 11 -5
 11942 -1810 10688 20.94 -86 75 -13
 11956 -5784 12308 20.96 -3029 822 -3583

MPU-6050 implementation

Related posts

Leave a Comment