hideakitai / MPU9250

Arduino library for MPU9250 Nine-Axis (Gyro + Accelerometer + Compass) MEMS MotionTracking™ Device
MIT License
279 stars 92 forks source link

Can't read accel and gyro data with 1000 Hz #78

Closed pezosanta closed 2 years ago

pezosanta commented 2 years ago

Hi,

First of all thank you for your amazing work with this arduino mpu9250 lib!

I am working on a project where I need to read accelerometer and gyroscope data with 1 kHz (at very least with 500 Hz) by using an Arduino Mega board.

To configure the IMU, I made a setting struct based on the _customsettings.ino example, where I set the FIFO sample rate to 1000 Hz. If I read accel and gyro data in the loop by checking if(mpu.update()) and counting the number of measurements in every seconds, I get only ~142 Hz (measurements/second). (By setting the FIFO sample rate to 125 Hz, the data rate is limited correctly to 125 Hz).

#include "MPU9250.h"
#include "eeprom_utils.h"

MPU9250 mpu;

void setup()
{    
  Serial.begin(115200);
  Wire.begin();
  delay(2000);

  MPU9250Setting setting;
  setting.accel_fs_sel = ACCEL_FS_SEL::A16G;
  setting.gyro_fs_sel = GYRO_FS_SEL::G2000DPS;
  setting.mag_output_bits = MAG_OUTPUT_BITS::M16BITS;
  setting.fifo_sample_rate = FIFO_SAMPLE_RATE::SMPL_1000HZ;
  setting.gyro_fchoice = 0x03;
  setting.gyro_dlpf_cfg = GYRO_DLPF_CFG::DLPF_41HZ;
  setting.accel_fchoice = 0x01;
  setting.accel_dlpf_cfg = ACCEL_DLPF_CFG::DLPF_45HZ;

  if (!mpu.setup(0x68, setting)) {  // change to your own address
        while (1) {
            Serial.println("MPU connection failed. Please check your connection with `connection_check` example.");
            delay(5000);
        }
    }

  mpu.calibrateAccelGyro();

  // save to eeprom
  saveCalibration();

  // load from eeprom
  loadCalibration();

  delay(1000);
}

uint16_t counter = 0;
unsigned long prev_time = millis();

void loop()
{
  if (mpu.update()) {        
        counter += 1;

        if ((millis() - prev_time) >= 1000){
          Serial.print("Hz: "); Serial.print(counter); Serial.println();
          prev_time = millis();
          counter = 0;
        }
  }
}

If I check if(mpu.available()) instead of if(mpu.update()) in the loop and calling _mpu.update_accelgyro() directly, I get 426 Hz (still not 1 kHz). (By setting the FIFO sample rate to 125/143/167/200/250/333 Hz, the measured data rate is limited accordingly).

#include "MPU9250.h"
#include "eeprom_utils.h"

MPU9250 mpu;

void setup()
{    
  Serial.begin(115200);
  Wire.begin();
  delay(2000);

  MPU9250Setting setting;
  setting.accel_fs_sel = ACCEL_FS_SEL::A16G;
  setting.gyro_fs_sel = GYRO_FS_SEL::G2000DPS;
  setting.mag_output_bits = MAG_OUTPUT_BITS::M16BITS;
  setting.fifo_sample_rate = FIFO_SAMPLE_RATE::SMPL_1000HZ;
  setting.gyro_fchoice = 0x03;
  setting.gyro_dlpf_cfg = GYRO_DLPF_CFG::DLPF_41HZ;
  setting.accel_fchoice = 0x01;
  setting.accel_dlpf_cfg = ACCEL_DLPF_CFG::DLPF_45HZ;

  if (!mpu.setup(0x68, setting)) {  // change to your own address
        while (1) {
            Serial.println("MPU connection failed. Please check your connection with `connection_check` example.");
            delay(5000);
        }
    }

  mpu.calibrateAccelGyro();

  // save to eeprom
  saveCalibration();

  // load from eeprom
  loadCalibration();

  delay(1000);
}

uint16_t counter = 0;
unsigned long prev_time = millis();

void loop()
{
  if (mpu.available()) {
        mpu.update_accel_gyro();

        counter += 1;

        if ((millis() - prev_time) >= 1000){
          Serial.print("Hz: "); Serial.print(counter); Serial.println();
          prev_time = millis();
          counter = 0;
        }
  }
}

Am I doing something wrong ? Any help would be appriciated :)

hideakitai commented 2 years ago

Hi, how about changing the clock frequency? https://www.arduino.cc/en/Reference/WireSetClock

pezosanta commented 2 years ago

Thanks @hideakitai, setting the I2C clock frequency to 400 kHz (fast mode) solved the data rate issue.

Running the code below samples the acc and gyro data with 1 kHz.

#include "MPU9250.h"
#include "eeprom_utils.h"

MPU9250 mpu;

void setup()
{    
  Serial.begin(115200);
  Wire.begin();
  Wire.setClock(400000);
  delay(2000);

  MPU9250Setting setting;
  setting.accel_fs_sel = ACCEL_FS_SEL::A16G;
  setting.gyro_fs_sel = GYRO_FS_SEL::G2000DPS;
  setting.mag_output_bits = MAG_OUTPUT_BITS::M16BITS;
  setting.fifo_sample_rate = FIFO_SAMPLE_RATE::SMPL_1000HZ;
  setting.gyro_fchoice = 0x03;
  setting.gyro_dlpf_cfg = GYRO_DLPF_CFG::DLPF_41HZ;
  setting.accel_fchoice = 0x01;
  setting.accel_dlpf_cfg = ACCEL_DLPF_CFG::DLPF_45HZ;

  if (!mpu.setup(0x68, setting)) {  // change to your own address
        while (1) {
            Serial.println("MPU connection failed. Please check your connection with `connection_check` example.");
            delay(5000);
        }
    }

  mpu.calibrateAccelGyro();

  // save to eeprom
  saveCalibration();

  // load from eeprom
  loadCalibration();

  delay(1000);
}

uint16_t counter = 0;
unsigned long prev_time = millis();

void loop()
{
  if (mpu.available()) {
        mpu.update_accel_gyro();

        counter += 1;

        if ((millis() - prev_time) >= 1000){
          Serial.print("Hz: "); Serial.print(counter); Serial.println();
          prev_time = millis();
          counter = 0;
        }
  }
}