ESP-NOW Communication bidirectionnelle entre les cartes ESP8266 NodeMCU

ESP-NOW Communication bidirectionnelle entre les cartes ESP8266 NodeMCU

Apprenez à établir une communication bidirectionnelle entre deux cartes ESP8266 NodeMCU à l’aide du protocole de communication ESP-NOW. Par exemple, deux cartes ESP8266 échangeront les lectures du capteur DHT. Nous utiliserons l’IDE Arduino.

ESP-NOW Communication bidirectionnelle entre les cartes ESP8266 NodeMCU

Nous avons d’autres tutoriels sur ESP-NOW avec l’ESP8266 :

Présentation d’ESP-NOW

ESP-MAINTENANT est un protocole de communication sans connexion développé par Espressif qui se caractérise par une transmission par paquets courts. Ce protocole permet à plusieurs appareils de se parler sans utiliser le Wi-Fi.

ESP-MAINTENANT - Logo ESP32

Il s’agit d’un protocole de communication rapide qui peut être utilisé pour échanger de petits messages (jusqu’à 250 octets) entre les cartes ESP32. ESP-NOW est très polyvalent et vous pouvez avoir une communication unidirectionnelle ou bidirectionnelle dans différents arrangements.

Dans ce tutoriel, nous allons vous montrer comment établir une communication bidirectionnelle entre deux cartes ESP8266.

Communication bidirectionnelle ESP-NOW ESP8266

Aperçu du projet

Le diagramme suivant montre un aperçu du projet que nous allons construire :

ESP8266 ESP-NOW Échange de communication bidirectionnelle Lectures du capteur DHT
  • Dans ce projet, nous aurons deux cartes ESP8266. Chaque carte est connectée à un capteur DHT ;
  • Chaque carte obtient des lectures de température et d’humidité de leurs capteurs correspondants ;
  • Chaque carte envoie ses lectures à l’autre carte via ESP-NOW ;
  • Lorsqu’une carte reçoit les lectures, elle les imprime sur le moniteur série. Vous pouvez connecter un écran OLED pour visualiser les lectures, par exemple.
  • Lorsqu’un message est envoyé, un message est imprimé indiquant si le paquet a été livré avec succès ou non.
  • Chaque carte doit connaître l’adresse MAC de l’autre carte pour envoyer le message.

Dans cet exemple, nous utilisons une communication bidirectionnelle entre deux cartes, mais vous pouvez ajouter plus de cartes à cette configuration et faire en sorte que toutes les cartes communiquent entre elles.

Conditions préalables

Avant de poursuivre ce projet, assurez-vous de vérifier les prérequis suivants.

Complément ESP8266 Arduino IDE

Nous allons programmer l’ESP8266 à l’aide de l’IDE Arduino. Par conséquent, avant de poursuivre ce didacticiel, vous devez avoir installé le module complémentaire ESP8266 dans votre IDE Arduino. Suivez le guide suivant :

Installation des bibliothèques DHT

Pour lire à partir du capteur DHT, nous utiliserons le Bibliothèque DHT d’Adafruit. Pour utiliser cette bibliothèque, vous devez également installer le Bibliothèque de capteurs unifiés Adafruit. Suivez les étapes suivantes pour installer ces bibliothèques.

1. Ouvrez votre IDE Arduino et accédez à Esquisser > Inclure la bibliothèque > Gérer les bibliothèques. Le gestionnaire de bibliothèque devrait s’ouvrir.

2. Recherchez « DHT » dans la zone de recherche et installez la bibliothèque DHT d’Adafruit.

Installation de la bibliothèque Adafruit DHT

3. Après avoir installé la bibliothèque DHT d’Adafruit, tapez « Capteur unifié Adafruit” dans le champ de recherche. Faites défiler vers le bas pour trouver la bibliothèque et installez-la.

Installation de la bibliothèque de pilotes Adafruit Unified Sensor

Après avoir installé les bibliothèques, redémarrez votre IDE Arduino.

Pièces requises

Pour ce tutoriel, vous avez besoin des pièces suivantes :

Vous pouvez utiliser les liens précédents ou accéder directement à MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !

1642759211 911 ESP NOW Communication bidirectionnelle entre les cartes ESP8266 NodeMCU

Obtenir l’adresse MAC des cartes

