1

Please let me know if this post has the wrong tags, I will make sure to change it.

My goal is to get the highest sampling rate possible from the Adafruit LSM6DSOX (6667Hz) using the Arduino MKR WIFI 1010 and I2C communication.

This is the library I am using: stm32duino/LSM6DSOX, specifically the LSM6DSOX_FIFO_Polling example.

I am trying to measure the actual sampling rate achieved with my code and hardware to find out if my implementation is correct and whether I am facing hardware limitations.

The only modifications to the example from the library were uncommenting Serial.print() statements, moving variable declaration and initialization outside of the loop() and adding my sampling rate calculation. Also removing the comment header in the example code to keep this post shorter.

Code

#include "LSM6DSOXSensor.h"

// #define SR 104 // Sample rate. Options are: 12.5, 26, 52, 104, 208, 417, 833, 1667, 3333 and 6667 Hz.
// #define WTM_LV 199 // Watermark threshold level. Max samples in this FIFO configuration is 512 (accel and gyro only).

// INCREASED SAMPLING RATE AND WATERMARK THRESHOLD LEVEL
#define SR 6667
#define WTM_LV 500

LSM6DSOXSensor lsm6dsoxSensor = LSM6DSOXSensor(&Wire, LSM6DSOX_I2C_ADD_L);

// MOVED VARIABLE DECLARATION AND INITIALIZATION OUTSIDE OF LOOP
static uint8_t wtmStatus = 0; // FIFO watermark status
uint8_t fullStatus = 0; // FIFO full status
uint16_t numSamples = 0; // number of samples in FIFO
uint8_t Tag; // FIFO data sensor identifier
int32_t acceleration[3]; // X, Y, Z accelerometer values in mg
int32_t rotation[3]; // X, Y, Z giroscope values in mdps

// VARIABLES DECLARATION AND INITIALIZATION FOR SAMPLING RATE CALCULATION
unsigned long lastUpdate = 0;
unsigned long totalInterval = 0;
unsigned long currentTime = 0;
int updateCount = 0;
float averageInterval = 0;
float samplingRate = 0;

void setup() {

  Serial.begin(921600);
  // Comment this line to skip waiting for serial:
  while(!Serial) delay(10);
  
  // i2c, fast mode
  Wire.begin();
  Wire.setClock(400000);

  // Initialize sensors
  lsm6dsoxSensor.begin();
  if (lsm6dsoxSensor.Enable_G() == LSM6DSOX_OK && lsm6dsoxSensor.Enable_X() == LSM6DSOX_OK) {
    Serial.println("Success enabling accelero and gyro");
  } else {
    Serial.println("Error enabling accelero and gyro");
    abort();
  }

  // Check device id
  uint8_t id;
  lsm6dsoxSensor.ReadID(&id);
  if (id != LSM6DSOX_ID) {
    Serial.println("Wrong id for LSM6DSOX sensor. Check that device is plugged");
    abort();
  } else {
    Serial.println("Success checking id for LSM6DSOX sensor");
  }

  // Set accelerometer scale. Available values are: 2, 4, 8, 16 G
  lsm6dsoxSensor.Set_X_FS(2);
  // Set gyroscope scale. Available values are: 125, 250, 500, 1000, 2000 dps
  lsm6dsoxSensor.Set_G_FS(250);
  
  // Set accelerometer Output Data Rate. Available values are: 1.6, 12.5, 26, 52, 104, 208, 417, 833, 1667, 3333, 6667 Hz
  lsm6dsoxSensor.Set_X_ODR(SR);
  // Set gyroscope Output Data Rate. Available values are 12.5, 26, 52, 104, 208, 417, 833, 1667, 3333, 6667 Hz
  lsm6dsoxSensor.Set_G_ODR(SR);
  
  // Set FIFO Batch Data Rate for accelerometer and gyroscope. Available values are: 0, 12.5, 26, 52, 104, 208, 417, 833, 1667, 3333, 6667 Hz
  lsm6dsoxSensor.Set_FIFO_X_BDR(SR);
  lsm6dsoxSensor.Set_FIFO_G_BDR(SR);

  /** Set FIFO operation mode. Available values are:
   * LSM6DSOX_BYPASS_MODE: FIFO is not used, the buffer content is cleared
   * LSM6DSOX_FIFO_MODE: bufer continues filling until it becomes full. Then it stops collecting data.
   * LSM6DSOX_STREAM_MODE: continuous mode. Older data are replaced by the new data.
   * LSM6DSOX_STREAM_TO_FIFO_MODE: FIFO buffer starts operating in Continuous mode and switches to FIFO mode when an event condition occurs.
   * LSM6DSOX_BYPASS_TO_STREAM_MODE: FIFO buffer starts operating in Bypass mode and switches to Continuous mode when an event condition occurs.
   * */
  lsm6dsoxSensor.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE); // flush any previous value in FIFO before start
  lsm6dsoxSensor.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE); // start batching in continous mode
  
  // Set FIFO watermark level. Can be used to check when the number of samples in buffer reaches this defined threshold level.
  lsm6dsoxSensor.Set_FIFO_Watermark_Level(WTM_LV);
  
  // FIFO size can be limited to the watermark level by setting the STOP_ON_WTM flag to 1
  //lsm6dsoxSensor.Set_FIFO_Stop_On_Fth(1);

  Serial.println("Starting...");
}

