ESP32 – MicroSD

Introduction

With little data, we can store them in flash memory or eeprom of microcontrollers. But in the process of working with applications and projects that require storing large amounts of data, they must have memory expansion modules. A microSD card is one of the easiest ways to expand memory with a large capacity, at an affordable price. In this article, I will guide you to connect as well as write and read microSD card data with ESP32 using visual studio code included with IO IDE platform.

Prepare

Hardware

In this project, they will need to use the esp32 module, specifically I chose esp32 wroom devkit v1. Picture below

A screenshot of a computer

Description automatically generated with low confidence
ESP32 DEV KIT V1

The choice of the microSD card module is also very important, there are many forms of communication between the microSD card module and the microcontroller such as SDIO or SPI. We’re using the microSD card module shown in the following figure – it communicates using SPI communication protocol. You can use any other microSD card module with an SPI interface.

Mạch Ghi Đọc Thẻ Micro SD - Nshop
microSD Card Module

The microSD card is the smallest consumer-focused flash memory card in use today. It’s a variation of the standard SD card (short for Secure Digital) and uses a similar set of electrical connections. That makes it possible to use microSD cards in standard SD card slots with the use of an adapter. MicroSD was introduced as a smaller alternative for portable electronics (picture below).

As you might expect, the microSD card is used to hold large volumes of data in devices that benefit from its miniature design. Larger devices still rely on regular SD cards when practical because they support much larger capacities, but in particular, devices like smartphones, dash cams, and small cameras (like action cameras) rely on the microSD card for its tiny shape.

Text

Description automatically generated with medium confidence
Picture3: MicroSD Card

3. SENSOR-MODULE/EXPANSION BOARD PINOUT DIAGRAM

3.1. Hardware

3.1.1. ESP32

Graphical user interface

Description automatically generated
ESP32 Dev kit board pinout

ESP32-WROOM-32 is a powerful, generic Wi-Fi+BT+BLE MCU module that targets a wide variety of applications, ranging from low-power sensor networks to the most demanding tasks, such as voice encoding, music streaming and MP3 decoding.

 At the core of this module is the ESP32-D0WDQ6 chip*. The chip embedded is designed to be scalable and adaptive. There are two CPU cores that can be individually controlled, and the CPU clock frequency is adjustable from 80 MHz to 240 MHz. The chip also has a low-power co-processor that can be used instead of the CPU to save power while performing tasks that do not require much computing power, such as monitoring of peripherals. ESP32 integrates a rich set of peripherals, ranging from capacitive touch sensors, Hall sensors, SD card interface, Ethernet, high-speed SPI, UART, I²S and I²C.

Table

Description automatically generated
Picture 5. : ESP32­WROOM­32 Specifications

3.1.2. Module microSD card

The micro- SD Card Module is a simple solution for transferring data to and from a standard SD card. The pin out is directly compatible with Arduino, but can also be used with other microcontrollers. It allows you to add mass storage and data logging to your project.

This module has SPI interface which is compatible with any sd card and it use 5V or 3.3V power supply which is compatible with Arduino UNO/Mega, ESP8266, ESP32.

SD module has various applications such as data logger, audio, video, graphics. This module will greatly expand the capability an Arduino can do with their poor limited memory. 

Specifications

  • + Working Voltage: 5V/3.3V
  • + Size:20x28mm
  • Interface: SPI
  • Compatible: MicroSD

3.2. Software Tool

Instead of choosing to work with the Arduino IDE project, in this project I chose the visual studio code with the PlatformIO IDE extension.It offers convenience as well as accompanying support.

A screenshot of a computer

Description automatically generated with medium confidence
Visual studio code and PlatformIO IDE interface

ESP32 and MicroSD Pin Connection

Connection between ESP32 and microSD card module

The microSD card module communicates using SPI communication protocol. You can connect it to the ESP32 using the default SPI pins.

Table

Description automatically generated
ESP32 and microSD pin connection

 

  • + VCC pin supplies power for the module and should be connected to 5V pin on the Arduino.
  • +GND should be connected to the Ground of Arduino.
  • +MISO (Master In Slave Out) is SPI output from the Micro SD Card Module
  • +MOSI (Master Out Slave In) is SPI input to the Micro SD Card Module.
  • +SCK (Serial Clock) pin accepts clock pulses which synchronize data transmission generated by Arduino.
    • +SCK (Serial Clock) pin accepts clock pulses which synchronize data transmission generated by Arduino.
    • +SS (Slave Select) pin is used by Arduino(Master) to enable and disable specific devices on SPI bus.

Wiring Diagram

A picture containing text, electronics, circuit

Description automatically generated
Wiring Diagram
A picture containing text

Description automatically generated
Actual Connection

Source code

+ Download SD library at link : 

https://github.com/espressif/arduino-esp32/tree/master/libraries/SD

+ Create new project with properties like the image below

A screenshot of a computer

Description automatically generated
Create new project with visual studio code

+ Copy folder SD in library previously downloaded into folder lib of project

+ Choose example do you want in forder example to play with microSD card

+ You can download the entire project source code at: https://github.com/hongthiet1994/esp32_sdcard

A screenshot of a computer

Description automatically generated with medium confidence
Project structure
#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(){

}

If you have difficulty using visual studio code, you can follow the video tutorial at the link:

Program output

SD- card Data rate(read/write) like sending file over ftp or something.

0 0 votes
Article Rating
Previous articleInterfacing Motion Sensor with Arduino
Next articleHow To interface Arduino with DTH11 Sensor
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments