Botched

MPU6050 Setup + Data Aquisition

In this tutorial I intend to run through the basics of the MPU6050, along with configuring the chip and reading data from it. I intend to cover filtering in a later post. Also please take everything I write with a pinch of salt, as at the end of the day I am still just an undergraduate, and could easily have misunderstood or misread something. The full source can be accessed at https://github.com/big5824/Quadrocopter.

Anyway, down to business.

The MPU6050 is a 6 degree of freedom chip from Invensense, containing a tri axis accelerometer and a tri axis gyroscope. It is operated off a 3.3V supply, and communicates via I2C at a maximum speed of 400kHz. This chip is also available in an SPI package known as the MPU6000, which I would have preferred to use given the choice due to the much higher throughput of SPI. However for some reason the world seems to prefer the I2C version, so this was the only version I could find with a breakout board.

The main pros of this chip are as follows:

  • Selectable +-2/4/8/16g accelerometer range
  • Selectable +-250/500/1000/2000 degrees/s gyroscope range
  • 16 bit output from both sensors
  • Gyroscope linear acceleration sensitivity of 0.1 degrees/s, a vast improvement over the tri axis gyroscopes of other companies.
  • Low noise on both outputs, see the datasheet
  • Data output rate up to 1000Hz, although the built in digital low pass filter has a maximum corner frequency of 256Hz. However, the register map documentation mentions turning off the DLPF, so I'm not sure which to believe at the moment.

Another feature of this chip is the onboard digital motion processor (DMP). In theory this can be used to directly output euler angles, quaternions, or a direction cosine matrix, and even perform filtering along with integrating the data from an external I2C compass. This sounds great on paper, but in reality Invensense have been very reluctant to provide any sort of source code or documention on how to use the DMP unless you sign a non disclosure agreement, so as far as I know nobody has really got this working to it's full potential as of yet.

To summarise, this chip is a massive improvement over all the previous sensors I have used, and it comes in a single package. There is even a 9DoF MPU9150 version coming, which I intend to acquire as soon as it's released in 2012 Q2.

I2C Setup

I was going to write an I2C tutorial, however unlike the MPU6050 there are already a lot of tutorials out there covering this module, so I will just point you here for an explanation of the I2C protocol, and to Microchips I2C example here for the code I based my I2C driver off.

Setting up the MPU6050

Setup is performed by writing to the various configuration registers. I only needed to write to three registers in the end, leaving the rest as zeros, however it is still good practise to write these zeros just in case the register didn't reset correctly. I used the code from here to save time, as this header file let me skip the tedious process of naming every register address myself.

The first line defines the address of the chip, which for me was 0x69 since I pulled AD0 high. This value is stored in the 7 most significant bits, with the least significant bit being the read/write bit. When cleared, this tells the chip a write is about to occur, and when set it tells the chip to send data from the specified register address. This setting and clearing is done by ORing the address with 0x01 for a read, or leaving it untouched for a write. This operation is performed by the I2C driver.

#define MPU6050_ADDRESS 0b11010010 // Address with end write bit
#define MPU6050_RA_XG_OFFS_TC 0x00 //[7] PWR_MODE, [6:1] XG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_YG_OFFS_TC 0x01 //[7] PWR_MODE, [6:1] YG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_ZG_OFFS_TC 0x02 //[7] PWR_MODE, [6:1] ZG_OFFS_TC, [0] OTP_BNK_VLD
#define MPU6050_RA_X_FINE_GAIN 0x03 //[7:0] X_FINE_GAIN
#define MPU6050_RA_Y_FINE_GAIN 0x04 //[7:0] Y_FINE_GAIN
#define MPU6050_RA_Z_FINE_GAIN 0x05 //[7:0] Z_FINE_GAIN
#define MPU6050_RA_XA_OFFS_H 0x06 //[15:0] XA_OFFS
#define MPU6050_RA_XA_OFFS_L_TC 0x07
#define MPU6050_RA_YA_OFFS_H 0x08 //[15:0] YA_OFFS
#define MPU6050_RA_YA_OFFS_L_TC 0x09
#define MPU6050_RA_ZA_OFFS_H 0x0A //[15:0] ZA_OFFS
#define MPU6050_RA_ZA_OFFS_L_TC 0x0B
#define MPU6050_RA_XG_OFFS_USRH 0x13 //[15:0] XG_OFFS_USR
#define MPU6050_RA_XG_OFFS_USRL 0x14
#define MPU6050_RA_YG_OFFS_USRH 0x15 //[15:0] YG_OFFS_USR
#define MPU6050_RA_YG_OFFS_USRL 0x16
#define MPU6050_RA_ZG_OFFS_USRH 0x17 //[15:0] ZG_OFFS_USR
#define MPU6050_RA_ZG_OFFS_USRL 0x18
#define MPU6050_RA_SMPLRT_DIV 0x19
#define MPU6050_RA_CONFIG 0x1A
#define MPU6050_RA_GYRO_CONFIG 0x1B
#define MPU6050_RA_ACCEL_CONFIG 0x1C
#define MPU6050_RA_FF_THR 0x1D
#define MPU6050_RA_FF_DUR 0x1E
#define MPU6050_RA_MOT_THR 0x1F
#define MPU6050_RA_MOT_DUR 0x20
#define MPU6050_RA_ZRMOT_THR 0x21
#define MPU6050_RA_ZRMOT_DUR 0x22
#define MPU6050_RA_FIFO_EN 0x23
#define MPU6050_RA_I2C_MST_CTRL 0x24
#define MPU6050_RA_I2C_SLV0_ADDR 0x25
#define MPU6050_RA_I2C_SLV0_REG 0x26
#define MPU6050_RA_I2C_SLV0_CTRL 0x27
#define MPU6050_RA_I2C_SLV1_ADDR 0x28
#define MPU6050_RA_I2C_SLV1_REG 0x29
#define MPU6050_RA_I2C_SLV1_CTRL 0x2A
#define MPU6050_RA_I2C_SLV2_ADDR 0x2B
#define MPU6050_RA_I2C_SLV2_REG 0x2C
#define MPU6050_RA_I2C_SLV2_CTRL 0x2D
#define MPU6050_RA_I2C_SLV3_ADDR 0x2E
#define MPU6050_RA_I2C_SLV3_REG 0x2F
#define MPU6050_RA_I2C_SLV3_CTRL 0x30
#define MPU6050_RA_I2C_SLV4_ADDR 0x31
#define MPU6050_RA_I2C_SLV4_REG 0x32
#define MPU6050_RA_I2C_SLV4_DO 0x33
#define MPU6050_RA_I2C_SLV4_CTRL 0x34
#define MPU6050_RA_I2C_SLV4_DI 0x35
#define MPU6050_RA_I2C_MST_STATUS 0x36
#define MPU6050_RA_INT_PIN_CFG 0x37
#define MPU6050_RA_INT_ENABLE 0x38
#define MPU6050_RA_DMP_INT_STATUS 0x39
#define MPU6050_RA_INT_STATUS 0x3A
#define MPU6050_RA_ACCEL_XOUT_H 0x3B
#define MPU6050_RA_ACCEL_XOUT_L 0x3C
#define MPU6050_RA_ACCEL_YOUT_H 0x3D
#define MPU6050_RA_ACCEL_YOUT_L 0x3E
#define MPU6050_RA_ACCEL_ZOUT_H 0x3F
#define MPU6050_RA_ACCEL_ZOUT_L 0x40
#define MPU6050_RA_TEMP_OUT_H 0x41
#define MPU6050_RA_TEMP_OUT_L 0x42
#define MPU6050_RA_GYRO_XOUT_H 0x43
#define MPU6050_RA_GYRO_XOUT_L 0x44
#define MPU6050_RA_GYRO_YOUT_H 0x45
#define MPU6050_RA_GYRO_YOUT_L 0x46
#define MPU6050_RA_GYRO_ZOUT_H 0x47
#define MPU6050_RA_GYRO_ZOUT_L 0x48
#define MPU6050_RA_EXT_SENS_DATA_00 0x49
#define MPU6050_RA_EXT_SENS_DATA_01 0x4A
#define MPU6050_RA_EXT_SENS_DATA_02 0x4B
#define MPU6050_RA_EXT_SENS_DATA_03 0x4C
#define MPU6050_RA_EXT_SENS_DATA_04 0x4D
#define MPU6050_RA_EXT_SENS_DATA_05 0x4E
#define MPU6050_RA_EXT_SENS_DATA_06 0x4F
#define MPU6050_RA_EXT_SENS_DATA_07 0x50
#define MPU6050_RA_EXT_SENS_DATA_08 0x51
#define MPU6050_RA_EXT_SENS_DATA_09 0x52
#define MPU6050_RA_EXT_SENS_DATA_10 0x53
#define MPU6050_RA_EXT_SENS_DATA_11 0x54
#define MPU6050_RA_EXT_SENS_DATA_12 0x55
#define MPU6050_RA_EXT_SENS_DATA_13 0x56
#define MPU6050_RA_EXT_SENS_DATA_14 0x57
#define MPU6050_RA_EXT_SENS_DATA_15 0x58
#define MPU6050_RA_EXT_SENS_DATA_16 0x59
#define MPU6050_RA_EXT_SENS_DATA_17 0x5A
#define MPU6050_RA_EXT_SENS_DATA_18 0x5B
#define MPU6050_RA_EXT_SENS_DATA_19 0x5C
#define MPU6050_RA_EXT_SENS_DATA_20 0x5D
#define MPU6050_RA_EXT_SENS_DATA_21 0x5E
#define MPU6050_RA_EXT_SENS_DATA_22 0x5F
#define MPU6050_RA_EXT_SENS_DATA_23 0x60
#define MPU6050_RA_MOT_DETECT_STATUS 0x61
#define MPU6050_RA_I2C_SLV0_DO 0x63
#define MPU6050_RA_I2C_SLV1_DO 0x64
#define MPU6050_RA_I2C_SLV2_DO 0x65
#define MPU6050_RA_I2C_SLV3_DO 0x66
#define MPU6050_RA_I2C_MST_DELAY_CTRL 0x67
#define MPU6050_RA_SIGNAL_PATH_RESET 0x68
#define MPU6050_RA_MOT_DETECT_CTRL 0x69
#define MPU6050_RA_USER_CTRL 0x6A
#define MPU6050_RA_PWR_MGMT_1 0x6B
#define MPU6050_RA_PWR_MGMT_2 0x6C
#define MPU6050_RA_BANK_SEL 0x6D
#define MPU6050_RA_MEM_START_ADDR 0x6E
#define MPU6050_RA_MEM_R_W 0x6F
#define MPU6050_RA_DMP_CFG_1 0x70
#define MPU6050_RA_DMP_CFG_2 0x71
#define MPU6050_RA_FIFO_COUNTH 0x72
#define MPU6050_RA_FIFO_COUNTL 0x73
#define MPU6050_RA_FIFO_R_W 0x74
#define MPU6050_RA_WHO_AM_I 0x75

