SD.begin() fails with Adafruit Micro SD Breakout Board

I have an Adafruit Micro SD Breakout Board that has been running along with a MPU6050 on a Photon for a couple of years. Due to my breaking the UFL antenna connector I am now trying to set this up on a Photon 2. I get a failure in sd.begin(). Tracing further there is a failure "SD_CARD_ERROR_CMD0" in SdSpiCard.cpp. I think this is where it checks "if (cardCommand(CMD0, 0) == R1_IDLE_STATE)". I have tried both SPI and SPI1 and made sure the pin connections are correct. I have tried OS 5.6, 5.82 and 5.9 to no avail. I have tried SdFat versions 1.0.15 and 1.0.16.
I use these pin definitions:
#define CLK S2//13 // SPI Clock, shared with SD card BM "SCLK"
#define MISO S1//12 // Input data, from VS1053/SD card BM "MISO"
#define MOSI S0//11 // Output data, to VS1053/SD card BM "MOSI"
#define SD_SPI_SETTING SPISettings(25000000, MSBFIRST, SPI_MODE0)
//const uint8_t chipSelect = S3;
const int SD_CS = S3;

My SD_card_setup is:

if (!sd.begin(SD_CS, SD_SCK_MHZ(25))) 
{
    led_blink(LED_FAILURE,3,LED_SLOW);
    Serial.println("SD Card Open Failed");
		return false;
}
else
{
    Serial.println("SD Card Open Good!");
}

Has anyone had success in getting the Adafruit Micro SD Breakout Board running on a Photon 2? Any help would be greatly appreciated.
Bob

Hi, I had the exact same issue you describe but on DeviceOS 5.8.0.
This was fixed on 5.8.2 and 5.9. Are you absolutely sure you tried upgrading to 5.9 and the device ended up running in 5.9?
Check from the console for double verification:

Cheers,

Yep, confirmed on both 5.82 and 5.9. Strange thing is, I have a Adafruit VS1053 Codec + MicroSD Breakout - MP3/WAV/MIDI/OGG Play + Record - v4 I was having issues with a while back and the upgrade from 5.8 to 5.82 solved the problem. I believe the MicroSD portion of that VS1054 breakout uses the same chip (HC4050M) as the standalone Micro Sd board I am having issues with. I am wondering if perhaps my SPI pin definitions are wrong or being ignored. The code for the Photon setup had these comments in it:
"// Primary SPI with DMA
// SCK => A3,MISO => A4,MOSI => A5, SS => A2(def)"
Which makes me wonder if these pins are not being set correctly for the Photon 2 on SPI. Those are listed on the first post and I think they are correct.

Bummer.

Would it be possible to add some logs to that code? Log.info() (or println if deep inside a lib) to double check the values.
Another thing I would try would be to connect the spi periph to the default pins to see if it works there.

Hello Gustavo,
Do you mean connect the Micro SD card reader to the pins in the following comment:
// SCK => A3,MISO => A4,MOSI => A5, SS => A2(def)"

If so, I don't think those are valid SPI or SPI1 pins on the Photon 2. They are valid for the Photon SPI. Of course if there are some substitutions going on in the library that could be possible. Right now I have the MPU6050 using I2C on pins A3 and A4. I have been trying to follow the sd.begin function back to its origin and hopefully find what variables are actually being used to initiate the SPI connection (SCK, SS, MISO and MOSI). So far no luck. The failure is on in SdSpiCard.cpp:
for (uint8_t i = 1;; i++) {
DBG_EVENT_COUNT(DBG_CMD0_COUNT);
if (cardCommand(CMD0, 0) == R1_IDLE_STATE) {
break;
}
if (i == SD_CMD0_RETRY) {
Serial.println("SD_CARD_ERROR_CMD0");
error(SD_CARD_ERROR_CMD0);
goto fail;
}
// stop multi-block write
spiSend(STOP_TRAN_TOKEN);
// finish block transfer
for (int i = 0; i < 520; i++) {
spiReceive();
}
}
I will try to get to the bottom of what SPI pins are actually being used. The original code that ran on the Photon just used A2 which is the SS pin for SPI when calling sd.begin().

