Gestion des fichiers
L’objectif de ce tutoriel est de prendre des photos en rafale et de les sauvegarder au fur et à mesure dans des fichiers numérotés à la racine de la carte Micro SD sous le format “photo_xxxxx.jpg”.
À cette étape, nous remplaçons l’extension « .jpg » par « .txt » pour faciliter la compréhension.
Le nom des fichiers
La fonction “donner_nom_fichier” construit le nom du fichier en fonction de l’index passé en paramètre d’entrée “index_P”. Le paramètre de sortie “nom_fichier_P” est utilisé pour passé le nom du fichier à l’appelant.
void donner_nom_fichier(char* nom_fichier_P, int index_P) { sprintf(nom_fichier_P, "/photo_%05d.jpg", index_P); }
Il est à remarquer que nous ne nous limitons pas à une longueur de 8 caractères dans le nom du fichier.
Écriture de fichiers
L’écriture d’un fichier commence par l’ouverture du fichier en mode écriture (“FILE_WRITE”) à l’aide de la méthode “open“ de l’objet SD. Cette méthode retourne un objet “fichier_l” de la classe “FILE” qui sera utilisé par la suite.
fichier_l = SD.open(nom_fichier_l, FILE_WRITE); if(!fichier_l) { sprintf(tampon_traces_g, "Erreur de creation du fichier '%s'.", nom_fichier_l); Serial.println(tampon_traces_g); }
Concernant le contenu du fichier, pour l’instant nous écrivons simplement le texte « Contenu de photo_xxxxx.txt » dans chaque fichier. Ceci est réalisé à l’aide de la méthode « println » de l’objet fichier_l.
sprintf(contenu_fichier_l, "Contenu du fichier \'%s\'.", nom_fichier_l+1); fichier_l.println(contenu_fichier_l);
Puis le fichier est fermé à l’aide de la méthode « close » de l’objet fichier_l, ce qui va forcer l’ESP32 à vider son tampon et donc à écrire physiquement le fichier sur la carte Micro SD (si cela n’a pas déjà été réalisé).
fichier_l.close();
Pour gérer la répétition de l’écriture des fichiers, une boucle for est utilisée et la constante « NOMBRE_PHOTOS » est définie:
#define NOMBRE_PHOTOS 15
Des fichiers sont déjà présents sur la carte SD ?
Comment faire au démarrage du programme si la carte Micro SD contient déjà des fichiers écrits lors d’une exécution précédente du programme ?
Le choix est fait de continuer la numérotation là où elle s’ést arrêtée précédemment.
La fonction “donner_prochain_index_fichier” est appelée au démarrage du programme. Elle teste incrémentalement la présence de fichiers par l’utilisation de la fonction donner_nom_fichier et en particulier la méthode “exists” de l’objet SD. Cette fonction retourne le prochain index disponible pour l’enregistrement d’un fichier.
int donner_prochain_index_fichier(void) { char nom_fichier_l[30]; int index_fichier_l; index_fichier_l = 0; do { index_fichier_l++; donner_nom_fichier(nom_fichier_l, index_fichier_l); } while(SD.exists(nom_fichier_l)); return(index_fichier_l); }
Code logiciel de gestion des fichiers
Voici le code complété avec la gestion des fichiers:
/* Déclaration des librairies utilisées */ #include <SD.h> /* Définition des constantes globaless */ // Brochage lecteur de cartes: #define PORT_CARD_SCLK 14 #define PORT_CARD_MISO 2 #define PORT_CARD_MOSI 15 #define PORT_CARD_CS 13 // Autres constantes #define NOMBRE_PHOTOS 15 /* Déclaration des fonctions */ bool SD_demarre(int port_CLK_p, int port_MISO_p, int port_MOSI_p, int port_CS_p); void donner_nom_fichier(char* nom_fichier_P, int index_P); int donner_prochain_index_fichier(void); /* Déclaration globales */ SPIClass hspi_G(HSPI); char tampon_traces_g[120]; // Fonction de démarrage, s'exécute une seule fois: void setup() { int ii_l; int prochain_index_fichier_l; File fichier_l; char nom_fichier_l[20]; char contenu_fichier_l[50]; // Pour le debug Serial.begin(115200); Serial.println("-----\n"); // Initialisation de la carte SD while(!SD_demarre(PORT_CARD_SCLK, PORT_CARD_MISO, PORT_CARD_MOSI, PORT_CARD_CS)) { // On bloque la poursuite du programme tant qu'une carte SD correcte n'a pas été insérée delay(1000); } // Parcourt les fichiers d'enregistrement déjà présents prochain_index_fichier_l = donner_prochain_index_fichier(); // Lancement de la série d'enregistrement de fichiers sur carte SD for(ii_l=0; ii_l<NOMBRE_PHOTOS; ii_l++) { donner_nom_fichier(nom_fichier_l, prochain_index_fichier_l+ii_l); fichier_l = SD.open(nom_fichier_l, FILE_WRITE); if(!fichier_l) { sprintf(tampon_traces_g, "Erreur de creation du fichier '%s'.", nom_fichier_l); Serial.println(tampon_traces_g); } else { sprintf(contenu_fichier_l, "Contenu du fichier \'%s\'.", nom_fichier_l+1); fichier_l.println(contenu_fichier_l); fichier_l.close(); sprintf(tampon_traces_g, "Fichier \'%s\' créé.", nom_fichier_l+1); Serial.println(tampon_traces_g); } } // Fermeture de la carte SD SD.end(); } // Fonction principale du programme, s'exécute en boucle: void loop() { } bool SD_demarre(int port_CLK_p, int port_MISO_p, int port_MOSI_p, int port_CS_p) { bool Retour_L; uint8_t type_carte_L; size_t nombre_secteurs_l, taille_secteur_l; // Valeur par defaut Retour_L = false; // Réassigne les ports SPI du bus HSPI hspi_G.begin(port_CLK_p, PORT_CARD_MISO, port_MOSI_p, port_CS_p); if (!SD.begin(port_CS_p, hspi_G, 80000000)) { 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 ou de %.2f Gio", nombre_secteurs_l, taille_secteur_l, ((float)nombre_secteurs_l * (float)taille_secteur_l)/(1000.0*1000.0*1000.0), ((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 Gio de disponibles.", ((float)SD.totalBytes()-(float)SD.usedBytes())/(1024.0*1024.0*1024.0)); Serial.println(tampon_traces_g); Retour_L = true; } } return(Retour_L); } void donner_nom_fichier(char* nom_fichier_P, int index_P) { sprintf(nom_fichier_P, "/photo_%05d.txt", index_P); } int donner_prochain_index_fichier(void) { char nom_fichier_l[30]; int index_fichier_l; index_fichier_l = 0; do { index_fichier_l++; donner_nom_fichier(nom_fichier_l, index_fichier_l); } while(SD.exists(nom_fichier_l)); return(index_fichier_l); }
Exécution du programme de gestion des fichiers
Afin de vérifier l’écriture des fichiers sur la carte Micro SD et la bonne gestion de leur numérotation, nous compilons et transférons ce programme dans l’ESP32-CAM. Les traces affichées sur le moniteur série confirme que 15 fichiers ont été créés avec une numérotation correcte:

On branche la carte Micro SD sur le PC pour poursuivre les tests…

Les fichiers créés sont bien visibles sur le PC.

En ouvrant un fichier avec un simple éditeur de texte comme le “Bloc-Notes” on vérifie également son contenu.

Il ne reste plus qu’à ajouter la gestion de la caméra et notre programme sera complet. Rendez-vous page suivante.
Super article, cela va beaucoup m’aider dans mon projet. Merci beaucoup.
Je suis content que cela vous soit utile…
De quel projet s’agit-il si ce n’est pas secret ? 😉