ESP-NOW : Recevoir des données de plusieurs cartes ESP8266 (plusieurs à un)

ESP-NOW : Recevoir des données de plusieurs cartes ESP8266 (plusieurs à un)

Ce tutoriel montre comment configurer une carte ESP8266 pour recevoir des données de plusieurs cartes ESP8266 via le protocole de communication ESP-NOW (configuration plusieurs à un). Cette configuration est idéale si vous souhaitez collecter des données de plusieurs nœuds de capteurs dans une seule carte ESP8266. Les cartes seront programmées à l’aide de l’IDE Arduino.

ESP-NOW avec ESP8266 recevoir des données de plusieurs cartes plusieurs à un

Autres guides ESP-NOW avec l’ESP8266 :

Aperçu du projet

Ce tutoriel montre comment configurer une carte ESP8266 pour recevoir des données de plusieurs cartes ESP8266 via le protocole de communication ESP-NOW (configuration plusieurs à un) comme indiqué dans la figure suivante.

Présentation du projet ESP-NOW avec ESP8266 NodeMCU Recevoir des données de plusieurs cartes Configuration plusieurs à un
  • Une carte ESP8266 agit comme un récepteur/esclave ;
  • Plusieurs cartes ESP8266 agissent en tant qu’expéditeurs/maîtres. À titre d’exemple, nous utiliserons deux expéditeurs. Vous devriez pouvoir ajouter plus de cartes à votre configuration ;
  • La carte émettrice reçoit un message d’accusé de réception indiquant si le message a été délivré avec succès ou non ;
  • La carte réceptrice ESP8266 reçoit les messages de tous les expéditeurs et identifie quelle carte a envoyé le message ;
  • A titre d’exemple, nous allons échanger des valeurs aléatoires entre les cartes. Vous devez modifier cet exemple pour envoyer des commandes ou des lectures de capteur.

Noter: dans la documentation ESP-NOW, il n’y a pas de « expéditeur/maître » et de « récepteur/esclave ». Chaque carte peut être un émetteur ou un récepteur. Cependant, pour garder les choses claires, nous utiliserons les termes « expéditeur » et « récepteur » ou « maître » et « esclave ».

Conditions préalables

Nous allons programmer les cartes ESP8266 à l’aide de l’IDE Arduino, donc avant de poursuivre ce tutoriel, assurez-vous que ces cartes sont installées dans votre IDE Arduino.

Obtention de l’adresse MAC de la carte du récepteur

Pour envoyer des messages via ESP-NOW, vous devez connaître l’adresse MAC de la carte réceptrice. Chaque carte a une adresse MAC unique (apprenez comment obtenir et modifier l’adresse MAC ESP8266).

Téléchargez le code suivant sur votre carte récepteur ESP8266 pour obtenir son adresse MAC.

// Complete Instructions to Get and Change ESP MAC Address: https://Raspberryme.com/get-change-esp32-esp8266-mac-address-arduino/

#ifdef ESP32
  #include <WiFi.h>
#else
  #include <ESP8266WiFi.h>
#endif

void setup(){
  Serial.begin(115200);
  Serial.println();
  Serial.print("ESP Board MAC Address:  ");
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}

Afficher le code brut

Après avoir téléchargé le code, appuyez sur le bouton RST/EN et l’adresse MAC devrait s’afficher sur le moniteur série.

Obtention de l'adresse MAC de la carte récepteur ESP8266 NodeMCU

Code d’expéditeur ESP8266 NodeMCU (ESP-NOW)

Le destinataire peut identifier chaque expéditeur par son adresse MAC unique. Cependant, traiter différentes adresses MAC du côté du récepteur pour identifier quelle carte a envoyé quel message peut être un peu délicat.

Ainsi, pour faciliter les choses, nous identifierons chaque carte avec un numéro unique (identifiant) qui commence à 1. Si vous avez trois cartes, l’une aura le numéro d’identification 1, l’autre le numéro 2 et enfin le numéro 3. L’ID sera envoyé au récepteur avec les autres variables.

