Dernière révision : septembre 2023










ESP8266 : présentation, flashage OTA et LittleFS

Philippe Notez (philippe.notez@musee-info.fr)





Sommaire

Introduction

L’électronique et l’informatique ont profondément modifié notre société. C’est certainement la révolution industrielle la plus rapide de l’histoire de l’humanité. En effet, l’ordinateur que nous connaissons aujourd’hui était tout simplement inimaginable il y a seulement une cinquantaine d’années. Et avec les Arduino, les ESP8266 ou les Raspberry Pi Pico, l'aventure est loin d'être terminée.

L’auteur ne pourra en aucun cas être tenu responsable des dommages qui résulteraient de l’utilisation des informations publiées sur ce site, sous licence Creative Commons BY-NC-SA. Toute reproduction ou modification d'un document, même partielle, est autorisée à condition que son origine et le nom de l'auteur soient clairement indiqués (BY), qu'il soit utilisé à des fins non commerciales (NC), que son mode de diffusion soit identique au document initial (SA), et que cela ne porte pas atteinte à l’auteur.

Ce document présente les caractéristiques et quelques fonctionnalités d'une carte ESP8266, en espérant toujours être le plus clair et précis possible. Malgré tout le soin apporté à la rédaction, l'auteur vous remercie de bien vouloir le contacter si vous relevez la moindre erreur ou omission, et vous souhaite une agréable lecture.

Si vous avez apprécié ce document, vous pouvez faire un don ici. Merci pour votre soutien.


Présentation

Le terme ESP8266 désigne une famille de microcontrôleurs développés en Chine, à partir de 2014, et proposant une connectivité wifi à bas coût. Le succès fut immédiat, grâce notamment à l'absence d'un produit équivalent sur le marché. Espressif (la société à l'origine de l'ESP8266) développera, à partir de ce moment là, une série de microcontrôleurs de plus en plus performants, intégrant tous le wifi.

La programmation s'effectue via un convertisseur USB - RS-232, suivant le même principe que l'Arduino. J'utilise d'ailleurs l'EDI de l'Arduino pour programmer l'ESP8266 (voir ici). Vous pouvez bien-sûr utiliser d'autres EDI (dont celui fourni par Espressif) et d'autres langages, comme Python que nous décrouvrirons plus bas.


ESP8266 (famille) ESP-12E (version du microcontrôleur)
NodeMCU (plate-forme) V3 (version de la plate-forme)
CH340G (convertisseur USB - RS-232).


Microcontrôleur : Tensilica Xtensa LX106 (32 bits, 80/160 MHz)

Mémoire vive : 64 kio1 (code) + 96 kio (data)

Mémoire flash : 512 kio à 16 Mio (ESP-01 : 512 kio, ESP-01S : 1 Mio), accès via bus SPI dédié (GPIO62 à 11)

E/S numériques : 11 + 6 (flash), PWM sur toutes les broches sauf GPIO16 (10 bits, 3,3 V max.)

Entrée analogique : 1 (résolution sur 10 bits, 1 V max., certaines cartes permettent d'aller jusqu'à 3,3 V)

Interruptions : toutes les E/S numériques sauf GPIO16

Bus I2C : 1

Bus SPI : 2, dont 1 réservé pour l'accès à la mémoire flash

Liaison RS-232 : 1

Convertisseur USB - RS-232 : CP2102 ou CH340

Wifi : 802.11 b/g/n

Alimentation : Vin (10 V max.), broche 5 V ou USB

Tension de fonctionnement : 3,3 V

Consommation : 60 à 200 mA

Attention, la tension de fonctionnement d'un ESP8266 est de 3,3 V, contrairement aux Arduino qui fonctionnent à 5 V (sauf l'Arduino Due qui fonctionne également à 3,3 V) ! Tout dépassement de cette valeur sur l'une des broches (sauf Vin bien-sûr) le détruira. Il faudra donc prévoir éventuellement des convertisseurs 3,3 V <> 5 V.



ESP8266 ESP-01 (512 Kio de mémoire flash) ou ESP-01S (1 Mio de mémoire flash).

Ce modèle ne dispose que de quatre E/S. Pour récupérer les deux E/S affectées à la liaison série, vous pouvez utiliser les lignes suivantes dans votre sketch :
  • pinMode(1,FUNCTION_3); // GPIO1 = GPIO
  • pinMode(3,FUNCTION_3); // GPIO3 = GPIO
