ESP-NOW imprévisible

Bonjour,

je tente de lier un ESP32-Wroom à plusieurs ESP-01.

Commençons par un seul ESP-01: celui qui gère un affichage MAX7219 pour en faire une horloge liée à un serveur NTP. Tout va bien chez lui. C’est donc dire que la communication wifi est bien activée et fonctionnelle.

D’autre part, j’ai mon ESP32-Wroom qui est agit comme chef d’orchestre. Il est destiné à pousser des infos à plusieurs autres ESP-01, en plus de celui mentionné ci-haut. Commençant par le commencement, j’y vais avec l’horloge.

Mon Wroom demande l’heure au ESP-01 et celui-ci doit retourner l’heure via communication esp_now. Puisque les deux doivent envoyer de l’info à l’autre, les deux sont configurés « Master » . J’ai suivi, en cela, les tutos (un pour ESP32, l’autre pour ESP8266) de ce site

Le problème n’est pas de faire fonctionner, mais de le faire fonctionner de manière stable. En l’état actuel, ça fonctionne une fois sur vingt environ. Je n’arrive pas à savoir dans quelles conditions ça fonctionne. J’ai essayé:

  • alimenter le wroom en premier
  • alimenter le ESP-01 en premier
  • triple vérification des MAC
  • redémarrer les deux micro-contrôleurs après un changement
  • et bien d’autres choses

Voici les éléments pertinents du code Wroom

//Gestion de l'éclairage
struct Lignes {
  String nom;
  bool etat;
  String RVB;
  int R;
  int V;
  int B;
  int stable;
  uint8_t MAC[6];
  String desc;
};
Lignes lignes[10] = {
  { "Panne", false,  "FFFFFF",   0,   0,   0, 0, {0x94, 0x54, 0xC5, 0x72, 0xC5, 0xA4}, "Buttons" },
  { "Avant", false,  "FFFFFF", 255, 255, 255, 0, {0x40, 0x91, 0x51, 0x52, 0x12, 0xB6}, "Avant" },
  { "Autel", false,  "FFFFFF", 255, 255, 255, 0, {0x4C, 0x75, 0x25, 0x34, 0xA7, 0x89}, "Autel" },
  { "Lgn1a", false,  "FFFFFF", 255, 255, 255, 0, {0x4C, 0x75, 0x25, 0x34, 0x71, 0x63}, "Ligne 1-A" },
  { "Lgn1b", false,  "FFFFFF", 255, 255, 255, 0, {0x4C, 0x75, 0x25, 0x34, 0x71, 0x63}, "Ligne 1-B" },
  { "Lgn2a", false,  "FFFFFF", 255, 255, 255, 0, {0x40, 0x91, 0x51, 0x51, 0xC1, 0x29}, "Ligne 2-A" },
  { "Lgn2b", false,  "FFFFFF", 255, 255, 255, 0, {0x40, 0x91, 0x51, 0x52, 0x12, 0xB6}, "Ligne 2-B" },
  { "Lgn3a", false,  "FFFFFF", 255, 255, 255, 0, {0x4C, 0x75, 0x25, 0x33, 0x7C, 0x08}, "Ligne 3" },
  { "Horlo", false,  "FFFFFF", 255, 255, 255, 0, {0x4C, 0x75, 0x25, 0x33, 0xA1, 0xD6}, "Horloge_dansSalleReunion" },
  { "Psaum", false,  "FFFFFF", 255, 255, 255, 0, {0x94, 0x54, 0xC5, 0x73, 0x83, 0x98}, "Psaumes" }
};

//Gestion des messages
struct VersAffichage {
  int genre;      //0: Changement à l'éclairage; 1: message à afficher; 2: heure reçue depuis ESP01 dans la fenêtre; 3: écran noir; 9: reset
  char contenu[30];
  int a;
  int b;
  int c;
  int d;
  int e;
};
VersAffichage versAffichage;

void calcueHeureACtu() {
  versAffichage.genre = 2;
  esp_now_send(lignes[8].MAC, (uint8_t *) &versAffichage, sizeof(versAffichage));
  Serial.println("Requête envoyée au module Horloge");
  affichonsHeure = true;
}