A titre d’exemple, nous allons échanger une structure qui contient le tableau identifiant nombre et deux nombres aléatoires X et y comme le montre la figure ci-dessous.

ESP-NOW avec ESP32 reçoit des données de plusieurs cartes (plusieurs à un) Exemple de données

Téléchargez le code suivant sur chacun de vos tableaux d’envoi. N’oubliez pas d’incrémenter le identifiant numéro pour chaque carte émettrice.

/*
  Rui Santos
  Complete project details at https://Raspberryme.com/esp-now-many-to-one-esp8266-nodemcu/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <ESP8266WiFi.h>
#include <espnow.h>

// REPLACE WITH RECEIVER MAC Address
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Set your Board ID (ESP32 Sender #1 = BOARD_ID 1, ESP32 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 2

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

// Create a struct_message called test to store variables to be sent
struct_message myData;

unsigned long lastTime = 0;
unsigned long timerDelay = 10000;

// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("rnLast Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);
 
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  } 
  // Set ESP-NOW role
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

  // Once ESPNow is successfully init, we will register for Send CB to
  // get the status of Trasnmitted packet
  esp_now_register_send_cb(OnDataSent);
  
  // Register peer
  esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

}
 
void loop() {
  if ((millis() - lastTime) > timerDelay) {
    // Set values to send
    myData.id = BOARD_ID;
    myData.x = random(1, 50);
    myData.y = random(1, 50);

    // Send message via ESP-NOW
    esp_now_send(0, (uint8_t *) &myData, sizeof(myData));
    lastTime = millis();
  }
}

Afficher le code brut

Comment fonctionne le code

Inclure le ESP8266Wi-Fi et espionner bibliothèques.

#include <ESP8266WiFi.h>
#include <espnow.h>

Insérez l’adresse MAC du récepteur sur la ligne suivante.

uint8_t broadcastAddress[] = {0x5C, 0xCF, 0x7F, 0x99, 0xA1, 0x70};

Définissez l’ID de la carte sur le BOARD_ID variable. N’oubliez pas de modifier cette variable pour chacune de vos cartes émettrices.

// Set your Board ID (ESP8266 Sender #1 = BOARD_ID 1, ESP8266 Sender #2 = BOARD_ID 2, etc)
#define BOARD_ID 2

Ensuite, créez une structure qui contient les données que nous voulons envoyer. Nous avons appelé cette structure struct_message et il contient trois variables entières : le plateau identifiant, X et y. Vous pouvez changer cela pour envoyer les types de variables que vous voulez (mais n’oubliez pas de changer cela du côté récepteur également).

typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

Créer une nouvelle variable de type struct_message que l’on appelle mes données qui stockera les valeurs des variables.

struct_message myData;

Fonction de rappel OnDataSent()

Ensuite, définissez le OnDataSent() une fonction. Il s’agit d’une fonction de rappel qui sera exécutée lors de l’envoi d’un message. Dans ce cas, cette fonction imprime si le message a été livré avec succès ou non.

void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("rnLast Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}

mettre en place()

Dans le mettre en place(), initialisez le moniteur série à des fins de débogage :

Serial.begin(115200);

Configurez l’appareil en tant que station Wi-Fi et déconnectez le Wi-Fi :

WiFi.mode(WIFI_STA);
WiFi.disconnect();

Initialiser ESP-NOW :

if (esp_now_init() != 0) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Définissez le rôle du conseil d’administration. Il s’agit d’une carte émettrice, nous allons donc la régler sur ESP_NOW_ROLE_CONTROLLER.

esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

Après avoir initialisé ESP-NOW avec succès, enregistrez la fonction de rappel qui sera appelée lors de l’envoi d’un message. Dans ce cas, inscrivez-vous au OnDataSent() fonction créée précédemment.

esp_now_register_send_cb(OnDataSent);

Ajouter un appareil pair

Pour envoyer des données à une autre carte (le récepteur), vous devez la coupler en tant que pair. La ligne suivante enregistre un nouveau pair.

esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);

le esp_now_add_peer() La fonction accepte les arguments suivants, dans cet ordre : adresse MAC, rôle d’homologue, canal Wi-Fi, clé et longueur de clé.

boucler()

Dans le boucler(), nous enverrons un message via ESP-NOW toutes les 10 secondes (vous pouvez modifier ce délai dans le timerDelay variable).

Attribuez une valeur à chaque variable.

myData.id = BOARD_ID;
myData.x = random(1, 50);
myData.y = random(1, 50);

N’oubliez pas de changer l’identifiant de chaque carte émettrice.

Rappelez-vous que mes données est une structure. Attribuez ici les valeurs que vous souhaitez envoyer à l’intérieur de la structure. Dans ce cas, nous envoyons simplement le identifiant et valeurs aléatoires X et y. Dans une application pratique, ceux-ci doivent être remplacés par des commandes ou des lectures de capteur, par exemple.

Envoyer un message ESP-NOW

Enfin, envoyez le message via ESP-NOW.

esp_now_send(0, (uint8_t *) &myData, sizeof(myData));

Code récepteur ESP8266 NodeMCU (ESP-NOW)

Téléchargez le code suivant sur votre carte récepteur ESP8266. Le code est préparé pour recevoir des données de deux cartes différentes. Vous pouvez facilement modifier le code pour recevoir des données d’un nombre différent de cartes.

/*
  Rui Santos
  Complete project details at https://Raspberryme.com/esp-now-many-to-one-esp8266-nodemcu/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <ESP8266WiFi.h>
#include <espnow.h>

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// Create a structure to hold the readings from each board
struct_message board1;
struct_message board2;

// Create an array with all the structures
struct_message boardsStruct[2] = {board1, board2};

// Callback function that will be executed when data is received
void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {
  char macStr[18];
  Serial.print("Packet received from: ");
  snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
           mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
  Serial.println(macStr);
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.printf("Board ID %u: %u bytesn", myData.id, len);
  // Update the structures with the new incoming data
  boardsStruct[myData.id-1].x = myData.x;
  boardsStruct[myData.id-1].y = myData.y;
  Serial.printf("x value: %d n", boardsStruct[myData.id-1].x);
  Serial.printf("y value: %d n", boardsStruct[myData.id-1].y);
  Serial.println();
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);
  WiFi.disconnect();

  // Init ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(OnDataRecv);
}

void loop(){
  // Access the variables for each board
  /*int board1X = boardsStruct[0].x;
  int board1Y = boardsStruct[0].y;
  int board2X = boardsStruct[1].x;
  int board2Y = boardsStruct[1].y;
  */
}

