How to use SdFat Library with Teensy 4.1 Built-In SD Slot

Status
Not open for further replies.

grinch

Well-known member
Hi, does anyone have an example of how to use the SdFat library with the Teensy 4.1's built-in SD card slot? This is related to my last question, but I think this specific piece of information may be the key to getting my project working, so I thought it was worth a separate post.

In the past I've just used the Teensy's SD.h library, and it has worked fine for everything I've wanted to do. Now however I need to use a library that is built around the SdFat library, so I need to switch over to that unless I want to rewrite a ton of library code.

As far as I can tell, these libraries have extremely similar functionality, most of the difference being some small points of syntax, which is where I'm getting tripped up. The SdFat library has an example for Teensy, but frankly it's a convoluted mess, and I can't for the life of me tell what it's even attempting to demonstrate ��. A clear example for how to open the SD card on the Teensy 4.1 would be extremely helpful to me, and I think to others as well.

TLDR: All I need to know is how to properly replicate the "SD.begin(BUILTIN_SDCARD)" function using the SdFat library, and the rest will fall into place. Can anyone share this one line of code?
 
Update to TeensyDuino 1.54 Beta 6 - Job Done.

It has replaced the SD.h CODE with SdFat ( Beta version 2.0.1 )

That may not expose anything and everything ? But anything SD.h had AFAIK is mapped into SdFat - tremendous speed increase - and as possible mapping to work with SdFat should work.

Find an issue and post it on the Beta thread.

No idea what other question - not linked and since related quite possible this answer would have applied there if kept on that thread ...
 
The begin function from the midi file library requires a pointer to the SdFat object. Trying to use the SD object throws an error, even when I updated to version 1.54 beta 6:

Library definition of begin code:
Code:
void MD_MIDIFile::begin(SdFat *psd)
{
  _sd = psd;
}

Here is some code showing how the error is generated.

Code:
#include <SD.h>
#include <MD_MIDIFile.h>

MD_MIDIFile SMF;

void setup(){
  // Initialize SD
  if (!SD.begin(BUILTIN_SDCARD))
  {
    DEBUGS("\nSD init fail!");
    while (true) ;
  }
  // Initialize MIDIFile
  SMF.begin(&SD); // <<<< this line throws an error
  SMF.setMidiHandler(midiCallback);
  SMF.looping(true);
}

Here is the error:

Code:
MD_MIDIFile_Loop_TeensyBuiltin: In function 'void setup()':
MD_MIDIFile_Loop_TeensyBuiltin:83: error: no matching function for call to 'MD_MIDIFile::begin(SDClass*)'
   SMF.begin(&SD);
 
Any ideas what I can do to fix this or work around this?

Is there a way I can get the built-in Teensy SD library to work with the Midi file library?

Is there a way I can get the SDFat library to work with the Teensy 4.1's built-in SD slot?
 
I'm not familiar with this MD_MIDIFile library. Can you give me a link?


Any ideas what I can do to fix this or work around this?

Yes, there is a workaround. But since this is beta, I'm imagining maybe adding a little code to make this nicer for you and everyone else in the future. That's why I'm asking for the link to the code you're using...
 
Try using this copy of SD.h (with 1.54-beta6, not 1.53). Put it in {Arduino}/hardware/teensy/avr/libraries/SD/src. On Windows, the default Arduino location is C:\Program Files (x86)\Arduino.

Please let me know if this fully solves the problem? Will put it into 1.54-beta7 if it works....
 

Attachments

  • SD.h
    6.2 KB · Views: 161