void Recevons(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&versAffichage, incomingData, sizeof(versAffichage));
  Serial.print  ("Nous sommes ici en ligne 185 avec ");
  Serial.print  ("le genre = ");
  Serial.print  (versAffichage.genre);
  if (versAffichage.genre == 0) {
    Serial.print  ("Action portée sur éclairage avec ");
  } else if (versAffichage.genre == 1) {
    Serial.println("Changeons contenu affichage");
    affichonsHeure = false;
    affichageDEL();
  } else if (versAffichage.genre == 2) {
    Serial.print  ("Recevons cette heure : ");
    Serial.print  (" : ");
    Serial.print  (versAffichage.a);
    Serial.print  (versAffichage.b);
    Serial.print  (":");
    Serial.print  (versAffichage.d);
    Serial.println(versAffichage.e);
    affichageDEL();
  } else {
    return;
  }
}

void setup(void) {
  WiFi.mode(WIFI_AP_STA);  //Mode de fonctionnement: serveur (AP), non-fonctionnel en tant que « station » - client
  WiFi.softAPConfig(APlocalIP, APgateway, APsousRes);
  WiFi.softAP(APssid, APpwsd);  //Point d'accès ... ceci servira aux ESP8266 satellites selon la syntaxe  WiFi.softAP(ssid, pwsd);
  Serial.print("Point d`accès a cette adresse : ");
  Serial.println(WiFi.softAPIP());

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  Serial.print  ("Mon adresse MAC : ");
  Serial.println(WiFi.macAddress());
  esp_now_register_recv_cb(esp_now_recv_cb_t(Recevons));

  Serial.println("Lancement de la communication ESPnow");
  if (esp_now_init() != ESP_OK) {
    Serial.println("ESP-NOW ne put être initialisé correctement.  Oups!");
    return;
  }
  Serial.println(WiFi.macAddress());
  peerInfo.channel = 0;
  peerInfo.encrypt = false;
  for (int x=0; x<9; x++) {
      memcpy(peerInfo.peer_addr, lignes[x].MAC, 6);
      if (esp_now_add_peer(&peerInfo) != ESP_OK){  Serial.print("Échec avec peerInfo num "); Serial.println(x); } else { Serial.println(String(x) + " chargé."); }
  }

}

Je prévois que vous direz … « ouais, mais t’as pas d’appel à la fonction calcueHeureACtu() », … oui, j’ai cet appel, mais ce n’est pas pertinent ici d’afficher comment puisque mon moniteur série affiche bien « Requête envoyée au module Horloge » lorsque vient son temps .

Voici ce que j’ai du côté du ESP-01

struct Lignes {
  String nom;
  bool etat;
  String RVB;
  int R;
  int V;
  int B;
  int stable;
  uint8_t MAC[6];
  String desc;
};
Lignes lignes[1] = {
  { "Psaum", false,  "FFFFFF", 255, 255, 255, 0, {0x94, 0x54, 0xC5, 0x73, 0x83, 0x98}, "Horloge_dansSalleReunion" }
};

//Gestion des messages
struct VersAffichage {
  int genre;      //0: Changement à l'éclairage; 1: message à afficher; 2: heure
  char contenu[30];
  int a;
  int b;
  int c;
  int d;
  int e;
};
VersAffichage versAffichage;

