Como conectar ESP32 e ESP8266 usando o protocolo ESP-Now

Tempo de leitura: 10 minutes

Este tutorial descreve como usar o protocolo ESP-Now para conectar ESP32 e ESP8266. Ambos os dispositivos suportam o protocolo ESP-Now.

O que é o protocolo ESP-Now?

ESP-Now é um protocolo desenvolvido pela Espressif que permite que vários dispositivos (ESP32 e ESP8266) se conectem entre si.

ESP-Now é um protocolo sem fio de baixa potência que conecta dispositivos ESP32 e ESP8266 sem usar WiFi. Ele permite a conexão direta sem fio entre dois dispositivos ESP sem WiFi. A mesma conexão pode ser estabelecida entre vários dispositivos ESP ao mesmo tempo. Na terminologia ESP-Now, um dispositivo é chamado de par. Assim que os dispositivos estiverem emparelhados, a conexão pode ser estabelecida sem um handshake.

Onde usar este protocolo wireless?

Este protocolo é útil quando queremos trocar dados entre dispositivos ESP32 e ESP8266 sem usar um roteador. É o protocolo ideal quando há a necessidade de controlar luzes inteligentes conectadas a dispositivos ESP ou quando queremos trocar dados entre dois ou mais pares (ou seja, leituras de sensor)

Limitações do ESP-Now

O ESP agora tem algumas limitações:

  • carga útil: o tamanho máximo da carga útil é 250 bytes
  • é compatível apenas com dispositivos ESP

Como conectar dispositivos ESP32 e ESP822

Existem vários cenários em que o protocolo ESP-Now pode ser usado para conectar ESP32 e ESP8266 ou outros dispositivos ESP. Além disso, esses dispositivos podem desempenhar funções diferentes.

Comunicação um para um

Em uma comunicação um para um, dois dispositivos ESP se conectam para trocar dados.

Usando a terminologia ESP-Now, existem neste cenário dois pares. É possível definir a função de cada par:

  • Mestre
  • Slave
  • Combo (Mestre e Slave ao mesmo tempo)

Um para muitos – Transmissão: Mestre e Slave

Em um-para-muitos (transmissão), ESP32 ou ESP8266 atua como um transmissor enviando a mesma mensagem para todos os pares conectados.

A emissora desempenha o papel de mestre que se conecta a vários escravos. Este cenário é útil quando queremos controlar vários dispositivos que atuam como escravos usando uma emissora que envia dados para eles. Você pode pensar em um sistema que apaga todas as luzes usando um controlador central.

Muitos para um: Gateway

O último cenário, onde o ESP-now pode ser usado, é a configuração muitos para um. Nesse cenário, há um gateway central que coleta todos os dados que chegam dos pares conectados a ele. Você pode imaginar vários sensores que enviam os dados adquiridos para um coletor central que de alguma forma tratará essas informações.

Durante este tutorial do ESP-Now, iremos descrever e implementar todos os cenários descritos acima.

Como usar ESP-Now com ESP32 e ESP8266

Antes de entrar em detalhes sobre como usar o ESP-Now para conectar o ESP32 e o ESP822, é útil entender as etapas a seguir para inicializar e conectar os dispositivos.

O protocolo ESP-Now é compatível com ESP32 e ESP8266, mesmo que haja algumas diferenças nos métodos. De qualquer forma, as principais etapas são válidas para ambos os dispositivos e são:

  1. Inicialize o protocolo ESP-Now
  2. Se estivermos desenvolvendo um mestre ou uma emissora
    • Adicionar par (se estivermos desenvolvendo um mestre ou transmissor)
    • Defina a função de retorno de chamada para saber se uma mensagem foi enviada
    • Envie uma mensagem
  3. Se estamos desenvolvendo um Slave
    • Adicione uma função de retorno de chamada para saber quando uma nova mensagem está chegando

Uma coisa importante a notar é que o protocolo ESP-Now suporta apenas 250 bytes como carga útil.

 

Funções ESP-Now