Well, I am about as frustrated as I can get trying to figure this SPI problem out. I traced it down to SdSpiCard::begin() and the csPin is 2.
m_spiDriver->begin(csPin) takes me to the following:

void SdSpiAltDriver::begin(uint8_t csPin) {
m_csPin = csPin;
Log.info("Crap3");
m_spi->begin();
pinMode(m_csPin, OUTPUT);
digitalWrite(m_csPin, HIGH);
}
but m_spi is defined as:
SPIClass *SdSpiAltDriver::m_spi
How in the heck does that make sense?? Does that mean the function is calling itself??

SPIClass in spark_wiring_spi.h has three begin() declarations but all three say "Function definition for 'begin' not found". Does that mean they are defined in the inherited class?

If anyone has got the Adafruit Micro Sd Card Reader to work on a Photon 2 I would much appreciate what SPI or SPI pins you are using and how those pins are defined.
As fart as I can tell the pin defs I use are not being used:
#define SCK S2//13 // SPI Clock, shared with SD card BM "SCLK"
#define MISO S1//12 // Input data, from VS1053/SD card BM "MISO"
#define MOSI S0//11 // Output data, to VS1053/SD card BM "MOSI"

This pin definition is being used:
const int SD_CS = D2;
if (!sd.begin(SD_CS, SD_SCK_MHZ(25)))
Thanks,
Bob

You have to use hardware SPI, either SPI or SPI1 on these pins:

Screenshot 2024-10-07 at 11.48.23 AM

While the SdFat library supports SoftSPI to arbitrary pins, Soft SPI does not work on the Photon 2 or P2. (Both hardware and software SPI worked on the Photon 1.)

I was sort of able to make it work on the Photon 2. It fails later in initialization (error 0x43). However there may be an issue with the library or the two cards that I was testing with, because it also fails with the same error on the Photon 1.

In any case, here's what I did in case it's helpful:

  • S3 to CS (orange)
  • SCK to SCK (yellow)
  • MOSI to DI (green)
  • MISO to DO (blue)
  • 3V3 to VCC (red)
  • GND to GND (black)

#include "Particle.h"

#include "SdFat.h"

SYSTEM_MODE(AUTOMATIC);
SYSTEM_THREAD(ENABLED);

SerialLogHandler logHandler(LOG_LEVEL_INFO);

const pin_t SD_CHIP_SELECT = S3;
SdFat sd(&SPI);
#define SD_SPI_SETTINGS SPISettings(25000000UL, MSBFIRST, SPI_MODE0)

void setup() {
    waitFor(Serial.isConnected, 10000); delay(2000);

    if (sd.begin(SD_CHIP_SELECT, SD_SPI_SETTINGS)) {
        Log.info("SD init succeeded!");
    }
    else {
        int err = sd.card()->errorCode();
        Log.info("SD init failed %d (0x%x)", err, err);
    }

}

void loop() {
}

Example error I got:

0000009259 [app] INFO: SD init failed 67 (0x43)

In SdInfo.h, this is SD_CARD_ERROR_ACMD41

This corresponds to this block of code:

  arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
  DBG_BEGIN_TIME(DBG_ACMD41_TIME);
  while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
    DBG_EVENT_COUNT(DBG_ACMD41_COUNT);
    // check for timeout
    if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
      error(SD_CARD_ERROR_ACMD41);
      goto fail;
    }
  }
  DBG_END_TIME(DBG_ACMD41_TIME);

Not sure why that's failing, but the Photon is able to communicate with the card up to that point, but then times out before the card gets to ready state.

Tested with Device OS 5.9.0 on Photon 2.

