You are currently viewing Photos sur Carte SD par SPI avec l’ESP32-CAM
Enregistrer des photos sur SD Card par SPI avec l'ESP32-CAM

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:

Traces de création de fichiers affichées sur le moniteur série
Traces de création de fichiers affichées sur le moniteur série

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

Insertion d'une carte Micro SD sur le port USB du PC
Insertion d’une carte Micro SD sur le port USB du PC

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

Liste de fichiers sur la carte Micro SD
Liste de fichiers sur la carte Micro SD

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

Vérification du contenu d'un fichier créé sur la carte Micro SD
Vérification du contenu d’un fichier créé sur la carte Micro SD

Il ne reste plus qu’à ajouter la gestion de la caméra et notre programme sera complet. Rendez-vous page suivante.

S’abonner
Notification pour
guest
2 Commentaires
Le plus ancien
Le plus récent Le plus populaire
Commentaires en ligne
Afficher tous les commentaires
Romain
Romain
2 mois il y a

Super article, cela va beaucoup m’aider dans mon projet. Merci beaucoup.