I have been playing around with MPU6050 for at least 6 years now. The tri-axis gyroscope and accelerometer MEMS is one of the cheapest IMU sensors available in the market. I wrote a Kalman filter library in Python[1] as a sensor fusion algorithm for this sensor in 2018 targeting Raspberry pi.
It was not until recently did I go through the datasheet[2] and register map[3] of the MPU6050 module in depth to leverage all that it has to offer for one of my research projects[4]. Two important features of the module on top of the sensors it hosts inside it, are the FIFO buffer and interrupt pin.
Figure 1. FIFO buffer in MPU6050[2]
Figure 2. FIFO ENABLE Register — 0x23[3]
A FIFO buffer of 1024 Bytes (1 KB) is available in the MPU6050 module (ref Figure 1) and the data to be written in the buffer is determined by the FIFO Enable register — 0x23 (ref Figure 2). FIFO buffer is populated by the sensor data in the ascending order of the selected data register addresses. For example if ACCEL_FIFO_EN bit and XG_FIFO_EN bit are set by writing 01001000 to the FIFO enable register, the data to the FIFO register will be written in the following order.
0x3B — ACCEL_XOUT_H
0x3C — ACCEL_XOUT_L
0x3D — ACCEL_YOUT_H
0x3E — ACCEL_YOUT_L
0x3F — ACCEL_ZOUT_H
0x40 — ACCEL_ZOUT_L
0x43 — GYRO_XOUT_H
0x44 — GYRO_XOUT_L
FIFO stack is updated as soon as it is read. For instance, in the given example, when FIFO is read once, ACCEL_XOUT_H data is removed from the buffer and ACCEL_XOUT_L data is pushed up. The amount of new data available to be read, can be found in registers FIFO_COUNTH — 0x72 and FIFO_COUNTL — 0x73. These registers too are updated after data is read from the FIFO buffer.
FIFO is really helpful when the data sampling frequency rate exceeds the data transfer rate. For example, consider 100 KHz, the speed of I2C bus in standard mode and data sampling rate of 1 KHz. It takes 9+9 = 18 bits including ACK bits to request data and receive data. Since each sensor data is 16 bit resolution, 16*6 = 96 bits are required and this is without taking into account, error correction and arbitration. In these cases, FIFO is used to reliably store data without losing them.
Figure 3. INT_PIN_CFG register [3]
Data ready interrupt pin goes low or high depending on the configuration of the INT_PIN_CFG register — 0x37, whenever a new data is written to the sensor data registers and so technically, at the frequency of data sampling rate. After the interrupt status register is read, the interrupt status goes back to 0.
Since data is written to the FIFO register, interrupt pin is redundant as polling for data from the FIFO register every 5 ms would do the job. However, setting up a physical interrupt feedback is the best rule of thumb in embedded systems and so I did.
I wrote an Interrupt Service Routine for the DATA_RDY_INT pin which reads the data from the FIFO. Here is the catch! As soon as data is written to the sensor data registers, interrupt pin goes low. However, data might not have been written to the FIFO. So, I wrote the following while loop in the data handler function to wait until FIFO count is equal to or more than 2, because in my project, I was only reading the data from X axis gyroscope.
fifo_count = get_fifo_count(&hi2c1);
while(fifo_count < 2){
fifo_count = get_fifo_count(&hi2c1);
}
With this code, after sometime (20 secs to 2 mins), the program would freeze. After some debugging, I found out that the program is stuck inside the while loop. Post some research, I found out that the SDA is held low by the MPU6050 due to consecutive reads of FIFO buffer count. This is not documented anywhere in the datasheet and I suspect is not an expected behavior.
So, I added a delay between FIFO count reads and voila, the problem was solved.
while(fifo_count < 2){
fifo_count = get_fifo_count(&hi2c1);
HAL_Delay(2);
}
I let the program run overnight and the system was still working properly the next morning.
[1] https://github.com/rocheparadox/Kalman-Filter-Python-for-mpu6050
[2] https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Datasheet1.pdf
[3] https://invensense.tdk.com/wp-content/uploads/2015/02/MPU-6000-Register-Map1.pdf