Nano 33 BLE IMU issues with SdFat LowLatencyLogger

Hi, I am having some trouble with getting the SdFat LowLatencyLogger working with the Nano 33 BLE's IMU (lsm9ds1)

The Nano 33 BLE works without issue with LowLatencyLoggerMPU6050 using an MPU6050 IMU and a Pololu micro SD (Pololu - Breakout Board for microSD Card), although the speed is limited to 84Hz sampling for reasons I can't figure. Setting the const uint32_t LOG_INTERVAL_USEC = 11765 or about 85Hz gives the error: Rate too fast, even with accelerometer only data which in the serial monitor achieves about 126Hz

With some slight modification of the LowLatencyLoggerMPU6050 file, the BLE’s internal sensors started working although would not go beyond about 33Hz sample rate with the Rate too fast error.

Now the odd thing, the Nano becomes unresponsive at a certain point, both in the SD writing and in the serial monitor(freezing and needing restart of Nano, not IDE). In the serial monitor it's always at 1498 lines written(including header), even when output speed is varied with const uint32_t interval =, it just stops at 1498, just faster or slower. The card write is similar.

The only changes made to the code were removing the MPU6050 related items and inserting:

#include "Arduino_LSM9DS1.h"

void acquireData(data_t* data) {
IMU.readAcceleration(data->ax, data->ay, data->az);
IMU.readGyroscope(data->gx, data->gy, data->gz);

Then changing all the relevant variables to float

Sample of code that was changed:

// User data functions.  Modify these functions for your data items.
// LSM9DS1
#include "UserTypes.h"
#include "Wire.h"
#include "I2Cdev.h"
#include "Arduino_LSM9DS1.h" //enable Nano 33 BLE onboard IMU

static uint32_t startMicros;
// Acquire a data record.
void acquireData(data_t* data) {
  data->time = millis();
  IMU.readAcceleration(data->ax, data->ay, data->az);
  IMU.readGyroscope(data->gx, data->gy, data->gz);

// setup AVR I2C
void userSetup() {
  Fastwire::setup(400, true);

// Print a data record.
void printData(Print* pr, data_t* data) {
  if (startMicros == 0) {
    startMicros = data->time;
  pr->print(data->time- startMicros);

// Print data header.
void printHeader(Print* pr) {
  startMicros = 0;


#ifndef UserTypes_h
#define UserTypes_h
#include "Arduino.h"
#define FILE_BASE_NAME "mpuraw"
struct data_t {
  unsigned long time;
  float ax;
  float ay;
  float az;
  float gx;
  float gy;
  float gz;
void acquireData(data_t* data);
void printData(Print* pr, data_t* data);
void printHeader(Print* pr);
void userSetup();
#endif  // UserTypes_h

Please help with this freezing, also is there anything that can be done with the poor sample rate, why would the external MPU6050 be faster?


I worked out a solution to the freezing by moving: IMU.begin();
void acquireData
void userSetup()

The SD log speed also increased to 82Hz failing at 82.5Hz, almost as fast as the external IMU.
My guess is the speed issue is related to the mBed platform issues as detailed here:

Without the LowLatencyLogger the logging rate to Sd card is at best 13Hz and inconsistent
theoretically the buffering in SdFat should be able to mitigate the issues a bit better than it has, but maybe something else is restricting it.

The section in the code reporting the “error: Rate too fast” is at line 414 with the recordBinFile function.

At line 393 the selected logging rate: LOG_INTERVAL_USEC is added to logTime which is initially set as:
logTime = micros();

So it is in the next section of code that is executed that leads to the error as the check at line 414 shows more time than the logging rate has elapsed:

if ((int32_t)(logTime - micros()) < 0) {
error(“Rate too fast”);

As I am a beginner I do not understand exactly what this section is doing or if there is anything that can be done anywhere that may fix the problem, changing buffer sizes has minimal effect i.e. lowering buffer to 6 allowed max 83Hz, buffers from 12 to 32 allowed max 82Hz. changing SD_SCK_MHZ(50) had no effect at all.

The section is this:

  bool closeFile = false;
  uint32_t bn = 0;
  uint32_t maxLatency = 0;
  uint32_t overrun = 0;
  uint32_t overrunTotal = 0;
  uint32_t logTime = micros();
  while(1) {
     // Time for next data record.
    logTime += LOG_INTERVAL_USEC;
    if (Serial.available()) {
      closeFile = true;
    if (closeFile) {
      if (curBlock != 0) {
        // Put buffer in full queue.
        fullQueue[fullHead] = curBlock;
        fullHead = fullHead < QUEUE_LAST ? fullHead + 1 : 0;
        curBlock = 0;
    } else {
      if (curBlock == 0 && emptyTop != 0) {
        curBlock = emptyStack[--emptyTop];
        if (emptyTop < minTop) {
          minTop = emptyTop;
        curBlock->count = 0;
        curBlock->overrun = overrun;
        overrun = 0;
      if ((int32_t)(logTime - micros()) < 0) {
        error("Rate too fast");

Full code here:

Any thoughts on what is happening there?