SD Card Reader not working on ESP32

Hi
Have had a Hydroponics Controller working for some time.
I had to change from the Arduino ESP32 Board to the esp32 by Espressiff Board and now the Card Reader doesn't work.
Have tried everything I can think of but to no avail. Different Boards and different Board Holders - MAKER STORE ESP32 Breakout Boards
Anybody else run into this issue and can help?
Garry

Sorry, I don’t have the specific board, but I have encountered issues with card readers before. Please post an annotated schematic showing exactly how everything is wired, including all power sources, connections, and hardware components such as resistors.

Also, include links to the correct technical documentation for each hardware device in the system. A clear picture of your setup would be helpful, as well as the code you’re using (be sure to use code tags as outlined in the guidelines). This information will make it much easier to assist you effectively.

I managed to get my SD cards to work with an ESP32 without to much issue, on both VSPI & HSPI.

Show us what you've tried.

First I have to reiterate that nothing has changed except I had to change the Arduino ESP32 Core on the Arduino IDE to the Espressif 32 Core to suit certain Library Requirements and the SD stopped working on all cards. Please find some of code below

// Libraries for SD card
#include <SD.h>
#include <FS.h>
#include <SPI.h>

#define SPI_PINS_USED // SD Card Connections
int SD_MOSI = 23;
int SD_MISO = 19;
int SD_SCLK = 18;
int SD_CS = 5;

 /*******************************************************************************************************************/
  // Initialize the SD card
  /*******************************************************************************************************************/
  Serial.println(line_break);
  Serial.print("Initializing SD card");

  int waiting = 0;
  int max_number_of_attempts = 3;

  Serial.println();
  Serial.println(line_break);

#ifdef SPI_PINS_USED
  SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
