dimanche 21 février 2021

ESP32/ESP8266: Écriture et lecture d'un fichier en mémoire flash

Il est possible d'enregistrer des fichiers dans la mémoire flash de l'ESP8266 et de l'ESP32. Par exemple, on peut utiliser la mémoire flash pour héberger les fichiers html d'un serveur web, ou encore pour enregistrer les données d'un data logger. Les fichiers sont préservés suite à un redémarrage, une coupure d'alimentation, ou le téléversement d'un nouveau programme.


SPIFFS ou LittleFS?

Pendant quelques années, le système de fichiers recommandé pour l'ESP8266 était SPIFFS, mais il n'est plus activement supporté par l'équipe de développement du core Arduino pour ESP8266, et il risque de disparaître totalement dans une future version. Il est plutôt recommandé d'utiliser le système de fichiers LittleFS, dont la bibliothèque est intégrée dans le core Arduino ESP8266.

Du côté de l'ESP32, la future disparition du format SPIFFS ne semble pas aussi explicite pour l'instant. Au moment où j'écris ces lignes, seule la bibliothèque SPIFFS est distribuée avec le core Arduino ESP32 (version 1.0.4) et il faut installer une bibliothèque supplémentaire pour utiliser LittleFS,  mais on indique que cette bibliothèque sera bientôt intégré au core ESP32 pour Arduino.

Un sketch rédigé pour le format SPIFFS ne nécessite que très peu de modifications pour fonctionner avec LittleFS. Cependant, si vous avez déjà enregistré des fichiers en format SPIFFS, ils seront effacés si vous exécutez ensuite un sketch qui utilise le format LittleFS.

J'ai utilisé Little FS sur les deux plateformes, car j'aime bien concevoir des programmes qui fonctionnent à la fois sur ESP8266 et sur ESP32.

LittleFS sur ESP8266

Il n'y a aucune bibliothèque à installer, puisqu'elle est déjà intégrée au core. Deux fichiers d'exemple sont fournis (Menu Fichier - Exemples - LittleFS(esp8266)).

LittleFS sur ESP32

Pour l'ESP32, j'ai installé la bibliothèque LITTLEFS par lorol en passant par le gestionnaire de bibliothèques de l'IDE Arduino.  (Attention, lecteur du futur: ce ne sera peut-être plus nécessaire au moment où tu liras ces lignes...)

Là encore, deux fichiers d'exemple sont fournis (Menu Fichier - Exemples - LittleFS_esp32).


Mon projet