Afficher le code brut

Comment fonctionne le code

Comme pour l’expéditeur, commencez par inclure les bibliothèques :

#include <ESP8266WiFi.h>
#include <espnow.h>

Créez une structure pour recevoir les données. Cette structure doit être la même que celle définie dans l’esquisse de l’expéditeur.

typedef struct struct_message {
    int id;
    int x;
    int y;
} struct_message;

Créer un struct_message variable appelée mes données qui contiendra les données reçues.

struct_message myData;

Ensuite, créez un struct_message variable pour chaque carte, afin que nous puissions affecter les données reçues à la carte correspondante. Ici, nous créons des structures pour deux cartes émettrices. Si vous avez plus de cartes émettrices, vous devez créer plus de structures.

struct_message board1;
struct_message board2;

Créez un tableau contenant toutes les structures du tableau. Si vous utilisez un nombre différent de cartes, vous devez changer cela.

struct_message boardsStruct[2] = {board1, board2};

onDataRecv()

Créez une fonction de rappel qui est appelée lorsque l’ESP8266 reçoit les données via ESP-NOW. La fonction s’appelle onDataRecv() et doit accepter plusieurs paramètres comme suit :

void OnDataRecv(uint8_t * mac_addr, uint8_t *incomingData, uint8_t len) {

Obtenez l’adresse MAC de la carte émettrice :

Serial.print("Packet received from: ");
snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x",
         mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]);
