Using an SD Card with the ESP32 [Guide + Code]

In this article, we will be discussing how to perform file reading and writing tasks using a micro SD card connected to an ESP32 using the Arduino IDE (Integrated Development Environment).  

A micro SD card is a secure digital memory card that is used in many applications from cell phones to laptops to digital cameras for storing large amounts of data.  It can also be used for storing data and other types of information for your ESP32.

  1. The hardware you’ll need
  2. Micro SD Card Reader Hardware Wiring
  3. Micro SD Card Reader SPI Connection Table
  4. ESP32 DevKit Pin Layout
  5. Test code for ESP32 with a Micro SD Card
  6. Micro SD Card Code Walkthrough
  7. Micro SD Card Test Sketch setup() function
  8. Micro SD Card Sketch loop() function
  9. Micro SD Card Test printDirectory() function
  10. Testing The ESP32 Micro SD Card Sketch
  11. Where To Go From Here

When a micro SD card reader is connected to your ESP32, it can be a great way to extend your ESP32 device’s memory capabilities.  But not only that, it’s a great way to add new functionality to your ESP32 projects for things like data logging, device provisioning and device configuring.  

At the end of this article, you’ll be able to connect a micro SD card reader to your ESP32 and read and write files to and from a micro SD card.  

The hardware you’ll need

Let’s get started with creating an example project.  You will need the following hardware for this project.  

A formatted micro SD card is required.  FAT32 formatting is the preferred format for the micro SD card for this example.  If you have an SD card reader on your laptop, you can format your micro SD card by selecting your SD card in a Windows file explorer window and then right clicking on your SD card.  From there you can format your micro SD card like in the screenshot below.

Format SD card via Windows Explorer

Micro SD Card Reader Hardware Wiring

The micro SD card reader communicates with the ESP32 using the SPI ( Serial Peripheral Interface ) communications protocol.  Once you have your ESP32 and your micro SD card reader you can connect the 2 devices together so they can talk to each other.  

Micro SD Card Reader SPI Connection Table

Your ESP32 and micro SD card reader are typically connected by using the ESP32’s default SPI pin connections below: 

SD Card ReaderESP32
MISOGPIO 19
MOSI GPIO 23
CLKGPIO 18
GNDGND
CSGPIO 5
VCC 3.3V ( or 5V )

ESP32 DevKit Pin Layout

In order to make these connections, you will need to know the pin layout of your ESP32 device.  You can find the ESP32 pin layout on Espressif’s website here: ESP32 Pin Layout.  

You can also download our “Easy Reader” ESP32 pinout on our guides page.

In the layout below you can see where the default SPI pins ( MOSI, MISO, CS, CLK ) are physically located on the ESP32 device.

ESP32 DevKit Pin Layout

You can either connect these GPIO pins with jumper wires to the corresponding devices using a breadboard, if you have a breadboard.  Or alternatively, you can connect the pins from the micro SD Card Reader directly to your ESP32’s GPIO pins.  Either technique is acceptable for making the required connections between devices.  An example is shown in the picture below.

One important note! Depending on your micro SD card reader and which ESP32 device you are using, you may need to wire your VCC on your SD card reader to 5V on your ESP32 device rather than 3.3V.

ESP32 GPIO Wiring Example

Test code for ESP32 with a Micro SD Card

The following sketch is an example of an ESP32 micro SD card test.  I know it looks like a lot, but in the next section we’ll break it down for you!

//  SD Card Test Example Sketch
//
//  Programming Electronics Academy
//
// include file system library

#include "FS.h"

// include SD card library

#include "SD.h"

// include SPI library

#include "SPI.h"

// Define SD card connection

#define SD_MOSI     23
#define SD_MISO     19
#define SD_SCLK     18
#define SD_CS       5

File myFile;

// Setup