Pour réaffecter les deux E/S à la liaison série :
  • pinMode(1,FUNCTION_0); // GPIO1 = TX
  • pinMode(3,FUNCTION_0); // GPIO3 = RX
Bon, le mieux est quand-même d'utiliser un modèle avec plus d'E/S !



ESP8266 ESP-12E NodeMCU V2 CP2102.



ESP8266 ESP-12F WeMos D1 mini. Petit, complet, et pas cher... Mon chouchou !

EN (chip enable) : active à l'état haut

RST (reset) : active à l'état bas

GPIO0 : 0 = programming (UART bootloader), 1 = flash startup (normal)

GPIO1 : UART0 (TX)

GPIO3 : UART0 (RX)

GPIO4 : I2C (SDA)

GPIO5 : I2C (SCL)

GPIO12 : HSPI (MISO)

GPIO13 : HSPI (MOSI)

GPIO14 : HSPI (SCLK)

GPIO15 : HSPI (CS)

D0 : GPIO16 (HIGH at boot, used to wake up from deep sleep if connected to RST)

D1 : GPIO5

D2 : GPIO4 (PWM)

D3 : GPIO0 (résistance à 3V3, BP "FLASH" à GND, boot fails if pulled LOW)

D4 : GPIO2 (résistance à 3V3, résistance + led à 3V3, HIGH at boot, boot fails if pulled LOW)

D5 : GPIO14 (PWM)

D6 : GPIO12 (PWM)

D7 : GPIO13

D8 : GPIO15 (PWM, résistance à GND, boot fails if pulled HIGH)

RX : GPIO3 (HIGH at boot)

TX : GPIO1 (HIGH at boot, boot fails if pulled LOW)



ESP8266 ESP-12F WeMos D1, une carte à la sauce... Arduino Uno !


Procédure pour installer les cartes

Ouvrez l'EDI Arduino (Arduino IDE) :
  • Fichiers, Préférences, URL de gestionnaire de cartes supplémentaires, ajoutez la ligne suivante :
    https://arduino.esp8266.com/stable/package_esp8266com_index.json
  • Outils, Type de carte, Gestionnaire de carte, esp8266, Installer
Dans le menu Outils, puis Type de carte, vous devriez voir la ligne ESP8266 Boards...


Flashage OTA

Puisque l'ESP8266 possède une connexion wifi, peut-on utiliser cette connexion pour téléverser un sketch ? La réponse est oui ! C'est ce qu'on appelle le flashage (écriture de la mémoire flash) OTA (Over The Air). Quel intérêt ? Plus besoin de câble USB, de convertisseur USB - RS-232, et de liaison série ! C'est bien pratique pour récupérer les deux E/S de l'ESP-01 affectées à la liaison série, c'est aussi très intéressant si on doit placer l'ESP8266 dans un endroit difficile d'accès, par exemple. Pour utiliser cette fonctionnalité, on a quand-même besoin une fois de la liaison série pour téléverser un premier sketch qui va initialiser l'OTA.

Il faut néanmoins savoir que l'OTA a un inconvénient, il nécessite deux fois plus de mémoire flash ! En effet, l'ESP8266 utilise la dernière version téléversée de votre sketch (qui contient l'initialisation de l'OTA) pour pouvoir téléverser une nouvelle version. Il faut donc toujours avoir un sketch fonctionnel dans la mémoire flash de l'ESP8266, car on peut avoir un problème avec la connexion wifi pendant le téléversement d'une nouvelle version (coupure de courant, par exemple), et il ne faut pas oublier que, dans un système embarqué, l'ESP8266 est souvent difficile d'accès. Il doit alors pouvoir redémarrer sans problème en mode OTA, même après un téléversement défectueux.

Ouvrez l'EDI Arduino (Arduino IDE), allez sur Outils, Type de carte, ESP8266 Boards, Generic ESP8266 Module. Allez ensuite sur Outils, puis Flash Size. Regardez la ligne avec 1MB (FS:none OTA:~502KB). On constate que l'OTA est bien défini à environ la moitié de la mémoire flash lorsque cette dernière ne contient pas de système de fichiers (FS:none). Environ, car n'oublions pas que l'ESP8266, tout comme l'Arduino, a besion d'un peu de place pour stocker sa configuration.