Esta é uma lista das funções mais úteis para usar o ESP-Now se quisermos trocar dados entre dispositivos ESP:

ESP32 ESP 8266 Descrição
esp_now_init() esp_now_init() Inicialize o protocolo ESP-Now
esp_now_add_peer() esp_now_add_peer() Adicione um novo par. Essas duas funções diferem nos parâmetros que aceitam
esp_now_register_send_cb() esp_now_register_send_cb() Função de retorno de chamada para saber informações sobre a mensagem enviada
esp_now_register_rcv_cb() esp_now_register_rcv_cb() Função de retorno de chamada invocada quando uma nova mensagem chega

Para obter mais informações, consulte o guia EspressIf para o ESP32 e aqui para o ESP8266.

 

Código de exemplo ESP-Now ESP8266

Neste parágrafo, vamos discutir como trocar dados entre dois dispositivos ESP8266 em uma configuração Um para um, em que um dos dispositivos é mestre e o outro escravo.

Este é um cenário muito simples, onde existe um dispositivo que envia dados e outro que os recebe. Teremos dois códigos diferentes: um para o remetente e outro para o destinatário.

 

Código-fonte do remetente ESP-Now ESP8266

O código-fonte do remetente é mostrado abaixo:

/**
 * ESP-NOW
 * 
 * Sender
*/
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
// Mac address of the slave
uint8_t peer1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
typedef struct message {
   int red;
   int green;
   int blue;
};
struct message myMessage;
void onSent(uint8_t *mac_addr, uint8_t sendStatus) {
  Serial.println("Status:");
  Serial.println(sendStatus);
}
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  // Get Mac Add
  Serial.print("Mac Address: ");
  Serial.print(WiFi.macAddress());
  Serial.println("ESP-Now Sender");
  // Initializing the ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Problem during ESP-NOW init");
    return;
  }
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  // Register the peer
  Serial.println("Registering a peer");
  esp_now_add_peer(peer1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
  Serial.println("Registering send callback function");
  esp_now_register_send_cb(onSent);
}
void loop() {
  myMessage.red = 10;
  myMessage.green = 80;
  myMessage.blue = 180;
  Serial.println("Send a new message");
  esp_now_send(NULL, (uint8_t *) &myMessage, sizeof(myMessage));
  delay(60000);
}

Uma breve descrição do código:

  • Linha 10: Este é o endereço MAC do escravo. Usamos este endereço para enviar dados
  • Linha 11-15: A estrutura da mensagem. Esta é a mensagem que queremos enviar para o par (ou escravo) ESP-Now. A mensagem pode conter vários campos (ou seja, char, int, float e assim por diante).
  • Linha 17-20: A função de retorno de chamada invocada quando a mensagem é enviada
  • Linha 29: O ESP-Now é inicializado antes de usá-lo
  • Linha 33: O ESP8266 define sua função. Esta é a função principal
  • Linha 36: O código adiciona o par à lista de pares. Nesse caso, o dispositivo, que atua como mestre, adiciona o outro ESP8266 (o escravo) usando o endereço Mac. Desta forma, os dois dispositivos ESP podem trocar dados por meio do protocolo ESP-Now
  • Linha 38: Registramos a função de retorno de chamada que é acionada assim que a mensagem é enviada
  • Linha 45: o mestre envia a mensagem para o outro ESP8266 por meio do ESP-Now

 

Código-fonte do receptor ESP8266

