SD library - speed

Status
Not open for further replies.

jacko91

Active member
Hey
I am using the datalogger example from the sd library with the teensy 3.5:

Code:
/*
  SD card datalogger
 
 This example shows how to log data from three analog sensors 
 to an SD card using the SD library.
 	
 The circuit:
 * analog sensors on analog ins 0, 1, and 2
 * SD card attached to SPI bus as follows:
 ** MOSI - pin 11, pin 7 on Teensy with audio board
 ** MISO - pin 12
 ** CLK - pin 13, pin 14 on Teensy with audio board
 ** CS - pin 4,  pin 10 on Teensy with audio board
 
 created  24 Nov 2010
 modified 9 Apr 2012
 by Tom Igoe
 
 This example code is in the public domain.
 	 
 */

#include <SD.h>
#include <Metro.h>

Metro data_exchange=Metro(5);
uint32_t time1, time2;

// On the Ethernet Shield, CS is pin 4. Note that even if it's not
// used as the CS pin, the hardware CS pin (10 on most Arduino boards,
// 53 on the Mega) must be left as an output or the SD library
// functions will not work.

// change this to match your SD shield or module;
// Arduino Ethernet shield: pin 4
// Adafruit SD shields and modules: pin 10
// Sparkfun SD shield: pin 8
// Teensy audio board: pin 10
// Teensy 3.5 & 3.6 on-board: BUILTIN_SDCARD
// Wiz820+SD board: pin 4
// Teensy 2.0: pin 0
// Teensy++ 2.0: pin 20
const int chipSelect = BUILTIN_SDCARD;

void setup()
{

  
 // Open serial communications and wait for port to open:
  Serial.begin(9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }


  Serial.print("Initializing SD card...");
  
  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
}

void loop()
{
  // make a string for assembling the data to log:
  String dataString = "";

  // read three sensors and append to the string:
  for (int analogPin = 0; analogPin < 3; analogPin++) {
    int sensor = analogRead(analogPin);
    dataString += String(sensor);
    if (analogPin < 2) {
      dataString += ","; 
    }
  }

  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }  
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  } 
  time2=time1;
  time1=millis();
  if(data_exchange.check()){
    Serial.println(time1-time2);
  }
}
it takes between 5-20ms for each saving routine. Is that normal? Is it possible to do faster savings?

Thanks
 
Possible optimizations are :
- Open the file once and keep it open instead of opening and closing it in each loop run.
- Save the to-be-logged Data in RAM first and write only full 512 byte blocks to SD.
 
I am still a bit confused about the SD and SDFAT libraries. The SDFAT one is the faster one, and it even enables DMA. The SD library works since Paul has modified it. Does the SDFAT work with the teensy?
 
Many paths lead to Rome. Each library has it‘s particular advantages. It’s up to you to decide (and/or make tests) in your specific project use case to find the optimal solution.
 
Thanks,
when I do the bench test I get:
Code:
write speed and latency
speed,max,min,avg
KB/Sec,usec,usec,usec
13088.17,13039,32,37
12952.54,12960,33,38

I then modified the bench test to simple writing to the card:
Code:
#include <Metro.h>
#include "SdFat.h"
#include "sdios.h"
#include "FreeStack.h"
SdFatSdioEX SD;

SdFile file;
#define error(s) SD.errorHalt(F(s))
Metro dataex=Metro(5);

const size_t BUF_SIZE = 512;
uint8_t buf[BUF_SIZE];
uint32_t time1=0;
uint32_t time2=0;
String dataString="";
void setup() {
   for (size_t i = 0; i < (BUF_SIZE-2); i++) {
    buf[i] = 'A' + (i % 26);
  }
  buf[BUF_SIZE-2] = '\r';
  buf[BUF_SIZE-1] = '\n';
  // Open serial communications and wait for port to open:
  Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
  }
  Serial.print("Initializing SD card...");

  if (!SD.begin()) {
    Serial.println("initialization failed!");
    return;
  }
  Serial.println("initialization done.");
  time1=micros();
  time2=micros();
  SD.remove("bench.dat");
}

void loop() {
  time2=time1;
  time1=micros();
   // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  if (!file.open("bench.dat", O_RDWR | O_CREAT | O_TRUNC)) {
    error("open failed");
    file.close();
  }
  file.truncate(0);
  // if the file opened okay, write to it:
  file.write(buf, sizeof(buf));
  file.close();

  if(dataex.check()){
    Serial.println(time1-time2);
  }
}

I then get writing times of
7ms to 14ms.
Am I missing something?
 
You are again opening, truncating and closing the file during each loop run. What an unnecessary waste of time...

Symbolic code:
open the File
start = millis
loop 1000 times {
write something
}
time = (millis - start)/1000
 
Hey,
I removed truncate and closing.
Code:
  if(opened==false){
  if (!file.open("bench.dat", O_RDWR | O_CREAT | O_TRUNC)) {
    error("open failed");
    file.close();
  }
  opened=true;
  }
  else{
  // if the file opened okay, write to it:
  file.write(buf, sizeof(buf));

  }


I now get around 40us mostly. Thats awesome. But sometimes It takes up to 10 or 50ms. Any hints to that?
 
Alright,
stupid me. So I want to make a datalogger which writes every 5ms data to sd card. But in the last attempt I always wrote as fast as possible. Now I have include that I only write every 5ms and now it constantly need 40us to write. I guess the problem with writing afap was that the sd card was not always ready.
Thanks guys.
 
This line looks misplaced in post #9? :: opened=true;

Are the 5ms writes all 512 bytes? If the card ever does 'management' there will be times it won't complete that fast.
 
Okay - may it is properly handled outside the snippet - otherwise next time through it will try to write to a closed file … marked opened
 
Status
Not open for further replies.
Back
Top