How to speed up the SD writing and saving code

Hi,

I am capturing EMG values for muscle spasm on a cheek. I want to capture values every 2ms. I am currently using a Arduino Due but have been using a Arduino Uno also.

I have arranged and rearranged my code many times, trying to make it more efficient. The slowest part of the code is the SD.open and the SD.close. I can dataFile.println three analogRead values to the SD card in about 100 microseconds (I have three sensors). But, after taking the values of 3 sensors, 100 times, I call for the SD.close, in order to save what I have, but that takes about 15-20 milliseconds to complete. How can I make my code more efficient? (code is posted below) Is there a way to write to the SD card faster so that i can go at a rate of 2ms or is this just not feasible. I thought with the Due it might work but it hasnt proved to be much faster. Any insight is much appreciated.

void loop() {
  // make a string for assembling the data to log:
  File dataFile = SD.open("moooppp.csv", FILE_WRITE);
  
   if (dataFile) {
     for(int i = 0; i<100; i++){
    // read three sensors and append to the sd:
      for (int analogPin = 0; analogPin < 3; analogPin++) {
       int sensor = analogRead(analogPin);
       dataFile.println(sensor);
       if(analogPin == 2){
        t=micros();
        dataFile.println(t);
        }
    }
  }
    dataFile.close();
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
  
}

Did u try flush() and keep the file Open all the time?

You write

I want to capture values every 2ms

but u dont have a time management. For me it looks like you’re reading as fast as you can and the speed is throttled by slow writing on the sd card.

To load analog data earliest after 2 millis, you can use the following.

          unsigned long start_ = millis();
          for(int i = 0; i<100; i++){//read three sensors and append to the sd:
            for (int analogPin = 0; analogPin < 3; analogPin++) {
              dataFile.println(analogRead(analogPin));
              if(analogPin == 2){
                dataFile.println(micros());
                while(millis() < start_ + ((i+1) * 2)){ }//simple wait up to 2 ms
              }
            }
          }

I have testet with MKR Zero (48Mhz):
open file + get analog values + println + close file → total duration: ~216 millis

opening file takes: 7 millis
closing file takes: 17 millis

by the way, flush() takes 17 millis too. it does not make sense to change the code for only flushing.

int sensor = analogRead(analogPin);//total 300x takes total ~110 millis
dataFile.println(…);//total 300x takes total ~80 millis

Total time for analogRead() + file.println() takes ~190 millis!!!
the ~17 millis for writing is just a small part of your time. u are writing 2400 bytes (imho bad for ur raw data) in 17 millis. so the performance is 137,87 kb/sec! thats ok.

But why does it bother you to wait 17 millis? Do you want to read and write continually values? It’s difficult if it’s unknown what you’re up to.

If u want to speed up the writing, u should try the following:

  1. check the performance with different libraries (SD, SdFat, SdFatEx)
  2. check the performance with different file classes (File, SdFile, FatFile) of the different libraries
  3. try to save 512 byte blocks (it can be much faster, check my thread 485894, even if I only read)
  4. try to reduce the amount of data and only write byte data (e.g. convert the 1024 int value to 2x byte, then only write fix 2x byte without \r\n delimer)
  5. simple preallocate filedata (speed’s up flush / file close by up to 50%: 7-9 millis vs 17 millis)