Tested on Device OS 2.3.1 on Photon 1. Connections were different as the SPI pins are different. Used A2 as the CS on Photon 1.

1 Like

Hello Rick,
Thank you for the information about SdFat library / Photon 2 incompatibility and the other suggestions/ possibilities. At least I feel like I haven't lost what remains of my marbles! Two possibilities I am looking into are:

1.Using the SD library although that probably has its own limitations. I need to be able to use long file names such as 20241004_02_00_03_Photon2XXX6_CONT.ogg and I have to see if that is supported.

  1. I have a Photon 2 with an Adafruit VS1053 V4 that has been running quite well on OS 5.8.2 and 5.9. It writes to the integrated SD micro card reader very reliably using the SdFat library. these are the pin defs:
    SdFat SD;
    #define CLK S2
    #define MISO S1
    #define MOSI S0
    #define SD_SPI_SETTING SPISettings(8000000, MSBFIRST, SPI_MODE0)

#define VS1053_FILEPLAYER_PIN_INT 5

// These are the pins used for the music maker FeatherWing
const int MP3_RESET = D1;
const int SD_CS = D2;
const int MP3_CS = D3;
const int DREQ = D4;
const int MP3_DCS = D5;

This is the Adafruit_VS1053_FilePlayer object:
Adafruit_VS1053_FilePlayer musicPlayer(MP3_RESET, MP3_CS, MP3_DCS, DREQ, SD_CS);

this is the SD code:
if (!SD.begin(SD_CS, SD_SPI_SETTING ))
{
Serial.println("SD failed, or not present");
while(1) yield(); // don't do anything more
}
Serial.println("SD OK!");

this is the musicPlayer code:
if (!musicPlayer.begin())
{ // initialise the music player
Serial.println("Couldn't find damn VS1053, do you have the right pins defined?");
while(1) yield();
}
Serial.println("VS1053B Found!");
Serial.printlnf("Burp2 _mosi:%d _miso:%d _clk:%d _reset:%d _cs:%d _dcs:%d _dreq:%d use_HDW_SPI:%d", musicPlayer._mosi,musicPlayer._miso,musicPlayer._clk,musicPlayer._reset,musicPlayer._cs,musicPlayer._dcs,musicPlayer._dreq, musicPlayer.useHardwareSPI);

if (musicPlayer.useInterrupt(VS1053_FILEPLAYER_PIN_INT))
{
//digitalWrite(D7, HIGH);
musicPlayer.setIsrCallback(blink);
}
else
{
Serial.println("DREQ pin is not an interrupt pin");
}

I made the spi pins (_mosi, _miso pin variables) as well as useHardwareSPI public in VS1053.cpp to obtain their values and they were:
Burp2 _mosi:-1 _miso:-1 _clk:-1 _reset:1 _cs:3 _dcs:5 _dreq:4 use_HDW_SPI:1.

So I am wondering if VS1053.cpp holds the bridging code that would make SdFat able to run on the Photon 2 using hardware SPI? Again I appreciate your help.
Bob

Hi Rick,
I tried your setup and got only as far as you did. I've spent a total of at least 20 hours trying to get my Photon 2 to work with the Adafruit MicroSD card breakout board+ to no avail. I've tried tracing the code and get hung up in routines that I have no source for. I've also tried to figure out why the Photon 2 works well with the Adafruit VS1053 Codec + MicroSD MP3/WAV/MIDI/OGG Play + Record - v4, which uses SdFat. It records to the MicroSD without a hitch and has been reliable through 3+ gigabytes of data and probably more than 200K write operations. I've tried to figure out how this is done but got hung up trying to trace code there also.

I really don't have the expertise or additional time to be debugging libraries nor am I familiar with the SPI or SdFat code.