void DemandeRecue(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&versAffichage, incomingData, sizeof(versAffichage));
  Serial.print  ("Avons reçu : ");
  Serial.println(versAffichage.genre);
  if (versAffichage.genre == 1) {
    affichons(0,12);
    affichons(1, versAffichage.d);
    affichons(2, versAffichage.c);
    affichons(3, versAffichage.b);
    horo = false;
  } else if (versAffichage.genre == 2) {
    versAffichage.genre = 2;
    versAffichage.a = cetHre[3]/10;
    versAffichage.b = cetHre[2];
    versAffichage.c = 11;
    versAffichage.d = cetHre[1]/10;
    versAffichage.e = cetHre[0];
    esp_now_send(lignes[0].MAC, (uint8_t *) &versAffichage, sizeof(versAffichage));
    Serial.print  ("Envoyons en retour: ");
    Serial.print  (versAffichage.genre);
    Serial.print  (" - ");
    Serial.print  (versAffichage.a);
    Serial.print  (versAffichage.b);
    Serial.print  (versAffichage.c);
    Serial.print  (versAffichage.d);
    Serial.println(versAffichage.e);
  }
}
void setup()  {
  if (esp_now_init() != 0) {
    return;
  }
  // Define Send function
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_register_recv_cb(DemandeRecue);
  esp_now_add_peer(lignes[0].MAC, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}

J’ai peut-être mis une commande en trop « esp_nom_set_self_role » que je ne vois pas dans la partie « communication bidi » du tuto. Mais c’est sans meilleur résultat (aucune communication entre les ESP ou - si une fois ou l’autre ça passe, c’est inexplicable).

On peut éliminer

  • la distance, car mes deux ESP sont à environ 40 cm
  • l’interférence, car chaque ESP est connecté en USB sur son propre ordinateur
  • les confusion ESP8266 et ESP32 car j’ai vérifié cela 1000 fois et - de toutes façons - la compilation entraîne des messages d’erreur lorsque j’oublie cet élément, les bibliothèques étant différentes

Il me semble qu'avoir 2 master c'est risqué ... ESP-NOW est sensible aux collisions sur des envois bidirectionnels non synchronisés et le fait d’avoir deux « masters » qui envoient et reçoivent en même temps doit provoquer des collisions et des pertes de paquets, surtout sur l’ESP-01 qui a moins de ressources (l’ESP32 est plus tolérant, mais le fonctionnement reste aléatoire si les rôles ne sont pas clairement définis).

➜ serait-ce si difficile que cela de créer une vraie architecture master-slave ?

Merci J-M-L
J’ai besoin d’une communication aller-retour.

J’ai trouvé une faille dans mon code quant à l’usage de MASTER et SLAVE et corrigé en conséquence, mais les résultats restent les mêmes.

Dans le code ESP-01, le setup est maintenant:

  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_add_peer(lignes[0].MAC, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0);

mais voilà que je découvre l’expression « CONTROLLER »
devrais-je mettre cette expression dans ma définition de rôle du WROOM ?

et puis … non … la communication esp_now à partir d’un ESP32 il n’y a pas lieu de définir MASTER ou SLAVE ( selon ma page de référence préférée en cela ).

À bien y regarder, la relation SLAVE / MASTER n’est possible qu’avec le ESP-01. J’ai tenté d’imposer “MASTER” au ESP32-WROOM et la requête a été rejetée par le compilateur.

D’ailleurs, le tuto du ESP32-WROOM ne mentionne ni MASTER ni SLAVE.

Je soupçonne que les limites du ESP-01 entraîne la limitation d’un seul des deux usages; ou bien SLAVE, ou bien MASTER. Si je pus obtenir quelques résultats impromptus c’est probablement du hasard.

J’attends un retour de la part de l’auteur du Tuto qui semble être très réactif.

pourquoi l'ESP-01 doit prendre l'initiative de parler au maître ?

Dans le scénario habituel le maître utilise un "heartbeat" pour vérifier que tous les esclaves sont bien là et en profite pour leur demander des infos régulièrement. Ce faisant les requêtes sont séquentielles et vous n'avez pas de superposition de communications qui génèrent des collisions et des pertes de paquets.

Pourquoi ne pas confier la tâche principale (NTP, ...) à l'ESP32 qui est plus capable que les petits ESP-01 totalement dépassés d'ailleurs et dont le firmware reste quand même buggy ? et au prix et tailles des ESP32-C6 c'est dommage de s'en priver

Pourriez vous aussi envisager de tout mettre sur le WiFi ? et utiliser des sockets de communication via IP ?

@Patriboom

  1. comment gères tu le canal WiFi utilisé par l’ESP32 et les ESP-01 pour ESP-NOW ?

  2. l’article d’Anacorp date de 2021, (dater un tuto c’est très important avec les ESP !) quelques changements sont intervenus dans l’API d’ESP-NOW pour ESP32
    infos actualisées sur cette API : ESP-NOW - - — Arduino ESP32 latest documentation , qui contient divers exemples ‘à jour’

Merci à vous,

D’abord parce que l’accès internet est trop loin du WROOM, le ESP-01 sert de relais,mais surtout ce n’est pas la tâche principale. Le ESP-01 ne consulte NTP qu’une fois aux 3 heures. Entre ces vérifications, l’horloge interne répond aux exigences. Le ESP-01 consulté est une horloge avec écran MAX7219. De temps à autres, le WROOM lui demande d’afficher des choses; autrement il lui demande l’heure.

Le wroom sert de mini-serveur web pour la gestion de son affichage MAX7219. esp_now sert alors à retransmettre ses ordres aux divers ESP-01.

Écrivant la dernière ligne, ça me fait penser que ce mini-serveur pourrait aussi attribuer des IP aux ESP-01 (je pense ici à voix haute) …

J’explorerai une piste aujourd’hui et vous reviendrai. Je crois que j’ai loupé un détail dans la recopie de l’exemple suivi. J’ai re-re-lu l’article précédemment mentionné et - oui - je lis que la communication bidirectionnelle est possible entre deux ESP-01 en mode esp_now.

Je refais donc mes devoirs.

Merci.

sans intérêt car si j’ai bien compris ESP_NOW n’utulise pas IP

BIen sûr, mais en pensant à haute voix, j’explore aussi une autre voie de communication entre les appareils (hors esp_now, mais via IP).

Les premiers tests sont intéressants.

La différence infusée est l’usage de deux objets différents pour le transport des informations:

  1. un objet pour les infos depuis ESP32-WROOM vers ESP-01
  2. un autre objet pour les infos en chemin inverse.

Ce tes a été effectué sur des micro-contrôlleurs de développement.

Lors de parfaites et stables communications en production, je vous ferai part du code pertinent.

Je reste donc dans l’univers du esp_now

Merci à tous.

Bonjour à tous,

merci de votre support et votre patience.

Je suis un peu à court d’idée, là!

Je ne travaille plus que sur l’ESP-01 gérant une horloge. Puisque mon code de test fonctionne parfaitement, je ne mets plus en doute le code de ESP32-Wroom.

Mon code de prod n’a pas grand chose de différent, mais il ne reçoit rien, ne retourne rien.

Devrais-je couper la connexion Wifi après chaque consultation de l’heure sur NTP afin de mieux la redémarrer ensuite ? C’est ma dernière idée, vue au gré de la copie du présent message.

Si oui, comment devrais procéder ?

Code hypothétique:

void RecuperonsHeure () {
  WiFi.begin(ssid, pswd);
  //dialogue avec le serveur NTP
  //gestion des valeurs etc.
  Wifi.close();
  
  //dois-je ici répéter  WiFi.mode(WIFI_STA); ? 
  //dois-je ici ré-initialiser esp_now    if (esp_now_init() != 0)  ??? 
}

void setup () {
  WiFi.mode(WIFI_STA);
  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println(F("Error initializing ESP-NOW"));
    return;
  }
}