void setup()
{
  Serial.begin(115200);
  while (!Serial) 
  {
    // Wait for serial port to connect. Needed for native USB port only
    ; 
  }

  Serial.println("Setup start");
  SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);
  if (!SD.begin(SD_CS)) 

  {

    Serial.println("SD Card MOUNT FAIL");

  } 

  else 

  {
    Serial.println("SD Card MOUNT SUCCESS");
    Serial.println("");
    uint32_t cardSize = SD.cardSize() / (1024 * 1024);
    String str = "SDCard Size: " + String(cardSize) + "MB";
    Serial.println(str);
    uint8_t cardType = SD.cardType();
    if(cardType == CARD_NONE)
    {
      Serial.println("No SD card attached");
    }
    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");
    }
    myFile = SD.open("/");
    printDirectory(myFile, 0);
    myFile.close();
    Serial.println("");

    // open a new file and immediately close it:

    Serial.println("Creating helloworld.txt...");
    myFile = SD.open("/helloworld.txt", FILE_WRITE);

    // Check to see if the file exists:

    if (SD.exists("/helloworld.txt")) 
    {
      Serial.println("helloworld.txt exists.");
    } 
    else 
    {
      Serial.println("helloworld.txt doesn't exist.");
    }

    // delete the file:
    Serial.println("Removing helloworld.txt...");
    SD.remove("/helloworld.txt");
    if (SD.exists("/helloworld.txt")) 
    {
      Serial.println("helloworld.txt exists.");
    } 
    else 
    {
      Serial.println("helloworld.txt doesn't exist.");
    }
    myFile.close();
    Serial.println("");

    // Open a file. Note that only one file can be open at a time,
    // so you have to close this one before opening another.
    myFile = SD.open("/test.txt", FILE_WRITE);

    // if the file opened okay, write to it.
    if (myFile) 
    {
      Serial.print("Writing to test.txt...");
      myFile.println("testing 1, 2, 3.");
      
    // close the file:
      myFile.close();
      Serial.println("done.");
    } 
    else 
    {

      // if the file didn't open, print an error.
      Serial.println("error opening test.txt");
    }

    // Re-open the file for reading.
    myFile = SD.open("/test.txt");
    if (myFile) 

    {

      Serial.println("test.txt:");
      // Read from the file until there's nothing else in it.
      while (myFile.available()) 
      {
        Serial.write(myFile.read());
      }
      
     // Close the file.
      myFile.close();
    } 
    else 
    {
    
     // If the file didn't open, print an error.
      Serial.println("error opening test.txt");
    }
    myFile.close();
  }
  SD.end();
  SPI.end();
  Serial.println("INFO: Setup complete");
}

// loop
void loop() 
{
  
   // Nothing to do here. 
}
   
   // printDirectory