O código do receptor é muito mais simples:

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
typedef struct message {
   int red;
   int green;
   int blue;
} message;
message myMessage;
void onDataReceiver(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
   Serial.println("Mensagem recebida.");
  // Não usamos mac para verificar o remetente
  // Vamos transformar os dados recebidos em nossa estrutura de mensagem
  memcpy(&myMessage, incomingData, sizeof(myMessage));
  Serial.print("Red:");
  Serial.println(myMessage.red); 
  Serial.print("Green:");
  Serial.println(myMessage.green);
  Serial.print("Blue:");
  Serial.println(myMessage.blue);
}
void setup() {
  Serial.begin(115200);
  WiFi.disconnect();
  ESP.eraseConfig();
 
  // Modo Wifi STA
  WiFi.mode(WIFI_STA);
  // Obter Mac Add
  Serial.print("Mac Address: ");
  Serial.print(WiFi.macAddress());
  Serial.println("\nReceptor ESP-Now");
  
  // Initializing the ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Problema durante a inicialização ESP-NOW");
    return;
  }
  
  //esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  // Podemos registrar a função de retorno de chamada do receptor
  esp_now_register_recv_cb(onDataReceiver);
}
void loop() {
 // coloque seu código principal aqui, para executar repetidamente:
}
  • Linha 10-21: Esta é a função de retorno de chamada acionada quando uma nova mensagem chega através do protocolo ESP-Now
  • Linha 35: como no remetente ESP8266, temos que inicializar o protocolo ESP-Now
  • Linha 42: registramos a função de retorno de chamada ESP-Now que será invocada assim que uma nova mensagem chegar ao ESP8266

 

Testando a conexão ESP-Now entre ESP8266

Executando o código: um no dispositivo emissor e o outro no receptor, o resultado obtido é algo como:

 

Conecte o ESP32 a vários ESP8266 por meio do protocolo ESP-Now

Este é um exemplo um pouco mais complexo que descreve como usar o ESP-Now com o ESP32. Nesse cenário, podemos supor que haja um ESP32 que é um transmissor e envia dados para vários dispositivos ESP8266 por meio do protocolo ESP-Now. Esta é uma configuração de um para muitos. Para descrever este cenário, vamos supor que:

  • ESP32 se conecta a dois dispositivos ESP8266 por meio do protocolo ESP-Now
  • O ESP32 transmite uma mensagem contendo informações de cores RGB para todos os dispositivos conectados
  • Os dispositivos ESP8266 recebem esta mensagem e controlam faixas de Led RGB.

Este exemplo é interessante porque podemos descrever como usar o ESP-Now para transmitir uma mensagem e como integrar ESP32 e ESP8266 usando o protocolo ESP-Now. Você pode usar todos os ESP32 ou todos os ESP8266 neste exemplo.

 

ESP32 esp agora transmitido: esp_now_send

Este código descreve como transmitir dados para vários pares usando ESP32:

/**
 * ESP-NOW: ESP32 Broadcast com ESP-Now
 * 
 * 
*/
#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
// ESP8266 endereço Mac (primeiro par)
uint8_t mac_peer1[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
// ESP8266 endereço Mac (segundo par)
uint8_t mac_peer2[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
esp_now_peer_info_t peer1;
esp_now_peer_info_t peer2;
int i = 0;
typedef struct message {
   int red;
   int green;
   int blue;
};
struct message myMessage;
void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);
  // Obter Mac Add
  Serial.print("Endereço MAC: ");
  Serial.print(WiFi.macAddress());
  Serial.println("ESP32 ESP-Now Broadcast");
  // Inicializando o ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Problema durante a inicialização ESP-NOW");
    return;
  }
  memcpy(peer1.peer_addr, mac_peer1, 6);
  peer1.channel = 4;
  peer1.encrypt = 0;
  // Registre o par
  Serial.println("Registrando um par 1");
  if ( esp_now_add_peer(&peer1) == ESP_OK) {
    Serial.println("Peer 1 adicionado");
  }  
  memcpy(peer2.peer_addr, mac_peer2, 6);
  peer2.channel = 4;
  peer2.encrypt = 0;
  // Registre o par
  Serial.println("Registrando um par 2");
  if ( esp_now_add_peer(&peer2) == ESP_OK) {
    Serial.println("Peer 2 adicionado");
  }  
}
void loop() {
  myMessage.red = random(0, 254);
  myMessage.green = random(0, 254);
  myMessage.blue = random(0, 254);
  Serial.println("Envie uma nova mensagem");
  esp_now_send(NULL, (uint8_t *) &myMessage, sizeof(myMessage));
  delay(2000);
}

