ESP8266. Comment lire, écrire, effacer l'EEPROM. Calculer l'espace nécessaire en bytes • Domotique et objets connectés à faire soi-même

L’ESP8266 dispose d’une zone mémoire réservée pour simuler l’EEPROM interne de l’Arduino. Initialement, cette zone était présente pour mimer le fonctionnement de l’Arduino et rendre plus facile la migration des programmes. On peut s’en servir pour stocker certains paramètres, tels qu’une adresse IP ou les paramètres Wi-Fi. La taille peut varier de 4 à 4096 bytes sur un ESP8266.

L’organisation de la mémoire Flash d’un module ESP8266

Comme un ordinateur, le module ESP8266 dispose d’une petite quantité de RAM utilisable par l’utilisateur (80ko) et d’un espace de stockage constitué d’un élément à  mémoire flash (similaire aux clés USB) accessible via le bus SPI.

La taille de la mémoire flash varie d’un fabricant à l’autre mais la norme est de 4Mo.

L’accès à la mémoire flash est entièrement géré par le SDK ESP-IDF du fabricant Espressif et se fait via le bus SPI.

La mémoire flash est découpée et chaque espace est réservée pour chaque fonction :

  • Sketch code C++ du projet
  • OTA update zone tampon utilisée pour télécharger une nouvelle mise à jour du sketch
  • File System (FS) c’est ce qui nous intéresse ici
  • EEPROM une petite zone mémoire qui simule celle de l’Arduino. On peut attribuer une taille allant de 4 à 4096 bytes.
  • WiFi config est une zone réservée pour le stockage des paramètres de connexion lorsqu’on développe directement en C++ avec le SDK ESP-IDF
|--------------|-------|---------------|--|--|--|--|--|
^ ^ ^ ^ ^
Sketch OTA update File system EEPROM WiFi config (SDK)

Comment calculer la dimension en byte à réserver ?

C’est tout simple, il suffit de réserver un byte par caractère.

Prenons un exemple d’identifiant et de mot de passe au réseau WiFi que l’on souhaite stocker dans la zone EEPROM de l’ESP8266.

  • L’identifiant réseau (SSID) qui se nomme ici ssidwifi fait 8 caractères. Il faudrait donc réserver en théorie 8 bytes. Par sécurité, on va en réserver 10. Donc, on utilisera les “cases” allant de 0 à 9
  • On va attribuer le mot de passe réseau password. Idem, en théorie, il faudrait réserver 8 bytes que l’on va passer à 10 par sécurité. Le mot de passe réseau sera stocké des bytes 10 à 19.

Voici ce que ça donne de façon plus visuelle.

-------------------------------------------------------
|0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|...|511|
|s|s|i|d|w|i|f|i| | |p |a |s |s |w |o |r |d |  |...|   |
-------------------------------------------------------
^                   ^
index_ssid (0)      index_password (10)

Un exemple d’écrire et de lecture dans la zone EEPROM

Voici un petit exemple qui enregistre l’identifiant réseau et le mot de passe.

Il est possible d’effacer l’EEPROM au démarrage en passant la variable RESET_EEPROM à true.

#include  

int addr_ssid = 0;         // ssid index
int addr_password = 20;    // password index
String ssid = "wifi_ssid"; // wifi ssid
String password = "wifi_password_demo"; // and password

// Set to true to reset eeprom before to write something
#define RESET_EEPROM false

void setup() {
  Serial.begin(115200);
  EEPROM.begin(512);
  Serial.println("");
  
  if ( RESET_EEPROM ) {
    for (int i = 0; i < 512; i++) {
      EEPROM.write(i, 0);
    }
    EEPROM.commit();
    delay(500);
  }
 
  Serial.println("");
  Serial.print("Write WiFi SSID at address "); Serial.println(addr_ssid);
  Serial.print("");
  for (int i = 0; i < ssid.length(); ++i)
  {
    EEPROM.write(addr_ssid + i, ssid[i]);
    Serial.print(ssid[i]); Serial.print("");
  }

  Serial.println("");
  Serial.print("Write WiFi Password at address "); Serial.println(addr_password);
  Serial.print("");
  for (int j = 0; j < password.length(); j++)
  {
    EEPROM.write(addr_password + j, password[j]);
    Serial.print(password[j]); Serial.print("");
  }

  Serial.println("");
  if (EEPROM.commit()) {
    Serial.println("Data successfully committed");
  } else {
    Serial.println("ERROR! Data commit failed");
  }

  Serial.println("");
  Serial.println("Check writing");
  String ssid;
  for (int k = addr_ssid; k < addr_ssid + 20; ++k)
  {
    ssid += char(EEPROM.read(k));
  }
  Serial.print("SSID: ");
  Serial.println(ssid);

  String password;
  for (int l = addr_password; l < addr_password + 20; ++l)
  {
    password += char(EEPROM.read(l));
  }
  Serial.print("PASSWORD: ");
  Serial.println(password);
}

void loop() {

}

Comment écriture dans l’EEPROM ?

On déclare la libraire qui permet de gérer la zone mémoire

#include 

Des variables contiennent l’index et le contenu à enregistrer, par exemple pour l’identifiant du réseau WiFi.

int addr_ssid = 0;         // ssid index
String ssid = "wifi_ssid"; // wifi ssid

Avant de pouvoir utiliser l’EEPROM, il faut l’initialiser en lui attribuant une taille en byte. La taille peut varier de 4 à 4096 bytes. Ici, on attribue 512 bytes mais c’est arbitraire.

EEPROM.begin(512);

On parcours la chaine de caractère contenant l’identifiant réseau et celle du mot de passe. On écrit avec la commande EEPROM.write() chaque caractère de la chaîne à l’aide d’une boucle for.

Remarquez le décalage qui permet de se positionner dans la bonne case mémoire addr_password + j à chaque itération de la boucle for.

for (int j = 0; j < password.length(); j++) { 
  EEPROM.write(addr_password + j, password[j]);  
}

La commande write n’écrit pas directement dans l’EEPROM. Elle prépare juste un tableau de bytes qu’il faut ensuite enregistrer dans la zone mémoire à l’aide de la commande commit().

EEPROM.commit()

Comment lire dans l’EEPROM ?

On lit dans l’EEPROM chaque bytes successivement à l’aide de la méthode read(position). On ajoutera successivement chaque caractère (char) à une chaîne (String)

String password;

Pour récupérer le mot de passe, on va lire de addr_password à addr_password + 20 puisqu’on a réservé 20 bytes pour le mot de passe, ce qui donne

for (int l = addr_password; l < addr_password + 20; ++l) { 
 password += char(EEPROM.read(l)); 
}

Comment effacer l’EEPROM en cas de problème ?

Tout simplement en écrivant 0 pour chaque byte. Le SDK ESP8266 est livré avec un exemple dont voici une version simplifiée.

#include   

void setup() {
  EEPROM.begin(512);
  // write a 0 to all 512 bytes of the EEPROM
  for (int i = 0; i < 512; i++) {
    EEPROM.write(i, 0);
  }
  EEPROM.end();
}

void loop() {
}

Peut-on stocker des caractères spéciaux dans l’EEPROM ?

Oui, à priori la majorité des caractères spéciaux peuvent être enregistrés.

J’ai testé avec succès les caractères spéciaux et accentués suivants (sans oublier l’espace)

& é ' ( § è ! ç à ) - @ # ^ ¨ % , ? ; . : / = + ! | _ -

Mises à jour

14/08/2020 Première publication de l’article

Avez-vous aimé cet article ?