Not all of these addresses are writable, and some aren't even mentioned in the datasheet, so I have no idea how the author figured out what they are. I ignored all those missing from the datasheet.
The first part of the setup is to check the I2C link is functioning. This is done by simply reading the register at 0x75, referred to as MPU6050_RA_WHO_AM_I. This contains the chips I2C address, which is always 0x68, regardless of the state of AD0. This little quirk caught me out for hours as I trawled through every bit of my I2C code trying to find out why it wouldn't return 0x69.

void MPU6050_Test_I2C()
{
    unsigned char Data = 0x00;
    LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_WHO_AM_I, &Data, 1);
 
    if(Data == 0x68)
    {
        printf("\nI2C Read Test Passed, MPU6050 Address: 0x%x", Data);
    }
    else
    {
        printf("ERROR: I2C Read Test Failed, Stopping");
        while(1){}    
    }    
}

The reads are performed using the LDByteReadI2C function, given the address of the chip (0x68 with the AD0 pin low, 0x69 with it high), the address of the register to read, the address of the 8 bit variable to store the data in, and the number of bytes to read (a value of 2 would read both 0x68 then 0x69, or 69 then 70).

If this communication is successful, you know your chip functions partially, congratulations! The next step is to write to all the configuration registers.

void Setup_MPU6050()
{
    //Sets sample rate to 8000/1+7 = 1000Hz
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_SMPLRT_DIV, 0x07);
    //Disable FSync, 256Hz DLPF
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_CONFIG, 0x00);
    //Disable gyro self tests, scale of 500 degrees/s
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_CONFIG, 0b00001000);
    //Disable accel self tests, scale of +-2g, no DHPF
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_CONFIG, 0x00);
    //Freefall threshold of |0mg|
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_FF_THR, 0x00);
    //Freefall duration limit of 0
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_FF_DUR, 0x00);
    //Motion threshold of 0mg
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_MOT_THR, 0x00);
    //Motion duration of 0s
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_MOT_DUR, 0x00);
    //Zero motion threshold
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_ZRMOT_THR, 0x00);
    //Zero motion duration threshold
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_ZRMOT_DUR, 0x00);
    //Disable sensor output to FIFO buffer
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_FIFO_EN, 0x00);
 
    //AUX I2C setup
    //Sets AUX I2C to single master control, plus other config
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_MST_CTRL, 0x00);
    //Setup AUX I2C slaves
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_ADDR, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_REG, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_CTRL, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_ADDR, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_REG, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_CTRL, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_ADDR, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_REG, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_CTRL, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_ADDR, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_REG, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_CTRL, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_ADDR, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_REG, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_DO, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_CTRL, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV4_DI, 0x00);
 
    //MPU6050_RA_I2C_MST_STATUS //Read-only
    //Setup INT pin and AUX I2C pass through
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_INT_PIN_CFG, 0x00);
    //Enable data ready interrupt
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_INT_ENABLE, 0x00);
 
    //MPU6050_RA_DMP_INT_STATUS        //Read-only
    //MPU6050_RA_INT_STATUS 3A        //Read-only
    //MPU6050_RA_ACCEL_XOUT_H         //Read-only
    //MPU6050_RA_ACCEL_XOUT_L         //Read-only
    //MPU6050_RA_ACCEL_YOUT_H         //Read-only
    //MPU6050_RA_ACCEL_YOUT_L         //Read-only
    //MPU6050_RA_ACCEL_ZOUT_H         //Read-only
    //MPU6050_RA_ACCEL_ZOUT_L         //Read-only
    //MPU6050_RA_TEMP_OUT_H         //Read-only
    //MPU6050_RA_TEMP_OUT_L         //Read-only
    //MPU6050_RA_GYRO_XOUT_H         //Read-only
    //MPU6050_RA_GYRO_XOUT_L         //Read-only
    //MPU6050_RA_GYRO_YOUT_H         //Read-only
    //MPU6050_RA_GYRO_YOUT_L         //Read-only
    //MPU6050_RA_GYRO_ZOUT_H         //Read-only
    //MPU6050_RA_GYRO_ZOUT_L         //Read-only
    //MPU6050_RA_EXT_SENS_DATA_00     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_01     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_02     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_03     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_04     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_05     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_06     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_07     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_08     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_09     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_10     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_11     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_12     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_13     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_14     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_15     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_16     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_17     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_18     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_19     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_20     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_21     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_22     //Read-only
    //MPU6050_RA_EXT_SENS_DATA_23     //Read-only
    //MPU6050_RA_MOT_DETECT_STATUS     //Read-only
 
    //Slave out, dont care
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV0_DO, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV1_DO, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV2_DO, 0x00);
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_SLV3_DO, 0x00);
    //More slave config
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_I2C_MST_DELAY_CTRL, 0x00);
    //Reset sensor signal paths
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_SIGNAL_PATH_RESET, 0x00);
    //Motion detection control
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_MOT_DETECT_CTRL, 0x00);
    //Disables FIFO, AUX I2C, FIFO and I2C reset bits to 0
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_USER_CTRL, 0x00);
    //Sets clock source to gyro reference w/ PLL
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_PWR_MGMT_1, 0b00000010);
    //Controls frequency of wakeups in accel low power mode plus the sensor standby modes
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_PWR_MGMT_2, 0x00);
    //MPU6050_RA_BANK_SEL            //Not in datasheet
    //MPU6050_RA_MEM_START_ADDR        //Not in datasheet
    //MPU6050_RA_MEM_R_W            //Not in datasheet
    //MPU6050_RA_DMP_CFG_1            //Not in datasheet
    //MPU6050_RA_DMP_CFG_2            //Not in datasheet
    //MPU6050_RA_FIFO_COUNTH        //Read-only
    //MPU6050_RA_FIFO_COUNTL        //Read-only
    //Data transfer to and from the FIFO buffer
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_FIFO_R_W, 0x00);
    //MPU6050_RA_WHO_AM_I             //Read-only, I2C address
 
    printf("\nMPU6050 Setup Complete");
}