As far as I can tell the Photon 2 is not compatible with the Adafruit MicroSD card breakout board using the SdFat library. I asked if anyone on this forum had been successful in doing so and to provide an example. The only response I got was from you, and I appreciate your insight and thoughts. However, I'm still stuck. It seems odd to me that such a fundamental capability worked on the Photon but not on the Photon 2. Is writing to a sd card reader so obscure that it has not been addressed for the Photon 2? I can't imagine that. What other options does one have available for applications that need to save 10 or 15 mb per hour. I have no Photons left to spare and I bet there are many other users who are in the same boat. What I do have is eight Photon 2 devices. Do you know if the software development team is working on a fix in for this issue?
Thanks,
Bob

I'm not convinced that the problem is specific to the Photon 2 as it also fails in the same way for me (error 0x43) with the same card, adapter, and a Photon 1. I've gotten the SdFat library to work with the Photon 1 before, so maybe it's that version of the library?

1 Like

I've tried SdFat 15 and 16 with the Photon 2. The only micro sd card reader I have is the adafruit one and it worked on the Photon1. Surely someone out there has been down this road before and has either solved it or given up. It looks like the last time the SdFat library was updated was before the Photon 2 was announced.

I wrote some logging into the SdFat files and used them in the Adafruit Micro SD card and MPU6050 project that is failing;
I also used them in the Adafruit Micro SD card and Adafruit VS1053B project that is running without a hitch;

Compare the two sections below:

************* Failure ********************
RLW_FatVolume::init() part = 1 in FatVolume.cpp
RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true in FatVolume.cpp
RLW_*FatVolume::cacheFetchData() in FatVolume.h
RLW_FatCache::read() in FatVolume.cpp
RLW_FatVolume::init() p->type = 0 p->totalSectors = 0 in FatVolume.cpp
RLW_FatVolume::init() pc->mbr.part[0] = 0
RLW_FatVolume::init() pc->mbr.part[1] = 0
RLW_FatVolume::init() pc->mbr.part[2] = 0
RLW_FatVolume::init() pc->mbr.part[3] = 0
RLW_FatVolume::init() pc->members = 0 0 0 0 0
RLW_FatVolume::init() not a valid partition fail in FatVolume.cpp
RLW_FatVolume::init() in FatVolume.cpp
RLW_FatVolume::init() part = 0 in FatVolume.cpp
RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true in FatVolume.cpp
RLW_*FatVolume::cacheFetchData() in FatVolume.h
RLW_FatCache::read() in FatVolume.cpp
RLW_FatVolume::init() not valid FAT volume fail in FatVolume.cpp
0000027359 [app] INFO: FatFileSystem::begin() ret1 = 0 ret2 = 0 ret3 = 0
SD Card Open Failed
SD Card Setup Failed

************* Success ********************
RLW_FatVolume::init() part = 1 in FatVolume.cpp
RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true in FatVolume.cpp
RLW_*FatVolume::cacheFetchData() in FatVolume.h
RLW_FatCache::read() in FatVolume.cpp
RLW_FatCache::read() if (!(option & CACHE_OPTION_NO_READ)) option = 0 cache option = 4 in FatVolume.cpp
RLW_SdSpiCard::spiStart() before spiActivate() in SdSpiCard.cpp
RLW_SdSpiCard::spiActivate() in SdSpiCard.h
RLW_SdSpiAltDriver::activate() in SdSpiParticle.cpp
RLW_beginTransaction_return = 0 in SdSpiParticle.cpp
RLW_SdSpiCard::spiStart() after spiActivate() in SdSpiCard.cpp
RLW_SdSpiAltDriver::select() in SdSpiDriver.h
RLW_FatVolume::init() p->type = 12 p->totalSectors = 62325760 in FatVolume.cpp

** Complete Log of failure with the Adafruit Micro SD card and MPU6050**

