Gestion de carte Micro SD et création de fichiers numérotés
Pour cette première partie, nous allons demander à l’ESP32 d’initialiser la carte Micro SD au démarrage en affichant ses caractéristiques sur la liaison série. Puis à chaque appui bouton, il nous créera un nouveau fichier nommé “Enr_???.dat”contenant le message “Contenu du fichier ‘Enr_???.dat’.” (les points d’interrogation sont le numéro du fichier).
Le câblage du lecteur de carte Micro SD
Le lecteur de carte de ce projet offre en interface une liaison SPI (Serial Peripheral Interface) avec 4 signaux logiques pour l’échange de données: CLK (SCK), MISO, MOSI et CS (SS).
Pour l’alimentation de la carte Micro SD:
- Fil rouge, la broche 3V3 est à relier au 3V3 de l’ESP32.
- Fil noir, la broche GND est à brancher à la masse (GND) de l’ESP32.
Pour les échanges d’information entre la carte Micro SD et l’ESP32 :
- Fil orange, la broche CS (Chip/Slave Select) du lecteur de carte à la sortie 5 (SS de l’interface SPI) de l’ESP32. C’est pour la sélection du destinataire.
- Fil bleu, la broche MOSI (Master Output, Slave Input) à la sortie 23 (MOSI de l’interface SPI) de l’ESP32. Ce sont les données envoyées par l’ESP32 à la carte Micro SD. Ces données peuvent être à écrire ou bien des données de protocole (commandes).
- Fil jaune, la broche CLK (Clock) à la sortie 18 (SCK de l’interface SPI) de l’ESP32. C’est pour le signal de synchronisation.
- Fil vert, la broche MISO (Master Input, Slave Output) à l‘entrée 19 (MISO de l’interface SPI) de l’ESP32. Ce sont les données que l’ESP32 reçoit de la carte Micro SD. Ces données sont lues sur la carte ou bien ce sont des données de protocole (réponses à des commandes).
Pour le bouton-poussoir:
- Fil noir, une broche est à brancher à la masse (GND) de l’ESP32.
- Fil blanc, l’autre broche à l’entrée 17 de l’ESP32. Cette entrée 17 sera configurée en Pull-Up (résistance de tirage) dans le code Arduino.
Le code logiciel de création de fichiers numérotés
Pour la gestion de la carte Micro SD, nous utilisons la bibliothèque SD déjà mise à disposition dans l’environnement de développement lors de l’installation de la carte ESP32 pour l’Arduino IDE. Il reste simplement à la déclarer par l’instruction:
#include <SD.h>
Les méthodes de l’objet SD utilisées dans ce tutoriel sont:
- begin: initialise la librairie et le lecteur de carte. Prend en paramètre la broche CS du lecteur de carte.
- cardType: retourne la famille technologique de la carte SD (MMC, SDSC, SDHC ou autre).
- numSectors: retourne le nombre de secteurs que contient la carte.
- sectorSize: retourne la taille d’un secteur.
- totalBytes: retourne la capacité de la carte (en octets).
- usedBytes: retourne l’espace mémoire déjà utilisé (en octets).
- remove: permet de supprimer un fichier existant. Prend en paramètre le chemin du fichier qui doit commencer par le caractère “/”.
- open: ouvre un fichier et retourne un pointeur sur le fichier ouvert. Prend en paramètre le chemin du fichier qui doit commencer par le caractère “/” et également le mode d’ouverture du fichier FILE_READ (lecture seule) ou FILE_WRITE (lecture et écriture).
- exists: vérifie l’existence d’un fichier. (Prend en paramètre le chemin du fichier qui doit commencer par le caractère “/”).
Pour une meilleure compréhension, les principales étapes de ce programme sont:
- L’initialisation de la carte SD et la récupération de ses caractéristiques qui sont regroupées dans la fonction “void SD_demarre(int port_CS_p)“.
- La détermination du numéro du prochain fichier à créer qui est réalisée par “donner_prochain_index_enregistrement“. Cette fonction va lire le contenu de la carte Micro SD et détecter le prochain numéro (index) disponible.
- La construction du nom du fichier à partir de cet index grâce à la fonction “donner_nom_fichier” .
- La création du fichier par la fonction “SD_cree_fichier_dat_pour_ecriture” qui va retourner un objet sur ce fichier pour pouvoir y effectuer des opérations.
- Nous écrivons ensuite le message dans le fichier à l’aide de la méthode println de l’objet avant de le fermer avec la méthode close.
Sans plus attendre, voici le code source complet de cette première partie:
/* Déclaration des librairies utilisées */ #include <SD.h> // Brochage lecteur de cartes: #define PORT_CARD_CS 5 // Brochage des boutons: #define PORT_BOUTON_ENREGISTRER 17 // Autres constantes #define NOM_RACINE_ENREGISTREMENT "/Enr_" /* Déclaration des fonctions */ void SD_demarre(int port_CS_p); File SD_cree_fichier_dat_pour_ecriture(char *nom_fichier_p); size_t SD_ecrire_son_dat(File fichier_p, byte *donnees_son_P, int taille_donnees_p); void donner_nom_fichier(char* nom_fichier_P, int index_P); int donner_prochain_index_enregistrement(void); /* Déclaration globales */ int prochain_index_enregistrement_g; bool bouton_relache_g; char tampon_traces_g[200]; /* Fonction de démarrage, s'exécute une seule fois: */ void setup() { // Pour le debug Serial.begin(115200); Serial.println("-----\n"); // Intialisation des variables globales bouton_relache_g = true; // Initialisation des ports des boutons pinMode(PORT_BOUTON_ENREGISTRER, INPUT_PULLUP); // Initialisation de la carte SD SD_demarre(PORT_CARD_CS); // Parcourt les fichiers d'enregistrement déjà présents prochain_index_enregistrement_g = donner_prochain_index_enregistrement(); } /* Fonction principale du programme, s'exécute en boucle: */ void loop() { char nom_fichier_l[13]; char contenu_fichier_l[50]; File fichier_enregistrement_l; if(digitalRead(PORT_BOUTON_ENREGISTRER) == LOW) { if(bouton_relache_g) { donner_nom_fichier(nom_fichier_l, prochain_index_enregistrement_g); fichier_enregistrement_l = SD_cree_fichier_dat_pour_ecriture(nom_fichier_l); sprintf(contenu_fichier_l, "Contenu du fichier \'%s\'.", nom_fichier_l+1); fichier_enregistrement_l.println(contenu_fichier_l); fichier_enregistrement_l.close(); sprintf(tampon_traces_g, "Fichier \'%s\' créé.", nom_fichier_l+1); Serial.println(tampon_traces_g); prochain_index_enregistrement_g = donner_prochain_index_enregistrement(); bouton_relache_g = false; delay(150); // Pour éviter les rebonds parasites } } else { bouton_relache_g = true; } } void SD_demarre(int port_CS_p) { uint8_t type_carte_L; size_t nombre_secteurs_l, taille_secteur_l; // Initialisation des ports du lecteur carte SD pinMode(port_CS_p, INPUT); // Carte SD insérée ? // Initialisation de la carte SD if (!SD.begin(port_CS_p)) { Serial.println("Carte SD absente, mal formatée ou lecteur mal câblé."); } else { // Identification du type de carte type_carte_L = SD.cardType(); if(type_carte_L == CARD_NONE) { Serial.println("Carte SD illisible"); } else { Serial.print("Type de carte SD: "); switch(type_carte_L) { case CARD_MMC: Serial.println("MMC"); break; case CARD_SD: Serial.println("SDSC"); break; case CARD_SDHC: Serial.println("SDHC"); break; default: Serial.println("Inconnu"); break; } } // Caractéristiques de la carte nombre_secteurs_l = SD.numSectors(); taille_secteur_l = SD.sectorSize(); sprintf(tampon_traces_g, "Découpée en %u secteurs de %u octets, soit une capacité de %.2f Go", nombre_secteurs_l, taille_secteur_l, ((float)nombre_secteurs_l * (float)taille_secteur_l)/(1024.0*1024.0*1024.0)); Serial.println(tampon_traces_g); sprintf(tampon_traces_g, "Il reste %.2f Go de disponibles.", ((float)SD.totalBytes()-(float)SD.usedBytes())/(1024.0*1024.0*1024.0)); Serial.println(tampon_traces_g); } } File SD_cree_fichier_dat_pour_ecriture(char *nom_fichier_p) { File fichier_l; SD.remove(nom_fichier_p); fichier_l = SD.open(nom_fichier_p, FILE_WRITE); if(!fichier_l) { sprintf(tampon_traces_g, "Erreur de creation du fichie \'%s\'.", nom_fichier_p+1); Serial.println(tampon_traces_g); } return(fichier_l); } int donner_prochain_index_enregistrement(void) { char nom_fichier_l[13]; int index_message_l; index_message_l = 0; do { index_message_l++; donner_nom_fichier(nom_fichier_l, index_message_l); } while(SD.exists(nom_fichier_l)); return(index_message_l); } void donner_nom_fichier(char* nom_fichier_P, int index_P) { sprintf(nom_fichier_P, "%s%03d%s", NOM_RACINE_ENREGISTREMENT, index_P, ".dat"); }
Compilation et test du programme de gestion de la carte Micro SD
Si vous souhaitez des explications sur la compilation du programme, son transfert dans l’ESP32-DevKit et la lecture des messages envoyés par le port série, je vous invite à vous reporter à l’article Programmer la carte ESP32-DevKitC avec l’Arduino IDE.
Concernant les tests, après avoir redémarré la carte ESP32-DevKitC par un bref appui sur le bouton reset identifié “EN”, vous obtenez les informations sur les caractéristiques de la carte Micro SD (1).
Et après chaque appui sur le bouton-poussoir, un message sur le moniteur série confirme la création d’un nouveau fichier (2).
Il ne vous reste plus qu’à brancher votre carte Micro SD sur votre PC…
… pour vérifier que les fichiers créés sont bien visibles sur votre PC.
En ouvrant un fichier avec un simple éditeur de texte comme le “Bloc-Notes” vous vérifiez également le contenu du fichier.
Si tout est correct, il est temps de passer à l’enregistrement des données du micro page suivante.
Une erreur de carte Micro SD que vous allez probablement rencontrer
Bien que vous ayez correctement câblé votre montage, bien inséré la carte Micro SD dans le lecteur (du bon côté), il se peut que vous voyiez le message suivant sur le moniteur série:
Je vous invite alors à vérifier le formatage de votre carte Micro SD.
Pour cela, insérer votre carte dans le PC,
Puis avec un clic droit de la souris sur le lecteur affiché correspondant à votre carte Micro SD, cliquez sur “Propriétés”. Vous obtenez alors le système de fichier correspondant à votre carte :
Si le système de fichiers affiché est différent de “FAT32”, vous devez formater votre carte Micro SD. Bin que le système de fichier FAT32 soit capable de gérer des disques d’une taille allant jusqu’à 2 To, Windows refuse de formater en FAT32 des disques supérieurs à 32 Go. Ayant une carte Micro SD d’une taille de 59 Go j’ai donc utilisé l’outil “FAT32 Format” de Ridgecrop, disponible sur le site officiel ou ici pour contourner cette limitation.
Après avoir vérifié que le lecteur sélectionné est bien ma carte Micro SD et pas mon disque dur (1), j’ai nommé ma carte ARD_VOIX (2) et coché l’option de formatage rapide (3) avant de cliquer sur “start” (4).
Une fois le formatage terminé, vous pouvez redémarrer les tests du programme.