I'm trying to write a driver for the MPU-6050 and I'm stuck on how to proceed regarding reading the raw accelerometer/gyroscope/temperature readings. For instance, the MPU-6050 has the accelerometer X readings in 2 registers: ACCEL_XOUT[15:8] at address 0x3B and ACCEL_XOUT[7:0] at address 0x3C. Of course to read the raw value I need to read both registers and put them together.
BUT
In the description of the registers (in the register map and description sheet, https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf) it says that to guarantee readings from the same sampling instant I must use burst reads b/c as soon as an idle I2C bus is detected, the sensor registers are refreshed with new data from a new sampling instant. The datasheet snippet shows the simple I2C burst read:
However, this approach (to the best of my understanding) would only work reading the ACCEL_X registers from the same sampling instant if the auto-increment was supported (such that the first DATA in the above sequence would be from ACCEL_XOUT[15:8] @ address 0x3B and the second DATA would be from ACCEL_XOUT[7:0] @ address 0x3C). But the datasheet (https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf) only mentions that I2C burst writes support the auto-increment feature. Without auto-increment on the I2C read side how would I go about reading two different registers whilst maintaining the same sampling instant?
I also recognize that I could use the sensor's FIFO feature or the interrupt to accomplish what I'm after, but (for my own curiosity) I would like a solution that didn't rely on either.
I also have the same problem, looks like the documentation on this topic is incomplete.
Reading single sample
I think you can burst read the
ACCEL_*OUT_*
,TEMP_OUT_*
andGYRO_*OUT_*
. In fact I tried reading the data one register at once, but I got frequent data corruption.Then, just to try, I requested 6 bytes from
ACCEL_XOUT_H
, 6 bytes fromGYRO_XOUT_H
and 2 bytes fromTEMP_OUT_H
and... it worked! No more data corruption!I think they simply forgot to mention this in the register map.
How to
Here is some example code that can work in the Arduino environment.
These are the function that I use, they are not very safe, but it works for my project:
At this point, you can simply read the values in this way:
Warning!
Looks like this cannot be done for other registers. For example, to read the FIFO_COUNT_* I have to do this (otherwise I get incorrect results):
Reading the FIFO
Looks like the FIFO works differently: you can burst read by simply requesting multiple bytes from the
FIFO_R_W
register and the MPU6050 will give you the bytes in the FIFO without incrementing the register.I found this example where they use
I2Cdev::readByte(SAD, FIFO_R_W, buffer)
to read a given number of bytes from the FIFO and if you look atI2Cdev::readByte()
(here) it simply requests N bytes from the FIFO register:How to
This is simple since the FIFO_R_W does not auto-increment:
Warning!
FIFO_size()
is very slow!Hope it helps ;)