#endif

  while (!SD.begin(SD_CS) && sd_status == false && waiting < max_number_of_attempts)
  {
    Serial.print(".");
    delay(1000);
    waiting++;

    if (SD.begin())
    {
      sd_status = true;
      Serial.println("SD Card MOUNT SUCCESS!");

      uint32_t cardSize = SD.cardSize() / (1024 * 1024);
      String sdcardsize = "SDCard Size: " + String(cardSize) + " MB";
      Serial.println(sdcardsize);

      etc etc ......... but it fails every time on every card now

The Arduino ESP32 core is only for the Nano ESP32.
The espressif core is for all of the others.

OK, but I am unsure how this helps me?

Well how about you show us first which board you actually have.

Hi Gjb17,

Since you have not showen us your details which @gilshultz and @Deva_Rishi requested, I can't directly solve your issue.

But I recommend as follows.

1. Use the default pin assignments when you specify the pin number for SPI.

I can't say if the following pin number are correct or not.

int SD_MOSI = 23;
int SD_MISO = 19;
int SD_SCLK = 18;
int SD_CS = 5;

But I recommend you to use MOSI, MISO SCK and SS which are defined in pins_arduino.h.

(For example, you can find it here for ESP32C2.)

There are many variations of Espressif boards, and it is impossible to determine whether the pin assignment is correct or not unless the board type is specified.

However, if the board library is set correctly, Arduino IDE will automatically load the pins_arduino.h for that board.

And since most boards have a predefined SPI pin assignments, it should work if you wire it accordingly.

This also increases the portability.

2. Always go back to basics.

To determine whether a problem is caused by software or hardware, it's always a good idea to check the examples that can be accessed from Arduino IDE.

If you're using one of the Expressif boards, you can access an example from IDE menu by selecting "Files --> Examples --> SD --> SD_Test".

However, not all examples will necessarily work as is. In this case, you need to rewrite some code at the top as follows :

/*
Uncomment and set up if you want to use custom pins for the SPI communication
*/
#define REASSIGN_PINS
int sck = SCK;
int miso = MISO;
int mosi = MOSI;
int cs = SS;

(There is a bit of waste in the use of variables, but we won't worry about that here.)

This example has a bit more error checking than your code, so it might help you to find the problem.

1 Like

The ESP 32 is the ESP32 Wrover Module which plugs into a Development Board.

The Development Board is here:-

Garry

That board is meant for the 38-pin devkit. The Wrover has a completely different pinout with power & GND pins in different places.

Please show us the exact ESP32 board (Picture) and where you got it from. (link)

I got them from Lonely Binary

I am getting a little confused with where this is going.
I have three of these controlling hydroponics systems for about 12 months and the SD card for logging stopped working a couple of months ago after changing to the Arduino IDE Core code to Espressif.
Everything else continues to work I2C for 24 relays, Wire for Temperature and OTA programming.
Garry

There are so many different dev-boards out there (with different pinouts) it is just important to make sure what you have.

The pinout matches the 38-pin dev-board, which matches the shield.

Have you considered rolling back to the other core ? What is forcing you to use the new core.

After changing back to the Arduino Core, I then get this error as it tries to Compile

Platform 'esp32:esp32' not found: platform not installed

Compilation error: Platform 'esp32:esp32' not found: platform not installed

uninstall whatever cores you have installed and re-install the core you want to use.

I removed the espressif core, installed the arduino 32 core and when I compiled it wouldn;t and gave the error
Compilation error: Platform 'esp32:esp32' not found: platform not installed
Uninstalled the arduino core, installed the espressif and back to where I was

which core version of what do you have installed ? what do you mean by 'arduino core' and 'espressif core' ?

What you should have installed is the ESP32 core by espressif,


but try an older version, not any of the version 3.x.x (i'm using 2.0.11 as you can see)

select the esp32 Dev Module

and also try the Esp32 Wrover module

Indeed, I use 2.0.14, seems to work with most libraries, newer versions do cause issues with various libraries.

Not sure why espresiff seem intent on causing issues with their core by making significant changes to the 'requirements' of external libraries.

They probably intend to improve upon, but the esp8266 core has similar issues.

OK
Tried everything with SD.h to no avail, even just a number of very simple SD programs.
Tried SdFat and low and behold it works in a simple test program but if incorporated into my main program it clashes with an email library and wont compile.
At least I confirm that the hardware is definitely OK
Garry

The ESP32 needs it's own SD.h library which is included in the core. This works for me, with a Yellow LED on GPIO 2 and using the default pins for VSPI 23, 18 & 18.

#define LED_YELLOW 2
#define SD_CS 15

#include "FS.h"
#include "SD.h"
#include "SPI.h"



void setup(){
    Serial.begin(115200);
    pinMode(LED_YELLOW,OUTPUT);
    digitalWrite(LED_YELLOW, LOW);  // active LOW
    delay(10000);
    digitalWrite(LED_YELLOW, HIGH);  // active LOW
    if(!SD.begin(SD_CS)){
        Serial.println("Card Mount Failed");
        return;
    }
    uint8_t cardType = SD.cardType();

    if(cardType == CARD_NONE){
        Serial.println("No SD card attached");
        return;
    }

    Serial.print("SD Card Type: ");
    if(cardType == CARD_MMC){
        Serial.println("MMC");
    } else if(cardType == CARD_SD){
        Serial.println("SDSC");
    } else if(cardType == CARD_SDHC){
        Serial.println("SDHC");
    } else {
        Serial.println("UNKNOWN");
    }

    uint64_t cardSize = SD.cardSize() / (1024 * 1024);
    Serial.printf("SD Card Size: %lluMB\n", cardSize);

    listDir(SD, "/", 0);
    createDir(SD, "/mydir");
    listDir(SD, "/", 0);
    removeDir(SD, "/mydir");
    listDir(SD, "/", 2);
    writeFile(SD, "/hello.txt", "Hello ");
    appendFile(SD, "/hello.txt", "World!\n");
    readFile(SD, "/hello.txt");
    deleteFile(SD, "/foo.txt");
    renameFile(SD, "/hello.txt", "/foo.txt");
    readFile(SD, "/foo.txt");
    testFileIO(SD, "/test.txt");
    Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
    Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
    digitalWrite(LED_YELLOW, LOW);  // active LOW    
    //digitalWrite(LED_BUILTIN, HIGH);  // active LOW 
}

void loop(){

}

void listDir(fs::FS &fs, const char * dirname, uint8_t levels){
    Serial.printf("Listing directory: %s\n", dirname);

    File root = fs.open(dirname);
    if(!root){
        Serial.println("Failed to open directory");
        return;
    }
    if(!root.isDirectory()){
        Serial.println("Not a directory");
        return;
    }

    File file = root.openNextFile();
    while(file){
        if(file.isDirectory()){
            Serial.print("  DIR : ");
            Serial.println(file.name());
            if(levels){
                listDir(fs, file.name(), levels -1);
            }
        } else {
            Serial.print("  FILE: ");
            Serial.print(file.name());
            Serial.print("  SIZE: ");
            Serial.println(file.size());
        }
        file = root.openNextFile();
    }
}

void createDir(fs::FS &fs, const char * path){
    Serial.printf("Creating Dir: %s\n", path);
    if(fs.mkdir(path)){
        Serial.println("Dir created");
    } else {
        Serial.println("mkdir failed");
    }
}

void removeDir(fs::FS &fs, const char * path){
    Serial.printf("Removing Dir: %s\n", path);
    if(fs.rmdir(path)){
        Serial.println("Dir removed");
    } else {
        Serial.println("rmdir failed");
    }
}

void readFile(fs::FS &fs, const char * path){
    Serial.printf("Reading file: %s\n", path);

    File file = fs.open(path);
    if(!file){
        Serial.println("Failed to open file for reading");
        return;
    }

    Serial.print("Read from file: ");
    while(file.available()){
        Serial.write(file.read());
    }
    file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Writing file: %s\n", path);

    File file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }
    if(file.print(message)){
        Serial.println("File written");
    } else {
        Serial.println("Write failed");
    }
    file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message){
    Serial.printf("Appending to file: %s\n", path);

    File file = fs.open(path, FILE_APPEND);
    if(!file){
        Serial.println("Failed to open file for appending");
        return;
    }
    if(file.print(message)){
        Serial.println("Message appended");
    } else {
        Serial.println("Append failed");
    }
    file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2){
    Serial.printf("Renaming file %s to %s\n", path1, path2);
    if (fs.rename(path1, path2)) {
        Serial.println("File renamed");
    } else {
        Serial.println("Rename failed");
    }
}

void deleteFile(fs::FS &fs, const char * path){
    Serial.printf("Deleting file: %s\n", path);
    if(fs.remove(path)){
        Serial.println("File deleted");
    } else {
        Serial.println("Delete failed");
    }
}

void testFileIO(fs::FS &fs, const char * path){
    File file = fs.open(path);
    static uint8_t buf[512];
    size_t len = 0;
    uint32_t start = millis();
    uint32_t end = start;
    if(file){
        len = file.size();
        size_t flen = len;
        start = millis();
        while(len){
            size_t toRead = len;
            if(toRead > 512){
                toRead = 512;
            }
            file.read(buf, toRead);
            len -= toRead;
        }
        end = millis() - start;
        Serial.printf("%u bytes read for %u ms\n", flen, end);
        file.close();
    } else {
        Serial.println("Failed to open file for reading");
    }


    file = fs.open(path, FILE_WRITE);
    if(!file){
        Serial.println("Failed to open file for writing");
        return;
    }

    size_t i;
    start = millis();
    for(i=0; i<2048; i++){
        file.write(buf, 512);
    }
    end = millis() - start;
    Serial.printf("%u bytes written for %u ms\n", 2048 * 512, end);
    file.close();
}

For using the other SPI bus, this works for me

#define LED_YELLOW 2
#define HSPI_SCK 17
#define HSPI_MISO 16
#define HSPI_MOSI 4
#define SD_CS 15
#define SPI_FRQ 32000000
#define TEST_BLOCKS 4

#include "FS.h"
#include "SD.h"
#include "SPI.h"

SPIClass * hspi = NULL;

void setup() {
  Serial.begin(115200);
  pinMode(LED_YELLOW, OUTPUT);
  digitalWrite(LED_YELLOW, LOW);  // active LOW
  hspi = new SPIClass(HSPI);

  hspi->begin(HSPI_SCK, HSPI_MISO, HSPI_MOSI, SD_CS);
  hspi->setFrequency(SPI_FRQ);

  if (!SD.begin(SD_CS, *hspi, SPI_FRQ)) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  uint64_t cardSize = SD.cardSize() / (1024 * 1024);
  Serial.printf("SD Card Size: %lluMB\n", cardSize);

  listDir(SD, "/", 0);
  createDir(SD, "/mydir");
  listDir(SD, "/", 0);
  removeDir(SD, "/mydir");
  listDir(SD, "/", 2);
  writeFile(SD, "/hello.txt", "Hello ");
  appendFile(SD, "/hello.txt", "World!\n");
  readFile(SD, "/hello.txt");
  deleteFile(SD, "/foo.txt");
  renameFile(SD, "/hello.txt", "/foo.txt");
  readFile(SD, "/foo.txt");
  testFileIO(SD, "/test.txt");
  Serial.printf("Total space: %lluMB\n", SD.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD.usedBytes() / (1024 * 1024));
  digitalWrite(LED_YELLOW, HIGH);  // active LOW

}

void loop() {

}

void listDir(fs::FS &fs, const char * dirname, uint8_t levels) {
  Serial.printf("Listing directory: %s\n", dirname);

  File root = fs.open(dirname);
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File file = root.openNextFile();
  while (file) {
    if (file.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(file.name());
      if (levels) {
        listDir(fs, file.name(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(file.name());
      Serial.print("  SIZE: ");
      Serial.println(file.size());
    }
    file = root.openNextFile();
  }
}

void createDir(fs::FS &fs, const char * path) {
  Serial.printf("Creating Dir: %s\n", path);
  if (fs.mkdir(path)) {
    Serial.println("Dir created");
  } else {
    Serial.println("mkdir failed");
  }
}

void removeDir(fs::FS &fs, const char * path) {
  Serial.printf("Removing Dir: %s\n", path);
  if (fs.rmdir(path)) {
    Serial.println("Dir removed");
  } else {
    Serial.println("rmdir failed");
  }
}

void readFile(fs::FS &fs, const char * path) {
  Serial.printf("Reading file: %s\n", path);

  File file = fs.open(path);
  if (!file) {
    Serial.println("Failed to open file for reading");
    return;
  }

  Serial.print("Read from file: ");
  while (file.available()) {
    Serial.write(file.read());
  }
  file.close();
}

void writeFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Writing file: %s\n", path);

  File file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }
  if (file.print(message)) {
    Serial.println("File written");
  } else {
    Serial.println("Write failed");
  }
  file.close();
}

void appendFile(fs::FS &fs, const char * path, const char * message) {
  Serial.printf("Appending to file: %s\n", path);

  File file = fs.open(path, FILE_APPEND);
  if (!file) {
    Serial.println("Failed to open file for appending");
    return;
  }
  if (file.print(message)) {
    Serial.println("Message appended");
  } else {
    Serial.println("Append failed");
  }
  file.close();
}

void renameFile(fs::FS &fs, const char * path1, const char * path2) {
  Serial.printf("Renaming file %s to %s\n", path1, path2);
  if (fs.rename(path1, path2)) {
    Serial.println("File renamed");
  } else {
    Serial.println("Rename failed");
  }
}

void deleteFile(fs::FS &fs, const char * path) {
  Serial.printf("Deleting file: %s\n", path);
  if (fs.remove(path)) {
    Serial.println("File deleted");
  } else {
    Serial.println("Delete failed");
  }
}

void testFileIO(fs::FS &fs, const char * path) {
  File file = fs.open(path);
  static uint8_t buf[512];
  size_t len = 0;
  uint32_t start = millis();
  uint32_t end = start;
  uint32_t ustart = micros();
  uint32_t uend = start;
  if (file) {
    len = file.size();
    size_t flen = len;
    start = millis();
    ustart = micros();
    while (len) {
      size_t toRead = len;
      if (toRead > 512) {
        toRead = 512;
      }
      file.read(buf, toRead);
      len -= toRead;
    }
    uend = micros() - ustart;
    end = millis() - start;
    if (end > 100) Serial.printf("%u bytes read for %u ms\n", flen, end);
    else Serial.printf("%u bytes read for %u us\n", flen, uend);
    file.close();
  } else {
    Serial.println("Failed to open file for reading");
  }


  file = fs.open(path, FILE_WRITE);
  if (!file) {
    Serial.println("Failed to open file for writing");
    return;
  }

  size_t i;
  start = millis();
  ustart = micros();
  for (i = 0; i < TEST_BLOCKS; i++) {
    file.write(buf, 512);
  }
  uend = micros() - ustart;
  end = millis() - start;
  
  if (end > 100) Serial.printf("%u bytes written for %u ms\n", TEST_BLOCKS * 512, end);
  else Serial.printf("%u bytes written for %u us\n", TEST_BLOCKS * 512, uend);

  file.close();
}

SPI pins are free assignable, and the choice of busses is done here

hspi = new SPIClass(HSPI);

The SDfat library that you have found probably is not meant for use with the ESP32 core.