MPU-6050 Accelerometer + Gyro
Navigation
Introduction
The InvenSense MPU-6050 sensor contains a MEMS accelerometer and a MEMS gyro in a single chip. It is very accurate, as it contains 16-bits analog to digital conversion hardware for each channel. Therefor it captures the x, y, and z channel at the same time.
The MPU-6050 is not expensive, especially given the fact that it combines both an accelerometer and a gyro.
Photo: GY-521 breakout board
Also note that Invensense has combined the MPU-6050 with a magnetometer (compass) in a single chip called MPU-9150.
Reading raw values is easy, the rest is not
Reading the raw values for the accelerometer and gyro is easy. The sleep mode has to be disabled, and then the registers for the accelerometer and gyro can be read.
But the sensor also contains a 1024 byte FIFO buffer. The sensor values can be programmed to be placed in the FIFO buffer. And the buffer can be read by the Arduino.
The FIFO buffer is used together with the interrupt signal. If the MPU-6050 places data in the FIFO buffer, it signals the Arduino with the interrupt signal so the Arduino knows that there is data in the FIFO buffer waiting to be read.
A little more complicated is the ability to control a second I2C-device.
The MPU-6050 always acts as a slave to the Arduino with the SDA and SCL pins connected to the I2C-bus.
But beside the normal I2C-bus, it has it's own I2C controller to be a master on a second (sub)-I2C-bus. It uses the pins AUX_DA and AUX_CL for that second (sub)-I2C-bus.
It can control, for example, a magnetometer. The values of the magnetometer can be passed on to the Arduino.
Things get really complex with the "DMP".
The sensor has a "Digital Motion Processor" (DMP), also called a "Digital Motion Processing Unit". This DMP can be programmed with firmware and is able to do complex calculations with the sensor values.
For this DMP, InvenSense has a discouragement policy, by not supplying enough information how to program the DMP. However, some have used reverse engineering to capture firmware.
The DMP ("Digital Motion Processor") can do fast calculations directy on the chip. This reduces the load for the microcontroller (like the Arduino). The DMP is even able to do calculations with the sensor values of another chip, for example a magnetometer connected to the second (sub)-I2C-bus.
Code
The accelerometer and gyro values are called the "raw" values. This is just as with other accelerometer and gyro sensors. A more sophisticated application is using the DMP to retrieve specific computed values from the sensor.
The example code on this page is just a simple and basic sketch to read the raw values.
For more serious use of the MPU-6050, Jeff Rowberg has done an excellent job.
See his I2C lib: http://www.i2cdevlib.com/devices/mpu6050
Or the latest code on github: https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050
The FreeIMU library includes the MPU-6050 code from Jeff Rowberg.
The FreeIMU library: http://www.varesano.net/projects/hardware/FreeIMU
To start with the MPU-6050, see the page of InvenSense: http://www.invensense.com/mems/gyro/mpu6050.html
For other programs and sensors, see the Degrees Of Freedom, 6DOF, 9DOF, 10DOF, 11DOF-section in the Playground index.
Multiple sensors
The pin "AD0" selects between I2C address 0x68 and 0x69. That makes it possible to have two of these sensors in a project. Most breakout boards have a pullup or pulldown resistor to make AD0 default low or high. Connect AD0 to GND or 3.3V for the other I2C address.
When more MPU-6050 sensors are needed in a project, the I2C-bus can be extended with multiplexers. However, someone in the forum mentioned a nice trick:
Trick
Using more than two MPU-6050 sensors can be achieved by connecting each of the AD0 pins to a seperate output of the Arduino. If the number of pins is a problem, then a shift register or a port expander can be used.
The output of a 5V Arduino can not be used. In that case a voltage divider or level shifter for 3.3 volts on each of the outputs is needed. The 5V output pins can also be converted in 3.3V open collector outputs by using transistors or an open-collector driver. Pullup resistors to 3.3V should be added for a high level of 3.3V.
Suppose all AD0 lines are default high (3.3V), so every MPU-6050 is I2C address 0x69. That I2C address is however never used ! The Arduino makes one of the AD0 lines low, and uses that sensor at I2C address 0x68. After that is finished, the Arduino selects another AD0 line, and can use that sensor.
So every sensor is used at I2C address 0x68 (one by one) and 0x69 is never used.
This should make it possible to have many MPU-6050 sensors in a project. Even more than 10 sensor should be possible.
Note that requesting data from many MPU-6050 sensors is slow, because the I2C-bus is slow. A sensor with SPI interface is faster.
At this moment (15 July 2014) it is not known if this trick works for the MPU-6050.
Breakout boards
There are a number of "breakout boards" or "sensor boards" with the MPU-6050.
Sparkfun SEN-11028
http://www.sparkfun.com/products/11028
With schematic and full information. This breakout board must be used with 3.3V. There is no voltage regulator and no
I2C-level shifter on the board. The pull-up resistors for the
I2C-bus are 10k.
Drotek IMU 10DOF - MPU6050 + HMC5883 + MS5611
Drotek MPU-6050 Invensense
GY-521
This sensor board has a voltage regulator. When using 3.3V to the VCC the resulting voltage (after the onboard voltage regulator) might be too low for a good working
I2C bus. It is preferred to apply 5V to the VCC pin of the sensor board. The board has pull-up resistors on the
I2C-bus. The value of those pull-up resistors are sometimes 10k and sometimes 2k2. The 2k2 is rather low. If it is combined with other sensor board which have also pull-up resistors, the total pull-up impedance might be too low.
This schematic is hard to find, so here is a copy:
http://playground.arduino.cc/uploads/Main/MPU6050-V1-SCH.jpg
I designed this part in Fritzing, I hope you find it useful: http://fritzing.org/projects/mpu-6050-board-gy-521-acelerometro-y-giroscopio
GY-52
This sensor board has a voltage regulator. So it can be used with 3.3V and with 5V. The board was originally designed for the MPU-3050, therefor the text "MPU-3050" or "MPU-X050" is sometimes printed on the board. The pull-up resistors are sometimes 10k and sometimes 4k7. If they are 10k, two extra pull-up resistors of 10k to the 3.3V could be added (from the SDA and SCL to the 3.3V of the sensor board or the 3.3V of the Arduino).
Flyduino MPU6050 Break Out onboard 3.3V reg
Flyduino 10DOF IMU GY-86 MPU6050+HMC5883l+MS5611
no name breakout board
In august 2012 the cheapest breakout board with the MPU-6050 was a breakout board (for about 12 dollars/ 10euros) without any name or code.
The header is on the right with the pins in this order: "5V", "3V3", "GND", "SCL", "SDA", "INT", "SYNC", "CLK", "ASCL", "ADSA".
There are two pull-up resistors for the SCL and SDA, but the value is unknown. On the back are three solder jumpers, one of them for AD0.
no name breakout board 2
In 2014 a new MPU-6050 appeared without any name or code.
http://www.i2cdevlib.com/forums/topic/8-mpu6050-connection-failed/?p=347
The header is on the left with the pins in this order: "VCC", "GND", "SCL", "SDA", "XDA", "XCL", "
AD0", "INT".
It is almost equal to the GY-521 board. There is a voltage regulator on the board for 3.3V. There are two 10k pull-up resistors for the SCL and SDA, and also 330 ohm resistors in the SCL and SDA signal. Because of the voltage regulator, connect 5V to the VCC of this sensor board.
Measurements
The raw values raises questions in the forums, since the raw values might seem unstable. Below are the raw values of the sensor that I measured, so you can compare them with your own raw values.
The raw values changes a lot due to a number of reasons. The default sensitivity is high, and the sensor returnes 16 bits, but the actual valid number of bits is less than 16 bits. Since they are 16 bits, a variation of 50 is just a very small variation.
The next measurement were done in these conditions:
- The sensor was placed as horizontal as possible.
- It was placed on concreet, not a wooden table.
- During the measurements, there was no traffic in the street.
- An battery of 12V was used, not the less stable voltage from the USB bus. I used a battery instead of an adapter to avoid any mains noise.
- The circuit was on for 15 minutes, to stabalize any temperature influence.
- The room temperature was 25 degrees Celcius.
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 184, -484, 14992
temperature: 29.635 degrees Celsius
gyro x,y,z : 367, 220, -812,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 116, -364, 15056
temperature: 29.635 degrees Celsius
gyro x,y,z : 373, 226, -766,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 232, -432, 15100
temperature: 29.682 degrees Celsius
gyro x,y,z : 382, 232, -790,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 280, -468, 15136
temperature: 29.635 degrees Celsius
gyro x,y,z : 368, 211, -820,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 140, -432, 15108
temperature: 29.588 degrees Celsius
gyro x,y,z : 388, 203, -806,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 220, -464, 14920
temperature: 29.541 degrees Celsius
gyro x,y,z : 374, 196, -774,
MPU-6050
Read accel, temp and gyro, error = 0
accel x,y,z: 172, -440, 15100
temperature: 29.588 degrees Celsius
gyro x,y,z : 363, 200, -769,
Example sketch
The sketch below is the code made with Arduino 1.0.1 and it uses I2C-bus communication.
The code uses the Arduino functions as much as possible. It is just a simple and basic sketch to get the MPU-6050 working.
The I2C-address depends on the AD0 pin of the sensor. If it is connected to ground, the address is 0x68. If it is connected to VLOGIC (+3.3V) it is 0x69. There are a few sensor boards with the MPU-6050 sensor already soldered on it. Some of those boards have a pull-down resistor at AD0 (address = 0x68), others have a pull-up resistor (address = 0x69).
Search in the sketch for "MPU6050_I2C_ADDRESS" and set that to your own I2C address.
A
i2c_scanner can be used to check if the device is connected to the i2c bus.
The acceleration and gyro values of the sketch are raw values, which are not yet compensated for offset. The very first acceleration and gyro values after power up are sometimes not valid.
The sketch is about 7kbyte, and will fit in a ATmega8.
-
// MPU-6050 Accelerometer + Gyro
-
// -----------------------------
-
//
-
// By arduino.cc user "Krodal".
-
//
-
// June 2012
-
// first version
-
// July 2013
-
// The 'int' in the union for the x,y,z
-
// changed into int16_t to be compatible
-
// with Arduino Due.
-
//
-
// Open Source / Public Domain
-
//
-
// Using Arduino 1.0.1
-
// It will not work with an older version,
-
// since Wire.endTransmission() uses a parameter
-
// to hold or release the I2C bus.
-
//
-
// Documentation:
-
// - The InvenSense documents:
-
// - "MPU-6000 and MPU-6050 Product Specification",
-
// PS-MPU-6000A.pdf
-
// - "MPU-6000 and MPU-6050 Register Map and Descriptions",
-
// RM-MPU-6000A.pdf or RS-MPU-6000A.pdf
-
// - "MPU-6000/MPU-6050 9-Axis Evaluation Board User Guide"
-
// AN-MPU-6000EVB.pdf
-
//
-
// The accuracy is 16-bits.
-
//
-
// Temperature sensor from -40 to +85 degrees Celsius
-
// 340 per degrees, -512 at 35 degrees.
-
//
-
// At power-up, all registers are zero, except these two:
-
// Register 0x6B (PWR_MGMT_2) = 0x40 (I read zero).
-
// Register 0x75 (WHO_AM_I) = 0x68.
-
//
-
-
#include <Wire.h>
-
-
-
// The name of the sensor is "MPU-6050".
-
// For program code, I omit the '-',
-
// therefor I use the name "MPU6050....".
-
-
-
// Register names according to the datasheet.
-
// According to the InvenSense document
-
// "MPU-6000 and MPU-6050 Register Map
-
// and Descriptions Revision 3.2", there are no registers
-
// at 0x02 ... 0x18, but according other information
-
// the registers in that unknown area are for gain
-
// and offsets.
-
//
-
#define MPU6050_AUX_VDDIO 0x01 // R/W
-
#define MPU6050_SMPLRT_DIV 0x19 // R/W
-
#define MPU6050_CONFIG 0x1A // R/W
-
#define MPU6050_GYRO_CONFIG 0x1B // R/W
-
#define MPU6050_ACCEL_CONFIG 0x1C // R/W
-
#define MPU6050_FF_THR 0x1D // R/W
-
#define MPU6050_FF_DUR 0x1E // R/W
-
#define MPU6050_MOT_THR 0x1F // R/W
-
#define MPU6050_MOT_DUR 0x20 // R/W
-
#define MPU6050_ZRMOT_THR 0x21 // R/W
-
#define MPU6050_ZRMOT_DUR 0x22 // R/W
-
#define MPU6050_FIFO_EN 0x23 // R/W
-
#define MPU6050_I2C_MST_CTRL 0x24 // R/W
-
#define MPU6050_I2C_SLV0_ADDR 0x25 // R/W
-
#define MPU6050_I2C_SLV0_REG 0x26 // R/W
-
#define MPU6050_I2C_SLV0_CTRL 0x27 // R/W
-
#define MPU6050_I2C_SLV1_ADDR 0x28 // R/W
-
#define MPU6050_I2C_SLV1_REG 0x29 // R/W
-
#define MPU6050_I2C_SLV1_CTRL 0x2A // R/W
-
#define MPU6050_I2C_SLV2_ADDR 0x2B // R/W
-
#define MPU6050_I2C_SLV2_REG 0x2C // R/W
-
#define MPU6050_I2C_SLV2_CTRL 0x2D // R/W
-
#define MPU6050_I2C_SLV3_ADDR 0x2E // R/W
-
#define MPU6050_I2C_SLV3_REG 0x2F // R/W
-
#define MPU6050_I2C_SLV3_CTRL 0x30 // R/W
-
#define MPU6050_I2C_SLV4_ADDR 0x31 // R/W
-
#define MPU6050_I2C_SLV4_REG 0x32 // R/W
-
#define MPU6050_I2C_SLV4_DO 0x33 // R/W
-
#define MPU6050_I2C_SLV4_CTRL 0x34 // R/W
-
#define MPU6050_I2C_SLV4_DI 0x35 // R
-
#define MPU6050_I2C_MST_STATUS 0x36 // R
-
#define MPU6050_INT_PIN_CFG 0x37 // R/W
-
#define MPU6050_INT_ENABLE 0x38 // R/W
-
#define MPU6050_INT_STATUS 0x3A // R
-
#define MPU6050_ACCEL_XOUT_H 0x3B // R
-
#define MPU6050_ACCEL_XOUT_L 0x3C // R
-
#define MPU6050_ACCEL_YOUT_H 0x3D // R
-
#define MPU6050_ACCEL_YOUT_L 0x3E // R
-
#define MPU6050_ACCEL_ZOUT_H 0x3F // R
-
#define MPU6050_ACCEL_ZOUT_L 0x40 // R
-
#define MPU6050_TEMP_OUT_H 0x41 // R
-
#define MPU6050_TEMP_OUT_L 0x42 // R
-
#define MPU6050_GYRO_XOUT_H 0x43 // R
-
#define MPU6050_GYRO_XOUT_L 0x44 // R
-
#define MPU6050_GYRO_YOUT_H 0x45 // R
-
#define MPU6050_GYRO_YOUT_L 0x46 // R
-
#define MPU6050_GYRO_ZOUT_H 0x47 // R
-
#define MPU6050_GYRO_ZOUT_L 0x48 // R
-
#define MPU6050_EXT_SENS_DATA_00 0x49 // R
-
#define MPU6050_EXT_SENS_DATA_01 0x4A // R
-
#define MPU6050_EXT_SENS_DATA_02 0x4B // R
-
#define MPU6050_EXT_SENS_DATA_03 0x4C // R
-
#define MPU6050_EXT_SENS_DATA_04 0x4D // R
-
#define MPU6050_EXT_SENS_DATA_05 0x4E // R
-
#define MPU6050_EXT_SENS_DATA_06 0x4F // R
-
#define MPU6050_EXT_SENS_DATA_07 0x50 // R
-
#define MPU6050_EXT_SENS_DATA_08 0x51 // R
-
#define MPU6050_EXT_SENS_DATA_09 0x52 // R
-
#define MPU6050_EXT_SENS_DATA_10 0x53 // R
-
#define MPU6050_EXT_SENS_DATA_11 0x54 // R
-
#define MPU6050_EXT_SENS_DATA_12 0x55 // R
-
#define MPU6050_EXT_SENS_DATA_13 0x56 // R
-
#define MPU6050_EXT_SENS_DATA_14 0x57 // R
-
#define MPU6050_EXT_SENS_DATA_15 0x58 // R
-
#define MPU6050_EXT_SENS_DATA_16 0x59 // R
-
#define MPU6050_EXT_SENS_DATA_17 0x5A // R
-
#define MPU6050_EXT_SENS_DATA_18 0x5B // R
-
#define MPU6050_EXT_SENS_DATA_19 0x5C // R
-
#define MPU6050_EXT_SENS_DATA_20 0x5D // R
-
#define MPU6050_EXT_SENS_DATA_21 0x5E // R
-
#define MPU6050_EXT_SENS_DATA_22 0x5F // R
-
#define MPU6050_EXT_SENS_DATA_23 0x60 // R
-
#define MPU6050_MOT_DETECT_STATUS 0x61 // R
-
#define MPU6050_I2C_SLV0_DO 0x63 // R/W
-
#define MPU6050_I2C_SLV1_DO 0x64 // R/W
-
#define MPU6050_I2C_SLV2_DO 0x65 // R/W
-
#define MPU6050_I2C_SLV3_DO 0x66 // R/W
-
#define MPU6050_I2C_MST_DELAY_CTRL 0x67 // R/W
-
#define MPU6050_SIGNAL_PATH_RESET 0x68 // R/W
-
#define MPU6050_MOT_DETECT_CTRL 0x69 // R/W
-
#define MPU6050_USER_CTRL 0x6A // R/W
-
#define MPU6050_PWR_MGMT_1 0x6B // R/W
-
#define MPU6050_PWR_MGMT_2 0x6C // R/W
-
#define MPU6050_FIFO_COUNTH 0x72 // R/W
-
#define MPU6050_FIFO_COUNTL 0x73 // R/W
-
#define MPU6050_FIFO_R_W 0x74 // R/W
-
#define MPU6050_WHO_AM_I 0x75 // R
-
-
-
// Defines for the bits, to be able to change
-
// between bit number and binary definition.
-
// By using the bit number, programming the sensor
-
// is like programming the AVR microcontroller.
-
// But instead of using "(1<<X)", or "_BV(X)",
-
// the Arduino "bit(X)" is used.
-
#define MPU6050_D0 0
-
#define MPU6050_D1 1
-
#define MPU6050_D2 2
-
#define MPU6050_D3 3
-
#define MPU6050_D4 4
-
#define MPU6050_D5 5
-
#define MPU6050_D6 6
-
#define MPU6050_D7 7
-
-
// AUX_VDDIO Register
-
#define MPU6050_AUX_VDDIO MPU6050_D7 // I2C high: 1=VDD, 0=VLOGIC
-
-
// CONFIG Register
-
// DLPF is Digital Low Pass Filter for both gyro and accelerometers.
-
// These are the names for the bits.
-
// Use these only with the bit() macro.
-
#define MPU6050_DLPF_CFG0 MPU6050_D0
-
#define MPU6050_DLPF_CFG1 MPU6050_D1
-
#define MPU6050_DLPF_CFG2 MPU6050_D2
-
#define MPU6050_EXT_SYNC_SET0 MPU6050_D3
-
#define MPU6050_EXT_SYNC_SET1 MPU6050_D4
-
#define MPU6050_EXT_SYNC_SET2 MPU6050_D5
-
-
// Combined definitions for the EXT_SYNC_SET values
-
#define MPU6050_EXT_SYNC_SET_0 (0)
-
#define MPU6050_EXT_SYNC_SET_1 (bit(MPU6050_EXT_SYNC_SET0))
-
#define MPU6050_EXT_SYNC_SET_2 (bit(MPU6050_EXT_SYNC_SET1))
-
#define MPU6050_EXT_SYNC_SET_3 (bit(MPU6050_EXT_SYNC_SET1)|bit(MPU6050_EXT_SYNC_SET0))
-
#define MPU6050_EXT_SYNC_SET_4 (bit(MPU6050_EXT_SYNC_SET2))
-
#define MPU6050_EXT_SYNC_SET_5 (bit(MPU6050_EXT_SYNC_SET2)|bit(MPU6050_EXT_SYNC_SET0))
-
#define MPU6050_EXT_SYNC_SET_6 (bit(MPU6050_EXT_SYNC_SET2)|bit(MPU6050_EXT_SYNC_SET1))
-
#define MPU6050_EXT_SYNC_SET_7 (bit(MPU6050_EXT_SYNC_SET2)|bit(MPU6050_EXT_SYNC_SET1)|bit(MPU6050_EXT_SYNC_SET0))
-
-
// Alternative names for the combined definitions.
-
#define MPU6050_EXT_SYNC_DISABLED MPU6050_EXT_SYNC_SET_0
-
#define MPU6050_EXT_SYNC_TEMP_OUT_L MPU6050_EXT_SYNC_SET_1
-
#define MPU6050_EXT_SYNC_GYRO_XOUT_L MPU6050_EXT_SYNC_SET_2
-
#define MPU6050_EXT_SYNC_GYRO_YOUT_L MPU6050_EXT_SYNC_SET_3
-
#define MPU6050_EXT_SYNC_GYRO_ZOUT_L MPU6050_EXT_SYNC_SET_4
-
#define MPU6050_EXT_SYNC_ACCEL_XOUT_L MPU6050_EXT_SYNC_SET_5
-
#define MPU6050_EXT_SYNC_ACCEL_YOUT_L MPU6050_EXT_SYNC_SET_6
-
#define MPU6050_EXT_SYNC_ACCEL_ZOUT_L MPU6050_EXT_SYNC_SET_7
-
-
// Combined definitions for the DLPF_CFG values
-
#define MPU6050_DLPF_CFG_0 (0)
-
#define MPU6050_DLPF_CFG_1 (bit(MPU6050_DLPF_CFG0))
-
#define MPU6050_DLPF_CFG_2 (bit(MPU6050_DLPF_CFG1))
-
#define MPU6050_DLPF_CFG_3 (bit(MPU6050_DLPF_CFG1)|bit(MPU6050_DLPF_CFG0))
-
#define MPU6050_DLPF_CFG_4 (bit(MPU6050_DLPF_CFG2))
-
#define MPU6050_DLPF_CFG_5 (bit(MPU6050_DLPF_CFG2)|bit(MPU6050_DLPF_CFG0))
-
#define MPU6050_DLPF_CFG_6 (bit(MPU6050_DLPF_CFG2)|bit(MPU6050_DLPF_CFG1))
-
#define MPU6050_DLPF_CFG_7 (bit(MPU6050_DLPF_CFG2)|bit(MPU6050_DLPF_CFG1)|bit(MPU6050_DLPF_CFG0))
-
-
// Alternative names for the combined definitions
-
// This name uses the bandwidth (Hz) for the accelometer,
-
// for the gyro the bandwidth is almost the same.
-
#define MPU6050_DLPF_260HZ MPU6050_DLPF_CFG_0
-
#define MPU6050_DLPF_184HZ MPU6050_DLPF_CFG_1
-
#define MPU6050_DLPF_94HZ MPU6050_DLPF_CFG_2
-
#define MPU6050_DLPF_44HZ MPU6050_DLPF_CFG_3
-
#define MPU6050_DLPF_21HZ MPU6050_DLPF_CFG_4
-
#define MPU6050_DLPF_10HZ MPU6050_DLPF_CFG_5
-
#define MPU6050_DLPF_5HZ MPU6050_DLPF_CFG_6
-
#define MPU6050_DLPF_RESERVED MPU6050_DLPF_CFG_7
-
-
// GYRO_CONFIG Register
-
// The XG_ST, YG_ST, ZG_ST are bits for selftest.
-
// The FS_SEL sets the range for the gyro.
-
// These are the names for the bits.
- &a
Powered By
OpenCart Cambodia Electronic Source © 2024