wollewald / MPU9250_WE

An Arduino library for the 9-axis accelerometer, gyroscope and magnetometer MPU9250 and MPU6500. It contains many example sketches make it easy to use.
https://wolles-elektronikkiste.de/en/mpu9250-9-axis-sensor-module-part-1
MIT License
56 stars 26 forks source link

setSampleRateDivider doesn't work #13

Closed JRoseCPMax closed 1 year ago

JRoseCPMax commented 1 year ago

Hello, first of all: great work with the library, i really appreachiate it! I searched for quite a time for a suitable MPU9250 library that supports the FIFO and SPI. The bolderflight library dropped their FIFO support a while ago.

But I still need a little help, i'm sure it is just a small error on my side. I want to use the library with the ESP32 multitasking to get a continuous 500Hz reading. For that I want to utilize the FIFO to get 50 Acc Value Triplet's every 100ms. That way it wouldn't influence the measurement when the reader call is 10ms late.

Im using an ESP32 Devkit C with PlatformIO Core 6.1.4 Home 3.4.3, and your library on Version 1.2.6. The Sensor I use is an MPU9250.

I used the following to Sketch to test the functionality, but it seems that the SampleRateDivider doesn't get set properly. If i lower the delay between the calls to 10ms I also get a reduced FIFO count, but it seems to still sample at more than 6 kHz.

#include <Arduino.h>
#include <SPI.h>
#include <MPU9250_WE.h>

SPIClass SPI_MPU(HSPI);
const int CS_MPU_1 = 26;

MPU9250_WE myMPU9250 = MPU9250_WE(&SPI_MPU, CS_MPU_1, 1);
uint8_t dataSets = 0;

float_t ax_mean = 0;
float_t ay_mean = 0;
float_t az_mean = 0;

uint32_t t_next_exec = 0;

void setup()
{
    Serial.begin(115200);
    while (!myMPU9250.init())
    {
        Serial.println("MPU9250 does not respond");
        delay(1000);
    }
    myMPU9250.setAccRange(MPU9250_ACC_RANGE_2G);
    myMPU9250.enableAccDLPF(true);
    myMPU9250.setAccDLPF(MPU9250_DLPF_1);
    myMPU9250.setFifoMode(MPU9250_STOP_WHEN_FULL);
    myMPU9250.setSampleRateDivider(99);     // this setting doesn't change anything

    myMPU9250.setSPIClockSpeed(4000000);
    myMPU9250.enableFifo(true);
    delay(100);
    myMPU9250.startFifo(MPU9250_FIFO_ACC);
}

void loop()
{
    myMPU9250.stopFifo();
    dataSets = myMPU9250.getNumberOfFifoDataSets();
    for (int i = 0; i < dataSets; i++)
    {
        xyzFloat gValue = myMPU9250.getGValuesFromFifo();
        ax_mean += gValue.x / dataSets;
        ay_mean += gValue.y / dataSets;
        az_mean += gValue.z / dataSets;
    }
    myMPU9250.resetFifo();
    myMPU9250.startFifo(MPU9250_FIFO_ACC);

    Serial.print(millis());
    Serial.print("   ");
    Serial.print(9.81 * ax_mean, 3);
    Serial.print("   ");
    Serial.print(9.81 * ay_mean, 3);
    Serial.print("   ");
    Serial.print(9.81 * az_mean, 3);
    Serial.print("   ");
    Serial.println(dataSets);         // prints 85 even at SRD set to 99 and delay of 20ms

    ax_mean = 0;
    ay_mean = 0;
    az_mean = 0;

    while (millis() < t_next_exec){}
    t_next_exec += 20;              // if lowered to 10, dataSets goes down to 61/62 ( -> samplerate >6kHz)
}

The Serial output shows the following:

09:53:22.205 > 3323 -0.286 -0.130 -10.059 85 09:53:22.223 > 3343 -0.280 -0.115 -10.035 85 09:53:22.243 > 3363 -0.301 -0.115 -10.035 85 09:53:22.263 > 3383 -0.280 -0.114 -10.029 85 09:53:22.283 > 3403 -0.312 -0.120 -10.044 85 09:53:22.303 > 3423 -0.295 -0.126 -10.023 85 09:53:22.323 > 3443 -0.305 -0.133 -10.052 85 09:53:22.343 > 3463 -0.297 -0.130 -10.039 85 09:53:22.363 > 3483 -0.296 -0.115 -10.026 85 09:53:22.383 > 3503 -0.307 -0.134 -10.051 85 09:53:22.403 > 3523 -0.293 -0.112 -10.013 85 09:53:22.423 > 3543 -0.290 -0.128 -10.044 85

JRoseCPMax commented 1 year ago

I realized, that i need to set both DLPF for the SRD to work, I thought if i only put acc data in the FIFO only the acc dlpf is relevant. I also took out the start/stop/reset part, as it hinders my goal of an uninteruped measurement, I thought these parts were necessary, since i found them in all the FIFO examples. The final working sketch looks like this, i changed it to sample data at 1kHz:

#include <Arduino.h>
#include <SPI.h>
#include <MPU9250_WE.h>

SPIClass SPI_MPU(HSPI);
const int CS_MPU_1 = 26;

MPU9250_WE myMPU9250 = MPU9250_WE(&SPI_MPU, CS_MPU_1, 1);
uint8_t dataSets = 0;

float_t ax_mean = 0;
float_t ay_mean = 0;
float_t az_mean = 0;

uint32_t t_next_exec = 0;
char msg_buffer[256];

void setup()
{
    Serial.begin(115200);
    while (!myMPU9250.init())
    {
        Serial.println("MPU9250 does not respond");
        delay(1000);
    }

    myMPU9250.enableGyrDLPF();
    myMPU9250.setGyrDLPF(MPU9250_DLPF_1);

    myMPU9250.setAccRange(MPU9250_ACC_RANGE_2G);
    myMPU9250.enableAccDLPF(true);
    myMPU9250.setAccDLPF(MPU9250_DLPF_1);
    myMPU9250.setSampleRateDivider(0);

    myMPU9250.setFifoMode(MPU9250_STOP_WHEN_FULL);
    myMPU9250.enableFifo(true);
    delay(100);
    myMPU9250.startFifo(MPU9250_FIFO_ACC);
}

void loop()
{
    dataSets = myMPU9250.getNumberOfFifoDataSets();
    for (int i = 0; i < dataSets; i++)
    {
        xyzFloat gValue = myMPU9250.getGValuesFromFifo();
        ax_mean += gValue.x / dataSets;
        ay_mean += gValue.y / dataSets;
        az_mean += gValue.z / dataSets;
    }

    ax_mean *= 9.81;
    ay_mean *= 9.81;
    az_mean *= 9.81;

    sprintf(msg_buffer, "%010d  %d   %+.3f m/s²  %+.3f m/s²  %+.3f m/s²", millis(), dataSets, ax_mean, ay_mean, az_mean);
    Serial.println(msg_buffer);

    ax_mean = 0;
    ay_mean = 0;
    az_mean = 0;

    while (millis() < t_next_exec){
        // waiting while the FIFO fills
    }
    t_next_exec += 50;
}

If you want, you can add this to the examples. I think a non blocking continuous measurement at a high sample rate could be interesting for a few people.

wollewald commented 1 year ago

@JRoseCPMax , I like the issues which are solved without my input! 😀 And yes, I think it could be interesting also for others. Do you start a pull request?