Increasing the Speed of writing to an SD Card

Hi all, I am using an ICM 20601 an arduino due and the AdaFruit data logger shield with rtc. I need the data to be written at least at 4kHz, but right now I am only getting 62Hz. From my understanding this is slow for writing to an SD card normally. Here is my code.

 /* Hardware setup:
  MPU9250 Breakout --------- Arduino
  VDD ---------------------- 3.3V
  VDDI --------------------- 3.3V
  SDA ----------------------- A4
  SCL ----------------------- A5
  GND ---------------------- GND
#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <string.h>
#include "RTClib.h"

//TODO:make faster by by holding write
//TODO:make name thing more effieceint

// how many milliseconds between grabbing data and logging it. 1000 ms is once a second
#define LOG_INTERVAL  500 // mills between entries (reduce to take more/faster data)

// how many milliseconds before writing the logged data permanently to disk
// set it to the LOG_INTERVAL to write each time (safest)
// set it to 10*LOG_INTERVAL to write all data every 10 datareads, you could lose up to 
// the last 10 reads if power is lost but it uses less power and is much faster!
#define SYNC_INTERVAL 5000 // mills between calls to flush() - to write data to the card
uint32_t syncTime = 0; // time of last sync()
RTC_PCF8523 rtc; // define the Real Time Clock object
// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;
#define ECHO_TO_SERIAL   1 // echo data to serial port
#define WAIT_TO_START 0 // Wait for serial input in setup()
// the logging file
File dataFile;
char fileName[13];

#include "quaternionFilters.h"
#include "MPU9250.h"

#define AHRS true         // Set to false for basic data read   ******if this is true it wont work at least on serial monitor
#define SerialDebug true  // Set to true to get Serial output for debugging

// Pin definitions
int intPin = 12;  // These can be changed, 2 and 3 are the Arduinos ext int pins
uint8_t dayCheck;

MPU9250 myIMU;

void error(char *str)
  Serial.print("error: ");

void setup() {
  Wire.setClock(400000L);//makes i2c faster
      if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  if (! rtc.initialized()) {
    Serial.println("RTC is NOT running!");
    // following line sets the RTC to the date & time this sketch was compiled
     rtc.adjust(DateTime(F(__DATE__), F(__TIME__)));
    Serial.print("Initializing SD card...");
  // make sure that the default chip select pin is set to
  // output, even if you don't use it:
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  Serial.println("card initialized.");

  // Read the WHO_AM_I register, this is a good test of communication
  byte c = myIMU.readByte(104, WHO_AM_I_MPU9250);//104 for implementation board 105 for chip
  if(c!=0xAC){//couldn't connect
    Serial.print("Couldn't connect to ICM20601 ");
// Calibrate gyro and accelerometers, load biases in bias registers
    myIMU.calibrateMPU9250(myIMU.gyroBias, myIMU.accelBias);
//initialize for active mode
    // Get magnetometer calibration from AK8963 ROM
      // Read the WHO_AM_I register of the magnetometer, this is a good test of
    // communication
   // byte d = myIMU.readByte(AK8963_ADDRESS, WHO_AM_I_AK8963);
    //Serial.print("AK8963 "); Serial.print("I AM "); Serial.print(d, HEX);
    //Serial.print(" I should be "); Serial.println(0x48, HEX);//uncomment these lines for debuggin purposes

void loop() {
  //the following is to make a name for the file
      sprintf(fileName,"0%c", now.month()+'0');
      uint8_t tensPlace=(;
        sprintf(fileName + strlen(fileName),"%c",(('0');
        sprintf(fileName + strlen(fileName),"%c",(('0');
        sprintf(fileName + strlen(fileName),"%c",(('0');
      sprintf(fileName + strlen(fileName),"%c",'0');
      sprintf(fileName + strlen(fileName),"0%c",'0');
  strcat(fileName + strlen(fileName), "20");
  uint8_t yearDecade=(now.year()%100-now.year()%10)/10;
      sprintf(fileName+strlen(fileName),"1%c", char(now.year()%10+'0'));
    else if(yearDecade==2){
      sprintf(fileName+strlen(fileName),"2%c", ((now.year()%10)-1)+'0');
    else if(yearDecade==3){
      sprintf(fileName+strlen(fileName),"3%c", now.year()%10+'0');
 else if(yearDecade==4){
      sprintf(fileName+strlen(fileName),"4%c", now.year()%10+'0');
   else if(yearDecade==5){
      sprintf(fileName+strlen(fileName),"5%c", now.year()%10+'0');
   else if(yearDecade==6){
      sprintf(fileName+strlen(fileName),"6%c", now.year()%10+'0');
   else if(yearDecade==7){
      sprintf(fileName+strlen(fileName),"7%c", now.year()%10+'0');
   else if(yearDecade==8){
      sprintf(fileName+strlen(fileName),"8%c", now.year()%10+'0');
     else if(yearDecade==9){
      sprintf(fileName+strlen(fileName),"9%c", now.year()%10+'0');
  else{sprintf(fileName + strlen(fileName),"0%c",now.year()%10+'0');}
  strcat(fileName + strlen(fileName), ".txt");
  // delay for the amount of time we want between readings
  delay((LOG_INTERVAL -1) - (millis() % LOG_INTERVAL));
//File dataFile =, FILE_WRITE);

      File dataFile =, O_CREAT | O_APPEND | O_WRITE);
if(dataFile){//if you could open file

    //get acceleration data
     if (myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01){//if there is new data to read
      myIMU.readAccelData(myIMU.accelCount);//reads the x/y/z adc values
      myIMU.getAres();//gets the acceleration resolution
      // Now we'll calculate the accleration value into actual g's
      // This depends on scale being set = (float)myIMU.accelCount[0] * myIMU.aRes; // - accelBias[0];
      myIMU.ay = (float)myIMU.accelCount[1] * myIMU.aRes; // - accelBias[1]; = (float)myIMU.accelCount[2] * myIMU.aRes; // - accelBias[2];
      myIMU.readGyroData(myIMU.gyroCount);  // Read the x/y/z adc values
      // Calculate the gyro value into actual degrees per second
      // This depends on scale being set
      myIMU.gx = (float)myIMU.gyroCount[0] * myIMU.gRes; = (float)myIMU.gyroCount[1] * myIMU.gRes;
      myIMU.gz = (float)myIMU.gyroCount[2] * myIMU.gRes;
     }//if(myIMU.readByte(MPU9250_ADDRESS, INT_STATUS) & 0x01)
     // Must be called before updating quaternions!
        // Print acceleration values in milligs!
        dataFile.print(now.hour(), DEC);
        dataFile.print(now.minute(), DEC);
        dataFile.print(now.second(), DEC);
        dataFile.print(" X-acceleration:"); dataFile.print(1000 *;
        dataFile.print(" Y-acceleration: "); dataFile.print(1000 * myIMU.ay);
        dataFile.print(" Z-acceleration: "); dataFile.print(1000 *;
        dataFile.print("gx = ");dataFile.print(myIMU.gx, 2);
        dataFile.print(" gy = "); dataFile.print(, 2);
        dataFile.print(" gz = "); dataFile.print( myIMU.gz, 2);
        dataFile.println(" deg/s");

With that delay() call you limit yourself to 2 Hz.

The speed didn't change after commenting out that line.

Closing and reopening a file on SDcard is very expensive in time. You should only close and open when the filename changes. You could also elect to flush less often too, that would help.