I have tried to outline what configuration changes I am making with every register write in the comments above each line.

I also have a function that reads every register to check for write errors, which do occur, so I recommend including this as well. I won't post it here to save space, but feel free to email me for it, I'm normally pretty quick with replies.

After this, your MPU6050 should be fully setup and ready to use! Below are a bunch of functions used to read and convert the sensor data, plus a function for determining the gyro offsets.

void Calibrate_Gyros()
{
	int x = 0;
	for(x = 0; x<1000; x++)
	{
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_H, &GYRO_XOUT_H, 1);
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_L, &GYRO_XOUT_L, 1);
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_YOUT_H, &GYRO_YOUT_H, 1);
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_YOUT_L, &GYRO_YOUT_L, 1);
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_ZOUT_H, &GYRO_ZOUT_H, 1);
		LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_ZOUT_L, &GYRO_ZOUT_L, 1);
 
		GYRO_XOUT_OFFSET_1000SUM += ((GYRO_XOUT_H<<8)|GYRO_XOUT_L);
		GYRO_YOUT_OFFSET_1000SUM += ((GYRO_YOUT_H<<8)|GYRO_YOUT_L);
		GYRO_ZOUT_OFFSET_1000SUM += ((GYRO_ZOUT_H<<8)|GYRO_ZOUT_L);
 
		__delay_ms(1);
	}	
	GYRO_XOUT_OFFSET = GYRO_XOUT_OFFSET_1000SUM/1000;
	GYRO_YOUT_OFFSET = GYRO_YOUT_OFFSET_1000SUM/1000;
	GYRO_ZOUT_OFFSET = GYRO_ZOUT_OFFSET_1000SUM/1000;
 
	printf("\nGyro X offset sum: %ld Gyro X offset: %d", GYRO_XOUT_OFFSET_1000SUM, GYRO_XOUT_OFFSET);
	printf("\nGyro Y offset sum: %ld Gyro Y offset: %d", GYRO_YOUT_OFFSET_1000SUM, GYRO_YOUT_OFFSET);
	printf("\nGyro Z offset sum: %ld Gyro Z offset: %d", GYRO_ZOUT_OFFSET_1000SUM, GYRO_ZOUT_OFFSET);
}	
 
//Gets raw accelerometer data, performs no processing
void Get_Accel_Values()
{
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_XOUT_H, &ACCEL_XOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_XOUT_L, &ACCEL_XOUT_L, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_YOUT_H, &ACCEL_YOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_YOUT_L, &ACCEL_YOUT_L, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_ZOUT_H, &ACCEL_ZOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_ACCEL_ZOUT_L, &ACCEL_ZOUT_L, 1);
 
	ACCEL_XOUT = ((ACCEL_XOUT_H<<8)|ACCEL_XOUT_L);
	ACCEL_YOUT = ((ACCEL_YOUT_H<<8)|ACCEL_YOUT_L);
	ACCEL_ZOUT = ((ACCEL_ZOUT_H<<8)|ACCEL_ZOUT_L);		
}	
 
//Converts the already acquired accelerometer data into 3D euler angles
void Get_Accel_Angles()
{
	ACCEL_XANGLE = 57.295*atan((float)ACCEL_YOUT/ sqrt(pow((float)ACCEL_ZOUT,2)+pow((float)ACCEL_XOUT,2)));
	ACCEL_YANGLE = 57.295*atan((float)-ACCEL_XOUT/ sqrt(pow((float)ACCEL_ZOUT,2)+pow((float)ACCEL_YOUT,2)));	
}	
 
//Function to read the gyroscope rate data and convert it into degrees/s
void Get_Gyro_Rates()
{
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_H, &GYRO_XOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_L, &GYRO_XOUT_L, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_YOUT_H, &GYRO_YOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_YOUT_L, &GYRO_YOUT_L, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_ZOUT_H, &GYRO_ZOUT_H, 1);
	LDByteReadI2C(MPU6050_ADDRESS, MPU6050_RA_GYRO_ZOUT_L, &GYRO_ZOUT_L, 1);
 
	GYRO_XOUT = ((GYRO_XOUT_H<<8)|GYRO_XOUT_L) - GYRO_XOUT_OFFSET;
	GYRO_YOUT = ((GYRO_YOUT_H<<8)|GYRO_YOUT_L) - GYRO_YOUT_OFFSET;
	GYRO_ZOUT = ((GYRO_ZOUT_H<<8)|GYRO_ZOUT_L) - GYRO_ZOUT_OFFSET;
 
 
	GYRO_XRATE = (float)GYRO_XOUT/gyro_xsensitivity;
	GYRO_YRATE = (float)GYRO_YOUT/gyro_ysensitivity;
	GYRO_ZRATE = (float)GYRO_ZOUT/gyro_zsensitivity;
}

If this code has worked for you, you should now have access to a gyroscope rate in degrees/s and an accelerometer angle. Just beware you will need to define your own gyro sensitivities, as it depends on what scale you select in the configuration. This doesn't matter with the accelerometers, as the atan2 function just relies on the ratio of the two.

