MPU6050 sampling rate is too low for Gyroflow

Hi everyone, I am working on building a gyrologger with an nano, MPU6050. The goal was to use this with Gyroflow. I have been able to get just about everything working but running into an issue with the sampling rate being low about 31Hz.

Some things that I have tried are reading raw values and also adjusting the time between samples to as low as possible. But nothing seems to be helping. Granted my programming experience is limited but maybe I have not initialized the 6050 with the correct parameters or just writing to the SD card is the limiting factor. At one point I was trying to buffer the data and then write to the SD card but when compiled was using more memory that the nano offered.

I have read a lot of posts around the MPU 6050 and looked at many examples, but I know I am missing something. I have posted the full code here:

#include <Wire.h>
#include <SD.h>
#include <SPI.h>
#include "I2Cdev.h"
#include "MPU6050.h"

// Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation
// is used in I2Cdev.h
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif


#define LOGGER_NAME "Arduino Logger" // Change this to whatever name you want

MPU6050 mpu;

File dataFile;

// Global Variables

int count = 0;                  // Variable to increment when button is pressed
char filename[13];              // Filename buffer

int16_t accelerometer[3];       // Accelerometer values
int16_t gyro[3];                // Gyroscope values
    

const int buttonPin = 2;        // Button pin *change this according to what pin you use*
const int ledPin = 7;           // LED pin *change this according to what pin you use*

int buttonState = 0;            // Current state of the button
int lastButtonState = 0;        // Previous state of the button
int ledState = LOW;             // Current state of the LED

bool toggleFlag = false;        // Flag to track the toggle state
bool incrementedFile = false;   //Flag to track if filename has been incremented
bool recordStart = false;       //track when recording started




void setup() {


  pinMode(ledPin, OUTPUT);           // For the LED Output
  pinMode(buttonPin, INPUT_PULLUP);  // Use internal pull-up resistor

  
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif
  
  
  
  // Initialize serial communication
  Serial.begin(115200);

  // Initialize the MPU6050 sensor
  Wire.begin();
  mpu.initialize();
  
  mpu.setFullScaleAccelRange(1); //0: 250deg/s | 1: 500deg/s | 2: 1000deg/s | 3: 2000deg/s 
  mpu.setFullScaleGyroRange(1); //0: 2g | 1: 4g | 2: 8g | 3: 16g
  mpu.setDLPFMode(0); // 0: 240Hz | 1: 184Hz | 2: 94Hz | 3: 44Hz | 4: 21Hz | 5: 10HZ | 6: 5HZ

  // Configure MPU6050 to operate in raw sensor mode
  mpu.setSleepEnabled(false); // Wake up the MPU6050 from sleep mode
  mpu.setDMPEnabled(false); // Disable the Digital Motion Processor (DMP)
  
  Serial.print("Initializing SD card...");

  if (!SD.begin(4)) {
    Serial.println("initialization failed!");
    while (1);
  }
  Serial.println("initialization done.");

  // Open the root directory
  File root = SD.open("/");
  if (!root) {
    Serial.println("Failed to open root directory!");
    return;
  }
  
  int highestNumber = 0;  // Variable to store the highest number found
  
  // Read filenames from the root directory
  while (true) {
    File entry = root.openNextFile();
    if (!entry) {
      // No more files
      break;
    }
    
    // Get the filename
    String filename = entry.name();
    entry.close();
    
    // Look for numbers in the filename
    String numbers = extractNumbers(filename);
    
    // Parse the number and check if it is higher than the current highest number
    if (numbers.length() > 0) {
      int currentNumber = numbers.toInt();
      if (currentNumber > highestNumber) {
        highestNumber = currentNumber;
      }
    }
  }
  
  root.close();
  
//  // Print the highest number found
  Serial.print("Highest number found: ");
  Serial.println(highestNumber);
  count = highestNumber;
  Serial.println(count);
}


void loop() {



// Check if it's time to take a sample (1kHz)
  static unsigned long prevTime = 0;
  unsigned long currentTime = micros();
  unsigned long timeInterval = 50; // Desired time interval between samples in microseconds

 
  if (currentTime - prevTime >= timeInterval) {
    prevTime = currentTime;

    // Read sensor data from MPU6050
    
    mpu.getMotion6(&accelerometer[0], &accelerometer[1], &accelerometer[2],
                  &gyro[0], &gyro[1], &gyro[2]);

    
  }

   buttonState = digitalRead(buttonPin);

  
    
  // Check if the button state has changed
  if (buttonState != lastButtonState) {
    // If the button was pressed (change from HIGH to LOW)
    if (buttonState == LOW) {
      toggleFlag = !toggleFlag;  // Toggle the flag
    }
    delay(50);  // Debounce delay
  }
  
  lastButtonState = buttonState;
 
  if (toggleFlag) {
    ledState = HIGH;  // Turn on the LED
    // Increment count and create new filename when button is pressed
    if (incrementedFile == false){
     createFilename(); 
     Serial.println(filename);
    }
    
    if (recordStart == false){
     Serial.println("");
     Serial.println("data logging started");
     Serial.println(currentTime);
    }
    recordStart = true;

     // Append the data to the file
    appendDataToFile(currentTime, gyro, accelerometer);
  }    

 
  else {
    ledState = LOW;   // Turn off the LED
    if (incrementedFile == true){
     Serial.println("");
     Serial.println("data logging stopped");
     Serial.println(currentTime);
    }
    incrementedFile = false;
    recordStart = false;  
  }
  
  digitalWrite(ledPin, ledState);
  
}