void printDirectory(File dir, int numTabs) 
{
  while (true) 
  {
    File entry =  dir.openNextFile();
    if (! entry) 
    {
      
     // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) 
    {
      Serial.print('t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) 
    {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } 
    else 
    {

      // Files have sizes, directories do not.
      Serial.print("tt");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

Micro SD Card Code Walkthrough

At the top of the program we’ll include the FS ( file system ) library for file handling, the SD library for micro SD card functionality and the SPI ( serial peripheral interface ) library for communicating between the ESP32 and the micro SD card reader.  

// include file system library
#include "FS.h"
// include SD card library
#include "SD.h"
// include SPI library
#include "SPI.h"

Micro SD Card Test Sketch setup() function

In the setup function, you’ll want to initialize a bunch of stuff!  

Initialize serial communication with the serial monitor using a baud rate of 115200.

Serial.begin(115200);

Now we initialize the SPI communications driver using the begin() function.  For your sketch, you will need to use the appropriate values of SCLK, MISO, MOSI, and CS for the SD card reader connected to your ESP32.  The values below are the ESP32’s default SPI pin values.

#define SD_MOSI     23
#define SD_MISO     19
#define SD_SCLK     18
#define SD_CS       5

SPI.begin(SD_SCLK, SD_MISO, SD_MOSI, SD_CS);

Initialize the micro SD card reader using the begin() function.  If no argument is passed to the begin function, the SPI will use the default chip select pin of GPIO 5.  

if (!SD.begin(SD_CS)) 
  {
    Serial.println("SD Card MOUNT FAIL");
  }

Get the micro SD card size.

uint32_t cardSize = SD.cardSize() / (1024 * 1024);

    String str = "SDCard Size: " + String(cardSize) + "MB";
    Serial.println(str);

Display the micro SD card type in the serial monitor.

uint8_t cardType = SD.cardType();

    if(cardType == CARD_NONE)
    {
      Serial.println("No SD card attached");
    }
    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");
    }

Now, call the printDirectory() function to list and display the contents of your micro SD card on the serial monitor.

myFile = SD.open("/");

    printDirectory(myFile, 0);
    myFile.close();

Next, let’s create a file named “helloworld.txt”.  

After we create the file using the SD.open() function, with the FILE_WRITE parameter for creating a new file for writing, we then check to see if the file exists and display the results of that test.  

If the file creation process worked for the “helloworld.txt” file, then we will delete the file from the micro SD card by using the SD.remove() function.  And, again, we will check for the file’s existence to make sure the file has been successfully deleted.

// open a new file and immediately close it:

    Serial.println("Creating helloworld.txt...");
    myFile = SD.open("/helloworld.txt", FILE_WRITE);

    // Check to see if the file exists:
    if (SD.exists("/helloworld.txt")) 
    {
      Serial.println("helloworld.txt exists.");
    } 
    else 
    {
      Serial.println("helloworld.txt doesn't exist.");
    }

    // delete the file:
    Serial.println("Removing helloworld.txt...");
    SD.remove("/helloworld.txt");
    if (SD.exists("/helloworld.txt")) 
    {
      Serial.println("helloworld.txt exists.");
    } 
    else 
    {
      Serial.println("helloworld.txt doesn't exist.");
    }
    myFile.close();

Finally, we will create another new file this time named “test.txt”.  After the file has been successfully opened, we will write a test string, “testing 1, 2, 3”, using the println() function to the new file.  

Please note that each time you open a file using a file handle object, you must close the file before using that file handle again.  This requirement is necessary because only one file can be open at a time with this file handle object!

// Open a file. Note that only one file can be open at a time,
    // so you have to close this one before opening another.

    myFile = SD.open("/test.txt", FILE_WRITE);

    // if the file opened okay, write to it.
    if (myFile) 
    {
      Serial.print("Writing to test.txt...");
      myFile.println("testing 1, 2, 3.");

      // close the file:
      myFile.close();
      Serial.println("done.");
    } 
    else 
    {

      // if the file didn't open, print an error.
      Serial.println("error opening test.txt");

    }

    // Re-open the file for reading.
    myFile = SD.open("/test.txt");
    if (myFile) 
    {
      Serial.println("test.txt:");

      // Read from the file until there's nothing else in it.
      while (myFile.available()) 
      {
        Serial.write(myFile.read());
      }

Micro SD Card Sketch loop() function

The entire SD card update occurs in the setup function.  So, there is nothing to do in the Arduino main loop.

You can of course add all the code you want to the loop, but in this example it’s not needed.

Micro SD Card Test printDirectory() function

The printDirectory() function recursively prints the contents, files and folders of your micro SD card using the openNextFile() function.

// printDirectory
void printDirectory(File dir, int numTabs) 
{
  while (true) 
  {
    File entry =  dir.openNextFile();
    if (! entry) 
    {

      // no more files
      break;
    }
    for (uint8_t i = 0; i < numTabs; i++) 
    {
      Serial.print('t');
    }
    Serial.print(entry.name());
    if (entry.isDirectory()) 
    {
      Serial.println("/");
      printDirectory(entry, numTabs + 1);
    } 
    else 
    {

      // Files have sizes, directories do not.
      Serial.print("tt");
      Serial.println(entry.size(), DEC);
    }
    entry.close();
  }
}

Testing The ESP32 Micro SD Card Sketch

Once you have connected the ESP32 and micro SD card reader together, upload the above sketch to your ESP32 device.  After the sketch has been uploaded to your ESP32, insert a micro SD card into your micro SD card reader with a file containing the following contents and press the reset ( RST ) button on your ESP32 device to restart your device.

ESP32 Micro SD Card Sketch File

You should see the contents of your micro SD card displayed on the serial monitor.

ESP32 Serial Monitor Output

Once the setup function has completed running, you can remove your SD card from your ESP32’s SD card reader and place it in the SD card reader on your computer.  You should then be able to view the contents of the “test.txt” file on you computer and see the following contents of the file:

ESP32 SD Card View Contents

And that is all there is to it.  It is that easy to read and write files to and from a micro SD card using your ESP32 device and the Arduino IDE!

Where To Go From Here

Adding a micro SD card reader to your ESP32 device can add a lot of functionality to your ESP32 projects including data logging and device provisioning among other things.

For practice, try connecting a micro SD Card reader to your ESP32 device and create a sketch that reads and writes the value of a counter to a test file stored on a micro SD card.  Then, increment the value of the counter after each iteration in your main loop.

For additional practice, try creating a sketch that reads the contents of a file on a micro SD card containing a WiFi SSID and Password and display those contents on the serial monitor.  

AppLab Bricks open in background with actual brick

Arduino AppLab Bricks → Marketing Garbage or New Powerful Interface?

Arduino Ventuno single board computer - top side

New Ventuno Q Dual Brain Single Board Computer

AppLab Pip Install

How to Add Python Packages in Arduino AppLab (No pip install needed)

Arduino Power Section Schematic

Kit-on-a-Shield Schematic Review

Just how random is the ESP32 random number generator?

Just how random is the ESP32 random number generator?

2 Comments

  1. Bryan on May 6, 2025 at 2:21 am

    Please sir I need help, I have a project already but I don’t know the exact point to put the SD card reader codes. Please help

    • Michael Cheich on May 6, 2025 at 7:36 am

      Hi Bryan, If you look at the code right below the header:
      “Test code for ESP32 with a Micro SD Card”

      This is the complete sketch – is this working for you?

Leave a Comment