Comments (124) Trackbacks (1)
  1. Hello,

    Great guide, love it!

    What are the values of the gyro sensitivity? I mean, I know that the gyro has several configs for the sensitivity as “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”.
    But do you write them as 250, or 500 and so on or is it something else?

    And do you know how we could combine the two sensors into 1?

    • Like you said, when in the +-250 degrees mode the gyro sensitivity is 131 LSB/dps, so divide by that and you will get an output in degrees. The sensitivities for the other scales are in the datasheet somewhere.

      As for combining both sensors into one, you need to implement some sort of fusion algorithm. I use a complementary filter in my quad code here https://github.com/big5824/Quadrocopter, but ideally you would use a kalman filter.

      • how to get values from DMP. ?? pls help me…..
        am using CCS as IDE and concerto [f28m35h52c1]

        now i can able to read Accelerometer,gyro,magneto values but i dnt have any idea about motion algorithm and DMP so pls help me……

  2. Hi,
    When i try to read the Who Am I register as you said ,im getting some wrong values and it changes always so do you what the problem could be.If u aware of it please help me to find out the solution (im using C8051f120 microcontroller)

    Thanks in advance

    Thanks and Reards
    Rajiv

    • The who am I register should always return 0x68, so yes something is definitely wrong.
      Have you looked at your SDA line on an oscilloscope to make sure it’s nice and clean? If that’s not the problem the only other things I can think of is you might be reading the wrong address, possibly by using a decimal in place of a hex or vice versa, or your I2C function may not be functioning right and might be trying to return data from the wrong pointer in your microcontroller (I’ve had this happen before).
      Other than that I can’t think of any other errors that would return changing data I’m afraid, keep me updated!

      Matt

      • HI,
        Thank your for ur reply,I tested the SDA line which is not clear and nice but i connected the SDA and SCL to Pull up resistor to 5V.So what can i do to make it clear Please help me to solve this problem

        Thanks in advance

        Regards
        Rajiv

        • You need two 1.8K pullup resistors on both lines, but only to 3.3V, not 5V! I’m not sure what effect putting 5V on your I2C lines will have had, so you might want to try swapping the chip out. And yes, 3.3V should still be able to interface to a 5V microcontroller just fine (usually).

          Matt

          • HI,
            I connected 3.3V and pull up resistor ,the SCL and SDA are fine.But now im not receiving the ACK (even after sending ADD+W ).The address is 0x68 and i tried with different frequencies then also no result.

            Thanks
            Rajiv

  3. Hi

    I am experimenting with adapted version of your code for the Raspberry Pi. I had similar problems to Rajiv but then they just sorted themselves out by magic after running the program a few times. I’ve no idea why. I can only assume that I had a dodgey connection or that random intermittent write errors meant that several attempts were needed to prime the registers during set-up? Any how – it seems to work now – just got to work out how to use the data – thanks.

    • I’ve successfully interfaced it to an RPi in the past too, and I fixed the intermittent bug by writing to the sleep register first. It seemed modifying that value in the middle of everything else could confuse the chip somehow.

  4. Hi,
    Do you have any calibration function for this MPU module? I was able to read raw data by reading your guide, great guide man.

  5. Hi,
    I am using MPU6050 with a HMC5883 to build an IMU. I’m at the first steps, now I can read data from gyro and accel registers. But something really confuse me the low-byte of this registers are always changing when my IMU is stable?!and the data are really non-sense (255- 1 – 23 – 127 – 7 ….) Is it because of noise? do I have to use the internal filters?
    Oh I forgot to say thank you very much dude , your tutorial really helped me…

    • I no longer have access to raw data from my sensor, but I’m sure when stationary the noise was never worse than around 10LSB peak to peak.

      The noise could be down to a faulty chip, i2c errors, incorrect data handling, it’s not really something I can diagnose over the internet. If you could provide an image of the waveform you are receiving during say a 90 degree turn along with the code you are using I might be able to help a little better.

  6. Hi there,

    Has anyone come across this problem before?

    I had my MPU6000 working perfectly. I then changed a few things on the SPI bus and all of a sudden the ACCEL_ZOUT_H and ACCEL_ZOUT_L only return 0. All the registers above and below the accel-zout still worked.

    So I swapped my chip to a new MPU6000 and then it worked well again. However after I changed something on my SPI bus again, it won’t respond at all… I can’t wake it up and it won’t return Who_am_I either even after I changed everything back to the way it was when it was last working.

    I think my circuit is ok because it has worked for weeks with no problem until I played with the SPI.

    Is there a chance I’ve mucked up its DMP? I’m only using raw values. Does the MPU6000 have volatile memory or eeprom? If so, can I reset it in any way?

    Any help or pity is appreciated 🙂

    Oti

    • Hmm I’ve never come across anything like this, but then I’ve never used the SPI model. Is it a specific change that breaks the chip? And I believe the DMP code is just stored at the end of the main volatile register block, and I don’t think it would modify the raw values.

  7. Hi, I’ve seen your code for your quadrocopter project. Why did you use complementary filtering again? Doesn’t the DMP Data Fusion feature from the MPU6050 already do the filtering for you? As in, fusing the datas from the gyroscope and accelerometer?

    Thanks.

    • Yes, if you can get the DMP working it should take care of all of the sensor fusion. However, at the time of writing this there was very little documentation on how to use the DMP feature, with only a handful of people being successful. This may not be the case anymore, I haven’t checked in a while.

      • I don’t know the connection for MPU6050 with Arduino…and get the error=2 when running the simple Arduino code for MPU6050…

        Please help me with the connection…

  8. Hi, I can’t find any schematic for connect MPU-6050 to ATXmega 128, Can u help me.

    Regards.

    • I too don’t know the connection for MPU6050 with Arduino…and get the error=2 when running the simple Arduino code for MPU6050…

      Please help me with the connection…

  9. What kind of microcontroller are you using? We are going to use 8051, just for study and test. We are done for test WHO_AM_I, but we are trying to read another regesters but not success. Any suggestion for that?

  10. can you plese help me im running the code on lpc 1768 but the chip gives me a proper read once then dosent respond

  11. Hey!! Thanks for your information. I’m sort of a rookie on this area and tryna figure out what memory adresses is all about was kinda of confusing for me but at the end of the day I guess my basic background programming skills helped me out.

    Truth be told I was following another steps given in the arduino forum. I got this MPU6050 based on the GY-521 die, I don’t know if you’ve seen the Jeff Rowberg website (https://github.com/jrowberg/i2cdevlib/tree/master/Arduino/MPU6050), hopefully yes, not tryina understimate your work, which seems to be really great!! Though I haven’t tested yet.

    There are codes and libraries in there, but this is what I did: Created the directory for the MPU6050 and I2Cdev into the Arduino/Libraries setup directory, but as I’m tryna get a 3D visual demonstration of the board motion I ran the MPU6050_DMP6.ino code and the displayed error (‘Quaternion’ does not name a type) is something I’ve been having troubles with for the last hours. Certainly is something about a missing library in the arduino directory, the thing is I don’t know which other library I need to add in order to get this code working. is it possible to create a sortof library directory with just one file in it (.h)?

    If you have seen this site , could you give me the steps to run the Processing sketch in the site? I mean the way of linking arduino sketch to Processing 3D sketch.

    Or even better, is there anyway of linking your code to a Processing sketch? Cause I really need to see the board’s motion to see if it working good.

    Regards

    Rodolfo

  12. Hej

    I was wondering if anyone can do raw log on 6 axes and tell me how many samplets you can get per second. I need to log at 500 samples per second and Python is not cutting it.

  13. Hello Admin 🙂
    the Gyro Regs contrain a 16bit 2’s complement answer
    so amm how do i get a signed value of the same?

  14. Hi, I am having a few issues running the code. Sometimes when I run I get master bit collisions. Also, when ever I write to any of the registers I do not get anything back when I read the sensor data. If you have ran into and found any solutions for any of these issues, please let me know.

  15. Sir,
    i am using your code as a baseline
    the problem is
    /////

    GYRO_XOUT_H=mpu_6050_read(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_H);
    GYRO_XOUT_L=mpu_6050_read(MPU6050_ADDRESS, MPU6050_RA_GYRO_XOUT_L);

    GYRO_XOUT = ((GYRO_XOUT_H<>8); lcd_data_raw(output_temp);}
    else
    { lcd_data(‘+’);
    // GYRO_XANGLE += GYRO_XRATE *dt;
    lcd_data_raw(GYRO_XRATE>>8);
    lcd_data_raw(GYRO_XRATE);
    }

    ///
    when i do this and out put the content to the LCD, i get the sensitivity only for one side.
    if the gyro is placed in one place, only the left side movement is detected whenever it turned back it dosnt detect that movement 🙁

  16. Hi, i’m using the library that you posted here (very well explained by the way) and i keep receiving the error message of the MPU6050_Test_I2C() function, i’ve tried to print the value of the WHO_AM_I register but all i get is 0. This means that i’m not being able to communicate correctly with the device, i think. Do you know why i’m receiving this message, or how can i solve it ?

    I’m using a dspic30f4011. I’ve made all the changes in the library to fit in this uC.

    Pre-thanks 🙂

    • A read of 0 basically means the MPU isn’t talking back. I’d get your I2C lines up on a digital storage oscilloscope and follow each read attempt through bit by bit until you find the error.

      • Hi, thanks I solved the last problem. But there is another one, when you integrate the measurements of the gyroscope to find the roll and pitch angles an error is accumulated. What do you do to eliminate this error ?

        • You use accelerometer data to estimate the bias. The most basic method I know of is the complementary filter, but a kalman filter is far far better.

  17. Hi,
    I follow ur tutorial. I was able to read the WHO AM I register and display 104 which is equal to 0x68. But somehow when I try to read others register, for example SMPLRT_DIV. The return value should be 0x01 but all I get was 0. Same case go to CONFIG, GYRO_CONFIG and ACCEL_CONFIG. The return value are all 0.

    Is it that I couldn’t successfully write into the register ?

    Regard
    Lin

    • If you’re able to read one register you should be able to read all of them. I would guess it’s now your write routine that is not working correctly.

      • I’m using PIC18F4550. I have solve the writing problem. If I may ask, I’m doing project micromouse. When there are no movement of the motor, everything went well. The moment the motor move, the whole PIC freezes. From what I interpret it, the motor somehow cause the PIC to miss out the ACK bit. Is that possible ? If it is how could I solve it, in the software part ?

        • Hi,
          I am getting the same problem.i.e.I can read who_am_I register. But when I try to read config register, it shows 0. When I write to RA_PWR_MGMT_1 register, the device resets successfully. But, other config registers cannot be written unsuccessfully. Can you please, tell me any possible error I have made? That would be a great help.

        • I have no idea what a micromouse is, but it sounds like noise from your motor is getting into the PIC. Try running them off seperate power supplies, and keep any flying leads as short as possible.

        • – you should use optocoupler for save pic from noise generated by the motor.
          – i am use mpu6050 controlled by PIC16F877A. but it is not work properly. Can you help me

          • hi moosa! I have a mpu6050. I want to use for myquadcopter.I use PIC16F877 as process.I use CCS C program language.But I dont know how to use this sensor.which pin connect to PIC16F877.is the INT pin used? can you tell me which pin connect to where? wait your answer!!
            THANKS…

  18. Hi,
    I am getting the same problem.i.e.I can read who_am_I register. But when I try to read config register, it shows 0. When I write to RA_PWR_MGMT_1 register, I can read back the same data. But, other config registers cannot be written successfully, although handshaking seems to be correct. Can you please, tell me any possible error I have made? That would be a great help.

    • Make sure you are waking the device up from sleep mode as the first command, other than that im not sure.

      • hi admin! I have a mpu6050. I want to use for myquadcopter.I use PIC16F877 as process.I use CCS C program language.But I dont know how to use this sensor.which pin connect to PIC16F877.is the INT pin used? can you tell me which pin connect to where? wait your answer!!
        THANKS…

  19. hi,
    can i get help to interface msp430g2553 launchpad with mpu6050 using i2c communication..thank you

  20. I have bought a IMU model GY-521 with MPU6050. I have read through your blog regarding the setup but I dont understand since my knowledge in registers is low. I wish you can help me in setting it up with a PIC16F877A and an LCD. I hope to hear from you soon!

  21. How do you run check the communication? Where do you actually print these out,
    printf(“\nI2C Read Test Passed, MPU6050 Address: 0x%x”, Data);
    printf(“ERROR: I2C Read Test Failed, Stopping”);

    • printf just prints data to stdout, which can be pointed anywhere. In my case I had these results outputting over a serial port, but you could easily change them to a different output.

      • Hi,
        Great tutorial and I have been able to read raw accel and gyro data from mpu6050 using pic16f877a. Just a simple question, when calculating gyro angle, you figured out the offset value first and then subtract that from raw data. But in case of accelerometer you have not considered the offset value. Could you please tell me the reason behind it. If you look at the tutorials of other analog accle and gyro sensors on the web you will find almost all of them considered offset value for both accel and gyro which is specified on the respective datasheet. But in case of mpu605 there is no mention of the offset value on the datasheet. Please help me out on this issue.

  22. Hi,
    Great tutorial and I have been able to read raw accel and gyro data from mpu6050 using pic16f877a. Just a simple question, when calculating gyro angle, you figured out the offset value first and then subtract that from raw data. But in case of accelerometer you have not considered the offset value. Could you please tell me the reason behind it. If you look at the tutorials of other analog accle and gyro sensors on the web you will find almost all of them considered offset value for both accel and gyro which is specified on the respective datasheet. But in case of mpu605 there is no mention of the offset value on the datasheet. Please help me out on this issue.

    • hi sagar! I have a mpu6050. I want to use for myquadcopter.I use PIC16F877 as process.I use CCS C program language.But I dont know how to use this sensor.which pin connect to PIC16F877.is the INT pin used? can you tell me which pin connect to where? wait your answer!!
      THANKS…

  23. -i am use mpu6050 with controller PIC16F877A.
    -only mpu6050 address is got but x,y,z coordinate value is not meet.
    -reply must
    -i am in trouble.
    main:

    HBusIn $68,$75,[var2]
    SerOut PORTB.1,16468,[“MPU6050 Address”,HEX3 var2,13,10]

    If var2=$69 Then
    GoTo main1
    Else
    GoTo main
    EndIf
    main1:
    var1[0]=HBusIn $68,59
    var1[1]=HBusIn $68,60
    var1[2]=HBusIn $68,61
    var1[3]=HBusIn $68,62
    var1[4]=HBusIn $68,63
    var1[5]=HBusIn $68,64
    var1[6]=HBusIn $68,65
    var1[7]=HBusIn $68,66
    var1[8]=HBusIn $68,67
    var1[9]=HBusIn $68,68
    var1[10]=HBusIn $68,69
    var1[11]=HBusIn $68,70
    var1[12]=HBusIn $68,71
    var1[13]=HBusIn $68,72
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[0],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[1],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[2],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[3],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[4],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[5],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[6],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[7],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[8],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[9],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[10],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[11],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[12],13,10]
    SerOut PORTB.1,16468,[“gyrox=”,HEX3 var1[13],13,10]
    DelayMS 100
    GoTo main

  24. i used your code, well the problem is i m not getting a full scale reading it runs from 0-70 and then once 70 is crossed it startsback from 0 running upwards.
    is there a problem in the datatypes? i m using an ARM7 core not a PIC.
    so i defined the accel_xangle from short to
    float ACCEL_XANGLE=0;
    float ACCEL_YANGLE=0;
    float ACCEL_ZANGLE=0;
    the final output runs from
    UART OPened

    43.936077
    43.936077
    43.936077
    43.936077
    43.946705
    0.000000
    0.000000
    0.000000
    0.000000
    0.000000
    52.221012
    52.221012
    52.221012
    52.221012
    10.327014
    0.458355
    0.458355
    0.458355
    0.458355
    1.608110
    1.601568
    1.601568
    1.601568
    1.601568
    48.682564
    48.682564
    48.682564
    48.682564
    48.682564
    50.614784
    50.614784
    50.614784
    50.614784
    41.772911
    40.713997
    40.713997
    40.713997
    40.713997
    42.806427
    41.262611
    41.262611
    41.262611
    41.262611
    31.450274
    30.625662
    30.625662
    30.625662
    30.625662
    15.112180
    15.112180
    15.112180
    15.112180
    15.112180
    3.714080
    3.714080
    3.714080
    3.714080
    3.714080
    86.658218
    86.658218
    86.658218
    86.658218
    86.231476
    86.159668
    86.159668
    86.159668
    86.159668
    86.595306
    86.567787
    86.567787
    86.567787
    86.567787
    86.975822
    87.055061
    87.055061
    87.055061
    87.055061
    87.477837
    87.477837
    87.477837
    87.477837
    87.477837
    88.619553
    88.619553
    88.619553
    88.619553
    88.619553
    43.262848
    43.262848
    43.262848
    43.262848
    43.378071
    43.372250
    43.372250
    43.372250
    43.372250
    34.327156
    34.602116
    34.602116
    34.602116
    34.602116
    35.193279
    45.811733
    45.811733
    45.811733
    45.811733
    46.509136
    46.508396
    46.508396
    46.508396
    46.508396
    46.959320
    46.959320
    46.959320
    46.959320
    46.959320
    0.936492
    0.936492
    0.936492
    0.936492
    0.928713

    the code is urs as a base.

  25. Hello Sir,
    i am stuck on the PID values, must say u have an awesome library linked here.
    any suggestions for what values to use for the PID?
    or any ways of what to go about in choosing values? 😕

    • not sure which PID controller you are referring to, but generally increase P until it responds nicely, then start increasing D to reduce the overshoot, then finally increase I to remove any offset.

      • hi! I use mpu 6050 and PIC16F877.I use CCS C as software language.there is a problem at comunication.can you help me..

        • With that amount of detail, no, there is no way I or anyone else can help you.

          • Hi,
            could you please tell me why the accelerometer offset value is not considered when calculating angle from the accelerometer. But you have considered the gyro offset value calculated during gyro calibration process. A prompt answer is appreciated..

          • At the time of writing this I did not know an accurate method for calculating the accelerometer bias, whereas the gyroscope bias is measured by just logging some data with it stationary. However, if you are going to implement any sort of gyroscope bias estimation you can omit this segment, as the bias is removed at a later stage.

          • Hi admin,
            Thank you for your reply. That was really quick. My problem is I have been able to read raw accel data from mpu6050 using pic16f877a. But when I want to calculate the angle using the accelerometer using the atan formula you gave, that angle would not be correct as the raw accelerometer data is not in “g” unit. So how can I calculate 3 axis in “g” using only accelerometer. I know the process for analog accel which is “value = (raw data – offset)/sensitivity”, but not for digital accel like mpu6050 where the raw data is 16 bit. Please advise me.
            Thank you.

          • The data is stored in 2s complement format. Just store it in a signed 16 bit integer, scale it correctly, and you are good to go. Also, the atan function doesnt care about the scaling of the input measurements, as atan(x/y) returns the same as atan(2x/2y).

          • Thank you very much.

  26. How do you store the accel data in 2s complement format in a signed 16 bit integer. And I am currently using arduino software and reading your post as a guide? Can I follow it as a guide? or no? And if I I wanted to get the velocity, I will be using the accelerometer value right?

  27. Admin,in my pic18f452
    ACCEL_XOUT = ((unsigned int) ACCEL_XOUT_H<<8 l ACCEL_XOUT_L)
    it will be ok.

  28. Thank you Admin.

  29. Hello. I am new to using IMU and I am trying to use the gy 521 with the MPU-6050 chip. Every time I try and use the above code I get “sketch_jun12a:4: error: ‘MPU6050_ADDRESS’ was not declared in this scope” help

  30. That is an awesome resource. But I am new for microcontroller. I am using MSP430G2553 by using CCS as my IDE. What header file must be included in order to invoke the LDByteRead() function?
    Thanks!

  31. Hi everyone,
    I just have a quick question about the MPU.

    I’ve been trying to use the MPU6050 with the arduino and I am able to read from the accel and gyro values fine.

    I used the example code from http://playground.arduino.cc/Main/MPU-6050

    But the weird thing is that the values of x,y,z from the accel seem to always be fixed values when the chip is left unmoved. This is as if the values are actually vector orientations as opposed to changes in accelerations.

    I am not sure if this is because of some setting or if thats what the values actually mean and was wondering if anyone has any ideas?

    Thanks!

  32. -i am use mpu6050 with controller PIC16F877A.
    -mpu6050 gives readings
    -compiler proton ide
    -in proton ide
    -variables types as follow.

    DIM Dog AS BYTE ‘ Create an 8-bit unsigned variable (0 to 255)
    DIM Cat AS BIT ‘ Create a single bit variable (0 or 1)
    DIM Rat AS WORD ‘ Create a 16-bit unsigned variable (0 to 65535)
    DIM Large_Rat as DWORD ‘ Create a 32-bit signed variable (-2147483647 to +2147483647)
    DIM Pointy_Rat as FLOAT ‘ Create a 32-bit floating point variable

    – “I don’t have signed 16-bit variable.”
    -How can i use this equation
    ACCEL_XOUT = ((ACCEL_XOUT_H<<8)|ACCEL_XOUT_L);

  33. sir….
    i m designing a quadcopter, i have used ur dmp library from github…..it works fine…shuld i use kalman filter now or its enough…..and which parameter shuld i feed to PId…queterenion,EUler or other as angle

  34. I really liked the tutorial specially fast response.
    please tell me which software has to preferred for mpu6050 simulation, to get all the details and readings.
    Thank You.

  35. how to get values from DMP. ?? pls help me…..
    am using CCS as IDE and concerto [f28m35h52c1]

    now i can able to read Accelerometer,gyro,magneto values but i dnt have any idea about motion algorithm and DMP so pls help me……

  36. Hello,
    I’have a problem to determine whether I need voltage levels shifting or not,
    while my board with MPU-6050 has +5V power supply and +3.3V too,
    but Im’m not sure: can I use 5V I2C bus (with my ATTiny85) or have to do mentioned voltage levels shifting (using 2 mosfets) as detailed in NXP application note for I/O of MPU-6050 on SDA and SCL at VLogic 3.3V?
    Whis is my MPU-6050:
    http://s5.postimg.org/6h2add5yf/MPU6050.jpg
    Does MPU-6050 is 5V I2C bus tolerant device or not and max SDA/SCL voltage is 3.3V?
    Do you use 3.3V i2C bus with MPU-6050?

    I have no schematics of this MPU-6050 board.
    It has +5V or +3.3V power, ADO setting, SDA, SCL and XDA i XCL for compass module I guess…
    I should talk with MPU-6050 via SDA and SCL I guess, but is it possible at +5V I2C bus,
    while I will power it up using this +5V pin?
    It has builtin LDO for internal 3.3V when powering from 5V pin…

    Regards.

    • I have a feeling that board may already contain pullup resistors between the SDA and SCL lines and the 3.3v rail, grab a multimeter and measure the resistance between those two points. If not, you will probably find the ATTiny85 can function just fine with 3.3v I2C, so just add some 1.8Kohm pullup resistors between SDA and SCL and the 3.3v rail.

      • Thank you for some hints how to deal with it.
        Do you mean measure the resistance between SDA and SCL?
        So, if connected to common supply voltage (3.3V) via pullups I should have some values in k Ohms…
        And you are right 🙂
        It has builtin 4.7k pullups beetween SDA/SCL and 3.3V power supply and about 9.4k beetween SDA and SCL.
        So, now only is question if this device is 5V tolerant, but I do not want to gamble and MPU-6050 datasheet as I remember says nothing about 5V inputs…
        I guess you did not used MPU-6050 with 5V I2C bus, but 3.3V ?
        If nobody used it with 5V logic I will try to do this voltage level shifting withg 2 mosfets in final environment (as described by NXP in this application note: http://ics.nxp.com/support/documents/interface/pdf/an97055.pdf) also to protect it from other I2C devices and make compatible with 5V I2C bus.

        Now, I hope I will be able to talk with this MPU-6050 using self-made optoisolated (5kV) RS232 (DE9) I2C interface, where I can set another I2C bus to any voltage level, while testing this from PC with Linux using native system calls to bypass serial port protocol and use its 5 pins for raw SDA/SCL I/O and PC side 5V power supply of this unit.

        I’d like to have PC I2C versatile interface (under Linux with C source code and I2C library) with PC LCD touch screen gathering, processing, loging and display compact information from many I2C devices, among others this MPU or run my PC as I2C slave with big LCD accessible by master ATTiny85 or other AVR.
        I will try first read MPU-6050 built in temperature sensor and then try to use it in DMP mode for automatic hardware sensor fusion.

  37. hola excelente tutorial!
    estoy trabajando con este sensor MPU6050, pero necesito controlarlo mediante una spartan 3e, me podrían ayudar con el código en lenguaje vhdl.

  38. how to get values from DMP. ?? pls help me….. am using CCS as IDE and concerto [f28m35h52c1] now i can able to read Accelerometer,gyro,magneto values but i dnt have any idea about motion algorithm and DMP so pls help me……

    • Look at this i2cdevlib MPU-6050 DMP6 example:
      jrowberg-i2cdevlib-e2fa9a6-20131008/Arduino/MPU6050/Examples/MPU6050_DMP6/MPU6050_DMP6.ino
      This is part of this file:
      >>>>>>>>>>>
      // MPU control/status vars
      bool dmpReady = false; // set true if DMP init was successful
      uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU
      uint8_t devStatus; // return status after each device operation (0 = success, !0 = error)
      uint16_t packetSize; // expected DMP packet size (default is 42 bytes)
      uint16_t fifoCount; // count of all bytes currently in FIFO
      uint8_t fifoBuffer[64]; // FIFO storage buffer

      // orientation/motion vars
      Quaternion q; // [w, x, y, z] quaternion container
      VectorInt16 aa; // [x, y, z] accel sensor measurements
      VectorInt16 aaReal; // [x, y, z] gravity-free accel sensor measurements
      VectorInt16 aaWorld; // [x, y, z] world-frame accel sensor measurements
      VectorFloat gravity; // [x, y, z] gravity vector
      float euler[3]; // [psi, theta, phi] Euler angle container
      float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector
      <<<<<<<<<<<<>>>>>>>>>>
      WARNING: Updating internal MPU-6050 sensor offsets…
      CONFIG: Calibration accel offsets: aXo: -2042 aYo: 3129 aZo: 1200
      CONFIG: Calibration gyro offsets: gXo: 0 gYo: 0 gZo: 0

      INFO: MPU-6050 temperature: 22.08 [*C]

      INFO: MPU-6050 accelerometer: 12568 8324 -9232 |17676.918|

      INFO: MPU-6050 gyroscope: -177 198 98 |283.085|
      <<<<<<<<<<<<<<<
      Now it is time to read some quaternion from MPU-6050 in DMP6 mode, and it will NOT be easy port to my PC Linux C (AVR is a target device).

  39. Hello, I’ve successfully run MPU6050 directly from my PC Linux using custom RS232 optoisolated I2C self made board.

    I’ve run for tests setup from this page, but only changed clock source to gyro X (gyro Y in this example while you are writting 0b00000010).
    >>>>>>>>>>>>>>
    int mpu6050_setup(unsigned char addr) {
    ….
    //Sets clock source to gyro X axis reference w/ PLL
    mpu6050_register_set(mpu_addr, MPU6050_RA_PWR_MGMT_1, 0b00000001);
    ….
    }
    <<<<<<<<<<<>>>>>>>>>>>
    MPU-6050: i: 5 t: 23.12 [*C] a: 12096 9184 -8548 |17427.776|

    MPU-6050: i: 6 t: 23.12 [*C] a: 12208 9276 -8572 |17565.837|

    MPU-6050: i: 7 t: 23.12 [*C] a: 12208 9232 -8636 |17574.003|

    MPU-6050: i: 8 t: 23.12 [*C] a: 12240 9284 -8752 |17680.717|

    MPU-6050: i: 9 t: 23.12 [*C] a: 12272 9300 -8680 |17675.814|

    MPU-6050: i: 10 t: 23.12 [*C] a: 12276 9184 -8660 |17607.999|
    <<<<<<<<<<<<<<
    But when calculated acceleration vector length it looks like it is not about 16384 average as i could expect ( 1g in +/-2g accel setup).
    MPU-6050 is not moveing as all.

    Do we need setup some offsets how explained below or measure those acceleration 3 axis offsets and update raw data read from MPU-6050?
    ?
    BTW DMP functions used there to remove gravity component:
    http://www.i2cdevlib.com/forums/topic/25-mpu-6050s-linear-acceleration-is-way-off/

  40. Please help if some one knows to use the STM32F4 instead of PIC.
    Please post the link. Aprreciated and thanks a lot

  41. Hello,

    I’m using MPU6050 IMU, i want to read all accelerometer’s axis values and also all gyrometer’s axis values. I’m using Keil MCB4357 Evaluation Board. The microcontroller model is LPC4357 but I can’t read out axis values can anyone help me to write i2c procedure to read values from accelerometer & gyrometers

    Thanks Tou

  42. sorry i made mistake for writing thanks you

  43. Hello,

    I’m having some problems with the gyroscope of the mpu6050.
    The raw data from for example the X axis has a weird output when holding the mpu6050 horizontal and not moving it.
    -32768
    -29607
    -32768
    -32768
    -22464
    -32768
    -10723
    -32768
    -26697
    -32768
    -32768
    -26775
    -32768
    -17560
    -32768
    -32626
    -32768
    -30346

    Is this normal for the MPU6050? the data from my accelerometer is correct.
    is it possible that i need to calibrate the gyro?

    I hope someone can help me out…

  44. Hey I know this is off topic but I was wondering if you knew of any widgets I could
    add to my blog that automatically tweet my newest twitter updates.
    I’ve been looking for a plug-in like this for quite some time and was hoping maybe you would have
    some experience with something like this. Please let
    me know if you run into anything. I truly enjoy reading your blog and I look forward to
    your new updates.

  45. Hi,can you please give me an instance on how to define gyro sensitivies????i am working on stm32f407 board

  46. can anyone help me to configure the mpu6050. i’m using pic16f877a. is all the registers are need to be configured??? i only configured 4 register. i have read WHO_AM_I register and got 104 in decimal. can’t read the raw accl,gyro data.

    void mpu_setup()
    {
    //sets sample rate to 8000/(1+7)=1000Hz
    mpu_write(mpuadd_w,SMPLRT_DIV,0x07)

    //disable FSYNC ,256Hz DLPF
    mpu_write(mpuadd_w,CONFIG,0x00);

    //disable gyro self test, FS_SEL to 500dps
    mpu_write(mpuadd_w,GYRO_CONFIG,0x08);

    //disable acc. self test, AFS_SEL to +-2g
    mpu_write(mpuadd_w,ACCEL_CONFIG,0x00);
    }

    • You need to look at the PWR_MGMT registers (0x6B and 0x6C)

      the 0x6B is in sleep mode when powered up, You have to write 0x00 to 0x6B, to turn off sleep mode.

  47. I just have a question. With this line:

    //Enable data ready interrupt
    LDByteWriteI2C(MPU6050_ADDRESS, MPU6050_RA_INT_ENABLE, 0x00);

    Do you want to enable the interrupt? this worked for you?. I thought it should be with 0X01 in order to enable it, am i wrong?

    Thanks for your help!

  48. how many times do we have to run the calibrate_gyro method? Only at the start or at every cycle?

  49. Hello MATT I’m running your code on my PIC32MX795f512l
    what will be the STRICT bit in control register of I2C be ; should it be set(1) or left 0

  50. PLEASE MATT check the registers set below in my code according to PIC32MX795F512l..

    void Setup_I2C(void) // kept in consideration by Muneeb http://ww1.microchip.com/downloads/en/DeviceDoc/80000480N.pdf
    {
    TRISAbits.TRISA14 = 1; //According to Muneeb’s controller the pins are at port A(
    TRISAbits.TRISA15 = 1;
    //This function will initialize the I2C(1) peripheral.

    //Set the I2C(1) BRG Baud Rate.
    //(((1/400KHz)-130ns)x40MIPs)-2 = 93
    I2C1BRG = 39; //(according to Muneeb’s controller and calculation using 36Mhz as FPB)

    //Now we will initialise the I2C peripheral for Master Mode, No Slew Rate
    //Control, SMbus levels, and leave the peripheral switched off.

    I2C1CONbits.ON = 0;//done by Muneeb according to Pic32 datasheet
    I2C1CONbits.SIDL = 0;//done by Muneeb according to Pic32 datasheet
    I2C1CONbits.SCLREL = 1;//done by Muneeb according to pic32 datasheet
    I2C1CONbits.STRICT = 1;//done by Muneeb according to PIC32 datasheet
    I2C1CONbits.A10M = 0;// done by Muneeb according to PIc32 datasheet
    I2C1CONbits.DISSLW = 1;//done by Muneeb according to Pic32 datasheet
    I2C1CONbits.SMEN = 0;// done by Muneeb according to pic32 datasheet
    I2C1CONbits.GCEN = 0;//done by Muneeb acording to Pic32 datasheet
    I2C1CONbits.STREN = 0;//done by Muneeb according to pic32 datasheet
    I2C1CONbits.ACKDT = 0;//done by Muneeb according to PIC32 datasheet
    I2C1CONbits.ACKEN = 0;//done by Muneeb according to PIC32 datasheet
    I2C1CONbits.RCEN = 0;//done by Muneeb according to PIc32 datasheet
    I2C1CONbits.PEN = 0;//done by Muneeb according to Pic32 datasheet
    I2C1CONbits.RSEN = 0;//done by Muneeb according to Pic32 datasheet
    I2C1CONbits.SEN = 0;//done by Muneeb according to Pic32 datasheet

    //Clearing the recieve and transmit buffers
    I2C1RCV = 0x0000;
    I2C1TRN = 0x0000;

    //Now we can enable the peripheral
    I2C1CONbits.ON = 1;

    // printf(“\nI2C Setup Complete”);
    }

    unsigned int StartI2C(void)
    {
    //This function generates an I2C start condition and returns status
    //of the Start.

    I2C1CONbits.SEN = 1; //Generate Start Condition
    Nop();
    while (I2C1CONbits.SEN); //Wait for Start Condition
    //return(I2C1STATbits.S); //Optionally return status

    }

  51. Is the control register set fine in the above code or please indicate any changes required!

  52. bit 9
    DISSLW: Slew Rate Control Disable bit
    1 =Slew rate control disabled for Standard Speed mode (100 kHz); also disabled for 1 MHz mode
    0 =Slew rate control enabled for High Speed mode (400 kHz)

    Ive set the baudrate according to 400khz operation so is DISSLW be 1 or 0 in my case???

  53. dear MATT ,
    FOR PIC32MX795F512L

    what should be the MPU6050_ADDRESS??

  54. MATT;
    why use 0XD2 as the MPU6050_ADDRESS ?
    why not 0xD0 ?

  55. Hi man, first, thanks you for sharing this, I have a doubt, when you make the average of the offset in the gyro (GYRO_XOUT_OFFSET), You run a function with 1000 interations, Do you have the sensor on a static position? Near to zero or in wich position you have the gyro when you determinate this offset? Thanks for your time

  56. Hi, i was wondering how do you get the MPU6050_ADDRESS 0b11010010 (0xD2)?? isn’t it suppose to be 0x68??
    i’m new to arduino programming, i m having a hard time finding these kind of info
    thanks

  57. am using mpu6050 interfaced with msp430g2553 so am unable to get idea where do i see the output?????? can u please help me out….

  58. Hi,
    Can anybody help me to get the stable values while mpu-6050 is in static position.
    I am using the code from Jeff Berg. However, I am not getting the values 0,0,0 while sensor in static mode.
    I also tried to change the offset values but could not find the result.
    Similar is the case with calculation of Euler angles.

    Urgent help would be appreciated in this regards.

  59. Can anyone please tell me the operating frequency of this module i.e. how soon I get a new data?

  60. Hai Everyone,

    I am trying to read Data from mpu6000 throgh I2C protocal by using PIC24FJ256GP210. I am getting Acknoledgement From slave but I am not getting data of “who am i ” register. I am at start up stage.

    Can anyone send how to read that register?

    How we can put start and stop conditions on bus?

  61. Thanks for this article, it help lot! Here is my first demo with MPU – 6050 + Arduino UNO with DC motors.
    https://www.youtube.com/watch?v=EbIGiKwFj3c

    • Congrats, glad it helped!

      • Dear Matt,

        What is the dt value in this line : GYRO_XANGLE += GYRO_XRATE*dt;

        I found u declared it #define dt 0.0025 in main.c. Will it be 1/500 (Sampling rate) Or it would 1/400 timer1 interrupt rate? Please answer. and Thank u vary much for ur hard work. I am converting it to ProtonBasic (Pic 18F4431). and i will declare ur name top of the code.

  62. Hi admin!
    iw want to interface PIC18F452 with MPU6050…and want to make a project using Camera 4DOF..plz help m begginer in this project…even no basic idea of programming…plz help me

  63. Hi, I have an MPU6050 with the funny effect that if I set the gyro range (bits 3 and 4 (FS_SEL[1:0])) in register 1b and read back that register, I get zero. It doesn’t matter what I wrote into bits 3 and 4, I get zero back. And the gyro seems to be be running as if zero, at 250 deg/s max.
    I do not suspect my I2C code in general. The same read-after-write check goes okay with other registers. Did somebody else experience this?

  64. Has anyone gotten the MPU-6500 or 6000 working over SPI. I have been trying with the 6500 for a few days with no success to interface with an MSP430F5152. I still have been unable to get a Who Am I response. It looks like most people are using I2C.

  65. salam ….
    i am using MPU6050 sensor , i have a problem …..
    how can i change the sensitivity of accelerometer and gyro ? if it is possible with help of registers values then plz tell me in detail how can i change ?

  66. If some one is interested and wants a simple implementation of MPU6050, they can also have a look at this simple Library,
    http://hobbylogs.me.pn/?p=47
    It also explains angle calculation combining gyroscope and accelerometer measurements to avoid drift problem.

  67. Hi I have connect my MPU6050(GY-521) directly to my PIC24FJ64GA002 I2C pin and the AD0 pin of MPU6050 is connected to Vdd. I expected the value 0x69 when read WHO_AM_I register instead i recieve 0x68. When i connect AD0 to GND and read WHO_AM_I register receive 0xff value. How is it possible? Can any one help?

    • Good question, this caught me out too. It turns out the who_am_I register always returns 0x68, regardless of the state of the ad0 pin, so don’t worry.

      • Thank you for the response. This thing was freaking me out.
        How is this possible? When i connect the MPU6050 on an Arduino Uno the state of AD0 pin make the WHO_AM_I register return 0x69 when is high and 0x68 when is low. Maybe the Schmitt Trigger input of the PIC24FJ64GA003 do something weird. The Arduino don’t have it.

  68. Hi,

    I was trying to write to my registers, it seems I need to actually wake the device up by setting the power management 1 register before it would take any of the other register values I was trying to set. Is this what you found as well because I could not see that any where in your tutorial?

  69. Thanks for a very useful resource.

    Im talking to the 6050 fine – I can write X to register Y and when I read Y, I get X back.

    When I read the ACCEL OUT registers I get numbers that look OK. But when I read them again, I get the same numbers. If I cycle the power, I get different numbers but they don’t change.

    I can also get new numbers by writing to various registers, e.g.:
    reg 6B to select a new clock source
    reg 1A set the FSYNC Bit Location to 0 = Input disabled
    reg 3A INT_STATUS write 0 to it (but it’s read-only!)
    reg 68 write to 0 it but not if I write 7 to it
    reg 6S set then clear the SIG_COND_RESET bit

    So it looks like the accelerometer registers don’t get refreshed automatically. Surely that’s not right? Shouldn’t I just read them repeatedly?

    (The gyro is similar.)

    Thanks

    Peter

    • I’m currently using the MPU in a different project and the only register I’m changing before attempting to read sensor data is I’m switching the clock source to the X gyro PLL, you could try that?

      • I think I understand what you’re suggesting.
        I set up the registers as in the Setup_MPU6050 code shown above.
        I do 4 successive reads (1 per sec) of the accelerometers (regs 0x3B to 0x40) and I get

        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C

        note how these are plausible values.

        The I write 0x01 to reg 0x6B (Power Management 1).

        I do 4 successive reads of the accelerometers and I get

        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C
        FF E8 FB 98 40 6C

        I get the same values.

        The I write 0x00 to reg 0x6B (Power Management 1).
        I do 4 successive reads of the accelerometers and I get

        FF D0 FB 58 40 08
        FF D0 FB 58 40 08
        FF D0 FB 58 40 08
        FF D0 FB 58 40 08

        These are a different set of values. Maybe the difference is noise.

        It’s as though by writing 0x00 to reg 0x6B, I triggered a read an accelerometer measurement.

        It’s as though the sample-clock just isn’t running.

        Peter

        • Thinking about it further …

          Reading an ACCEL OUT register gives me the last accelerometer measurements written into the “user-facing read register”.

          Accelerometer measurements are written into the “user-facing read register” when “the serial interface is idle”.

          But what does “the serial interface is idle” mean? It seems to mean that the 6050 must have seen a Stop on the I2C interface.

          So you must put a Stop after the last read of an ACCEL OUT register. I wasn’t doing that.

          I’m reading each ACCEL OUT register as a single-byte read. So I mustn’t put a Stop after the first 5 reads. But I must put a Stop after the last read.

          I don’t see how the sample code above does that.

          I guess I’d better learn how to do multi-byte reads.

          Peter


Leave a comment