Mon but était de rédiger un sketch fonctionnant aussi bien avec l'ESP8266 qu'avec l'ESP32. Trois boutons sont connectés au module: un premier bouton lit le contenu d'un fichier intitulé "document.txt", un deuxième bouton ajoute des données dans le fichier (un nombre entier qui augmente à chaque écriture", et le troisième bouton supprime le fichier.

Les boutons sont branchés de la façon suivante:

  • Bouton "Lecture du fichier": GPIO 4
  • Bouton "Écriture dans le fichier": GPIO 5
  • Bouton "Suppression du fichier": GPIO 15

Schéma des connexion sur module Wemos D1 mini:



Schéma des connexions sur module ESP32:


Le sketch

Il existe quelques différences de syntaxe entre la version ESP8266 et la version ESP32, ce qui m'a obligé à utiliser des directives au préprocesseur (#defined ARDUINO_ARCH_ESP32 et #defined ARDUINO_ARCH_ESP8266).

Par exemple, dans la version ESP8266, il faut écrire "LittleFS" alors que c'est "LITTLEFS" dans la version ESP32.

Pour l'ESP32, j'ai utilisé l'expression "LITTLEFS.begin(1)" pour qu'un répertoire en format LittleFS soit créé s'il n'en existe pas déjà un.  Mais pour obtenir le même comportement avec l'ESP8266, il faut simplement écrire "LittleFS.begin()".

De plus, la routine "listDir" qui fait la liste des fichiers est assez différentes pour les deux microcontrôleurs.

-

/*
Écriture/lecture d'un fichier (LITTLEFS) sur ESP8266 ou ESP32
Un bouton permet de lire le contenu d'un fichier.
Un autre bouton permet d'ajouter du contenu dans le fichier.
Un troisième bouton supprime le fichier
Plus d'infos:
https://electroniqueamateur.blogspot.com/2021/02/esp32esp8266-ecriture-et-lecture-dun.html
*/
#include "FS.h"
#if defined ARDUINO_ARCH_ESP32 // spécifique à l'ESP32
#define LittleFS LITTLEFS
#include <LITTLEFS.h>
#elif defined ARDUINO_ARCH_ESP8266 // spécifique à l'ESP8266
#include <LittleFS.h>
#endif
// connexion des boutons:
#define boutonLecture 4 // GPIO4
#define boutonEcriture 5 // GPIO5
#define boutonSupprimer 15 // GPIO15
int compteur = 0;
// lecture d'un fichier
void readFile(const char * path) {
Serial.printf("Lecture du fichier: %s ", path);
File file = LittleFS.open(path, "r");
if (!file || file.isDirectory()) {
Serial.println("...echec de la lecture...ce fichier existe-t-il?");
return;
}
Serial.println("reussie. Contenu:");
while (file.available()) {
Serial.write(file.read());
}
Serial.println();
}
// ajout d'information dans un fichier
// si le fichier n'existe pas déjà, il est créé.
void appendFile(const char * path, const char * message) {
Serial.printf("Ajout de donnees dans le fichier: %s ", path);
File file = LittleFS.open(path, "a");
if (!file) {
Serial.println(" :echec de l'ouverture du fichier!");
return;
}
if (file.print(message)) {
Serial.println("reussie.");
} else {
Serial.println(" :echec de l'ajout au fichier!");
}
Serial.println();
}
// Liste des fichiers présents
void listDir() {
Serial.println("Liste des fichiers:");
#if defined ARDUINO_ARCH_ESP32
File root = LITTLEFS.open("/", "r");
if (!root) {
Serial.println("- echec de l'ouverture du repertoire");
return;
}
File file = root.openNextFile();
while (file) {
Serial.print(" Nom: ");
Serial.print(file.name());
Serial.print("\tTaille: ");
Serial.println(file.size());
file = root.openNextFile();
}
#elif defined ARDUINO_ARCH_ESP8266
Dir dir = LittleFS.openDir ("");
while (dir.next ()) {
Serial.print(" Nom: ");
Serial.print (dir.fileName ());
Serial.print("\tTaille: ");
Serial.println (dir.fileSize ());
}
#endif
Serial.println();
}
void deleteFile(const char * path) {
Serial.printf("Suppression du fichier: %s ", path);
if (LittleFS.remove(path)) {
Serial.println(" reussie");
} else {
Serial.println(" : echec de la suppression!");
}
Serial.println();
}
void setup() {
Serial.begin(115200);
Serial.println();
pinMode(boutonLecture, INPUT);
pinMode(boutonEcriture, INPUT);
#if defined ARDUINO_ARCH_ESP32 // spécifique à l'ESP32
if (!LITTLEFS.begin(1)) {
Serial.println("Echec du montage LITTLEFS");
return;
}
#elif defined ARDUINO_ARCH_ESP8266 // spécifique à l'ESP8266
if (!LittleFS.begin()) {
Serial.println("Echec du montage LITTLEFS");
return;
}
#endif
listDir();
}
void loop() {
char nombre[6]; // chaîne de caractères pour la conversion de la valeur du compteur
if (digitalRead(boutonLecture)) {
readFile("/document.txt");
Serial.println("");
delay(300); // anti rebond
}
if (digitalRead(boutonEcriture)) {
Serial.print("Compteur = ");
Serial.println(compteur);
sprintf(nombre, " %i", compteur); // transformation du nombre en chaîne de caractères
appendFile("/document.txt", nombre);
compteur++;
delay(300); // anti rebond
}
if (digitalRead(boutonSupprimer)) {
deleteFile("/document.txt");
listDir();
delay(300); // anti rebond
}
}
-

On peut constater l'effet de l'appui sur un bouton en regardant l'affichage du moniteur série:


À lire également


Yves Pelletier (TwitterFacebook


Aucun commentaire:

Enregistrer un commentaire