Uma breve descrição do código:

  • Linha 10-12: definimos duas variáveis chamadas peer1 e peer2 que conterão as informações relacionadas aos dois ESP8266 que receberão as mensagens
  • Linha 30: inicializamos o protocolo ESP-Now
  • Linha 34-36: Definimos os detalhes do par1:
    • seu endereço Mac,
    • o canal que usaremos para enviar dados (você pode escolher o canal ESP-Now de sua preferência)
    • a criptografia (falsa neste cenário)
  • Linha 39: O ESP32 adiciona o ESP8266 (o par1) à lista de pares
  • Linha 42-44: Definimos os detalhes do par2:
    • seu endereço Mac,
    • o canal que usaremos para enviar dados (você pode escolher o canal ESP-Now de sua preferência)
    • a criptografia (falsa neste cenário)
  • Linha 47: O ESP32 adiciona o ESP8266 (o par2) à lista de pares
  • Linha 56: Estamos enviando a mensagem. Observe aqui que usamos NULL, o que significa que queremos enviar a mensagem para todos os pares registrados

 

Peer receptor ESP8266: onDataReceiver

Este receptor é quase o mesmo descrito anteriormente, com a única diferença que quando o ESP8266 receber uma mensagem irá definir a cor do LED.

#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <Adafruit_NeoPixel.h>
#define NUM_OF_LEDS D6
#define PIN 12
typedef struct message {
   int red;
   int green;
   int blue;
} message;
uint8_t key[] =  {0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44, 0x33, 0x44};
message myMessage;
// Faixa de LEDs Neopixel
Adafruit_NeoPixel pixels(NUM_OF_LEDS, PIN, NEO_GRB + NEO_KHZ800);
void onDataReceiver(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
   Serial.println("Message received.");
   // Não usamos o mac para verificar o remetente 
   // Vamos transformar os dados de entrada em nossa estrutura de mensagem
   memcpy(&myMessage, incomingData, sizeof(myMessage));
   Serial.print("Red:");
   Serial.println(myMessage.red); 
   Serial.print("Green:");
   Serial.println(myMessage.green);
   Serial.print("Blue:");
   Serial.println(myMessage.blue);
   pixels.fill(pixels.Color(myMessage.red, myMessage.green, myMessage.blue));
   pixels.show();
}
void setup() {
  Serial.begin(115200);
  WiFi.disconnect();
  ESP.eraseConfig();
  // Inicializar Neopixel
  pixels.begin();
  // Modo Wifi STA
  WiFi.mode(WIFI_STA);
  // Obter Mac Add
  Serial.print("Endereço MAC:");
  Serial.print(WiFi.macAddress());
  Serial.println("\nReceptor ESP-Now");
  
  // Inicializando o ESP-NOW
  if (esp_now_init() != 0) {
    Serial.println("Problema durante a inicialização ESP-NOW");
    return;
  }
  
  //esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  // Podemos registrar a função de retorno de chamada do receptor
  esp_now_register_recv_cb(onDataReceiver);
}
void loop() {
  // coloque seu código principal aqui, para executar repetidamente:
}

Se você estiver usando o Wemos D1 mini, pode haver um bug que impede este dispositivo de receber mensagens de broadcast.

 

Testando o ESP-Now com LEDs de controle ESP32 e ESP8266

Se você executar o código nos dispositivos ESP32 e ESP8266, notará que em 2 segundos os LEDs, conectados ao ESP8266, mudam de cor. O ESP32 envia mensagens com valores RGB aleatórios.

 

Use ESP32 para coletar dados do sensor

Este é o código do gateway ESP32 que está conectado a outro ESP8266 usando ESP-Now:

#include <Arduino.h>
#include <WiFi.h>
#include <esp_now.h>
 
typedef struct message {
  float temperature;
  float humidity;
};
 
struct message myMessage;
 
