SD and SDFat Compatibility?

Hi,

I'm using the Adafruit VS1053 MP3 Player library ( GitHub - adafruit/Adafruit_VS1053_Library: This is a Arduino library for the Adafruit VS1053 Codec Breakout and Music Maker Shields ) which includes <SD.h> in the .h and .cpp files.

I want to use SDFat in my Sketch in order to give myself long filename support. The SDFat readme says that, to make SDFat compatible with SD, I should include the following to the Sketch:

//remove #include <SD.h>

#include <SDFat.h>
SDFat SD

If I add those lines to the Sketch, VS1053.h complains that "File" doesn't name a type.

If I add the lines to the Sketch and VS1503.cpp, then VS1503.h complains about Redefinition of 'SdFat SD'

If I change the 'constructor' in VS1503.h to 'SdFat SD1' and change the references to SD within VS1503.cpp to SD1 it does compile without error BUT the Sketch obviously doesn't pass the "File" filename to VS1503.cpp as SD and SD1 are now two different things.

Any advice would be appreciated,

Thanks,

John.

There needs to be only one SD object. In the SD.h library it is declared in SD.cpp and SD.h has an extern definition of SD.

You can achieve this by making the following changes.

In Adafruit_VS1053.h comment out SD.h and include SdFat.h.

//#include <SD.h>
#include <SdFat.h>

In Adafruit_VS1053.cpp comment out SD.h, include SdFat.h, and add an extern for SD.

//#include <SD.h>
#include <SdFat.h>
extern SdFat SD;

In your sketch comment out SD.h, include SdFat.h, and define SD.

//#include <SD.h>
#include <SdFat.h>
SdFat SD;

I am considering an option to define SD in the SdFat library. This would need to be a configuration option since SdFat now has three classes that could define the SD object. There is the standard SdFat class, the SdFatSoftSpi template for fast software SPI, and the SdFatLibSpi class that uses the standard Arduino SPI library.

I would add a symbol in SdFatConfig.h, say DEFINE_SD_OBJECT. When DEFINE_SD_OBJECT is defined nonzero like this, SD would be defined as in SD.h.

#define DEFINE_SD_OBJECT 1

You would only need to replace all SD.h includes with SdFat.h.

Unfortunately there is a huge amount of SdFat code and examples with a lower case sd.

SdFat sd;

Maybe I should just put the extern in SdFat.h and depend on the user to declare SD. Then you would change all includes from SD.h to SdFat.h and declare SD in your sketch.

It appears that the VS1053 MP3 Player library may use SPI transactions. You can enable SPI transactions in SdFat by editing SdFatConfig.h and setting ENABLE_SPI_TRANSACTION nonzero in this define.

#define ENABLE_SPI_TRANSACTION 1

Thank you :slight_smile:

It was 'extern' that I was missing.

Perhaps just an addition to your Readme explaining how to handle libraries which use #include <SD.h> would be simplest for novices like me :slight_smile:

I've also changed #define ENABLE_SPI_TRANSACTION 1 in SdFatConfig.h but I couldn't see SdFatConfig.h in SdFat.h or SdFat.cpp, do I need to #include it explicitly in my Sketch? It compiles with or without it.

Thanks,

John.

SdFatConfig.h is included automatically, you don't need to included it from your program.

Perhaps just an addition to your Readme explaining how to handle libraries which use #include <SD.h> would be simplest for novices like me

I will add a section in the html documentation on moving from SD.h to SdFat. Your experience helps me understand what I need to add in the section.

Too bad a newer SdFat can't replace the five year old version that is the base for SD.h.

Hi,

I also would like to use your new SdFat library with the same Adafruit library mentionned in post#1. For the recording example (record_ogg.ino). I am using an Arduino Mega.

I have made all replacement within the .ino and .cpp :

//#include <SD.h>
#include <SdFat.h>
extern SdFat SD;

and for .h

//#include <SD.h>
#include <SdFat.h>

I have also edit the SdFatConfig.h (value of 1).

But when I launch the code checking, I am having a compilation error :