Serial.println(macStr);

Copiez le contenu du entrantDonnées variable de données dans la mes données variable.

memcpy(&myData, incomingData, sizeof(myData));

Maintenant le mes données structure contient plusieurs variables avec les valeurs envoyées par l’un des expéditeurs ESP8266. On peut identifier quelle carte envoie le paquet par son ID : myData.id.

De cette façon, nous pouvons affecter les valeurs reçues aux cartes correspondantes sur le planchesStruct déployer:

boardsStruct[myData.id-1].x = myData.x;
boardsStruct[myData.id-1].y = myData.y;

Par exemple, imaginez que vous recevez un paquet de la carte avec l’identifiant 2. La valeur de myData.id est 2.

Donc, vous voulez mettre à jour les valeurs de planche2 structure. le planche2 structure est l’élément d’indice 1 sur la planchesStruct déployer. C’est pourquoi nous soustrayons 1, car les tableaux en C ont une indexation de 0. Cela peut aider si vous regardez l’image suivante.

Structure de données ESP-NOW ESP8266 NodeMCU

mettre en place()

Dans le mettre en place(), initialisez le moniteur série.

Serial.begin(115200);

Configurez l’appareil en tant que station Wi-Fi et déconnectez le Wi-Fi.

WiFi.mode(WIFI_STA);
WiFi.disconnect();

Initialiser ESP-NOW :

if (esp_now_init() != ESP_OK) {
  Serial.println("Error initializing ESP-NOW");
  return;
}

Définissez le rôle du conseil d’administration. Il s’agit d’une carte réceptrice, nous allons donc la régler sur ESP_NOW_ROLE_SLAVE.

Enregistrez-vous pour une fonction de rappel qui sera appelée lorsque les données seront reçues. Dans ce cas, nous nous inscrivons au OnDataRecv() fonction créée précédemment.

esp_now_register_recv_cb(OnDataRecv);

Les lignes suivantes commentées sur la boucle illustrent ce que vous devez faire si vous souhaitez accéder aux variables de chaque structure de carte. Par exemple, pour accéder au X valeur de planche1:

int board1X = boardsStruct[0].x;

Manifestation

Téléchargez le code de l’expéditeur sur chacun de vos tableaux d’envoi. N’oubliez pas de donner un identifiant différent à chaque carte.

Téléchargez le code du récepteur sur la carte du récepteur ESP8266. N’oubliez pas de modifier la structure pour correspondre au nombre de cartes émettrices.

Sur le moniteur série des expéditeurs, vous devriez recevoir un message « Delivery Success » si les messages sont livrés avec succès.

ESP-NOW envoie des données de plusieurs cartes à un moniteur série du récepteur ESP8266 NodeMCU Arduino IDE

Sur la carte réceptrice, vous devriez recevoir les paquets de toutes les autres cartes. Dans ce test, nous recevions des données de 2 cartes différentes.

ESP-NOW reçoit des données de plusieurs cartes ESP8266 NodeMCU Arduino IDE Serial Monitor

Conclusion

Dans ce didacticiel, vous avez appris comment configurer un ESP8266 pour recevoir des données de plusieurs cartes ESP8266 à l’aide d’ESP-NOW (configuration plusieurs à un). Vous pouvez faire quelque chose de similaire avec les cartes ESP32 (ESP32 ESP-NOW : Many-to-one).

Par exemple, nous avons échangé des nombres aléatoires. Dans une application pratique, ceux-ci doivent être remplacés par des lectures ou des commandes de capteur réelles. C’est idéal si vous souhaitez collecter des données à partir de plusieurs nœuds de capteurs.

Nous avons d’autres tutoriels liés à ESP-NOW que vous pourriez aimer :

En savoir plus sur ESP8266 avec nos ressources :

Merci d’avoir lu.