Ce guide montre comment utiliser une carte microSD avec l’ESP32 : vous apprendrez à lire et à écrire des fichiers sur la carte microSD. Pour interfacer la carte microSD avec la carte ESP32, nous utiliserons un module de carte microSD (protocole de communication SPI). L’utilisation d’une carte microSD avec l’ESP32 est particulièrement utile pour l’enregistrement de données ou le stockage de fichiers qui ne rentrent pas dans le système de fichiers (SPIFFS). L’ESP32 sera programmé à l’aide du noyau Arduino.
Dans ce didacticiel, nous aborderons les sujets suivants :
Module de carte microSD
Il existe différents modules de carte microSD compatibles avec l’ESP32. Nous utilisons le module de carte microSD illustré dans la figure suivante – il communique à l’aide du protocole de communication SPI. Vous pouvez utiliser n’importe quel autre module de carte microSD avec une interface SPI.
Ce module de carte microSD est également compatible avec d’autres microcontrôleurs comme l’Arduino et les cartes ESP8266 NodeMCU. Pour apprendre à utiliser le module carte microSD avec l’Arduino, vous pouvez suivre le tutoriel suivant :
Où acheter?
Vous pouvez cliquer sur le lien ci-dessous pour vérifier les différents magasins où vous pouvez obtenir le module de carte microSD :
Brochage du module de carte MicroSD – SPI
Le module de carte microSD communique à l’aide du protocole de communication SPI. Vous pouvez le connecter à l’ESP32 en utilisant les broches SPI par défaut.
Module de carte microSD | ESP32 |
3V3 | 3.3V |
CS | GPIO 5 |
MOSI | GPIO 23 |
CLK | GPIO 18 |
MISO | GPIO 19 |
Terre | Terre |
Pièces requises
Pour ce tutoriel, vous avez besoin des pièces suivantes :
Vous pouvez utiliser les liens précédents ou accéder directement à MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !
ESP32 avec module de carte microSD – Schéma de principe
Pour câbler le module de carte microSD à la carte ESP32, vous pouvez suivre le schéma suivant (pour les broches ESP32 SPI par défaut) :
Lecture recommandée : Référence de brochage ESP32 : Quelles broches GPIO devez-vous utiliser ?
Préparation de la carte microSD
Avant de poursuivre le didacticiel, assurez-vous de formater votre carte microSD en FAT32. Suivez les instructions suivantes pour formater votre carte microSD ou utilisez un outil logiciel comme Formateur de carte SD (compatible avec Windows et Mac OS).
1. Insérez la carte microSD dans votre ordinateur. Allez dans Poste de travail et faites un clic droit sur la carte SD. Sélectionnez Format comme indiqué dans la figure ci-dessous.
2. Une nouvelle fenêtre apparaît. Sélectionnez FAT32, appuyez sur Démarrer pour initialiser le processus de formatage et suivez les instructions à l’écran.
Préparation de l’IDE Arduino
Nous allons programmer la carte ESP32 à l’aide de l’IDE Arduino. Assurez-vous donc que le module complémentaire ESP32 est installé. Suivez le tutoriel suivant :
Si vous préférez utiliser VSCode + PlatformIO, suivez plutôt le tutoriel suivant :
ESP32 Gestion des fichiers avec un module de carte MicroSD
Il existe deux bibliothèques différentes pour l’ESP32 (incluses dans le noyau Arduino de l’ESP32) : la Bibliothèque SD et le Bibliothèque SDD_MMC.h.
Si vous utilisez la bibliothèque SD, vous utilisez le contrôleur SPI. Si vous utilisez la bibliothèque SDD_MMC, vous utilisez le contrôleur ESP32 SD/SDIO/MMC. Vous pouvez en savoir plus sur le Pilote ESP32 SD/SDIO/MMC.
Il existe plusieurs exemples dans Arduino IDE qui montrent comment gérer les fichiers sur la carte microSD à l’aide de l’ESP32. Dans l’IDE Arduino, accédez à Fichier > Exemples > SD(esp32) > SD_Test, ou copiez le code suivant.
/*
Rui Santos
Complete project details at https://Raspberryme.com/esp32-microsd-card-arduino/
This sketch can be found at: Examples > SD(esp32) > SD_Test
*/
#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(5)){
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(){
}
Cet exemple montre comment effectuer presque toutes les tâches dont vous pourriez avoir besoin avec la carte microSD :
Vous pouvez également utiliser les exemples SD_MMC – ils sont similaires aux exemples SD, mais utilisent le pilote SDMMC. Pour le pilote SDMMC, vous avez besoin d’un module de carte microSD compatible. Le module que nous utilisons dans ce didacticiel ne prend pas en charge SDMMC.
Comment fonctionne le code
Tout d’abord, vous devez inclure les bibliothèques suivantes : FS.h pour gérer les fichiers, SD.h pour s’interfacer avec la carte microSD et SPI.h pour utiliser le protocole de communication SPI.
#include "FS.h"
#include "SD.h"
#include "SPI.h"
L’exemple fournit plusieurs fonctions pour gérer les fichiers sur la carte microSD.
Lister un répertoire
La fonction listDir() liste les répertoires sur la carte SD. Cette fonction accepte comme arguments le système de fichiers (SD), le nom du répertoire principal et les niveaux à atteindre dans le répertoire.
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();
}
}
Voici un exemple d’appel de cette fonction. Le / correspond au répertoire root de la carte microSD.
listDir(SD, "/", 0);
Créer un répertoire
La fonction createDir() crée un nouveau répertoire. Passez en argument le système de fichiers SD et le chemin du nom du répertoire.
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");
}
}
Par exemple, la commande suivante crée un nouveau répertoire à la root appelé mydir.
createDir(SD, "/mydir");
Supprimer un répertoire
Pour supprimer un répertoire de la carte microSD, utilisez la fonction removeDir() et passez en argument le système de fichiers SD et le chemin du nom du répertoire.
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");
}
}
Voici un exemple:
removeDir(SD, "/mydir");
Lire le contenu du fichier
La fonction readFile() lit le contenu d’un fichier et imprime le contenu dans le moniteur série. Comme pour les fonctions précédentes, passez en argument le système de fichiers SD et le chemin du fichier.
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();
}
Par exemple, la ligne suivante lit le contenu du fichier hello.txt.
readFile(SD, "/hello.txt")
Écrire du contenu dans un fichier
Pour écrire du contenu dans un fichier, vous pouvez utiliser la fonction writeFile(). Passer en argument, le filesystem SD, le chemin du fichier et le message
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();
}
La ligne suivante écrit Hello dans le fichier hello.txt.
writeFile(SD, "/hello.txt", "Hello ");
Ajouter du contenu à un fichier
De même, vous pouvez ajouter du contenu à un fichier (sans écraser le contenu précédent) à l’aide de la fonction appendFile().
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();
}
La ligne suivante ajoute le message World!\n dans le fichier hello.txt. Le \n signifie que la prochaine fois que vous écrivez quelque chose dans le fichier, il sera écrit dans une nouvelle ligne.
appendFile(SD, "/hello.txt", "World!\n");
Renommer un fichier
Vous pouvez renommer un fichier en utilisant la fonction renameFile(). Passez comme arguments le système de fichiers SD, le nom de fichier d’origine et le nouveau nom de fichier.
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");
}
}
La ligne suivante renomme le fichier hello.txt en foo.txt.
renameFile(SD, "/hello.txt", "/foo.txt");
Supprimer un fichier
Utilisez la fonction deleteFile() pour supprimer un fichier. Passez en argument le système de fichiers SD et le chemin d’accès du fichier que vous souhaitez supprimer.
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");
}
}
La ligne suivante supprime le fichier foo.txt de la carte microSD.
deleteFile(SD, "/foo.txt");
Tester un fichier
Les fonctions testFileIO() indiquent le temps nécessaire pour lire le contenu d’un fichier.
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();
}
La fonction suivante teste le fichier test.txt.
testFileIO(SD, "/test.txt");
Initialiser la carte microSD
Dans setup(), les lignes suivantes initialisent la carte microSD avec SD.begin().
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;
}
Si vous ne transmettez aucun argument à la fonction begin(), elle essaiera d’initialiser la communication SPI avec la carte microSD sur la broche de sélection de puce (CS) par défaut. Si vous souhaitez utiliser une autre broche CS, vous pouvez la passer en argument à la fonction begin(). Par exemple, si vous souhaitez utiliser GPIO 17 comme broche CS, vous devez utiliser les lignes de code suivantes :
Serial.begin(115200);
if(!SD.begin(17)){
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
Si vous souhaitez utiliser des broches SPI personnalisées avec la carte microSD, allez dans cette rubrique.
Obtenir le type de carte microSD
Les lignes suivantes impriment le type de carte microSD sur le moniteur série.
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");
}
Obtenir la taille de la carte microSD
Vous pouvez obtenir la taille de la carte microSD en appelant la méthode cardSize() :
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
Test des fonctions de la carte MicroSD
Les lignes suivantes appellent les fonctions que nous avons vues précédemment.
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));
Manifestation
Téléchargez le croquis précédent sur votre carte ESP32. Après cela, ouvrez le moniteur série et appuyez sur le bouton RST embarqué ESP32. Si l’initialisation réussit, vous obtiendrez des messages similaires sur le moniteur série.
Utiliser des broches SPI personnalisées avec la carte MicroSD
Les bibliothèques SD.h et SD_MMC.h utilisent les broches VSPI SPI (23, 19, 18, 5) par défaut. Vous pouvez définir d’autres broches comme broches SPI. L’ESP32 dispose de deux interfaces SPI : HSPI et VSPI sur les broches suivantes :
IPS | MOSI | MISO | CLK | CS |
VSPI | GPIO 23 | GPIO 19 | GPIO 18 | GPIO 5 |
HSPI | GPIO 13 | GPIO 12 | GPIO 14 | GPIO 15 |
Lecture recommandée : Référence de brochage ESP32 : Quelles broches GPIO devez-vous utiliser ?
Pour utiliser d’autres broches SPI, vous pouvez procéder comme suit :
Au début de votre code, déclarez les pins que vous souhaitez utiliser, par exemple :
#define SCK 17
#define MISO 19
#define MOSI 23
#define CS 5
Créez une nouvelle classe SPI sur HSPI ou VSPI. Nous utilisons VSPI. Les deux fonctionneront bien.
SPIClass spi = SPIClass(VSPI);
Dans le setup(), initialisez le protocole de communication SPI sur les broches définies précédemment :
spi.begin(SCK, MISO, MOSI, CS);
Enfin, initialisez la carte microSD avec la méthode begin(). Passez en argument la broche CS, l’instance SPI que vous souhaitez utiliser et la fréquence du bus.
if (!SD.begin(CS,spi,80000000)) {
Serial.println("Card Mount Failed");
return;
}
Voici l’exemple de code modifié pour utiliser des broches SPI personnalisées :
/*
Rui Santos
Complete project details at https://Raspberryme.com/esp32-microsd-card-arduino/
This sketch was mofidied from: Examples > SD(esp32) > SD_Test
*/
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#define SCK 17
#define MISO 19
#define MOSI 23
#define CS 5
SPIClass spi = SPIClass(VSPI);
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);
spi.begin(SCK, MISO, MOSI, CS);
if (!SD.begin(CS,spi,80000000)) {
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(){
}
Exemple : Enregistrement de données ESP32 sur une carte microSD
L’utilisation d’une carte microSD est particulièrement utile pour les projets d’enregistrement de données. À titre d’exemple, nous allons vous montrer comment enregistrer les lectures de capteur d’un capteur BME280 avec des horodatages (heure d’époque).
Conditions préalables
Pour cet exemple, assurez-vous que les bibliothèques suivantes sont installées :
Vous pouvez installer ces bibliothèques à l’aide du gestionnaire de bibliothèque Arduino. Dans votre IDE Arduino, accédez à Sketch> Inclure la bibliothèque> Gérer les bibliothèques… Ensuite, recherchez les noms des bibliothèques et installez-les.
Si vous utilisez VS Code avec PlatformIO, copiez les lignes suivantes dans le fichier platformio.ini pour inclure toutes les bibliothèques nécessaires.
lib_deps = adafruit/Adafruit BME280 Library @ ^2.1.0
adafruit/Adafruit Unified Sensor @ ^1.1.4
Diagramme schématique
Pour cet exemple, vous devez câbler le module de carte microSD et le capteur BME280 à l’ESP32. Voici une liste des pièces nécessaires :
Câblez le circuit en suivant le schéma suivant.
Vous pouvez également consulter les tableaux suivants :
BME280 | ESP32 |
NIV | 3V3 |
Terre | Terre |
SCL | GPIO 22 |
SDA | GPIO 21 |
Module de carte microSD | ESP32 |
3V3 | 3.3V |
CS | GPIO 5 |
MOSI | GPIO 23 |
CLK | GPIO 18 |
MISO | GPIO 19 |
Terre | Terre |
Code
Copiez le code suivant dans votre IDE Arduino. Cette esquisse obtient les lectures du capteur BME280 (température, humidité et pression) et les enregistre dans un fichier sur la carte microSD toutes les 30 secondes. Il enregistre également l’horodatage (heure d’époque demandée à un serveur NTP).
/*
Rui Santos
Complete project details at https://Raspberryme.com/esp32-microsd-card-arduino/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
// Libraries for SD card
#include "FS.h"
#include "SD.h"
#include <SPI.h>
//Libraries for BME280 sensor
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
// Libraries to get time from NTP Server
#include <WiFi.h>
#include "time.h"
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Timer variables
unsigned long lastTime = 0;
unsigned long timerDelay = 30000;
// BME280 I2C
Adafruit_BME280 bme;
// Variables to hold sensor readings
float temp;
float hum;
float pres;
String dataMessage;
// NTP server to request epoch time
const char* ntpServer = "pool.ntp.org";
// Variable to save current epoch time
unsigned long epochTime;
// Function that gets current epoch time
unsigned long getTime() {
time_t now;
struct tm timeinfo;
if (!getLocalTime(&timeinfo)) {
//Serial.println("Failed to obtain time");
return(0);
}
time(&now);
return now;
}
// Initialize WiFi
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
// Init BME280
void initBME(){
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
}
// Initialize SD card
void initSDCard(){
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);
}
// Write to the SD card
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();
}
// Append data to the SD card
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 setup() {
Serial.begin(115200);
initWiFi();
initBME();
initSDCard();
configTime(0, 0, ntpServer);
// If the data.txt file doesn't exist
// Create a file on the SD card and write the data labels
File file = SD.open("/data.txt");
if(!file) {
Serial.println("File doesn't exist");
Serial.println("Creating file...");
writeFile(SD, "/data.txt", "Epoch Time, Temperature, Humidity, Pressure \r\n");
}
else {
Serial.println("File already exists");
}
file.close();
}
void loop() {
if ((millis() - lastTime) > timerDelay) {
//Get epoch time
epochTime = getTime();
//Get sensor readings
temp = bme.readTemperature();
//temp = 1.8*bme.readTemperature() + 32;
hum = bme.readHumidity();
pres = bme.readPressure()/100.0F;
//Concatenate all info separated by commas
dataMessage = String(epochTime) + "," + String(temp) + "," + String(hum) + "," + String(pres)+ "\r\n";
Serial.print("Saving data: ");
Serial.println(dataMessage);
//Append the data to file
appendFile(SD, "/data.txt", dataMessage.c_str());
lastTime = millis();
}
}
Insérez vos informations d’identification réseau dans les variables suivantes et le code fonctionnera immédiatement :
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Cet exemple utilise les fonctions que nous avons vues précédemment pour écrire et ajouter des données à la carte microSD (fonctions writeFile() et appendFile()).
Pour mieux comprendre le fonctionnement de cet exemple, nous vous recommandons de jeter un œil aux tutoriels suivants :
Manifestation
Téléchargez le code sur votre tableau. Vous pouvez vérifier sur le moniteur série si tout fonctionne comme prévu.
Laissez le projet fonctionner pendant un certain temps pour recueillir quelques lectures. Ensuite, insérez la carte microSD sur votre ordinateur et vous devriez avoir un fichier appelé data.txt avec les lectures du capteur.
Exemple : Serveur Web ESP32 avec fichiers de la carte microSD
Vous pouvez enregistrer les fichiers pour créer un serveur Web avec l’ESP32 sur une carte microSD (fichiers HTML, CSS, JavaScript et image). Cela peut être utile si les fichiers sont trop volumineux pour tenir sur le système de fichiers ESP32, ou cela peut également être plus pratique en fonction de votre projet.
Pour vous montrer comment procéder, nous allons créer un serveur Web simple qui sert un fichier HTML, un CSS et un fichier PNG pour créer une page Web et afficher un favicon.
Déplacez les fichiers suivants sur votre carte microSD (cliquez sur les liens pour télécharger les fichiers) :
Remarque : déplacez uniquement les fichiers vers la carte microSD, pas les dossiers.
Ensuite, téléchargez le code suivant sur votre IDE Arduino.
/*
Rui Santos
Complete project details at https://Raspberryme.com/esp32-web-server-microsd-card/
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
*/
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
void initSDCard(){
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);
}
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.print("Connecting to WiFi ..");
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(1000);
}
Serial.println(WiFi.localIP());
}
void setup() {
Serial.begin(115200);
initWiFi();
initSDCard();
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SD, "/index.html", "text/html");
});
server.serveStatic("/", SD, "/");
server.begin();
}
void loop() {
}
Insérez vos informations d’identification réseau dans les variables suivantes et le code devrait fonctionner immédiatement :
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Manifestation
Après avoir téléchargé les fichiers sur la carte microSD et l’esquisse sur votre carte ESP32, ouvrez le moniteur série à un débit en bauds de 115200. Appuyez sur le bouton RST intégré à l’ESP32. L’adresse IP ESP32 sera affichée sur le moniteur série.
Sur votre réseau local, ouvrez un navigateur Web et saisissez l’adresse IP ESP32. Vous devriez avoir accès à la page Web suivante construite avec les fichiers stockés sur la carte microSD.
Pour une explication détaillée de ce projet, reportez-vous au tutoriel suivant :
Conclusion
Dans ce tutoriel, vous avez appris à interfacer une carte microSD avec l’ESP32 et à lire et écrire des fichiers. Vous avez également appris à l’utiliser pour des projets d’enregistrement de données ou à stocker des fichiers à servir dans vos projets de serveur Web.
Pour des projets plus approfondis avec la carte microSD, nous vous recommandons de jeter un œil à ce qui suit :
Nous espérons que vous avez trouvé ce tutoriel utile. En savoir plus sur l’ESP32 avec nos ressources :
Cette vidéo vous emmène dans l’histoire de Raspberry Pi :
-
AZDelivery 5 x SPI Reader Mémoire Lecteur Micro SD TF Memory Card Module Shield Compatible avec Arduino incluant Un E-Book!✅ Notre AZ-Delivery SPI Reader Micro est une extension facile à utiliser et économique de votre espace de stockage microcontrôleur en utilisant une fente pour carte SD. ✅ Ces lecteurs de cartes SD pratiques vous permettront de communiquer facilement avec le microcontrôleur via le protocole SPI. ✅ AZ-Delivery Micro SD Card SPI Reader Module supporte les cartes Micro SD (2G), Micro SDHC (32G) (carte haute vitesse). ✅ Notre module SPI Reader Micro SD Card Reader Shield Module supporte une alimentation de 5 volts. ✅ Ce produit inclut un E-Book qui fournit des informations utiles sur la façon de commencer votre projet. Il permet une installation rapide et fait gagner du temps sur le processus de configuration. On y trouve une série d'exemples d'applications, des guides d'installation complets et des bibliothèques.
-
kwmobile Lot 2X Module Carte Micro SD - Lecteur Carte mémoire - Compatible avec Cartes Arduino Raspberry et Autres microcontrôleursLIRE ET ÉCRIRE : Avec le module card micro-SD de kwmobile, lecture et écriture de données sont possibles sur Arduino par exemple. PETIT ET PRATIQUE : Grâce à son design compact, vous pouvez amener votre accessoire partout. DONNÉES TECHNIQUES : Les tensions d'entrée sont comprises entre 4,5 et 5,5 Volts. Le module dispose de 6 broches. COMPATIBLE AVEC : des cartes Arduino, Raspberry Pi ainsi que d'autres micro contrôleurs. UTILISATION : Vous pouvez par exemple vous servir du module pour installer une station de contrôle avec carte mémoire externe ou pour faire de votre Arduino un lecteur MP3.
-
HALJIA SPI 3 pcs Lecteur Carte mémoire Micro SD TF Carte mémoire Shield Module de Lecture écriture des données Compatible avec Arduino Raspberry PiAvec ce module de carte Micro SD, vous pouvez lire et écrire des données sur votre Arduino, Raspberry Pi, etc Tension d'entrée : 5 V Prend en charge les cartes Micro SD, les cartes Micro SDHC (carte haute vitesse) L'interface de communication est l'interface SPI standard 4 trous de vis M2, facile à installer