Voici mes deux codes complets.

Le premier fonctionne bien; le voici

#include <espnow.h>//https://github.com/esp8266/Arduino/blob/master/tools/sdk/include/espnow.h
#include <ESP8266WiFi.h>

uint8_t adresseMAC[] = {0x94, 0x54, 0xC5, 0x73, 0x83, 0x98};// REPLACE WITH OTHER STATION MAC ADDRESS

struct VersAffichage {
  int genre;      //0: Changement à l'éclairage; 1: message à afficher; 2: heure reçue depuis ESP01 dans la fenêtre; 3: écran noir; 9: reset
  int a;
  int b;
  int c;
  int d;
  int e;
};
VersAffichage interESP;
VersAffichage interHORO;

unsigned long previousTime=0;

// callbacks for sending and receiving data
void Envoyames(uint8_t *mac_addr, uint8_t status) {
  Serial.print("\r\nNous expédié, et voici le résultat : \t");
  Serial.println(status == 0 ? " OK " : " Oups! ");
}

void Recevons(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&interHORO, incomingData, sizeof(interHORO));
  Serial.print("\r\nGenre: ");
  Serial.print  (interHORO.genre);
  Serial.print  ("\taussi : ");
  Serial.print  (interHORO.a);
  Serial.print  (interHORO.b);
  Serial.print  (interHORO.c);
  Serial.print  (interHORO.e);
  Serial.println(interHORO.e);
  Serial.println(" et retournons illico.");
  interESP.genre = interHORO.genre;
  esp_now_send(adresseMAC, (uint8_t *) &interESP, sizeof(interESP));
}
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println(F("Error initializing ESP-NOW"));
    return;
  }
  Serial.print(F("Reciever initialized : "));
  Serial.println(WiFi.macAddress());

  // Define callback functions
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //ESP_NOW_ROLE_SLAVE if slave
  //esp_now_register_send_cb(Envoyames);
  esp_now_register_recv_cb(Recevons);

  // Register peer
  esp_now_add_peer(adresseMAC, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0); //ESP_NOW_ROLE_CONTROLLER if slave
}

