SPARKFUN QWIIC 6DOF - LSM6DSO - it looks like setAccelDataRate() doesnt set the rate

Hello,

I have a Sparkfun thing plus c connected using the qwiic system to a SparkFun Qwiic 6DoF - LSM6DSO.

I am using the following code, which is supposed to output 104hz. I am trying to verify the actual sampling rate by logging the data from the LSM6DSO and the timestamp to the SD card.

the expected period between samples is: 104hz = ~9615 microseconds. but the actual period between samples is ~29,000 microseconds.

I use the setAccelDataRate(104) to set freq, and when i use the setAccelDataRate() it returns 104 as expected.

Am I doing something wrong?

Thank you!

#include <SPI.h>
#include <SD.h>
#include "SparkFunLSM6DSO.h"
#include "SparkFun_Qwiic_OpenLog_Arduino_Library.h"
#include <Wire.h>
#include <Arduino.h>

LSM6DSO imu1;

const int sd_cs = 5; //Thing Plus C SD card pin
String dataMessage;


void appendFile(fs::FS &fs, const char * path, const char * message) {
  // Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }

  if (file.print(message)) {
    // Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char * path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char * path) {
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  if (file) {
    len = file.size();
    size_t flen = len;
    start = millis();
    while (len) {
      size_t toRead = len;
      if (toRead > 512) {
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    end = millis() - start;
    Serial.printf("%u bytes read for %u ms\n", flen, end);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }


  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  for (i = 0; i < 2048; i++) {
    file.write(buf, 512);
  }
  end = millis() - start;
  Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
  file.close();
}

/* end sd card functions */


void setup() {
  Serial.begin(115200);

  delay(500); 

  Serial.println("SD test");

  if (!SD.begin(sd_cs)) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  Wire.begin();
  delay(10);

  if(imu1.begin())
    Serial.println("IMU1 is Ready.");
  else { 
    Serial.println("Could not connect to IMU1.");
    Serial.println("Freezing");
  }

  if( imu2.begin() )
    Serial.println("IMU2 is Ready.");
  else { 
    Serial.println("Could not connect to IMU2.");
    Serial.println("Freezing");
  }

  if( imu1.initialize(BASIC_SETTINGS) )
    Serial.println("Loaded IMU1 Settings.");


  if( imu2.initialize(BASIC_SETTINGS) )
    Serial.println("Loaded IMU2 Settings.");    

  imu1.setAccelDataRate(104);

  writeFile(SD, "/datab.txt", "Reading IMUS \r\n");


}

void loop() {

  dataMessage = "AccX: " +  String(imu1.readFloatAccelX()) + "\r\n";
  appendFile(SD, "/datab.txt", dataMessage.c_str()); 

  // Calculate the timestamp in micros
  unsigned long currentMicros = micros();
  dataMessage = "Timestamp: " + String(currentMicros) + "\r\n";
  appendFile(SD, "/datab.txt", dataMessage.c_str()); 

}

It looks like 104Hz is a valid rate for both linear & angular data, so that part is good…I would lean toward the serial functions causing delays and hang-ups (write speed to SD card, serial function call delays)

Double check the timing accuracy of the board by running/comparing micros() and also ensure the IMU has been calibrated too…any luck?

You make the common beginner mistake of opening the output file, writing one line of data and closing it again. That is an extremely slow operation requiring the MCU to read in an entire 512 byte buffer, update the buffer and write it out again, TWICE if the write operation crosses a buffer boundary. It also vastly increases the SD card current draw and error rate.

The simple fix, which will dramatically increase the speed of data collection, is to open the file once in setup(), collect and write the data, then close the file only when you are all done collecting data.

Thank you very much! open and close the file, only once, increase the speed of data collection and the setAccelDataRate() function works as expected.

Excellent!