025573 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 4
0000025594 [comm.dtls] INFO: session cmd (CLS,DIS,MOV,LOD,SAV): 3
RLWSD_card_setup() in fart1.cpp
RLW_SdFat::begin() in SdFat.h
RLW_SdSpiCard::begin() in SdSpiCard.cpp
0000026433 [app] INFO: csPin 18
RLW_SdSpiAltDriver::begin() in SdSpiParticle.cpp
RLW_SdSpiCard::spiStart() before spiActivate() in SdSpiCard.cpp
RLW_SdSpiCard::spiActivate() in SdSpiCard.h
RLW_SdSpiAltDriver::activate() in SdSpiParticle.cpp
RLW_beginTransaction_return = 0 in SdSpiParticle.cpp
RLW_SdSpiCard::spiStart() after spiActivate() in SdSpiCard.cpp
RLW_SdSpiAltDriver::select() in SdSpiDriver.h
RLW_SdSpiAltDriver::select() in SdSpiDriver.h
RLW_SdSpiCard::begin() (cardCommand(CMD0, 0) == R1_IDLE_STATE) Success in SdSpiCard.cpp
RLW_SdSpiCard::begin() (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) STD Cap V2 SD card in SdSpiCard.cpp
RLW_SdSpiCard::begin() ((spiReceive() & 0XC0) == 0XC0) High Capacity SD card in SdSpiCard.cpp
RLW_SdSpiCard::begin() returning true in SdSpiCard.cpp
RLW_SdFileSystem<SdDriverClass>::begin() in SdFat.h
RLW_FatFileSystem::begin() in FatFileSystem.h
RLW_FatFileSystem::begin() part = 0  blockdev = 268938688 in FatFileSystem.h
RLW_vwd_close_OK = 1 in FatFileSystem.h 
RLW_FatVolume::init() in FatVolume.cpp
RLW_FatVolume::init() part = 1  in FatVolume.cpp
RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true  in FatVolume.cpp
**RLW_*FatVolume::cacheFetchData()  in FatVolume.h**
**RLW_FatCache::read() in FatVolume.cpp**
**RLW_FatVolume::init()  p->type = 0  p->totalSectors = 0  in FatVolume.cpp**
**RLW_FatVolume::init() pc->mbr.part[0] = 0**
**RLW_FatVolume::init() pc->mbr.part[1] = 0**
**RLW_FatVolume::init() pc->mbr.part[2] = 0**
**RLW_FatVolume::init() pc->mbr.part[3] = 0**
**RLW_FatVolume::init() pc->members =  0  0  0  0  0  **
**RLW_FatVolume::init() not a valid partition fail  in FatVolume.cpp**
**RLW_FatVolume::init() in FatVolume.cpp**
**RLW_FatVolume::init() part = 0  in FatVolume.cpp**
**RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true  in FatVolume.cpp**
**RLW_*FatVolume::cacheFetchData()  in FatVolume.h**
**RLW_FatCache::read() in FatVolume.cpp**
**RLW_FatVolume::init() not valid FAT volume fail  in FatVolume.cpp**
**0000027359 [app] INFO: FatFileSystem::begin() ret1 = 0  ret2 = 0  ret3 = 0  **
**SD Card Open Failed**
**SD Card Setup Failed**

**Complete Log of success with the Adafruit Micro SD card and Adafruit VS1053B **