void loop() {
  if((millis() -previousTime)>30000){
    // Set values to send
    interESP.genre = 4;
    interESP.a = random(4);
    interESP.b = random(10);
    interESP.c = random(10);
    interESP.d = random(10);
    interESP.e = random(10);

    // Retournons un heure aléatoire
    uint8_t result = esp_now_send(adresseMAC, (uint8_t *) &interESP, sizeof(interESP));

    previousTime=millis();
  }
}

Le deuxième ne fonctionne pas. Outre la connexion au serveur NTP et la gestion d’un écran MAX7219, ne vois pas de différence structurelle ou fondamentale.

#include <espnow.h>
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <NTPClient.h>            // Serveur de temps sur internet
#include <TimeLib.h>              // Gestion de l'heure en Arduino
#include <LedControl.h>
#include "chiffres_et_symboles.h"

bool points = false;
int precMillis = 0;
bool horo = true;
const int MesIntensites[2] { 1, 8 };
int intensite = MesIntensites[1];
int precIntensite = intensite;

// Définition des broches de raccordement ESP-01 → Matrice LED pilotée par MAX7219
#define broche_CLK          0         // GPIO-00 de ESP-01 vers la broche CLK de la matrice LED
#define broche_DIN          1         // GPIO-02 de ESP-01 vers la broche DIN de la matrice LED
#define broche_CS           2         // TX      de ESP-01 vers la broche CS  de la matrice LED
#define brochePresence      3         // GPIO-03 de ESP-01 vers la broche DIN du module de présence
#define nbMatrices          4         // Nombre pouvant aller de 1 à 8 (nombre maxi de matrice led pilotable ici)
// Instanciation du panneau 4 x 8x8 MAX3179
LedControl matriceLed = LedControl(broche_DIN, broche_CLK, broche_CS , nbMatrices);

const char* ssidA = "ssidA";        // SSID
const char* pswdA = "MotPasseA";    // WIFI
const char* ssidB = "ssidB";        // SSID
const char* pswdB = "MotPasseB";    // WIFI
const char* ssidC = "ssidC";        // SSID
const char* pswdC = "MotPasseC";    // WIFI
int rendu = 0;                      // Décompte des passages sans mise à jour de l'affichage

uint8_t adresseMAC[] = {0x94, 0x54, 0xC5, 0x73, 0x83, 0x98};//Adresse du ESP01-WROOM

//Gestion des messages
struct VersAffichage {
  int genre;      //0: Changement à l'éclairage; 1: message à afficher; 2: heure
  int a;
  int b;
  int c;
  int d;
  int e;
};
VersAffichage interESP;
VersAffichage interHORO;

unsigned long millisHoro = millis();       // Mise à jour de l'heure du système, une fois à l'heure ( 60 * 60 * 1000) = 3600000 milli-secondes
unsigned int  echecs = 0;

//Préparation de l'horloge
WiFiUDP ntpUDP;
NTPClient horlogeNTP(ntpUDP, "ntp2.qix.ca", (-4 * 3600), 3600);  // 'ntp2.qix.ca' est un serveur d'heure canadien auquel nous demadons l'heure UTF (moins 4  * 3600 secondes) et demandons mise à jour aux 3 heures  (3 * 60 * 60000 millisecondes)

int Connectons() {
    //Processus normal,habituel, tout ce qu'il a de plus standard en termes de connexion à l'internet Wifi afin de récupérer l'heure d'un serveur NTP ultérieurement
}

void MAJheure () {
  unsigned long unix_epoch = horlogeNTP.getEpochTime();    // Récupérer l'heure depuis le serveur NTP
    //Section coupée: Traitement des valeurs reçues
  interESP.d = round(refHre/10);
  interESP.c = refHre - interESP.d*10;
  interESP.b = round(refMin/10);
  interESP.a = refMin - interESP.b*10;
  rendu = round(second(unix_epoch)/5);
  millisHoro = millis();
}

void affichons(int indexMatrice, int quel) {
  // Processus d'affichage des valeurs sur le panneau DEL
}

void animons() {
    //Non pertinent, coupons du code ici .. ce n'est que de la gestion d'affichage DEL
}