Pour envoyer des messages entre chaque carte, nous avons besoin de connaître leur adresse MAC. Chaque carte a une adresse MAC unique (découvrez comment obtenir et modifier l’adresse MAC ESP32).

Téléchargez le code suivant sur chacune de vos cartes pour obtenir leur adresse MAC.

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

#include "WiFi.h"
 
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  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.

Obtenir le moniteur série de l'adresse MAC ESP8266

Notez l’adresse MAC de chaque carte pour les identifier clairement.

Carte ESP8266 NodeMCU Obtenir l'adresse MAC

Schéma de principe ESP8266 et DHT11/DHT22

Avant de poursuivre le didacticiel, câblez le capteur de température et d’humidité DHT11 ou DHT22 à l’ESP8266 comme indiqué dans le schéma suivant.

Circuit de schéma de principe ESP8266 DHT11 DHT22

Dans cet exemple, nous connectons la broche de données DHT au GPIO5 (D1), mais vous pouvez utiliser n’importe quel autre GPIO approprié. Lisez notre guide de référence ESP8266 GPIO pour en savoir plus sur les GPIO ESP8266.

Vous aimerez peut-être : ESP8266 DHT11/DHT22 Serveur Web de température et d’humidité avec Arduino IDE

ESP8266 Communication bidirectionnelle Code ESP-NOW

Téléchargez le code suivant sur chacun de vos tableaux. Avant de télécharger le code, vous devez entrer l’adresse MAC de l’autre carte (la carte à laquelle vous envoyez des données).