0000003745 [ncp.rltk.client] TRACE: NCP connection state changed: 1
0000003746 [net.rltkncp] TRACE: NCP event 2
0000003746 [net.rltkncp] TRACE: State changed event: 1
0000003749 [ncp.rltk.client] INFO: Try to connect to ssid: xxxx
Adafruit VS1053 Ogg Recording Test
Burp1 _mosi:-1  _miso:-1  _clk:-1  _reset:1  _cs:3  _dcs:5  _dreq:4  use_HDW_SPI:1
Particle.subscribe(particle/device/name successful
RLW_SdFat::begin() in SdFat.h
RLW_SdSpiCard::begin() in SdSpiCard.cpp
0000005210 [app] INFO: csPin 18
RLW_SdSpiAltDriver::begin() in SdSpiParticle.cpp
RLW_SdSpiCard::spiStart() before spiActivate() in SdSpiCard.cpp
RLW_SdSpiCard::spiActivate() in SdSpiCard.h
RLW_SdSpiAltDriver::activate() in SdSpiParticle.cpp
RLW_beginTransaction_return = 0 in SdSpiParticle.cpp
RLW_SdSpiCard::spiStart() after spiActivate() in SdSpiCard.cpp
RLW_SdSpiAltDriver::select() in SdSpiDriver.h
RLW_SdSpiAltDriver::select() in SdSpiDriver.h
RLW_SdSpiCard::begin() (cardCommand(CMD0, 0) == R1_IDLE_STATE) Success in SdSpiCard.cpp
RLW_SdSpiCard::begin() (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) STD Cap V2 SD card in SdSpiCard.cpp
RLW_SdSpiCard::begin() ((spiReceive() & 0XC0) == 0XC0) High Capacity SD card in SdSpiCard.cpp
RLW_SdSpiCard::begin() returning true in SdSpiCard.cpp
RLW_SdFileSystem<SdDriverClass>::begin() in SdFat.h
RLW_FatFileSystem::begin() in FatFileSystem.h
RLW_FatFileSystem::begin() part = 0  blockdev = 268937676 in FatFileSystem.h
RLW_vwd_close_OK = 1 in FatFileSystem.h 
RLW_FatVolume::init() in FatVolume.cpp
RLW_FatVolume::init() part = 1  in FatVolume.cpp
RLW_FatVolume::init() USE_SEPARATE_FAT_CACHE = true  in FatVolume.cpp
**RLW_*FatVolume::cacheFetchData()  in FatVolume.h**
**RLW_FatCache::read() in FatVolume.cpp**
**RLW_FatCache::read() if (!(option & CACHE_OPTION_NO_READ)) option = 0 cache option = 4   in FatVolume.cpp**
**RLW_SdSpiCard::spiStart() before spiActivate() in SdSpiCard.cpp**
**RLW_SdSpiCard::spiActivate() in SdSpiCard.h**
**RLW_SdSpiAltDriver::activate() in SdSpiParticle.cpp**
**RLW_beginTransaction_return = 0 in SdSpiParticle.cpp**
**RLW_SdSpiCard::spiStart() after spiActivate() in SdSpiCard.cpp**
**RLW_SdSpiAltDriver::select() in SdSpiDriver.h**
**RLW_FatVolume::init()  p->type = 12  p->totalSectors = 62325760  in FatVolume.cpp**
**RLW_FatVolume::init() pc->mbr.part[0] = 62325760**
**RLW_FatVolume::init() pc->mbr.part[1] = 0**
**RLW_FatVolume::init() pc->mbr.part[2] = 0**
**RLW_FatVolume::init() pc->mbr.part[3] = 0**
**RLW_FatVolume::init() pc->members =  0  0  0  0  0**
**RLW_*FatVolume::cacheFetchData()  in FatVolume.h**
**RLW_FatCache::read() in FatVolume.cpp**
**RLW_FatCache::read() if (!(option & CACHE_OPTION_NO_READ)) option = 0 cache option = 4   in FatVolume.cpp**
**RLW_SdSpiCard::spiStart() before spiActivate() in SdSpiCard.cpp**
**RLW_SdSpiCard::spiActivate() in SdSpiCard.h**
**RLW_SdSpiAltDriver::activate() in SdSpiParticle.cpp**
**RLW_beginTransaction_return = 0 in SdSpiParticle.cpp**
**RLW_SdSpiCard::spiStart() after spiActivate() in SdSpiCard.cpp**
**RLW_SdSpiAltDriver::select() in SdSpiDriver.h**
**0000006177 [app] INFO: FatFileSystem::begin() ret1 = 1  ret2 = 1  ret3 = 1  **
**SD OK!**