Pour résumer :
  1. on utilise la liaison série pour le premier téléversement
  2. on débranche le câble USB et on redémarre l'ESP8266 (il faudra donc l'alimenter via la broche Vin, par exemple)
  3. on téléverse une nouvelle version dans la mémoire flash inoccupée (environ la moitié de la mémoire totale)
  4. si le téléversement s'est bien passé, l'ancienne version est écrasée et l'ESP8266 redémarre sur la nouvelle version (la moitié de la mémoire flash redevient inoccupée)
  5. on retourne à l'étape 3 lors d'une nouvelle version...
La nouvelle version étant compressée, il est théoriquement possible d'utiliser un sketch légèrement supérieur à la moitié de la mémoire totale.

Pour initialiser l'OTA, vous pouvez utiliser l'exemple suivant :

esp-01.ino
// initialiser l'OTA sur un ESP8266

#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>

#define nom_wifi "" // saisissez le nom (SSID) de votre réseau wifi 
#define mdp_wifi "" // saisissez le mot de passe de votre réseau wifi
#define nom_ota "Mon premier sketch OTA"
#define mdp_ota "12345678"

IPAddress ip(192,168,1,47);
IPAddress masque(255,255,255,0);
IPAddress passerelle(192,168,1,1);
IPAddress dns(192,168,1,1);

void setup()
  {
  // WiFi.mode(WIFI_AP);                        // Access Point mode (box)
  // WiFi.softAPConfig(ip,passerelle,masque);
  // WiFi.softAP(nom_wifi,mdp_wifi,1,false,8);  // channel (1 to 13, default = 1), ssid_hidden (true or false, default = false), max_connection (0 to 8, default = 4)
  // WiFi.setOutputPower(5.0);                  // puissance d'émission (0 à 20.5 dBm, -3 dBm pour une puissance divisée par 2, +3 dBm pour une puissance multipliée par 2)
  WiFi.mode(WIFI_STA);
  WiFi.config(ip,passerelle,masque,dns);
  WiFi.begin(nom_wifi,mdp_wifi);
  Serial.begin(9600);
  Serial.write(13);
  Serial.write(10);
  Serial.write("Numéro de série de l'ESP8266 : ");
  Serial.println(ESP.getChipId());
  Serial.write("Fréquence CPU (MHz) : ");
  Serial.println(ESP.getCpuFreqMHz());
  Serial.write("Fréquence mémoire flash (MHz) : ");
  Serial.println(ESP.getFlashChipSpeed()/1000000);
  Serial.write("Capacité mémoire flash (octets) : ");
  Serial.println(ESP.getFlashChipRealSize());
  Serial.write("Mémoire flash utilisée (octets) : ");
  Serial.println(ESP.getSketchSize());
  Serial.write("Mémoire flash disponible (octets) : ");
  Serial.println(ESP.getFreeSketchSpace());
  Serial.write("Connexion au réseau wifi");
  while (WiFi.status()!=WL_CONNECTED)
    {
    Serial.write('.');
    delay(100);
    }
  Serial.write(13);
  Serial.write(10);
  Serial.write("Connecté au réseau wifi !");
  Serial.write(13);
  Serial.write(10);
  Serial.write("Nom du réseau : ");
  Serial.println(WiFi.SSID());
  Serial.write("Force du signal : ");
  Serial.print(WiFi.RSSI());  // Received Signal Strength Indication
  Serial.write(" dBm");       // dB mW, 0 dBm = puissance max. (1 mW)
  Serial.write(13);
  Serial.write(10);
  Serial.write("Adresse MAC : ");
  Serial.println(WiFi.macAddress());
  Serial.write("Adresse IP : ");
  Serial.println(WiFi.localIP());
  Serial.write("Masque de sous-réseau : ");
  Serial.println(WiFi.subnetMask());
  Serial.write("Passerelle : ");
  Serial.println(WiFi.gatewayIP());
  Serial.write("Serveur DNS : ");
  Serial.println(WiFi.dnsIP());
  ArduinoOTA.setHostname(nom_ota);
  ArduinoOTA.setPassword(mdp_ota);
  ArduinoOTA.begin();
  Serial.write("OTA démarré !");
  }

void loop()
  {
  ArduinoOTA.handle();    
  }

