Skip to content

uPesy only delivers currently in France.

Contents Menu Expand Light mode Dark mode Auto light/dark mode

Your first steps with your uPesy microSD board reader

This page will guide you through getting started with the uPesy SD board reader. It is compatible with Arduino Uno, Arduino Nano, ESP8266, ESP32 and the Raspberry Pi Pico. This module uses the SPI bus to interface the microSD board to your microcontroller through the CS, MISO, MOSI and SCLK pins.

micro SD reader for Arduino, ESP32 and Raspberry Pi Pico

UPesy micro SD reader for Arduino, ESP32, Raspberry Pi Pico …

Module connection

The uPesy reader contains an integrated logic level converter (from 5V to 3.3V) to be used on boards operating in 5V (Arduino) and in 3.3V (ESP and Pi Pico). You can only power the reader with 5V on the Arduino and between 3.3V and 5V on the ESP8266, ESP32 and Pi Pico. However, it is recommended to supply the module with 5V to avoid possible stability problems. The reader’s built-in linear regulator converts the power supply from 5V to 3.3V.

Unlike other SD readers, an additional EN pin allows the module to be completely turned off to save power via a logic signal. By default, if the spindle is not used, this function is disabled. On the other hand, if we impose a high logic state on this pin (5V or 3.3V depending on the microcontroller), the module will be off and, therefore, the micro SD board.

Here are the connections to make depending on your board:

Wiring between the SD module and the different boards

SD reader

Arduino Uno | Nano

ESP32

Pi Pico

CS | SS

D10

GPIO 5

GPIO 17

SCK | SCLK

D13

GPIO 18

GPIO 18

MOSI

D11

GPIO 23

GPIO 19

MISO

D12

GPIO 19

GPIO 16

5V

+5V

+5V ou +3.3V

+5V

GND

GND

GND

GND

Communicate with the micro SD board

Once the connections are made, we will verify that we can communicate with the microSD board with a simple test sketch. Note that there are many examples included in the Arduino IDE software to test this reader. However, it is not necessarily always the same CS pin used, so I recommend that you first use the codes below to verify that you can chat with the micro SD board. Subsequently, if you have an error, you will know that it is not coming from the reader but rather from the code.

If you encounter errors during the test code, I invite you to consult this step-by-step guide to solve your problem with the (micro) SD board reader.

MicroSD reader test for Arduino Uno & Nano

/*
uPesy SD card test

    (Micro) SD card attached to SPI bus as follows:
** MOSI - pin 11 on Arduino Uno
** MISO - pin 12 on Arduino Uno
** CLK - pin 13 on Arduino Uno
** CS - pin 10 (can be changed)
** 5V - +5V of Arduino
*/

#include <SPI.h>
#include <SD.h>

Sd2Card card;
SdVolume volume;
SdFile root;

const int CS = 10;

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
    ; // wait for serial port to connect. Needed for native USB port only
}

Serial.print("\nInitializing SD card...");

// we'll use the initialization code from the utility libraries
// since we're just testing if the card is working!
if (!card.init(SPI_HALF_SPEED, CS)) {
    Serial.println("initialization failed. Things to check:");
    Serial.println("* is a card inserted?");
    Serial.println("* is your wiring correct?");
    Serial.println("* did you change the CS pin to match your shield or module?");
    while (1);
} else {
    Serial.println("Wiring is correct and a card is present.");
}

// print the type of card
Serial.println();
Serial.print("Card type:         ");
switch (card.type()) {
    case SD_CARD_TYPE_SD1:
    Serial.println("SD1");
    break;
    case SD_CARD_TYPE_SD2:
    Serial.println("SD2");
    break;
    case SD_CARD_TYPE_SDHC:
    Serial.println("SDHC");
    break;
    default:
    Serial.println("Unknown");
}

// Now we will try to open the 'volume'/'partition' - it should be FAT16 or FAT32
if (!volume.init(card)) {
    Serial.println("Could not find FAT16/FAT32 partition.\nMake sure you've formatted the card");
    while (1);
}

Serial.print("Clusters:          ");
Serial.println(volume.clusterCount());
Serial.print("Blocks x Cluster:  ");
Serial.println(volume.blocksPerCluster());

Serial.print("Total Blocks:      ");
Serial.println(volume.blocksPerCluster() * volume.clusterCount());
Serial.println();

// print the type and size of the first FAT-type volume
uint32_t volumesize;
Serial.print("Volume type is:    FAT");
Serial.println(volume.fatType(), DEC);

volumesize = volume.blocksPerCluster();    // clusters are collections of blocks
volumesize *= volume.clusterCount();       // we'll have a lot of clusters
volumesize /= 2;                           // SD card blocks are always 512 bytes (2 blocks are 1KB)
Serial.print("Volume size (Kb):  ");
Serial.println(volumesize);
Serial.print("Volume size (Mb):  ");
volumesize /= 1024;
Serial.println(volumesize);
Serial.print("Volume size (Gb):  ");
Serial.println((float)volumesize / 1024.0);

Serial.println("\nFiles found on the card (name, date and size in bytes): ");
root.openRoot(volume);

// list all files in the card with date and size
root.ls(LS_R | LS_DATE | LS_SIZE);
}

void loop(void) {
}

MicroSD reader test for ESP32 boards

/*
uPesy SD card test

(Micro) SD card attached to SPI bus as follows:
** MOSI - pin 18 on ESP32
** MISO - pin 19 on ESP32
** CLK - pin 23 on ESP32
** CS - pin 5
** 5V - +5V of ESP32
*/

#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.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();
}

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(){

}

MicroSD reader test for the Raspberry Pi Pico board

/*
    uPesy SD card test

    (Micro) SD card attached to SPI bus as follows:
    ** MOSI - pin 19 on Pi Pico
    ** MISO - pin 16 on Pi Pico
    ** CLK - pin 18 on Pi Pico
    ** CS - pin 17 on Pi Pico
    ** 5V - +5V of Pi Pico
*/

#include <SPI.h>
#include <SD.h>

File root;

void setup() {
    delay(5000);
    // Open serial communications and wait for port to open:
    Serial.begin(115200);

    Serial.print("Initializing SD card...");

    if (!SD.begin(SS)) {
        Serial.println("initialization failed!");
        return;
    }
    Serial.println("initialization done.");

    root = SD.open("/");

    printDirectory(root, 0);

    Serial.println("done!");
}

void loop() {
// nothing happens after setup finishes.
}

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("\t\t");
    Serial.print(entry.size(), DEC);
    time_t cr = entry.getCreationTime();
    time_t lw = entry.getLastWrite();
    struct tm * tmstruct = localtime(&cr);
    Serial.printf("\tCREATION: %d-%02d-%02d %02d:%02d:%02d", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
    tmstruct = localtime(&lw);
    Serial.printf("\tLAST WRITE: %d-%02d-%02d %02d:%02d:%02d\n", (tmstruct->tm_year) + 1900, (tmstruct->tm_mon) + 1, tmstruct->tm_mday, tmstruct->tm_hour, tmstruct->tm_min, tmstruct->tm_sec);
    }
    entry.close();
}
}

Using the energy-saving mode

The low power mode is handy for saving the battery. It is all the more interesting with the ESP8266 / ESP32 boards, which already have an economy mode (Deep Sleep): you can combine the 2 to have a very economical datalogger.

I invite you to consult the technical documentation of the microSD reader uPesy for more information on its consumption, its included protections and recommendations for use .

We use cookies to make your visit to the site as pleasant as possible. Privacy Policy