SDFat File Opening Error, 0x4,0xFF


#1

Hi all,

Having a bit of an issue with SDFat on an Electron. Setup is:

  • Particle Dev
  • FW 0.7.0
  • Adafruit 5V MicroSD Breakout on breadboard
  • SD_FAT_VERSION 20170302

I’ve used the sample programs, and TryMeFirst.cpp works just fine, as does SDInfo.cpp. When I try to run very similar code, it chokes out every time, and returns SD errorCode 0x4,0xFF. The SD reader is the only SPI device currently, although I’m running other sensors on I2C. I know that breadboards can be an issue, so I’m running the SPI_SIXTEENTH_SPEED modifier. I’ve been trying a few things, so apologies if the code is a bit messy. What really has me confused is I’m not really doing anything, just opening the file, which works fine in TryMeFirst.cpp, so I figure I’m missing something obvious… Any thoughts?

Thanks,
Peter

#pragma once

 /*
 Cryo_MicroSD.h
 Wrapper for SDFat library.
 Used for logging to SPI SD card, initially at 20s intervals.
 Originally heavily based on SDCardLogHandlerRK.
 */

#include <string>
#include "SdFat.h"

class Cryo_MicroSD {
public:
  Cryo_MicroSD ();
  virtual ~Cryo_MicroSD ();
  void Begin(std::string logFileName);
  void LogToSD(std::string stringToLog);


private:
  /* data */
  std::string _logFileName;
  std::string _stringToLog;
  int _SDCSPin = SS;
  SdFat spiSDCard;
  bool lastBeginResult = false; //!< Last result from sd.begin().
      //Will be false if there's not a valid SD card inserted.
  unsigned long cardCheckPeriod = 10000;
  File currentLogFile;

  unsigned long lastCardCheck = 0;  //millis() value at last time checked for SD card
    //related to cardCheckPeriod

  int TryOpeningCard(int SDCSPin = SS);

};

#include "Cryo_MicroSD.h"
#include <string>
#include "SdFat.h"

#define SDCARD_DEBUG_LEVEL 2

// Don't change these, just change the debugging level above
// Note: must use Serial.printlnf here, not Log.info, as these are called from the log handler itself!
#if SDCARD_DEBUG_LEVEL >= 1
#define DEBUG_NORMAL(x) Serial.printlnf x
#define SPI_SPEED SPI_SIXTEENTH_SPEED  //Apparently full speed can have issues on breadboards.
#else
#define DEBUG_NORMAL(x)
#define SPI_SPEED SPI_FULL_SPEED
#endif

#if SDCARD_DEBUG_LEVEL >= 2
#define DEBUG_HIGH(x) Serial.printlnf x
#else
#define DEBUG_HIGH(x)
#endif


Cryo_MicroSD::Cryo_MicroSD(){

}

Cryo_MicroSD::~Cryo_MicroSD(){

}

void Cryo_MicroSD::Begin(std::string logFileName){
  _logFileName = logFileName;
  TryOpeningCard();
}

int Cryo_MicroSD::TryOpeningCard(int SDCSPin){
  _SDCSPin = SDCSPin;
  pinMode(_SDCSPin, OUTPUT);
  lastBeginResult = spiSDCard.begin(_SDCSPin, SPI_SPEED);
  if(!lastBeginResult)
    DEBUG_NORMAL(("Begin failed."));
  return lastBeginResult;
}

void Cryo_MicroSD::LogToSD(std::string stringToLog){
  _stringToLog = stringToLog;
  if(!lastBeginResult){
    TryOpeningCard();
  }
  //char logFileNameCStr[11] = "201811.csv";
  //strcpy(logFileNameCStr, _logFileName.c_str());
  //Serial.println(logFileNameCStr);
  if(!currentLogFile.open("test.txt", O_RDWR | O_CREAT | O_AT_END)){
    DEBUG_NORMAL(("Failed to open log file."));
    Serial.println(digitalRead(_SDCSPin));
    spiSDCard.errorPrint(&Serial);
  }
  currentLogFile.println(_stringToLog.c_str());
  currentLogFile.close();
}


#2

Just a note on this one, more or less the exact same code in the mail loop of the program works, so it looks like it’s something to do with how I implemented this… Bit confused, but I’ll keep poking at it.


#3

Strange error. Normally I would suggest a hardware issue with an error like that, but if the other firmware consistently works that wouldn’t make sense.

But first of all, your code allows for you to attempt to open the file even if TryOpeningCard() returns a false value. Maybe you’ve ruled that out from your debug logs, but you should probably be more explicit with that, and not attempt to open the file if the last open failed. Just log the error and return the function.

If you successfully began the card, but couldn’t open the file I would be really surprised.

The one difference I see is that you call pinmode(_SDCSPin, OUTPUT);. Neither SDFat nor my code call that. I tested that on my firmware and had no issues.

I’ll be honest with you, as someone who has gone through a development cycle for a uSD card with SDFat, worth really being meticulous with your hardware connections. Measure impedances, keep everything short.

I’ve also had problems in the past with poorly formatted cards. Run the SDFormatter code just to be safe. Try deleting “test.txt” directly from the SD card before opening it.


#4

Thanks for the info. At this point I don’t think it’s the wiring, as the other tests have worked well. I’m running the recommended formatter from the SD Association, so I think I’ve got that covered as well. For now I’ll rip the library apart and make it as clean and simple as I can, my fault for trying to get fancy and using half of another library to start out with.


#5

I’d be surprised if it was actually a problem within the SDFat library.

I would recommend trying to just call the SDFat classes and functions directly from your main file, but in the way you want, just to make sure there isn’t somehow an issue with the way you are calling / handling the additional class abstraction. Then if that works, revisit the way you are structuring and using your Cryo_MicroSD class.

If you post some of the code where you are using the class in your main program perhaps we can see if anything sticks out there too.