SD.h compared to SdFat.h


Much is written about the advantages and disadvantages of those libraries. In this study, I inserted #ifdef wherever necessary to compile and excute with either linbrary. The differences are not tremendous.

/*
 * compiles with eiter library, SD.h or SdFat.h
 * SD converts filename to UPPER, SdFat ratains it
 *               SD.h    SdFat.h
 * FLASH usage  21528     21028
 * SRAM usage    1199      1159
 * 
 * to modify edit the next line */
#define SDFA T


// === Libraries === :

#ifdef SDFAT
#include <SdFat.h>
#else
#include <SD.h>
#endif

#include <Wire.h>
#include <RTClib.h>

#include <DallasTemperature.h>

// === variables === :
/* SD:
   SPI
   CS:   Pin-10
   MOSI: Pin-11
   MISO: Pin-12
   SCK:  Pin-13
*/
#ifdef SDFAT
const byte chipSelect = SS;
SdFat sd;
SdFile file;
#else
const byte chipSelect = 10;
File root;
#endif

char filename[] = "GradC001.csv";

/* RTC:
  I2C
  SDA:  Pin-A4
  SCL:  Pin-A5
*/
RTC_DS1307 RTC;

// DS1820:
const byte pin1 = 9;
OneWire wire1(pin1);
DallasTemperature sensor1(&wire1);
DeviceAddress da1;

// other:
const long dt     = 100;
long t            = millis() + dt;
boolean RECORDING = false;

void setup() {
  Serial.begin(9600);
  Serial.println(F(__FILE__));
#ifdef SDFAT
  if (!sd.begin(chipSelect, SPI_HALF_SPEED)) sd.initErrorHalt();
  Serial.println(F("Library: SdFat.h"));
#else
  if (!SD.begin(chipSelect)) {
    Serial.println(F("Card failed, or not present"));
    while (true);
  }
  Serial.println(F("Library: SD.h"));
#endif
  Serial.println(F("SD o.k.\nExisting files:"));
  //=========--
  printDirectory();
  Serial.print(F("free RAM:_"));
  Serial.println(freeRam());
  /* */
  // === NEXT FILE NAME === :
#ifdef SDFAT
  while (sd.exists(filename)) incFileNum();
#else
  while (SD.exists(filename)) incFileNum();
#endif
  Serial.print(F("File name is: "));
  Serial.println(filename);
  // === TIME === :
  Wire.begin();
  RTC.begin();
  if (!RTC.isrunning()) {
    Serial.println(F("RTC is NOT running!"));
    /* following line sets the RTC to the
      date & time this sketch was compiled */
    RTC.adjust(DateTime(__DATE__, __TIME__));
  }
  // der Parameter fileDateTime ist die Callback-Funktion
  SdFile::dateTimeCallback(fileDateTime);
  Serial.println(F("S3 = RECORD, S2 = STOP"));
  // === SENSOR === :
  sensor1.begin();
  sensor1.getAddress(da1, 0);
  sensor1.setResolution(da1, 12);
}

void loop() {
  if (digitalRead(A2) == 0 && RECORDING) {
    RECORDING = false;
    Serial.println(F("STOP"));
  }
  if (digitalRead(A3) == 0 && !RECORDING) {
    RECORDING = true;
    Serial.println(F("START RECORD"));
  }
  if (millis() < t) return;
  t = millis() + dt;
  if (!RECORDING) return;
  // read sensor:
  sensor1.requestTemperatures();
  float val1 = sensor1.getTempC(da1);
  Serial.println(val1); // for Serial plotter
  //store value:
#ifdef SDFAT
    boolean b = file.open(filename, FILE_WRITE);
    if (b)
#else
    File file = SD.open(filename, FILE_WRITE);    
    if (file)
#endif    
    {
      String s = String(val1);
      for (byte i = 0; i < s.length(); i++)
        if (s[i] == '.') s[i] = ',';
      file.println(s); // for Excel
      file.close();
    }
    // if the file isn't open, pop up an error:
    else {
      Serial.print(F("error opening "));
      Serial.println(filename);
    }
}

// generate next file name (001 - 999):
void incFileNum() {
  filename[7]++;
  if (filename[7] > '9') {
    filename[7] = '0';
    filename[6]++;
    if (filename[6] > '9') {
      filename[6] = '0';
      filename[5]++;
    }
  }
}

//void printDirectory(File dir, int numTabs) {
void printDirectory() {
#ifdef SDFAT
  dir_t eintrag; // must be declared before loop!
  // open next file in root.  The volume working directory, vwd, is root
  while (file.openNext(sd.vwd(), O_READ)) {
    char name[13];
    file.dirName(&eintrag, name);
    file.dirEntry(&eintrag);
    char groesse[8]; // max 99.000.000
    ltoa(eintrag.fileSize, groesse, 10);
    byte L = strlen(name) + strlen(groesse);
    Serial.print(name);
    if (file.isDir()) Serial.println(F("/")); // no recursion
    else {
      for (byte i = L; i < 21; i++) Serial.print(F(" "));
      Serial.print(groesse);
      Serial.print(F("b ")); // bytes
      word time = eintrag.lastWriteTime;
      print2(FAT_HOUR(time), ':');
      print2(FAT_MINUTE(time), ':');
      print2(FAT_SECOND(time), ' ');
      word date = eintrag.lastWriteDate;
      print2(FAT_DAY(date), '.');
      print2(FAT_MONTH(date), '.');
      print2(FAT_YEAR(date) % 100, '\n');
      file.close();
    }
  }
#else  
  File dir = SD.open("/");
  while (true) {
    File entry = dir.openNextFile();
    if (!entry) {
      //if (numTabs == 0) 
      Serial.println(F("** Done **"));
      return;
    }
    //for (byte i = 0; i < numTabs; i++) Serial.print(F("\t"));
    char groesse[8];
    ltoa(entry.size(), groesse, 10);
    byte L = strlen(entry.name()) + strlen(groesse);
    Serial.print(entry.name());
    if (entry.isDirectory()) Serial.println(F("/"));
    else {
      for (byte i = L; i < 21; i++) Serial.print(F(" "));
      Serial.print(groesse);
      Serial.println(F("_b"));
    }
    entry.close();
  }
#endif  
}

void print2(byte x, char c) {
  if (x < 10) Serial.print(0);
  Serial.print(x);
  Serial.print(c);
}

/*This function returns the date and time
  for SD card file access and modify time */
void fileDateTime (word* date, word* time) {
  DateTime now = RTC.now();
  *date = FAT_DATE(now.year(), now.month(), now.day());
  *time = FAT_TIME(now.hour(), now.minute(), now.second());
}

int freeRam () {
  extern int __heap_start, *__brkval;
  int v;
  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
}



contact: nji(at)gmx.de