void onDataReceiver(const uint8_t * mac, const uint8_t *incomingData, int len) {
  Serial.println("Message received.");
 // Não usamos mac para verificar o remetente
 // Vamos transformar os dados recebidos em nossa estrutura de mensagem
 memcpy(&myMessage, incomingData, sizeof(myMessage));
 Serial.println("=== Data ===");
 Serial.print("endereço MAC: ");
 for (int i = 0; i < 6; i++) {
     Serial.print("0x");
     Serial.print(mac[i], HEX);
     Serial.print(":");
 }
    
 Serial.print("\n\nTemperatura: ");
 Serial.println(myMessage.temperature);
 Serial.print("\nUmidade: ");
 Serial.println(myMessage.humidity);
 Serial.println();
}
 
void setup() {
 Serial.begin(115200);
 WiFi.mode(WIFI_STA);
 
 // Obter Mac Add
 Serial.print("Endereço MAC:");
 Serial.print(WiFi.macAddress());
 Serial.println("ESP32 ESP-Now Broadcast");
 
 // Inicializando o ESP-NOW
 if (esp_now_init() != 0) {
   Serial.println("Problema durante a inicialização ESP-NOW");
   return;
 }
 esp_now_register_recv_cb(onDataReceiver);
}
 
void loop() {
 // coloque seu código principal aqui, para executar repetidamente:
}

Observe que a mensagem (linha 5-8) é diferente de antes porque mantém a temperatura e a umidade. Os outros aspectos são quase os mesmos abordados anteriormente.

 

Transmissor ESP8266

Existem dois remetentes ESP8266 que enviam dados sem fio para o ESP32. O código do remetente ESP é mostrado abaixo:

/**
* ESP-NOW
*
* Sender
*/
 
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <espnow.h>
#include <SPI.h>
#include <Wire.h>
#include <DHT.h>
 
#define DHTTYPE DHT11
#define DHTPin D6
 
uint8_t peer1[] = {0x24, 0x6F, 0x28, 0x10, 0x67, 0xD8};
 
typedef struct message {
  float temperature;
  float humidity;
};
 
struct message myMessage;
 
// Inicializa o sensor DHT.
DHT dht(DHTPin, DHTTYPE);
 
void onSent(uint8_t *mac_addr, uint8_t sendStatus) {
 Serial.println("Status:");
 Serial.println(sendStatus);
}
 
void setup() {
 Serial.begin(115200);
 
 dht.begin();
 
 WiFi.mode(WIFI_STA);
 
 // Obter Mac Add
 Serial.print("Endereço MAC:");
 Serial.print(WiFi.macAddress());
 Serial.println("ESP-Now Sender");

 // Inicializando o ESP-NOW
 if (esp_now_init() != 0) {
   Serial.println("Problema durante a inicialização ESP-NOW");
   return;
 }
 
 esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
 // Registre o par
 Serial.println("Registrando um par");
 esp_now_add_peer(peer1, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
 Serial.println("Registrando a função de retorno de chamada");
 esp_now_register_send_cb(onSent);
}
 
void loop() {
 myMessage.temperature = dht.readTemperature();
 myMessage.humidity = dht.readHumidity();
 
 Serial.println("Envie uma nova mensagem");
 esp_now_send(NULL, (uint8_t *) &myMessage, sizeof(myMessage));
 
 delay(60000);
}

A cada minuto, esses dois aparelhos ESP8266 enviam a temperatura e a umidade adquiridas pelo sensor DHT11.

O resultado final é mostrado na imagem abaixo:

 

 

Empacotando

Esta postagem descreve como usar o protocolo sem fio ESP-Now. O ESP-Now é um protocolo rápido e confiável que conecta diferentes dispositivos. Existem diferentes cenários onde podemos usar ESP-Now. Usamos o protocolo ESP-Now para conectar o ESP8266 a um ESP8266 na configuração um a um. Além disso, aprendemos como usar o ESP-Now para conectar o ESP32 e o ESP8266, onde o ESP32 recebe dados de vários dispositivos ESP8266. Por outro lado, o ESP8266 pode enviar dados para ESP8266.

Visits: 4 Visits: 1191093