void Envoyames(uint8_t *mac_addr, uint8_t status) {
  Serial.print("\r\nNous expédié, et voici le résultat : \t");
  Serial.println(status == 0 ? " OK " : " Oups! ");
}

void Recevons(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&interHORO, incomingData, sizeof(interHORO));
  Serial.print  ("Avons reçu : ");
  Serial.println(interHORO.genre);
  if (interHORO.genre == 1) {
    //Affichage des données reçues sur le panneau à DEL
    horo = false;   // Pendant une minute, ces données ont précéance sur l'heure et seront affichées au détriment de celle-ci
  } else if (interHORO.genre == 2) {   //genre == 2 ... c'est une demande l'heure reçue depuis le ESP32-WROOM
    interESP.genre = 2;
    esp_now_send(adresseMAC, (uint8_t *) &interESP, sizeof(interESP));
    Serial.print  ("Envoyons en retour: ");
    Serial.print  (interESP.genre);
    Serial.print  (" - ");
    Serial.print  (interESP.a);
    Serial.print  (interESP.b);
    Serial.print  ("h");
    Serial.print  (interESP.c);
    Serial.print  (interESP.d);
    Serial.print  ("  jour = ");
    Serial.println(interESP.e);
  }
}

void setup()  {
  Serial.begin(115200);
  delay(250);
  int a = 0;
  //Connexin au réseau Wifi
  pinMode(brochePresence, INPUT);
  WiFi.mode(WIFI_STA);
  if (Connectons() > 60) { Serial.println("Erreur réseau");
  } else {
    horlogeNTP.begin();
    MAJheure();
    //Affichage de l'heure sur le panneau DEL
  }

  if (esp_now_init() != 0) {
    Serial.println(F("Oups, un erreur esp_now! "));
    a = a + 1;
    return;
  }
  Serial.println(WiFi.macAddress());

  // Define Send function
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //ESP_NOW_ROLE_SLAVE if slave
  esp_now_register_send_cb(Envoyames);
  esp_now_register_recv_cb(Recevons);
  esp_now_add_peer(adresseMAC, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0); //ESP_NOW_ROLE_CONTROLLER if slave


}  // Fin de setup()

void loop() {
    //Ici, au gré de la progression du temps, l'affichage de l'horloge est adapté.  Quelle surprise!
    //Les valeurs de interESP sont elles aussi mises à jour
}

De mémoire — sur ESP32, le Wi-Fi classique et ESP-NOW peuvent cohabiter mais il y a des contraintes. ESP-NOW utilise le même matériel radio que le Wi-Fi, donc il fonctionne généralement en mode station ou softAP avec Wi-Fi activé, mais certaines fonctionnalités Wi-Fi (comme le mode AP+STA avec plusieurs connexions) peuvent interférer. Il faut aussi gérer soigneusement les callbacks et éviter de faire de longs blocages dans le code.

Sur ESP-01 (ESP8266), ce n’est pas conçu pour coexister avec un Wi-Fi actif en même temps. Les resources sont limitées et Il faut choisir soit ESP-NOW soit le Wi-Fi classique, ou jongler entre les deux ce qui est beaucoup moins pratique et source de complexité.

➜ Dans votre code, une fois que vous appellez WiFi.begin() pour NTP, vous modifiez la configuration du Wi-Fi et ça peut casser ESP-NOW. Le simple fait de couper le Wi-Fi après la consultation NTP peut fonctionner, mais il faut à mon avis réinitialiser complètement ESP-NOW ensuite.