/*
  Rui Santos
  Complete project details at https://Raspberryme.com/esp-now-two-way-communication-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>

#include <Adafruit_Sensor.h>
#include <DHT.h>

// REPLACE WITH THE MAC Address of your receiver 
uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

// Digital pin connected to the DHT sensor
#define DHTPIN 5    

// Uncomment the type of sensor in use:
//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

DHT dht(DHTPIN, DHTTYPE);

// Define variables to store DHT readings to be sent
float temperature;
float humidity;

// Define variables to store incoming readings
float incomingTemp;
float incomingHum;

// Updates DHT readings every 10 seconds
const long interval = 10000; 
unsigned long previousMillis = 0;    // will store last time DHT was updated 

// Variable to store if sending data was successful
String success;

//Structure example to send data
//Must match the receiver structure
typedef struct struct_message {
    float temp;
    float hum;
} struct_message;

// Create a struct_message called DHTReadings to hold sensor readings
struct_message DHTReadings;

// Create a struct_message to hold incoming sensor readings
struct_message incomingReadings;

// Callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.print("Last Packet Send Status: ");
  if (sendStatus == 0){
    Serial.println("Delivery success");
  }
  else{
    Serial.println("Delivery fail");
  }
}

// Callback when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&incomingReadings, incomingData, sizeof(incomingReadings));
  Serial.print("Bytes received: ");
  Serial.println(len);
  incomingTemp = incomingReadings.temp;
  incomingHum = incomingReadings.hum;
}

void getReadings(){
  // Read Temperature
  temperature = dht.readTemperature();
  // Read temperature as Fahrenheit (isFahrenheit = true)
  //float t = dht.readTemperature(true);
  if (isnan(temperature)){
    Serial.println("Failed to read from DHT");
    temperature = 0.0;
  }
  humidity = dht.readHumidity();
  if (isnan(humidity)){
    Serial.println("Failed to read from DHT");
    humidity = 0.0;
  }
}

void printIncomingReadings(){
  // Display Readings in Serial Monitor
  Serial.println("INCOMING READINGS");
  Serial.print("Temperature: ");
  Serial.print(incomingTemp);
  Serial.println(" ºC");
  Serial.print("Humidity: ");
  Serial.print(incomingHum);
  Serial.println(" %");
}
 
void setup() {
  // Init Serial Monitor
  Serial.begin(115200);

  // Init DHT sensor
  dht.begin();
 
  // 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_COMBO);

  // 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_COMBO, 1, NULL, 0);
  
  // Register for a callback function that will be called when data is received
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;

    //Get DHT readings
    getReadings();

    //Set values to send
    DHTReadings.temp = temperature;
    DHTReadings.hum = humidity;

    // Send message via ESP-NOW
    esp_now_send(broadcastAddress, (uint8_t *) &DHTReadings, sizeof(DHTReadings));

    // Print incoming readings
    printIncomingReadings();
  }
}

Afficher le code brut

Comment fonctionne le code

Continuez à lire pour savoir comment le code fonctionne ou passez à la section Démonstration.

Importer des bibliothèques

Commencez par importer les bibliothèques requises.

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

le espnow.h La bibliothèque est installée par défaut lorsque vous installez la carte ESP8266. Lors de la compilation du code, assurez-vous d’avoir une carte ESP8266 sélectionnée dans le menu Cartes.

Incluez les bibliothèques DHT à lire à partir du capteur DHT.

#include <Adafruit_Sensor.h>
#include <DHT.h>

Dans la ligne suivante, insérez l’adresse MAC de la carte réceptrice :

uint8_t broadcastAddress[] = {0x2C, 0x3A, 0xE8, 0x0E, 0xBB, 0xED};

Définissez le GPIO auquel la broche DHT est connectée. Dans ce cas, il est relié à GPIO 5 (D1).

#define DHTPIN 5    

Ensuite, sélectionnez le type de capteur DHT que vous utilisez. Dans notre exemple, nous utilisons le DHT22. Si vous utilisez un autre type, il vous suffit de décommenter votre capteur et de commenter tous les autres.

//#define DHTTYPE    DHT11     // DHT 11
#define DHTTYPE    DHT22     // DHT 22 (AM2302)
//#define DHTTYPE    DHT21     // DHT 21 (AM2301)

Instancier un DHT objet avec le type et la broche définis précédemment.

DHT dht(DHTPIN, DHTTYPE);

Définissez des variables pour stocker les lectures DHT à envoyer :

float temperature;
float humidity;

Définissez plus de deux variables pour stocker les lectures entrantes :

float incomingTemp;
float incomingHum;

Nous enverrons des lectures DHT via ESP-NOW toutes les 10 secondes. Cette période est définie dans le intervalle variable. Vous pouvez modifier cet intervalle.

const long interval = 10000; 
unsigned long previousMillis = 0;    // will store last time DHT was updated 

La variable suivante stockera un message de réussite si les lectures sont livrées avec succès à l’autre carte.

// Variable to store if sending data was successful
String success;

Créez une structure qui stocke les relevés de température et d’humidité.

typedef struct struct_message {
    float temp;
    float hum;
} struct_message;

Ensuite, vous devez créer deux instances de cette structure. Un pour recevoir les lectures et un autre pour stocker les lectures à envoyer.

le Lectures DHT stockera les lectures à envoyer.

struct_message DHTReadings;

le lectures entrantes stockera les données provenant de l’autre carte.

struct_message incomingReadings;

Fonction de rappel OnDataSent()

le OnDataSent() La fonction sera appelée lorsque de nouvelles données seront envoyées. Cette fonction imprime simplement si le message a été livré avec succès ou non.

Si le message est livré avec succès, la variable d’état renvoie 0, afin que nous puissions définir notre message de réussite sur « Réussite de la livraison »:

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

Si le message de réussite revient 1, cela signifie que la livraison a échoué :

else {
  success = "Delivery Fail :(";
}

Fonction de rappel OnDataRecv()

le OnDataRecv() La fonction est exécutée lorsqu’un nouveau paquet arrive.

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

Nous enregistrons le nouveau paquet dans le lectures entrantes structure que nous avons créée précédemment :

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

Nous imprimons la longueur du message sur le moniteur série. Vous ne pouvez envoyer que 250 octets dans chaque paquet.

Serial.print("Bytes received: ");
Serial.println(len);

Ensuite, stockez les lectures entrantes dans leurs variables correspondantes. Pour accéder au Température variables à l’intérieur lectures entrantesstructure, il vous suffit d’appeler lectures entrantes.temp comme suit:

incomingTemp = incomingReadings.temp;

Le même processus est effectué pour l’humidité :

incomingHum = incomingReadings.hum;

getLectures()

le getLectures() La fonction obtient la température et l’humidité du capteur DHT. La ligne suivante récupère la température actuelle et l’enregistre dans le Température variable:

temperature = dht.readTemperature();

Cette ligne précédente renvoie la température en degrés Celsius. Pour obtenir la température en Fahrenheit, commentez la ligne précédente et décommentez ce qui suit :

//float t = dht.readTemperature(true);

Parfois, vous n’êtes pas en mesure d’obtenir des lectures du capteur. Lorsque cela se produit, le capteur revient Nan. Si tel est le cas, nous définissons le Température à 0.0.

Un processus similaire est effectué pour obtenir les lectures d’humidité. La valeur d’humidité actuelle est enregistrée sur le humidité variable:

humidity = dht.readHumidity();
if (isnan(humidity)){
  Serial.println("Failed to read from DHT");
  humidity = 0.0;
}

printIncomingReadings()

le printIncomingReadings() fonction imprime simplement les lectures reçues sur le moniteur série.

La température reçue est enregistrée sur le entrantTemp variable et l’humidité reçue est enregistrée sur le Hum entrant variable comme nous le verrons dans un instant.

void printIncomingReadings(){
  // Display Readings in Serial Monitor
  Serial.println("INCOMING READINGS");
  Serial.print("Temperature: ");
  Serial.print(incomingTemp);
  Serial.println(" ºC");
  Serial.print("Humidity: ");
  Serial.print(incomingHum);
  Serial.println(" %");
}

mettre en place()

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

Serial.begin(115200);

Initialisez le capteur DHT :

dht.begin();

Définissez l’ESP8266 en tant que station :

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 ESP8266 ESP-NOW. Dans cet exemple, l’ESP8266 reçoit et envoie des lectures via ESP-NOW, alors définissez le rôle sur ESP_NOW_ROLE_COMBO.

esp_now_set_self_role(ESP_NOW_ROLE_COMBO);

Ensuite, inscrivez-vous au OnDataSent fonction de rappel.

 esp_now_register_send_cb(OnDataSent);

Pour envoyer des données à une autre carte, vous devez la coupler en tant que pair. La ligne suivante ajoute un nouveau pair.

esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_COMBO, 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é.

Enfin, inscrivez-vous au OnDataRecv fonction de rappel.

esp_now_register_recv_cb(OnDataRecv);

boucler()

Dans le boucler(), vérifiez s’il est temps d’obtenir de nouvelles lectures :

unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
  // save the last time you updated the DHT values
  previousMillis = currentMillis;

Si c’est le cas, appelez le getLectures fonction pour lire la température et l’humidité actuelles.

getReadings();

Ensuite, mettez à jour le Lectures DHT structure avec les nouvelles valeurs de température et d’humidité :

DHTReadings.temp = temperature;
DHTReadings.hum = humidity;

Envoyez la structure via ESP-NOW :

esp_now_send(broadcastAddress, (uint8_t *) &DHTReadings, sizeof(DHTReadings));

Enfin, appelez le printIncomingReadings() fonction pour imprimer les lectures entrantes sur le moniteur série.

printIncomingReadings();

Manifestation

Après avoir téléchargé le code sur chaque carte, ouvrez une fenêtre Arduino IDE Serial Monitor. Alternativement, vous pouvez ouvrir deux connexions série différentes (en utilisant Mastic) pour voir les deux cartes interagir simultanément.

Lectures du capteur d'échange de carte ESP-NOW ESP8266 NodeMCU Arduino IDE

Comme vous pouvez le voir, cela fonctionne comme prévu. Chaque carte imprime les lectures de l’autre carte.

Carte ESP8266 NodeMCU ESP-NOW Communication bidirectionnelle échange de lectures du capteur d'humidité de la température

Conclusion

Dans ce tutoriel, nous vous avons montré comment établir une communication bidirectionnelle avec deux cartes ESP8266 à l’aide d’ESP-NOW. Il s’agit d’un protocole de communication très polyvalent qui peut être utilisé pour envoyer des paquets jusqu’à 250 octets. Le protocole de communication ESP-NOW peut également être utilisé avec les cartes ESP32 : Mise en route avec ESP-NOW (ESP32 avec Arduino IDE).

À titre d’exemple, nous vous avons montré l’interaction entre deux cartes, mais vous pouvez ajouter plusieurs cartes à votre configuration. Vous avez juste besoin de connaître l’adresse MAC de la carte à laquelle vous envoyez des données. Nous publierons d’autres tutoriels sur ESP-MAINTENANT, alors restez à l’écoute.

Nous espérons que vous avez trouvé ce tutoriel utile. Pour en savoir plus sur la carte ESP8266, assurez-vous de consulter nos ressources :

Merci d’avoir lu.