La solution vue dans le sujet TCO Web interactif avec des ESP32 et des ESP8266 (1) est une solution qui centralise la commande des appareils de voie. Cela a pour conséquence pour certains réseaux importants une plus grande longueur de câblage entre le circuit imprimé et les aiguillages, donc une moins bonne immunité au bruit et une plus grande difficulté de mise au point.
TCO Web interactif
TCO Web interactif avec des ESP32 et des ESP8266 (2)
Utilisant le protocole de communication ESP-NOW
.
Par :
DIFFICULTÉ :★★☆
Le réseau suivant est un exemple de réseau de type point à point, où la distance entre les deux petites gares peut être de plusieurs mètres.
Espressif Systems (le fabricant des ESP32 et des ESP8266) a développé ESP-NOW qui est un protocole de communication sans connexion. Il permet aux appareils ESPxxx [1] de communiquer facilement entre eux, directement sans se connecter à un réseau WiFi.
ESP32-NOW, qu’est-ce que c’est ?
Les principales caractéristiques de ce protocole de communication sont les suivantes :
- Un ESPxxx envoie des données à plusieurs ESPxxx (un émetteur, un ou plusieurs récepteurs) ;
- Ou un ESPxxx reçoit des données de plusieurs ESPxxx (un récepteur, un ou plusieurs émetteurs) ;
- Le couplage entre les appareils est nécessaire avant leur communication. Une fois l’appariement terminé, la connexion est sécurisée et permanente ;
- La distance entre chaque ESPxxx doit être inférieure à 200 m ;
- La taille des données circulant entre les ESPxxx est inférieure à 250 octets ;
- Si la communication n’est pas chiffrée, il ne peut y avoir plus de 20 ESPxxx interconnectés (la limite est de 10 si la communication est chiffrée).
De plus amples informations sont disponibles sur Internet, par exemple sur ESP-NOW (Yakafab.grandbesancon.fr) (en français) ou Random Nerd Tutorials : Getting Started with ESP-NOW (ESP32 with Arduino IDE) (en anglais).
Le schéma ci-dessous donne le principe de fonctionnement de la solution à mettre en œuvre, solution basée sur l’utilisation du protocole ESP-Now.
Le module émetteur B
permet, comme dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1), d’afficher sur l’écran A
de la tablette ou du smartphone le TCO envisagé, de cliquer sur un appareil de voie pour lui faire changer d’état.
Le code du sketch est identique à plus de 80%, les différences étant la prise en compte du protocole ESP-NOW, la gestion d’une table des modules récepteurs et l’envoi de la commande à exécuter au module récepteur C
concerné.
Comme vu dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1), les vignettes des éléments du TCO sont hébergées par un site Web. Nous profiterons de cette nouvelle version pour utiliser le SPIFFS pour stocker ces images dans le module émetteur.
SPIFFS [2] est un système de fichiers léger adapté aux microcontrôleurs disposant d’une mémoire Flash SPI tel que les ESPxxx. La librairie Arduino SPIFFS.h
pour les ESP32 ou FS.h
pour les ESP8266 permet d’accéder à la mémoire Flash comme s’il s’agissait d’un système de fichiers normal identique à celui d’un ordinateur (en bien plus simple évidemment).
Les modules récepteurs C
, quant à eux, doivent prendre en compte le protocole ESP-NOW, gérer la réception des messages depuis le module émetteur B
et faire exécuter la commande reçue. La carte du circuit imprimé sera identique à celle vue dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1), seul le code hébergé par l’ESP32 étant différent. Une solution à base d’ESP8266 aura une carte adaptée à ce microprocesseur et le même code que la carte basée sur l’ESP32.
A noter : cette solution permet d’augmenter le nombre limite des moteurs (donc des appareils de voie) commandables par le TCO Web.
Pourquoi utiliser un ESP8266 ?
La compilation du croquis présenté dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1) fournit les mesures suivantes :
- Le croquis utilise 754 Ko sur 1 310 Ko (soit 57% de l’espace réservé au code dans le schéma de partition par défaut) ;
- Les données utilisées occupent 39 Ko sur 289 Ko réservés (soit 11% de la ressource).
L’ESP32 est surdimensionné pour le travail qui lui est confié, surtout compte tenu du fait que le nombre de broches d’E/S utilisé est réduit (3 broches pour commander les 74HC595). Dans ces conditions, il est intéressant d’utiliser les ESP8266 disponibles en fond de tiroir ou bien de les acheter neufs (ils sont moins chers que les ESP32).
Les différents types d’ESP8266 sont présentés dans le tableau suivant :
C’est l’ESP8266 NodeMCU 12-F qui a été choisi pour ses similitudes avec l’ESP32 NodeMCU, ce qui simplifie la conception du circuit imprimé. Son brochage est présenté dans la figure suivante :
La procédure de prise en compte de l’ESP8266 dans l’IDE Arduino est similaire à la procédure mise en œuvre pour l’ESP32 (voir cette procédure dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1)). Il est possible également d’utiliser la procédure décrite en anglais par Rui Santos en suivant le lien suivant Random Nerd Tutorials : Getting Started with ESP8266 NodeMCU Development Board.
Le module Emetteur.
Le transfert des images dans la mémoire Flash de l’émetteur.
Des informations générales sur SPIFFS sont données en français sur le site Projetsdiy.fr : Débuter avec la librairie SPIFFS.h pour lire, écrire, modifier des fichiers.
Si cela n’a pas été déjà fait, il faut installer dans l’IDE Arduino un outil (plugin) appelé Sketch Data Upload
. Pour l’ESP32, la procédure d’installation est décrite en français en suivant le lien Projetsdiy.fr : Sketch data upload pour IDE Arduino. Téléverser des fichiers SPIFFS sur la mémoire Flash ou en anglais Random Nerd Tutorials : Install ESP32 Filesystem Uploader in Arduino IDE.
Pour l’ESP8266, la procédure est décrite par Random Nerd Tutorials : ESP8266 Web Server using SPIFFS with Arduino IDE (NodeMCU).
La vérification de la bonne installation du ou des plugins se fait en regardant le menu Outils
de l’IDE Arduino, comme dans la figure suivante.
Ensuite, il faut aller dans le répertoire du croquis du module émetteur et créer un sous-répertoire nommé Data
. Ce sous-répertoire recevra toutes les vignettes permettant de constituer un TCO. La figure suivante montre l’arborescence à mettre en place :
Enfin, l’exécution du plugin Sketch Data Upload
permet de recopier les vignettes du sous-répertoire Data
dans la mémoire Flash de l’ESP32.
Attention :avant de faire cette manipulation, il faut s’assurer que le Moniteur Série et le Traceur Série sont bien fermés sous peine d’erreur de transfert.
Le petit croquis ci-dessous permet de s’assurer que les vignettes ont bien été copiées :
#include "FS.h"
#include "SPIFFS.h"
#define FORMAT_SPIFFS_IF_FAILED true
//=======================================================
void setup()
//=======================================================
{
Serial.begin(115200);
if(!SPIFFS.begin(FORMAT_SPIFFS_IF_FAILED))
{
Serial.println("Pb au demarrage de SPIFFS");
return;
}
listDir(SPIFFS, "/", 0);
delay(500);
}
//=======================================================
void loop()
//=======================================================
{
}
//=======================================================
void listDir(fs::FS &fs, const char * dirname, uint8_t levels)
//=======================================================
{
Serial.printf("Liste répertoire : %s\r\n", dirname);
File root = fs.open(dirname);
if(!root){
Serial.println("- failed to open directory");
return;
}
if(!root.isDirectory()){
Serial.println(" - not a directory");
return;
}
File file = root.openNextFile();
while(file){
if(file.isDirectory()){
Serial.print(" DIR : ");
Serial.println(file.name());
if(levels){
listDir(fs, file.name(), levels -1);
}
} else {
Serial.print(" Fichier : ");
Serial.print(file.name());
Serial.print("\tTaille : ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
Le code du croquis de l’émetteur.
Le code du croquis de l’émetteur découle très largement du croquis présenté dans le sujet TCO Web interactif avec des ESP32 et des ESP8266 (1). Les seules différences concernent :
- La prise en compte du protocole ESP-NOW (librairie, initialisation, etc.) ;
- La définition de la table des récepteurs et du format du message envoyé aux récepteurs ;
- La définition de la fonction
OnDataSent
(callback des données envoyées) ; - L’appairage avec les modules ESPxxx récepteurs ;
- La modification de la fonction
CommandeAppareil
{} qui, au lieu d’envoyer la commande aux 74HC595, l’envoie (la déporte) aux récepteurs.
Le code MAC [3] des récepteurs peut être récupéré en jouant le croquis suivant sur chaque récepteur (c’est ce code qui devra alimenter le tableau des récepteurs – voir plus loin) :
#ifdef ESP32
#include <WiFi.h>
#else
#include <ESP8266WiFi.h>
#endif
void setup()
{
Serial.begin(115200);
Serial.println();
Serial.print("Addresse MAC : ");
Serial.println(WiFi.macAddress());
}
void loop()
{
}
La liste des librairies utilisées :
// Import required libraries
#ifdef ESP32
#include <esp_now.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <SPIFFS.h>
#else
#include <Arduino.h>
#include <espnow.h>
#include <ESP8266WiFi.h>
#include <Hash.h>
#include <ESPAsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include "FS.h"
#endif
La définition du tableau des récepteurs et du format des messages :
/*--------------------------------------------------------------------------
* DONNEES PROTOCOLE ESP-NOW
---------------------------------------------------------------------------*/
#define NBMAC 2
typedef struct recepteur
{
bool actif;
uint8_t bcAdr[6];
} recepteur;
recepteur t_Mac[NBMAC] =
{
// mettre ici les adresses MAC de vos récepteurs
{ false, {0x30, 0xC6, 0xF7, 0x2F, 0xF5, 0x8C}},
{ false, {0x0C, 0xB8, 0x15, 0xF7, 0x85, 0xA0}}
};
typedef struct
{
byte numApp; // numéro appareil (de 1 à 8)
char typApp; // type de l'appareil ('A', 'J', 'T', 'S')
char etaApp; // état de l'appareil ( de '1' à '4')
byte noMot1; // No du 1er moteur (de 1 à 8)
byte noMot2; // No du 2me moteur (de 1 à 8)
} comm;
//Create a struct_message called myComm
comm myComm;
// gestion des appariements
#ifdef ESP32
esp_now_peer_info_t peerInfo;
#endif
Le nombre de récepteurs #define NBMAC
est à adapter à votre besoin et les codes MAC doivent être ceux de vos ESPxxx.
Le code de la fonction OnDataSent
:
#ifdef ESP32
/*********************************************************************/
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status)
/*********************************************************************/
// callback when data is sent
{
Serial.println(status == ESP_NOW_SEND_SUCCESS ? "==> Livraison acceptée" : "==> Livraison refusée");
}
#else
/*********************************************************************/
void OnDataSent(uint8_t *mac_addr, uint8_t status)
/*********************************************************************/
// callback when data is sent
{
Serial.println(status == 0 ? "==> Livraison acceptée" : "==> Livraison refusée");
}
#endif
Dans la fonction setup
, prise en compte d’ESP-NOW, appairage des récepteurs, initialisation SPIFFS, initialisation des appareils et démarrage WiFi :
// Connection à ESP-NOW
//------------------------------------------------------------------
WiFi.mode(WIFI_STA);
Serial.print("Initialisation ESP-NOW : ");
// fonction callback
#ifdef ESP32
if (esp_now_init() != ESP_OK) {
Serial.println("Erreur");
return;
}
Serial.println("Ok");
esp_now_register_send_cb(OnDataSent);
#else
if (esp_now_init() != 0) {
Serial.println("Erreur");
return;
}
Serial.println("Ok");
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
esp_now_register_send_cb(OnDataSent);
#endif
// Appairage des récepteurs
//------------------------------------------------------------------
// register all peers
char macStr[18];
for (int noMac = 0; noMac < NBMAC; noMac++)
{
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
t_Mac[noMac].bcAdr[0], t_Mac[noMac].bcAdr[1], t_Mac[noMac].bcAdr[2],
t_Mac[noMac].bcAdr[3], t_Mac[noMac].bcAdr[4], t_Mac[noMac].bcAdr[5]);
Serial.print("Appairage avec ");
Serial.print(macStr);
Serial.print(" : ");
#ifdef ESP32
peerInfo.channel = 0;
peerInfo.encrypt = false;
// register peer
memcpy(peerInfo.peer_addr, t_Mac[noMac].bcAdr, 6);
if (esp_now_add_peer(&peerInfo) != ESP_OK)
{
Serial.println("Echec");
t_Mac[noMac].actif = false;
}
else
{
Serial.println("Ok");
t_Mac[noMac].actif = true;
}
#else
if (esp_now_add_peer(t_Mac[noMac].bcAdr, ESP_NOW_ROLE_SLAVE, 1, NULL, 0) != 0)
{
Serial.println("Echec");
t_Mac[noMac].actif = false;
}
else
{
Serial.println("Ok");
t_Mac[noMac].actif = true;
}
#endif
}
// Initialisation SPIFFS
//------------------------------------------------------------------
if(!SPIFFS.begin())
{
Serial.println("Initialisation SPIFFS incorrecte");
return;
}
else
{
Serial.println("Initialisation SPIFFS : OK");
}
// Connection à Wi-Fi
//------------------------------------------------------------------
Serial.print ( "Initialisation Wifi " );
WiFi.begin(ssid, password);
...
// Initialisation Appareils
//------------------------------------------------------------------
InitialiseAppareils();
Serial.println ( "Initialisation appareils terminée " );
Attention :il faut mettre l’initialisation d’ESP-NOW avant l’initialisation du WiFi.
La fonction CommandeAppareil
:
void CommandeAppareil(const String& nomTyp, const String& etaApp)
/*********************************************************************/
{
int colPos = nomTyp.indexOf(':');
String nomApp = nomTyp.substring(0, colPos); // nom de l'appareil
String typApp = nomTyp.substring(colPos+1); // type de l'appareil (Aig, Tjd, ...
String numApp = nomTyp.substring(3, colPos); // numéro de l'appareil
int no_App = numApp.toInt() - 1; // ...en indice de table
t_App[no_App].etaApp = etaApp[0]; // maj état de l'appareil
myComm.numApp = no_App;
myComm.typApp = typApp[0];
myComm.etaApp = etaApp[0];
myComm.noMot1 = t_App[no_App].noMot1;
myComm.noMot2 = t_App[no_App].noMot2;
int noMac = int(t_App[no_App].noRcpt) - 1;
// Debug : affichage des appareils et de leur état
//===================================================================
char macStr[18];
Serial.print ( nomApp );
Serial.print ( ", Etat" );
Serial.print ( etaApp );
Serial.print ( " ==> Mac[");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
t_Mac[noMac].bcAdr[0], t_Mac[noMac].bcAdr[1], t_Mac[noMac].bcAdr[2],
t_Mac[noMac].bcAdr[3], t_Mac[noMac].bcAdr[4], t_Mac[noMac].bcAdr[5]);
Serial.print(macStr);
Serial.print ( "] : ");
if ((noMac >= 0) && (t_Mac[noMac].actif))
{
#ifdef ESP32
esp_err_t result1 = esp_now_send(t_Mac[noMac].bcAdr, (uint8_t *) &myComm, sizeof(comm));
(result1 == ESP_OK) ? Serial.print("Envoi OK " ) : Serial.print ("Envoi KO ");
#else
esp_now_send(t_Mac[noMac].bcAdr, (uint8_t *) &myComm, sizeof(comm));
Serial.print("Envoi OK " );
#endif
delay(500);
}
else
{
Serial.println("Pas de récepteur");
}
}
La carte électronique.
Aucun composant électronique n’accompagne l’ESP32 dans sa fonction de serveur web et d’émetteur de commandes d’appareil de voie. Cependant, afin de protéger le microcontrôleur, il paraît judicieux de prévoir un support, comme dans la figure suivante :
Veuillez noter que vous devez faire attention au brochage de votre ESP32 ainsi qu’à celui de votre carte d’extension, et plus particulièrement à la largeur des broches d’insertion de l’ESP32. Par exemple, la carte d’extension rouge est destinée à des ESP32 étroits et par conséquent, ne convient pas à l’ESP32 NodeMCU d’AZ-Delivery.
Il existe des cartes d’extension comme celle de droite (la verte) pour les ESP8266 NodeMCU.
Le ou les modules Récepteurs.
Le code du croquis.
Le code du croquis du récepteur comprend, dans l’ordre :
- Les includes nécessaires au programme : Esp-Now, et WiFi ;
- Une fonction
getWiFiChannel
pour récupérer le channel WiFi de l’émetteur ; - Les constantes et variables générales du programme (initialisation Esp-Now, gestion des 74HC595, etc.) ;
- Une fonction pour actionner les appareils à la demande du module émetteur ;
- La fonction
setup
qui permet l’initialisation de la communication Esp-Now ; - La fonction
loop
qui détecte les demandes de changement de position des aiguilles et les exécute.
Selon que le module récepteur est basé sur un ESP32 ou un ESP8266, les librairies ne sont pas les mêmes.
#ifdef ESP32
#include <esp_now.h>
#include <esp_wifi.h>
#include <WiFi.h>
#else
#include <espnow.h>
#include <ESP8266WiFi.h>
#endif
Si le récepteur n’a pas le même code channel que l’émetteur, les messages ne pourront pas être reçus par le récepteur. La récupération de ce channel se fait grâce à la fonction suivante :
/*--------------------------------------------------------------------------
* RECUPERATION CHANNEL DE L'EMETTEUR
---------------------------------------------------------------------------*/
constexpr char WIFI_SSID[] = "... le nom de votre routeur ...";
int32_t getWiFiChannel(const char *ssid)
{
if (int32_t n = WiFi.scanNetworks())
{
for (uint8_t i = 0; i < n; i++)
{
if (!strcmp(ssid, WiFi.SSID(i).c_str()))
{
return WiFi.channel(i);
}
}
}
return 0;
}
La structure de communication entre l’émetteur et les récepteurs est comme suit :
/*--------------------------------------------------------------------------
* DONNEES PROTOCOLE ESP-NOW
---------------------------------------------------------------------------*/
//Structure to receive data : Must match the sender structure
typedef struct
{
byte numApp; // numéro appareil (de 1 à 8)
char typApp; // type de l'appareil ('A', 'J', 'T', 'S')
char etaApp; // état de l'appareil ( de '1' à '4')
byte noMot1; // No du 1er moteur (de 1 à 8)
byte noMot2; // No du 2me moteur (de 1 à 8)
} comm;
//Create a struct_message called myComm
comm myComm;
comm oldComm;
Les données de commandes des 74HC595, intermédiaires entre le récepteur et les appareils de voie sont comme ci-après :
/*--------------------------------------------------------------------------
* GESTION DES 74HC595
---------------------------------------------------------------------------*/
#ifdef ESP32
const byte verrou = 2; // ST_CP (latch)
const byte donnee = 4; // DS (data)
const byte horloge = 0; // SH_CP (clock)
#else
const byte verrou = 13; // ST_CP (latch) D7
const byte donnee = 14; // DS (data) D5
const byte horloge = 12; // SH_CP (clock) D6
#endif
uint16_t u_Data = 0b0101010101010101; // data pour les 74hc595
const uint16_t k_Msk = 0b1100000000000000; // Masque
const uint16_t k_Dir = 0b0100000000000000; // Moteur direct
const uint16_t k_Dev = 0b1000000000000000; // Moteur dévié
La fonction ActionneAppareil
met en œuvre l’algorithme suivant :
La fonction OnDataRcv
permet la récupération des données envoyées par l’émetteur et d’afficher sur le moniteur série ces données si la directive #define DEBUG
est opérationnelle.
#ifdef ESP32
/*********************************************************************/
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len)
/*********************************************************************/
//callback function that will be executed when data is received
{
memcpy(&myComm, incomingData, sizeof(myComm));
#ifdef DEBUG
Serial.print("Octets reçus : ");
Serial.println(len);
Serial.print("Nom appareil : ");
(myComm.typApp == 'J') ? Serial.print("Tjd") : Serial.print("Aig");
Serial.print(String(myComm.numApp+1));
Serial.print(" Type : ");
Serial.print(String(myComm.typApp));
Serial.print(" Etat : ");
Serial.println(String(myComm.etaApp));
#endif
}
#else
/*********************************************************************/
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len)
/*********************************************************************/
{
memcpy(&myComm, incomingData, sizeof(myComm));
#ifdef DEBUG
Serial.print("Octets reçus : ");
Serial.println(len);
Serial.print("Nom appareil : ");
(myComm.typApp == 'J') ? Serial.print("Tjd") : Serial.print("Aig");
Serial.print(String(myComm.numApp+1));
Serial.print(" Type : ");
Serial.print(String(myComm.typApp));
Serial.print(" Etat : ");
Serial.println(String(myComm.etaApp));
#endif
}
#endif
La fonction setup
, quant à elle, permet de :
- Initialiser le moniteur série à 115 200 bauds ;
- Affecter les broches de communication avec les 74HC595 ;
- Positionner le channel du récepteur à l’identique du channel de l’émetteur ;
- Lancer l’initialisation de ESP-NOW.
Le positionnement du channel se fait comme suit :
#ifdef ESP32
//WiFi.printDiag(Serial); // Uncomment to verify channel number before
esp_wifi_set_promiscuous(true);
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
esp_wifi_set_promiscuous(false);
//WiFi.printDiag(Serial); // Uncomment to verify channel change after
#else
//WiFi.printDiag(Serial); // Uncomment to verify channel number before
wifi_promiscuous_enable(1);
wifi_set_channel(channel);
wifi_promiscuous_enable(0);
//WiFi.printDiag(Serial); // Uncomment to verify channel change after
#endif
La fonction loop
a pour rôle de :
- Détecter une demande de changement de position pour un appareil de voie ;
- Dans tous les cas, d’exécuter la demande (appel de la fonction
ActionneAppareil
).
void loop()
/*********************************************************************/
{
if (myComm.numApp != oldComm.numApp ||
myComm.typApp != oldComm.typApp ||
myComm.etaApp != oldComm.etaApp)
{
ActionneAppareil();
oldComm.numApp = myComm.numApp;
oldComm.typApp = myComm.typApp;
oldComm.etaApp = myComm.etaApp;
delay(500);
}
}
Important :après le téléversement du croquis dans l’ESP8266, il faut relancer le croquis en appuyant sur le bouton Reset de l’ESP8266, sous peine de dysfonctionnement.
Le circuit imprimé du récepteur.
Circuit imprimé avec utilisation d’un ESP32
Si le module récepteur est construit autour d’un ESP32, le circuit imprimé est identique à celui vu dans l’article TCO Web interactif avec des ESP32 et des ESP8266 (1), à savoir :
Circuit imprimé avec utilisation d’un ESP8266
Implantation des composants (ESP8266)
Schéma de câblage (ESP8266)
Alimentation des récepteurs
Si vous disposez d’une alimentation multi-tensions (comme une alimentation d’ordinateur de bureau), vous pouvez l’utiliser pour alimenter les cartes des modules récepteurs ainsi que les moteurs de commande des appareils de voie.
Des tutoriaux pour la mise en œuvre d’une alimentation de ce type sont consultables sur les sites
https://www.instructables.com/Alime... ou https://www.firediy.fr/article/fabr....
Le schéma ci-après montre comment connecter les modules récepteurs à cette alimentation.
Conclusion
La solution proposée dans cet article permet de traiter un TCO pour un réseau de taille relativement importante de manière économique et évolutive.
Le TCO de la figure suivante est un exemple de ce qui peut être entrepris (il est défini par le fichier PO-Midi2_ifs.h
) joint au zip du croquis de l’émetteur.
[1] ESPxxx : ESP32 et/ou ESP8266.
[2] SPIFFS : Serial Peripheral Interface Flash File System
[3] MAC : media access control – adresse physique du matériel.