Personnellement j'ai n'utilise plus aucun ESP-01 (ni ESP8266 en général), le prix et la taille des cartes à bases de divers ESP32 maintenant fait qu'il n'y a pas à se poser la question à mon avis... (et si je suis trop loin pour le WiFi, j'utilise LoRa).

L’une d’elles est que le canal WIFi soit le même pour ESP-NOW et la connection en WiFI, d’ou ma question précédente sur la maitrise du canal.

Effectivement ça fait partie des contraintes vu que les 2 technos partagent le même hardware.

Dans mon cas, il est inutile de garder la connexion Wifi active. Une fois l’heure ajustée, je déconnecte et ça me suffit. Une mise à jour de l’heure à raison de 2 ou trois fois par jour, c’est plus que nécessaire.

Voici le code que j’ai bidouillé dans mon insomnie (il est plus que temps d’aller me re-coucher!)

void MAJheure () {
  if (Connectons() < 60 && esp_now_deinit() != 0) {
    horlogeNTP.begin();
    horlogeNTP.update();
    unsigned long unix_epoch = horlogeNTP.getEpochTime();    // Récupérer l'heure depuis le serveur NTP
    horlogeNTP.end();
    WiFi.close();
    int ceMois = month(unix_epoch);
    int refMin = minute(unix_epoch);
    int refHre = hour(unix_epoch);
    if (ceMois == 11 || ceMois == 12 || ceMois == 1 || ceMois == 2 ) { refHre = refHre - 1; }
    if (refHre < 0 ) { refHre = 23; }
    interESP.e = ceMois;

    interESP.d = round(refHre/10);
    interESP.c = refHre - interESP.d*10;
    interESP.b = round(refMin/10);
    interESP.a = refMin - interESP.b*10;
    rendu = round(second(unix_epoch)/5);
  } else {
    interESP.e = 0;
    interESP.d = 1;
    interESP.c = 2;
    interESP.b = 3;
    interESP.a = 4;
  }
  if (interESP.d == 0) { matriceLed.clearDisplay(3);  } else { affichons(3, interESP.d); }
  affichons(2, interESP.c);
  affichons(1, interESP.b);
  affichons(0, interESP.a);
  while (esp_now_init() != 0) { delay(50); }
  millisHoro = millis();
}

/// et

void setup()  {
  //Serial.begin(115200);
  delay(250);
  int a = 0;
  //Connexin au réseau Wifi
  pinMode(brochePresence, INPUT);
  WiFi.mode(WIFI_STA);
  MAJheure();

  //Serial.println(WiFi.macAddress());

  // Define Send function
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE); //ESP_NOW_ROLE_SLAVE if slave
  esp_now_register_send_cb(Envoyames);
  esp_now_register_recv_cb(Recevons);
  esp_now_add_peer(adresseMAC, ESP_NOW_ROLE_CONTROLLER, 1, NULL, 0); //ESP_NOW_ROLE_CONTROLLER if slave

  for (int x=0; x<4; x++) {
    matriceLed.shutdown(x,false);
    matriceLed.setIntensity(x,MesIntensites[1]);
    matriceLed.clearDisplay(x);
  }

}  // Fin de setup()

J’y ai inclus:

  • démarrage et arrêt de la connexion WiFi
  • démarrage et arrêt du service NTP
  • arrêt et redémarrage de esp_now

J’espère que ça fonctionnera. Nous verrons demain.

ça a l'air OK sur le principe, les seules limites viennent de la fragilité inhérente à l’ESP-01 quand on alterne Wi-Fi et ESP-NOW...

Je pense que j’aurai tout essayé. Même ce script au Wifi démarré puis coupé le temps d’une lecture NTP refuse de coopérer.

J’ai mis suffisamment de temps là-dessus.
J’opterai pour une autre carte que le vieux ESP-01 et voilà tout.

Résumé à qui suivrait ce fil jusuq’ici: le but est de faire en sorte qu’un ESP-01 reçoive et envoie via la communication esp_now. Cet ESP-01 est dédié au maintien d’un écran MAX7219 affichant l’heure. Il peut-être appelé par d’autres ESP à faire connaître l’heure.
La conclusion: il est impossible au ESP-01 de communiquer à la fois avec un serveur NTP de l’internet (Wifi_STA(ssid+pswd) et avec des modules ESP (esp_now).

Merci à tous d’avoir suivi et contribué.

Désolé que ça ne fonctionne pas - mais pas surprenant vue la stabilité du firmware de l’ESP-01 et ses capacités.

Si vous avez encore un peu d’énergie à y consacrer, il faudrait tester le reboot de la carte quand vous changez de mode…

Je suis disposé à faire des essais, mais si je reboote je perds l’heure recueillie sur internet. Je ne vois pas comment à la fois rebooter et garder l’info venue du net.

une petite RAM nommée RTC-RAM permet de conserver des informations lors des redémarrages sans coupure d’alimentation.

je vois même qu’une bobliothèque existe pour simplifier son utilisation

n’utilsant plus du tout les ESP8266 depuis des années je n’en sais pas plus (RTC-RAM est simple à exploiter avec les ESP32)