FWIW, I got it to compile without error on this (based on msg #4). No way to know if it really works, as I'm not up to speed on using this library. Depending on you for that feedback.

Code:
#include <SD.h>
#include <MD_MIDIFile.h>

MD_MIDIFile SMF;

void setup(){
  // Initialize SD
  if (!SD.begin(BUILTIN_SDCARD))
  {
    //DEBUGS("\nSD init fail!");
    while (true) ;
  }
  // Initialize MIDIFile
  SMF.begin(&(SD.sdfs)); // <<<< this line throws an error
  //SMF.setMidiHandler(midiCallback);
  SMF.looping(true);
}

void loop() {
}
 
Try using this copy of SD.h (with 1.54-beta6, not 1.53). Put it in {Arduino}/hardware/teensy/avr/libraries/SD/src. On Windows, the default Arduino location is C:\Program Files (x86)\Arduino.

Please let me know if this fully solves the problem? Will put it into 1.54-beta7 if it works....

Okay, I'll try this. Do you know where I might be able to locate this folder on OSX? Is this folder inside the contents of the Teensy program itself (stuff revealed by right click > show package contents on Teensyduino icon), or is this a different application support folder?
 
Yup, show package contents, then look for "hardware" inside Contents/Java.

If you're on Catalina or Big Sur, changing any file will break the digital signature which Gatekeeper checks. Usually not a problem if you don't move Arduino anywhere else on your computer. But Apple is regularly tightening security with each update, so best to rename this copy before you edit so you'll later remember it's been edited and might trigger Apple security warnings in the future.
 
Okay, I replaced SD.h in the location "Teensyduino.app/Contents/Java/hardware/teensy/avr/libraries/SD/src/SD.h" I'm still getting the same error when I try to compile. Tried restarting Teensyduino after changing out the file, but it didn't appear to make a difference. Anything else I should check?

For reference here is the complete code I'm using to test this. Just modifying the MidiFileLoop example from the Midi File library to use the built-in SD lib in place of SD fat:

Code:
// Play a file from the SD card in looping mode, from the SD card.
// Example program to demonstrate the use of the MIDFile library
//
// Hardware required:
//  SD card interface - change SD_SELECT for SPI comms

#include <SD.h>
#include <MD_MIDIFile.h>

#define USE_MIDI  1  // set to 1 for MIDI output, 0 for debug output

#if USE_MIDI // set up for direct MIDI serial output

#define DEBUGS(s)
#define DEBUG(s, x)
#define DEBUGX(s, x)
#define SERIAL_RATE 31250

#else // don't use MIDI to allow printing debug statements

#define DEBUGS(s)     Serial.print(s)
#define DEBUG(s, x)   { Serial.print(F(s)); Serial.print(x); }
#define DEBUGX(s, x)  { Serial.print(F(s)); Serial.print(x, HEX); }
#define SERIAL_RATE 57600

#endif // USE_MIDI


// SD chip select pin for SPI comms.
// Arduino Ethernet shield, pin 4.
// Default SD chip select is the SPI SS pin (10).
// Other hardware will be different as documented for that hardware.
const uint8_t SD_SELECT = 10;

#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))

// The files in the tune list should be located on the SD card 
// or an error will occur opening the file and the next in the 
// list will be opened (skips errors).
const char *loopfile = "LOOPDEMO.MID";  // simple and short file

MD_MIDIFile SMF;

void midiCallback(midi_event *pev)
// Called by the MIDIFile library when a file event needs to be processed
// thru the midi communications interface.
// This callback is set up in the setup() function.
{
#if USE_MIDI
  if ((pev->data[0] >= 0x80) && (pev->data[0] <= 0xe0))
  {
    Serial.write(pev->data[0] | pev->channel);
    Serial.write(&pev->data[1], pev->size-1);
  }
  else
    Serial.write(pev->data, pev->size);
#endif
  DEBUG("\nM T", pev->track);
  DEBUG(":  Ch ", pev->channel+1);
  DEBUGS(" Data");
  for (uint8_t i=0; i<pev->size; i++)
  {
    DEBUGX(" ", pev->data[i]);
  }
}

void setup(void)
{
  int  err;

  Serial.begin(SERIAL_RATE);

  DEBUGS("\n[MidiFile Looper]");

  // Initialize SD
  if (!SD.begin(BUILTIN_SDCARD))
  {
    DEBUGS("\nSD init fail!");
    while (true) ;
  }

  // Initialize MIDIFile
  SMF.begin(&SD);
  SMF.setMidiHandler(midiCallback);
  SMF.looping(true);

  // use the next file name and play it
  DEBUG("\nFile: ", loopfile);
  err = SMF.load(loopfile);
  if (err != MD_MIDIFile::E_OK)
  {
    DEBUG("\nSMF load Error ", err);
    while (true);
  }
}

void loop(void)
{
  // play the file
  if (!SMF.isEOF())
  {
    SMF.getNextEvent();
  }
}
 
Anything else I should check?

Maybe somewhere in the stuff Arduino prints is a message about duplicate libraries? It's supposed to tell you the full path of the SD lib it's actually using, and the location of any others it ignored.

If you don't see that message, use File > Preferences to turn on verbose output while compiling.

Those full paths are the way to make sure you're editing the right file. Easiest thing is to open the SD.h file and intentionally add a syntax error. If you see the error with that exact line appear, then you know you've got the file Arduino is actually using.
 
Maybe somewhere in the stuff Arduino prints is a message about duplicate libraries? It's supposed to tell you the full path of the SD lib it's actually using, and the location of any others it ignored.

If you don't see that message, use File > Preferences to turn on verbose output while compiling.

Those full paths are the way to make sure you're editing the right file. Easiest thing is to open the SD.h file and intentionally add a syntax error. If you see the error with that exact line appear, then you know you've got the file Arduino is actually using.

I actually do get a message about duplicate libraries, but when I read the message it appears to says the used copy and the alternative copy are both the same filepath:

Code:
Multiple libraries were found for "SD.h"
 Used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/hardware/teensy/avr/libraries/SD
 Not used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/libraries/SD

Any idea what might be going on here? Or where I can find the SD library I should actually be editting?
 
This first one is correct - installed with TeensyDuino
Used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/hardware/teensy/avr/libraries/SD

This second is the copy Arduino itself supplies - not for Teensy:
Not used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/libraries/SD
 
This first one is correct - installed with TeensyDuino
Used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/hardware/teensy/avr/libraries/SD

This second is the copy Arduino itself supplies - not for Teensy:
Not used: /private/var/folders/j0/_sxbhppj1b9bmytyldk9lt600000gp/T/AppTranslocation/3127E6DE-31DD-4821-B385-FE0225410D7C/d/Teensyduino_BetaEdit.app/Contents/Java/libraries/SD

Okay, thanks for catching that. The extremely long file path where almost everything is the same is easy to misread. So this indicates that I'm using the correct folder, which should have the updated SD.h file.
 
You also need this, to convert SD to SdFat type

SMF.begin(&(SdFat &)SD);

This worked for me. After replacing the SD file in the folder you specified and changing this line in my midi code it compiles. Thank you!

Is there an estimate on when the new file will be incorporated into a downloadable Teensyduino release? Into a beta and a stable release respectively? This firmware is for an open ended hardware platform that I'm going to release to the public so to speak, so having an easy setup is important. Just wondering so I can adjust my project timeline accordingly.

Really appreciate everyone's quick responses on this and being so willing to work with me in-depth.
 
Is there an estimate on when the new file will be incorporated into a downloadable Teensyduino release? Into a beta and a stable release respectively?

I've committed the code on github, so it'll certainly be in future releases.

https://github.com/PaulStoffregen/SD/commit/bd9b8316df6940691ae866c2c44606c7579e7fe7

Timing of future releases is difficult to predict. Anything I say right now will probably turn out to be wrong. With that in mind, 1.54-beta7 is probably a couple weeks away. Timing for a final 1.54 release is much less certain. It is long overdue, but substantial issues remain with MTP which I really want to resolve for 1.54.



If you have any contact with Marco Colli (author of MD_MIDIFile) or whoever is maintaining it, this usage could be much cleaner if another begin() function is added which takes a C++ reference.

For example, in MD_MIDIFile.h:

Code:
  void begin(SdFat *psd);
  void begin(SdFat & sd);

and in MD_MIDIFile.cpp:

Code:
void MD_MIDIFile::begin(SdFat *psd)
{
  _sd = psd;
}

void MD_MIDIFile::begin(SdFat & sd)
{
  _sd = &sd;
}

With this change, user-level code would not need to (but still could) use the "&" pointer syntax. Then the sketch could could be:

Code:
  SMF.begin(SD);

The compiler is smarter about inferring the desired type of SdFat and converts Teensy's SD to SdFat automatically without any extra (somewhat ugly) syntax.

When / if Arduino and others migrate from the ancient SD to SdFat, if they use Teensy's SD.h or build something similar, hopefully they'll gain similar ability to allow SD to be used with MD_MIDIFile.
 
I've committed the code on github, so it'll certainly be in future releases.

https://github.com/PaulStoffregen/SD/commit/bd9b8316df6940691ae866c2c44606c7579e7fe7

Timing of future releases is difficult to predict. Anything I say right now will probably turn out to be wrong. With that in mind, 1.54-beta7 is probably a couple weeks away. Timing for a final 1.54 release is much less certain. It is long overdue, but substantial issues remain with MTP which I really want to resolve for 1.54.

Cool, I think if I just tell people to download the beta that should be good enough. Is there some type of notification I can sign up for to let me know when a new beta comes out or should I just be checking the forums periodically?
 
If you have any contact with Marco Colli (author of MD_MIDIFile) or whoever is maintaining it, this usage could be much cleaner if another begin() function is added which takes a C++ reference.

No contact with Marco Colli unfortunately. Just the only library I could find online that was already written to work with midi files. Seems like it's kind of an old project, but I really didn't want to re-invent the wheel so it was worth figuring out how to work with it.
 
Hi, I'm trying to make a patch I can distribute to people with the stable release of Teensyduino by including the updated SD.h and .cpp files as PaulSD.h and .cpp in my patch folder. I've changed all of my <SD.h> includes to "PaulSD.h". However when I try to compile, I get the following error:

Code:
redefinition of 'class SDFile'

This doesn't happen when I'm including the exact same code as a library file, what's going on here? I've checked and I'm not including SD.h anywhere in my patch.
 
Status
Not open for further replies.
Back
Top