void createFilename() {
  // Generate new filename
  count++;
  snprintf(filename, sizeof(filename), "data%d.csv", count);
  incrementedFile = true;

unsigned long timeStamp = micros();
   
   // Open a file for writing
  dataFile = SD.open(filename, FILE_WRITE);

  if (dataFile) {
    // Write the header line
    dataFile.println("GYROFLOW IMU LOG");
    dataFile.println("version,1.3");
    dataFile.print("id,");
    dataFile.println(LOGGER_NAME);
    dataFile.println("orientation,XYZ");
    dataFile.print("timestamp,");
    dataFile.println(timeStamp);
    dataFile.println("tscale,0.000001");
    dataFile.println("gscale,0.00013309054");
    dataFile.println("ascale,0.00012207031");
    dataFile.println("t,gx,gy,gz,ax,ay,az");
    dataFile.close();
    Serial.print("Header Lines Created for: ");
    Serial.print(filename);
    Serial.println("");
    Serial.print("File created :");
    Serial.println(filename);
    Serial.println("");
    Serial.println("data logging started");
    
  } else {
    Serial.println("Error opening file!");
  }
}

String extractNumbers(String str) {
  String numbers = "";
  for (int i = 0; i < str.length(); i++) {
    if (isDigit(str.charAt(i))) {
      numbers += str.charAt(i);
    }
  }
  return numbers;
}

void appendDataToFile(unsigned long time, int16_t* gyro, int16_t* accelerometer)
{

  // Create a file on the SD card
  File dataFile = SD.open(filename, FILE_WRITE);
  
  if (dataFile) {
    
    // Write the data to the file
    dataFile.print(time);
    dataFile.print(",");
    dataFile.print(gyro[0]);
    dataFile.print(",");
    dataFile.print(gyro[1]);
    dataFile.print(",");
    dataFile.print(gyro[2]);
    dataFile.print(",");
    dataFile.print(accelerometer[0]);
    dataFile.print(",");
    dataFile.print(accelerometer[1]);
    dataFile.print(",");
    dataFile.println(accelerometer[2]);

    // Close the file
    dataFile.close();
  } 
  
  else {
    Serial.println("Error opening file!");
  }
}

Any help would be greatly appreciated!

I can't help much right now never mind why.

ButI wonder if you can do some kind of test to see if your desired 1000 Hz sampling is happening.

You could... add print statements, but they can confuse an experiment as they will take time.

You could toggle an output pin and measure the frequency. I'd do two of those. One to check the loop frequency, and another near the gyro thing to see if it makes the time slice.

Just ideas.

a7

That low rate is due to the time taken up by SD file functions.

The function appendDataToFile(), which is executed for every gyro sample, opens the file, writes a tiny bit of data to it, then closes the file.

This is a common beginner mistake that greatly increases the time required to log data, greatly increases the overall power draw, and greatly increases the SD card error and failure rate.

It is much, much faster to open the file once in setup(), write all the data for one session, and close the file only when you are all done collecting data.

Thanks very much for the explanation. I think I came across this before. It makes sense, but I'm also trying to think how I can now accomplish writing multiple files with keeping the file open. Right now I'm using a button to start data logging and stopping it. Each time it does so it creates a new file. So I'm just trying to wrap my head around that. Or is there a faster library that can interface with the SD card? Appreciate your reply and guidance.

I should add if I don't use the datafile. Close() it will never create the file. I think I was trying to do as you proposed but it threw an error. Maybe there is a better library to use for this purpose?

Thanks for the advice. That also crossed my mind. But looks like as I suspected it is both writing the file to SD card and also my code. I just have to found a way to open the file and write to it until I'm done collecting data. It always throws an error unless I'm grabbing data a closing the file maybe there is an append option to keep it open?

You can open more than one file IF you have memory for the file buffers. But why do you want to?

All data written to a file will be lost if it is not properly closed.

I should add if I don't use the datafile. Close() it will never create the file

Don't open a file that you don't use. It sounds like you just need to think a bit more about what the program should do, and plan accordingly.

There is hardly ever a reason to have more than one output file open at a time.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.