1
\$\begingroup\$

MPU6050 datasheet says that maximum accelerometer data output is 1Khz, so in theory when measuring time it takes to receive 1000 data samples through I2C, so I should receive all data in no less than 1 second, but somehow i always get sub 0.3 seconds.


Does CPU clock halts when waiting for data incoming from I2C slave?
How to have constant MPU6050 1khz output data rate, and measure it?

#include <wiringPi.h>
#include <wiringPiI2C.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define Device_Address 0x68 /* i2c-MPU6050*/

#define PWR_MGMT_1   0x6B
#define SMPLRT_DIV   0x19
#define CONFIG       0x1A
#define GYRO_CONFIG  0x1B
#define INT_ENABLE   0x38
#define ACCEL_XOUT_H 0x3B
#define ACCEL_YOUT_H 0x3D
#define ACCEL_ZOUT_H 0x3F
#define GYRO_XOUT_H  0x43
#define GYRO_YOUT_H  0x45
#define GYRO_ZOUT_H  0x47


int fd;

void MPU6050_Init(){

    wiringPiI2CWriteReg8 (fd, PWR_MGMT_1, 0x00);    /* Disable sleep mode*/
    wiringPiI2CWriteReg8 (fd, SMPLRT_DIV, 0x07);    /* 8khz/(1+7)=1khz */
    wiringPiI2CWriteReg8 (fd, CONFIG, 0x00);        /* FSYNC and DLPG_CFG disabled for maximum bandwith*/
    wiringPiI2CWriteReg8 (fd, GYRO_CONFIG, 0x00);   /* +- 200°/s, and acc by default +-2g's*/

    } 
short read_raw_data(int addr){
    short high_byte,low_byte,value;
    high_byte = wiringPiI2CReadReg8(fd, addr);
    low_byte = wiringPiI2CReadReg8(fd, addr+1);
    value = (high_byte << 8) | low_byte;
    return value;
}
void passtime(int uSeconds)
{


    // Storing start time 
    clock_t start_time = clock();  //time in microseconds. 

    // looping till required time is not achieved 
    while (clock() < start_time +uSeconds);


}

int main(){
    double time_spent = 0.0;


    float Acc_x,Acc_y,Acc_z;
    float Gyro_x,Gyro_y,Gyro_z;
    float Ax=0, Ay=0, Az=0;
    float Gx=0, Gy=0, Gz=0;
    fd = wiringPiI2CSetup(Device_Address);   /*Initializes I2C with device Address*/
    MPU6050_Init();                          /* Initializes MPU6050 */
    int count =0;
    passtime(10000);

    clock_t begin = clock();

    while(count<1000)
    {

        //Maximum output rate of MPU6050 is Accelerometer+Gyroscope = 1khz => 1 data read per milisecond 
        /*Read raw value of Accelerometer and gyroscope from MPU6050*/


        Acc_x = read_raw_data(ACCEL_XOUT_H);
        Acc_y = read_raw_data(ACCEL_YOUT_H);
        Acc_z = read_raw_data(ACCEL_ZOUT_H);

        Gyro_x = read_raw_data(GYRO_XOUT_H);
        Gyro_y = read_raw_data(GYRO_YOUT_H);
        Gyro_z = read_raw_data(GYRO_ZOUT_H);

        /* Divide raw value by sensitivity scale factor for +-2g's, and +-250/s */

        Ax = Acc_x/16384.0;
        Ay = Acc_y/16384.0;
        Az = Acc_z/16384.0;

        Gx = Gyro_x/131;
        Gy = Gyro_y/131;
        Gz = Gyro_z/131;



        //printf("\n Gx=%.3f \tGy=%.3f \tGz=%.3f \tAx=%.3f g\tAy=%.3f g\tAz=%.3f g\n",Gx,Gy,Gz,Ax,Ay,Az);

        count++;

    }


        clock_t end = clock();

        time_spent += (double)(end-begin)/CLOCKS_PER_SEC;

        printf("Time spent %lf after %d data reads\n",time_spent,count);

    getchar();    
    return 0;
}
/* OUTPUT:
 * Time spent 0.2312s after 1000data reads*/
\$\endgroup\$
2
\$\begingroup\$

First of all, my time measuring was faulty. I've noticed that during data sampling intervals systemcalls do not increase my measured overall time, wallclock time was much higher. After raising i2c port speed from 100khz to 400hz i was able to get 4 times as much samples. So i assume,that I've encountered i2c bottleneck

\$\endgroup\$
1
\$\begingroup\$

The data output rate refers to the rate at which data are accumulated in the MPU6050's FIFO. This is different to the rate at which the data can be read out of the FIFO, which is what you are measuring.

In the datasheet, it says:

An on-chip 1024 Byte FIFO buffer helps lower system power consumption by allowing the system processor to read the sensor data in bursts and then enter a low-power mode as the MPU collects more data.

The MPU6050 is sampling data at 1 kHz (set by you) and stores that in it's FIFO. Then, you read that out when convenient. It is a power saving feature, as the system processor doesn't haven't to be awake constantly, it just has to wake up and quickly grab the data that was accummulated while it was in low power sleep. The MPU6050 has I2C and SPI interfaces, so you can "download" the data even faster than you are already.

EDIT - not using FIFO...

In the while (count < 1000) loop, you are not waiting for new data to be sampled by the MPU6050. You should use the data ready interrupt on the INT pin (pin 12), which will be asserted when new data are ready. Assuming you've set it active high, you could put a stall in with while (INT == 0), or put it in an ISR depending on your application.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the help, but i don't think that i enabled FIFO anywhere. Plus i have tried adding this to MPU6050 init(); function: Writing to register 0x6A, value 0x5 //Clears and disables FIFO + Sensor Data registers. and writing to register 0x23 value 0x0) //Disables all sensor write in a FIFO buffer and i still get the same results. \$\endgroup\$ – eimvs Mar 22 at 13:16
  • \$\begingroup\$ Ah - you're not accummulating in the FIFO then, but you're just reading out the same data from the registers (I will change the answer). You should use the interrupt pin (INT, 12) to trigger your read out. \$\endgroup\$ – awjlogan Mar 22 at 13:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.