Example Code for Arduino-SD Card
Last revision 2026/02/05
This article offers comprehensive example code for utilizing an SD card with Arduino, detailing hardware setup, wiring instructions, and SD and File class functions, enabling users to access, manipulate, and manage files and directories effectively.
Hardware Preparation
- FireBeetle 2 ESP32-E (SKU: DFR0654) ×1
- MicroSD Card Module(SKU: DFR0229)×1
- USB Data Cable ×1
- Dupont Wires
Wiring Diagram

Pin Connections:
| FireBeetle 2 ESP32-E | MicroSD Card Module |
|---|---|
| VCC | +5V |
| GND | GND |
| SCK | SCK |
| MO | MOSI |
| MI | MISO |
| D6 | SS |
Other Preparation Work
1. SD Library
The SD class provides the functionality to access the SD card and manipulate files and folders. Its member functions are as follows:
-
begin()
-
Description: Initializes the SD card library and SD card.
-
Syntax: SD.begin() and begin(cspin)
When using SD.begin(), the default is to connect the SS pin of the Arduino SPI to the CS enable selection pin of the SD card. You can also use begin(cspin) to specify a pin to connect to the CS enable selection pin of the SD card, but you need to ensure that the SS pin of the SPI is in output mode, otherwise the SD card library will not work.
-
Parameters
-
CS pin, the Arduino pin connected to the SD card CS pin.
-
Return value: a boolean value, true if initialization is successful, false if initialization fails.
-
-
-
exists()
-
Description: Checks if a file or folder exists on the SD card.
-
Syntax: SD.exists(filename)
-
Parameters:
-
Filename, the name of the file to check. It can include a path, separated by "/".
-
Return value: a boolean value, true if the file or folder exists, false if it does not exist.
-
-
-
open()
-
Description: Opens a file on the SD card. If the file does not exist and is opened for writing, the Arduino will create a file with the specified filename. (The path must exist in advance)
-
Syntax: SD.open(filename) and SD.open(filename, mode)
-
Parameters:
-
Filename, the name of the file to open. It can include a path, separated by "/".
-
mode (optional), the mode to open the file. The default is to open in read-only mode. You can also open the file in the following two modes:
-
FILE_READ: open the file in read-only mode;
-
FILE_WRITE: open the file in write mode.
-
-
Return value: returns an object corresponding to the opened file. If the file cannot be opened, false is returned.
-
-
-
remove()
-
Description: Removes a file from the SD card. If the file does not exist, the function returns an uncertain value. Therefore, it is best to use SD.exists(filename) to check if the file exists before removing the file.
-
Syntax: SD.remove(filename)
-
Parameters:
-
Filename, the name of the file to remove. It can include a path, separated by "/".
-
Return value: a boolean value, true if the file is successfully removed, false if the file removal fails.
-
-
-
mkdir()
-
Description: Creates a folder.
-
Parameters:
-
Filename, the name of the folder to create. It can include a path, separated by "/".
-
Return value: a boolean value, true if the creation is successful, false if the creation fails.
-
-
-
rmdir()
-
Description: Removes a folder. The folder to be removed must be empty.
-
Syntax: SD.rmdir(filename)
-
Parameters:
-
Filename, the name of the folder to remove. It can include a path, separated by "/".
-
Return value: a boolean value, true if the removal is successful, false if the removal fails.
-
-
2. File Class
The File class provides the functionality to read/write files, and its member functions are similar to the serial-related functions previously used. The member functions are as follows:
-
available()
-
Description: Checks the number of bytes of readable data in the current file.
-
Syntax: file.available()
-
Parameters:
-
File, an object of the File type.
-
Return value: the number of available bytes.
-
-
-
close()
-
Description: Closes the file and ensures that the data has been completely written to the SD card.
-
Syntax: file.close()
-
Parameters:
-
File, an object of the File type.
-
Return value: none.
-
-
-
flush()
-
Description: Ensure that data has been written to the SD card. When the file is closed, flush() will run automatically.
-
Syntax: file.flush()
-
Parameters:
-
File, an object of type File.
-
Return value: None.
-
-
-
peek()
-
Description: Read the current byte but does not move to the next byte.
-
Parameters:
-
File, an object of type File.
-
Return value: The next byte or character. Returns -1 if there is no readable data.
-
-
-
position()
-
Description: Get the position in the current file (i.e. the position of the next byte to be read/written).
-
Syntax: file.position()
-
Parameters:
-
File, an object of type File.
-
Return value: The position in the current file.
-
-
-
print()
-
Description: Output data to a file. The file to be written to should already be open and waiting to be written to.
-
Syntax: file.print(data) or file.print(data, BASE)
-
Parameters:
-
File, an object of type File. data, the data to be written (can be of type char, byte, int, long, or String).
-
BASE (optional), specifies the output format of the data: BIN (binary); OCT (octal); DEC (decimal); HEX (hexadecimal).
-
Return value: The number of bytes sent.
-
-
-
println()
-
Description: Output data to a file and add a newline.
-
Syntax: file.println(data) or file.println(data, BASE)
-
Parameters:
-
File, an object of type File.
-
Data, the data to be written (can be of type char, byte, int, long, or String). BASE (optional), specifies the output format of the data: BIN (binary); OCT (octal); DEC (decimal); HEX (hexadecimal).
-
Return value: The number of bytes sent.
-
-
-
seek()
-
Description: Seek to a specified position. The position must be between 0 and the size of the file.
-
Syntax: file.seek(pos)
-
Parameters:
-File, an object of type File.
-
Pos, the position to seek to.
-
Return value: A boolean value. True if the seek was successful, false if it failed.
-
-
-
size()
-
Description: Get the size of the file.
-
Syntax: file.size()
-
Parameters:
-
file, an object of type File.
-
Return value: The size of the file in bytes.
-
-
-
read()
-
Description: Read 1 byte of data.
-
Syntax: file.read()
-
Parameters:
-
File, an object of type File.
-
Return value: The next byte or character. Returns -1 if there is no readable data.
-
-
-
write()
-
Description: Write data to a file.
-
Syntax: file.write(data) and file.write(buf, len)
-
Parameters:
-
File, an object of type File.
-
Data: the data to be written, can be of type byte, char, or string (char*). buf: a character array or byte data.
-
Len: the number of elements in the buf array.
-
Return value: The number of bytes sent.
-
-
-
isDirectory()
-
Description: Determine whether the current file is a directory.
-
Syntax: file.isDirectory()
-
Parameters:
-
File, an object of type File.
-
Return value: A boolean value. True if the file is a directory, false if it is not.
-
-
-
openNextFile()
-
Description: Open the next file.
-
Syntax: file.openNextFile()
-
Parameters:
-
File, an object of type File.
-
Return value: The object corresponding to the next file.
-
-
-
rewindDirectory()
-
Description: Return to the first file in the current directory.
-
Syntax: file.rewindDirectory()
-
Parameters:
-
File, an object of type File.
-
Return value: None.
-
-
Sample Code
The following program implements functions such as accessing SD card, manipulating files and folders, including reading and writing files.
/* Connect the SD card to the following pins:
* SD Card | ESP32
* MISO MISO
* SCK SCK
* ss D6
* MOSI MOSI
* GND GND
* +5V VCC
*/
#include "FS.h"
#include "SD.h"
#include "SPI.h"
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.path(), 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();
}
void setup(){
Serial.begin(115200);
if(!SD.begin()){
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));
}
void loop(){
}
Result
When the program is successfully uploaded, open the serial monitor, you will a series of operations on the SD card, as well as reading its memory.

Was this article helpful?