Si vous voulez utiliser le DHCP de votre box, vous pouvez supprimer la ligne WiFi.config. Sinon, n'oubliez pas de modifier les valeurs ip, masque, passerelle, et dns, en fonction de votre réseau. Les quatre premières lignes mises en commentaires dans la fonction setup configurent l'ESP8266 en mode Access Point (comme une box). Dans notre exemple, nous utilisons l'ESP8266 en mode Station, puisqu'il se connecte sur une box. Nous utilisons également un mot de passe (12345678) pour sécuriser les téléversements via l'OTA :


Lors du premier téléversement utilisant la liaison série, ouvrez le moniteur série (il doit être configuré à 9600 bauds). En fonction de votre configuration, vous devriez obtenir :



Si tout va bien, on peut fermer le moniteur série et supprimer toutes les lignes commençant par Serial :

esp-01.ino
// initialiser l'OTA sur un ESP8266

#include <ESP8266WiFi.h>
#include <ArduinoOTA.h>

#define nom_wifi "" // saisissez le nom (SSID) de votre réseau wifi 
#define mdp_wifi "" // saisissez le mot de passe de votre réseau wifi
#define nom_ota "Mon premier sketch OTA"
#define mdp_ota "12345678"

IPAddress ip(192,168,1,47);
IPAddress masque(255,255,255,0);
IPAddress passerelle(192,168,1,1);
IPAddress dns(192,168,1,1);

void setup()
  {
  WiFi.mode(WIFI_STA);
  WiFi.config(ip,passerelle,masque,dns);
  WiFi.begin(nom_wifi,mdp_wifi);
  while (WiFi.status()!=WL_CONNECTED) delay(100);
  ArduinoOTA.setHostname(nom_ota);
  ArduinoOTA.setPassword(mdp_ota);
  ArduinoOTA.begin();
  }

void loop()
  {
  ArduinoOTA.handle();    
  }  

Nous pouvons maintenant débrancher le câble USB de l'ordinateur, alimenter l'ESP8266 via la broche Vin, 5V, ou brancher le câble USB sur un chargeur de téléphone, par exemple. Vous devriez voir dans Outils, Port, Ports réseau, Mon premier sketch OTA at X.X.X.X (Generic ESP8266 Module).


LittleFS

Une partie de la mémoire flash peut être utilisée pour contenir un système de fichiers. C'est intéressant pour faire de l'acquisition de données, par exemple.

Le premier système de fichiers se nomme SPIFFS (Serial Peripheral Interface Flash File System). Pour l'installer, vous devez :
  • récupérer la dernière version ici
  • décompresser le fichier zip dans le dossier tools (qui se trouve dans le dossier Arduino)
  • créer un dossier data dans le même dossier que le sketch (fichier ino)
  • relancer l'EDI
  • aller dans Outils, Flash Size, et choisir une configuration avec FS : 4MB (FS:2MB OTA:~1019KB), par exemple
  • aller dans Outils, ESP8266 Sketch Data Upload pour transférer le contenu du dossier data vers la mémoire flash (attention, le moniteur série doit être fermé)
SPIFFS ne possède pas d'arborescence, on peut néanmoins utiliser le caractère / dans le nom du fichier.

SPIFFS n'est plus utilisé, il est remplacé par LittleFS qui s'installe de la même façon :
  • récupérer la dernière version ici
  • décompresser le fichier zip dans le dossier tools (qui se trouve dans le dossier Arduino)
  • créer un dossier data dans le même dossier que le sketch (fichier ino)
  • relancer l'EDI
  • aller dans Outils, Flash Size, et choisir une configuration avec FS : 4MB (FS:2MB OTA:~1019KB), par exemple
  • aller dans Outils, ESP8266 LittleFS Data Upload pour transférer le contenu du dossier data vers la mémoire flash (attention, le moniteur série doit être fermé)
Codez les fichiers en UTF-8, fin de ligne \r\n (Carriage Return et Line Feed), 32 caractères max. (inclus le \0). Si vous utilisez l'OTA, l'authentification doit être désactivée. Le téléchargement ne se fait que dans un sens, du dossier data vers la mémoire flash. Il faudra donc prévoir dans le sketch la lecture d'un fichier et la restitution de son contenu sur une page web, par exemple.


1 : 1 ki (kilo informatique) = 1024 et non pas 1000, donc 1 kio = 1024 octets et 16 kio = 16384 octets.

2 : General Purpose Input/Output (Entrée/Sortie à usage général).



Haut de page