Adafruit VS1053 Library\Adafruit_VS1053.cpp.o:(.bss.SD+0x0): multiple definition of `SD'
record_ogg.cpp.o:(.bss.SD+0x0): first defined here
e:/program files (x86)/arduino/hardware/tools/avr/bin/../lib/gcc/avr/4.8.1/../../../../avr/bin/ld.exe: Disabling relaxation: it will not work with multiple definitions
collect2.exe: error: ld returned 1 exit status

I have deleted th SD library from the Arduino libraries directrory as well as from the Arduino sketches libraries

Any advice ?

Thanks

Franck

SD.h must still be included in some .h or .cpp file. SD.h includes must be replace for all files used in the project. Check all library files.

You need this in the .ino file.

// #include <SD.h>
#include <SdFat.h>
SdFat SD;

In every .cpp and .h file replace the SD.h include like this.

// #include <SD.h>
#include <SdFat.h>
extern SdFat SD;

Thank you, problem solved.

I'm keen to convert my medium sized sketch to use SdFat rather than SD library for the long file names and higher log rates. Ive followed above suggestions and did this:

//#include <SD.h>                               // SD library
#include <SdFat.h>                                      // better SD library 
SdFat SD;

but I think I've stumbled on an unlucky conflict between SdFat and Streaming libraries. Here's the compilation error report:

Arduino: 1.6.8 (Windows 10), Board: "Arduino/Genuino Uno"
In file included from D:\10 CJ base\02 ARDUINO\Sketches\AdaSDlog\xMISC.ino:31:0:
D:\10 CJ base\02 ARDUINO\Sketches\libraries\Streaming/Streaming.h:100:21: error: 'endl' redeclared as different kind of symbol
enum _EndLineCode { endl };

  • ^*
    In file included from D:\10 CJ base\02 ARDUINO\Sketches\libraries\SdFat/utility/bufstream.h:27:0,
  • from D:\10 CJ base\02 ARDUINO\Sketches\libraries\SdFat/utility/ArduinoStream.h:29,*
  • from D:\10 CJ base\02 ARDUINO\Sketches\libraries\SdFat/utility/FatLib.h:23,*
  • from D:\10 CJ base\02 ARDUINO\Sketches\libraries\SdFat/SdFat.h:27,*
  • from D:\10 CJ base\02 ARDUINO\Sketches\AdaSDlog\xMISC.ino:30:*
    D:\10 CJ base\02 ARDUINO\Sketches\libraries\SdFat/utility/iostream.h:40:17: error: previous declaration of 'ostream& endl(ostream&)'
    inline ostream& endl(ostream& os) {
  • ^*
    exit status 1
    Error compiling for board Arduino/Genuino Uno

I really like Mikal Harts' the Streaming library for it's easy syntax and often it actually makes code smaller compared to using Serial.print . So I'm not at all keen to ditch it.

Any and all suggestions welcomed
TIA

You can remove endl from SdFat by editing iostream.h. Remove endl at about line 40.

Delete this code.

/** insert endline
 * \param[in] os The Stream
 * \return The stream
 */
inline ostream& endl(ostream& os) {
  os.put('\n');
#if ENDL_CALLS_FLUSH
  os.flush();
#endif  // ENDL_CALLS_FLUSH
  return os;
}

You will no longer be able to use endl in SdFat.  Just use the string "\n".

easy fix - compiling OK now. Many thanks. (I already use and prefer '\n' anyway)

Another issue you may able to help with. Even if using SdFat in my sketch when I try to copy the CSV file from microSD card to my windows PC I often have an error pop up indicating file corruption. If I scan & repair the SD using the iCare Data Recovery Pro tool utility I can copy and read the CSV file OK.

This doesn't happen every time, but seems to happen most times lately, on several different microSD cards, and quick format makes no difference. (Note it was occasionally happening before I moved to from SD.h to SdFat.h too)

here is my SD writing function:

void addLogEntry(){
  entryNo++;
  char timeStamp[14];                                    // "MM,DD,HH,mm,ss" used in logging
  sprintf(timeStamp, "%02d,%02d,%02d,%02d,%02d",LOCmon,LOCday,LOChour,LOCmin,LOCsec);
  File dataFile = SD.open(logFileName, FILE_WRITE);
  if (dataFile){
    dtostrf(entryNo,3,0,valBuffer);              dataFile.print(valBuffer); dataFile.print(","); // entryNo. (NB: only displays 3 digits)
                                                 dataFile.print(timeStamp); dataFile.print(","); 
                                                 dataFile.print(F("DDD"));  dataFile.print(","); 
    dtostrf(GPS.latitudeDegrees, 7,6,valBuffer); dataFile.print(valBuffer); dataFile.print(","); // latitude,
    dtostrf(GPS.longitudeDegrees,7,6,valBuffer); dataFile.print(valBuffer); dataFile.print(","); // longitude,
    dtostrf(GPSkph,5,2,valBuffer);               dataFile.print(valBuffer); dataFile.print(","); // kph,
    dtostrf(GPS.angle,3,0,valBuffer);            dataFile.print(valBuffer); dataFile.print(","); // compass heading,
    dtostrf(GPS.altitude,3,0,valBuffer);         dataFile.print(valBuffer); dataFile.println();    // altitude\n
                Serial.print(F("write: ")); Serial.print(entryNo); Serial.print("/");Serial.println(timeStamp);} // and report progress
  else         {Serial.print(F("LOG OPEN FAIL [")); Serial.println(logFileName);}
  dataFile.close();
  }

I've attached whole sketch if you need to see it.

Any clues appreciated!

AdaSDlog.j.zip (9.71 KB)