void loop() {

  // MOVED VARIABLE DECLARATION AND INITIALIZATION OUTSIDE OF LOOP
  // static uint8_t wtmStatus = 0; // FIFO watermark status
  // uint8_t fullStatus = 0; // FIFO full status
  // uint16_t numSamples = 0; // number of samples in FIFO
  // uint8_t Tag; // FIFO data sensor identifier
  // int32_t acceleration[3]; // X, Y, Z accelerometer values in mg
  // int32_t rotation[3]; // X, Y, Z giroscope values in mdps

  // Get number of samples in buffer
  lsm6dsoxSensor.Get_FIFO_Num_Samples(&numSamples);
  // Serial.print("Samples in FIFO: "); Serial.println(numSamples);
  // Serial.flush();

  // Check if FIFO threshold level was reached.
  lsm6dsoxSensor.Get_FIFO_Watermark_Status(&wtmStatus);

  if (wtmStatus != 0) {
    // Serial.println("-- FIFO Watermark level reached!, fetching data.");
    // Serial.flush();

    // fetch data from FIFO
    for (uint16_t i = 0; i < WTM_LV; i++) {

      lsm6dsoxSensor.Get_FIFO_Tag(&Tag); // get data identifier
      
      // Get gyroscope data
      if (Tag == 1) { 
        lsm6dsoxSensor.Get_FIFO_G_Axes(rotation);
        // #if 1 // set to 1 for printing values
        // Serial.print("mdps: "); Serial.print(rotation[0]); 
        // Serial.print(", "); Serial.print(rotation[1]); 
        // Serial.print(", "); Serial.print(rotation[2]); 
        // Serial.println();
        // Serial.flush();
        // #endif
      }
      
      // Get accelerometer data
      else if (Tag == 2) {
        lsm6dsoxSensor.Get_FIFO_X_Axes(acceleration); 
        // #if 1 // set to 1 for printing values
        // Serial.print("mG: "); Serial.print(acceleration[0]); 
        // Serial.print(", "); Serial.print(acceleration[1]); 
        // Serial.print(", "); Serial.print(acceleration[2]); 
        // Serial.println();
        // Serial.flush();
        // #endif
      }
    }

    currentTime = micros();

    if (lastUpdate != 0) {
      totalInterval += (currentTime - lastUpdate)/(float)numSamples;
      updateCount++;
    }

    lastUpdate = currentTime;
  }

  // Check if FIFO is full.
  lsm6dsoxSensor.Get_FIFO_Full_Status(&fullStatus);

  if (fullStatus != 0) {
    // Serial.println("-- FIFO is full!, consider reducing Watermark Level or Buffer Data Rate.\nFlushing data from FIFO.");
    // Serial.flush();
    lsm6dsoxSensor.Set_FIFO_Mode(LSM6DSOX_BYPASS_MODE); // flush FIFO data
    lsm6dsoxSensor.Set_FIFO_Mode(LSM6DSOX_STREAM_MODE); // continue batching
  }

  if (updateCount >= 10) {  // Average over 10 cycles to reduce the frequency of serial output.
    averageInterval = totalInterval / (float)updateCount;
    samplingRate = 1000000.0 / averageInterval; // Convert from microseconds to Hz
    Serial.print("Average Sampling Rate: ");
    Serial.print(samplingRate);
    Serial.println(" Hz");

    // Reset for next average calculation
    totalInterval = 0;
    updateCount = 0;
  }

  delay(10); // Small delay to prevent continuous polling
}

Serial Monitor

Success enabling accelero and gyro
Success checking id for LSM6DSOX sensor
Starting...
Average Sampling Rate: 1652.89 Hz
Average Sampling Rate: 1652.62 Hz
Average Sampling Rate: 1652.62 Hz

Questions

Is the sampling rate I am achieving limited due to software (LSM6DSOX implementation, sampling rate calculation) or hardware (I2C communication, MKR WIFI 1010 board)?

How can I find out the optimal FIFO buffer parameters (FIFO mode, watermark threshold level) for this application?

Thanks a lot in advance, any help is appreciated!

2
  • If you want to measure the performance, 1) don't do the unrelated calculation, especially with floating point and division as they take several clock cycles, 2) don't do Serial.print() as it is slow even at 961200bps baud rate, your printing of 30+ characters costs 300us+ of time. 3) don't do delay. DO toggle a pin and use oscilloscope or logic analyser to observe the pin and the frequency of the toggle.
    – hcheung
    May 15 at 7:43
  • thank you for the suggestion, I will try that. May 16 at 8:08

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.