Bonjour,
Grace au programme joint, je fait communiquer 3 x D1 mini(esp8266), qui pour l'instant transmettent leur numéro respectif . Au setup(), elle entrent toutes dans une boucle infinie : pour en sortir ; soit appuie sur un bouton (Pin D2) soit activé par réception message qui change état de la pin D3, ensuite les cartes activés par pin D3 envoie un message pour fournir leur numéro. Chaque carte enregistre dans un tableau le numéro des cartes dont elle a eu réception.
Le problème est : instabilité des réceptions .
Il arrive que j'ai les bon tableau : chaque carte a 3 présent avec leur numéro
puis a l'essai suivant, une carte n'est pas reçu par les deux autres (ceci quelque soit la carte employé pour appuyer sur le bouton)
Nb ; j'ai volontairement omis la fonction onDataSend() car elle est toujours a "success" avec l'utilisation de l'adresse MAC universelle 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF
La documentation vente la stabilité, l'efficacité du protocole esp_now, mais j'avoue que je n'y arrive pas, outre que les exemples internet donne des exemples ou informations avec des bibliothèques qui ont peut être beaucoup évoluées, et aussi très différentes entre esp8266 et esp32
Quelqu'un a t il déjà été confronté a ce problème, et existe t il une solution ?
/**
* @file main.cpp
*
* @brief Programme de test de l'ESP_NOW sur ESP8266
* avec des modules ESP8266 D1 mini en trois exemplaires.(le nombre de carte peut etre modifié dans le tableau tabJoueur[]) limite 20 cartes
* Il n'y a pas de "master", pas de "slave", pas de "controller"
* chaque carte est autonome et peut envoyer et recevoir des données (mode combo)
* Au démarrage du set up, chaque carte est bloqué par une boucle infinie : pour
* en sortir, on met PIN_BOUTON à la masse sur l'une des cartes, ce qui déclenche l' envoie d'un message de type Message
* sur les autre cartes, qui reçoivent le message et se débloquent par changement d'état de la pin D3 (PIN_PRESENCE),
* ce qui déclenche pour ces cartes l'envoie d'un message de type Message.
* Le message contient uniquement le numéro de la carte qui a envoyé le message.
* Au final, chaque carte a le numéro de toutes les cartes qui sont présentes.
* a l'issue de la boucle d'attente, on a le tableau tabJoueur[] qui contient le numéro de toutes les cartes présentes.
*
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
// Universal MAC Address
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// #define NUMERO_CARTE 1
// #define NUMERO_CARTE 2
#define NUMERO_CARTE 3
#define PIN_BOUTON D2 // le bouton joueur est sur la pin D2 de la D1 mini
#define PIN_PRESENCE D3 // Pin D3 de la D1 mini : rien n'est branché dessus
#define LED_BUILDIN D4 // Pin D4 de la D1 mini : led de presence
#define PROGRAMME_NAME "Pong"
#define VER "1.0" // version du programme
#define VERSION "1.0" // version du programme
//********************************************************* variables ***********************************************************************
typedef struct
{
uint8_t _numeroCarte = 0;
} Message;
Message OutgoingDatas; // structure pour envoyer les données
Message IncomingDatas; // structure pour recevoir les données
uint8_t tabJoueur[] = {NUMERO_CARTE, 0, 0,0}; // tableau pour les joueurs
uint8_t nbJoueur = 1; // nombre de joueurs
bool InDatas = false; // si je recois des donnees ou pas
bool isBtnPressed = false; // variable pour savoir si le bouton est appuyé ou pas
unsigned long timer = 0;
unsigned long delayTime = 3000;
bool new_data = 0; // Flag to send data only once
//********************************************************* Declarations fonctions ***********************************************************************
void init_programme(void);
void OnDataSend(uint8_t *mac_addr, uint8_t sendStatus);
void OnDataRecv(uint8_t *mac_addr, uint8_t *incomingData, uint8_t len);
void allumeLedBuiltIn(bool action); // allume ou eteint la led de presence
void dumpTabJoueur();
void halte(void);
bool attenteMode(void);
//********************************************************* SETUP() ***********************************************************************
void setup()
{
init_programme();
isBtnPressed = attenteMode(); // on lance le mode attente
if (isBtnPressed == true) // si le bouton est appuyé, on copntinue
{
Serial.printf("Bouton presse par : %d\n", NUMERO_CARTE);
}
else
{
Serial.println("J'ai ete actionne par une autre carte.");
if (InDatas == true) // si je recois des donnees, je les traite
{
Serial.println("Je recois des donnees.");
digitalWrite(PIN_PRESENCE, HIGH); // pour arreter attentmode sur les autre cartes
}
}
allumeLedBuiltIn(false); // eteint la led de presence
OutgoingDatas._numeroCarte = NUMERO_CARTE;
esp_now_send(broadcastAddress, (uint8_t *)&OutgoingDatas, sizeof(OutgoingDatas));
timer = millis(); // on initialise le timer pour le delay
while (millis() - timer < delayTime) // on attend quelques secondes pour les reponses ,avant de lancer le jeu
{
yield(); // on laisse le temps à l'ESP de faire son boulot
}
dumpTabJoueur(); // on affiche les valeurs de la structure
halte(); // on arrete le programme ici pour ne pas faire de conneries
}
//********************************************************* LOOP() ***********************************************************************
void loop()
{
// put your main code here, to run repeatedly:
}
//********************************************************* Definitions fonctions ***********************************************************************
void allumeLedBuiltIn(bool action)
{
if (action == false)
{
digitalWrite(LED_BUILTIN, HIGH); // eteint la led de presence
}
else
{
digitalWrite(LED_BUILTIN, LOW); // allume la led de presence
}
} // allume ou eteint la led de presence
void OnDataSend(uint8_t *mac_addr, uint8_t sendStatus)
{
Serial.print("\n\tDans OnDataSend() ");
Serial.println((sendStatus == 0) ? "\t -> Delivery success" : "\t -> Delivery Fail");
}
void OnDataRecv(uint8_t *mac_addr, uint8_t *DataEntrante, uint8_t len)
{
memcpy(&IncomingDatas, DataEntrante, sizeof(IncomingDatas));
Serial.printf("\n\tDans OnDataRecv() : Bytes received : %u de carte %d\n", len,IncomingDatas._numeroCarte);
digitalWrite(PIN_PRESENCE, HIGH); // pour arreter attentMode
if (IncomingDatas._numeroCarte != NUMERO_CARTE)
{
tabJoueur[nbJoueur++] = IncomingDatas._numeroCarte;
}
}
bool attenteMode(void)
{
bool fin = false;
bool ret = false;
while (fin == false)
{
if (digitalRead(PIN_BOUTON) == LOW) // si le bouton est appuyé
{
fin = true;
ret = true;
break;
}
if (digitalRead(PIN_PRESENCE) == HIGH) // fin du mode attenteMode par reception message
{
fin = true;
ret = false;
break;
}
delay(10);
}
Serial.println("Fin du mode attente.");
return ret;
}
void halte(void)
{
Serial.println("Dans fct halte()");
while (true)
{
yield();
}
}
void dumpTabJoueur()
{
Serial.printf("\n\tNombre de joueurs : %d\n\n\tDumping tabJoueur:\n", nbJoueur);
for (int i = 0; i < nbJoueur; i++)
{
Serial.print("tabJoueur[");
Serial.print(i);
Serial.print("] : ");
Serial.println(tabJoueur[i]);
}
Serial.println();
}
void init_programme(void)
{
Serial.begin(115200);
while (!Serial)
{
yield(); // wait for serial port to connect. Needed for native USB port only
}
pinMode(PIN_BOUTON, INPUT_PULLUP); // Etat hAUT par defaut
pinMode(PIN_PRESENCE, OUTPUT); // sert pour detection nombre de raquette presente et allumé
digitalWrite(PIN_PRESENCE, LOW);
pinMode(LED_BUILTIN, OUTPUT); // sert pour detection nombre de raquette presente et allumé
allumeLedBuiltIn(true); // allume la led de presence
WiFi.mode(WIFI_STA);
WiFi.disconnect(); // Onb a pas besoin d'établir de connection WiFi, juste ESP_NOW
Serial.println("\n");
Serial.print("\tProgramme : ");
Serial.print(PROGRAMME_NAME);
Serial.print(", VER : ");
Serial.print(VER);
Serial.print(", carte numero : ");
Serial.print(NUMERO_CARTE);
Serial.print(", macAddress : ");
Serial.println(WiFi.macAddress()); // pour récupérer l'adresse MAC de la carte
Serial.println();
// init de l'ESP_NOW
if (esp_now_init() != 0)
{
Serial.println("Erreur de l'initialisation de l'ESP_NOW");
return;
}
else
{
Serial.println("ESP_NOW initialise.");
//esp_now_register_send_cb(OnDataSend);
esp_now_register_recv_cb(OnDataRecv);
esp_now_set_peer_channel(broadcastAddress, 1); // Set the channel to 1 for all peers
esp_now_set_self_role(ESP_NOW_ROLE_COMBO); // Set the role to combo for self
esp_now_set_peer_role(broadcastAddress, ESP_NOW_ROLE_COMBO); // Set the role to combo for peer
}
}