fbpixel
Etiquetas: ,
5
(2)

Neste tutorial, veremos como configurar dois ESP8266s para estabelecer comunicação usando o protocolo ESP-NOW. O ESP8266 é uma placa de desenvolvimento que integra Bluetooth e WiFi. Pode, portanto, ligar-se e trocar dados com dispositivos ligados à mesma rede.

Hardware

  • Computador
  • NodeMCU ESP8266 ou Wemos x2
  • Cabo USB A macho para Mini B macho x2

Descrição ESP-NOW

O ESP-NOW é um protocolo de comunicação desenvolvido pela Espressif, que permite a comunicação sem fios entre vários dispositivos sem a necessidade de uma rede específica. Permite a troca de pequenos pacotes de dados a alta velocidade nas bandas de frequência de 2,4 GHz, até 200 m de distância. Requer um emparelhamento inicial, mas uma vez efectuado, a comunicação é persistente e estabelece-se quando o ESP8266 é ligado. Uma das grandes vantagens, para além do facto de utilizar uma rede dedicada, é que uma ou mais estações ESP8266 podem ligar-se à rede Wifi em paralelo.

O EPS-NOW também pode ser utilizado para comunicar entre várias placas ESP8266 e ESP32. Basta adaptar o código ao tipo de placa.

Código

Para testar a comunicação ESP-NOW entre dois ESP8266, utilizamos a biblioteca espnow.h disponível quando o gestor de cartões está instalado. Vamos definir e enviar uma estrutura de dados entre o cartão mestre e o cartão escravo. Esta estrutura deve ser idêntica entre as duas placas para que os dados sejam entendidos corretamente.

Código émetteur

Para que a placa emissora possa comunicar com outra placa ESP8266, precisa do seu endereço MAC. Este endereço pode ser obtido quando o cartão recetor é iniciado a partir de mensagens enviadas através da função setup() (Serial.println(WiFi.macAddress());). Vamos definir uma função que é executada depois de uma mensagem ter sido enviada para verificar se a transmissão foi bem sucedida.

Não te esqueças de definir o papel do esp para CONTROLLER na configuração: esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);

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

uint8_t broadcastAddress[] = {0xDC, 0x4F, 0x22, 0x58, 0xD2, 0xF5};// REPLACE WITH RECEIVER MAC ADDRESS
// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
 char a[32];
 int b;
 float c;
 String d;
 bool e;
} struct_message;
struct_message myData;

unsigned long previousTime=0;

// callback when data is sent
void OnDataSent(uint8_t *mac_addr, uint8_t status) {
 Serial.print(F("\r\n Master packet sent:\t"));
 Serial.println(status == 0 ? "Delivery Success" : "Delivery Fail");
}
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("\nReciever initialized : "));
 Serial.println(WiFi.macAddress());
 
 // Define Send function
 esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
 esp_now_register_send_cb(OnDataSent);
 // Register peer
 esp_now_add_peer(broadcastAddress, ESP_NOW_ROLE_SLAVE, 1, NULL, 0);
}
void loop() {
  if((millis() -previousTime)>1000){
     // Set values to send
     strcpy(myData.a, "data type char");
     myData.b = random(1, 20);
     myData.c = 1.2;
     myData.d = "hello";
     myData.e = false;
     // Send message via ESP-NOW
     uint8_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData));
     if (result == 0) {
       Serial.println(F("Sent with success"));
     }
     else {
       Serial.println(F("Error sending the data"));
     }
     previousTime=millis();
  }
}

Código récepteur

No código do recetor, vamos criar uma função que é executada quando uma mensagem é recebida. Esta função é utilizada para processar a informação recebida. Neste exemplo, exibimos os dados contidos na estrutura.

Não te esqueças de definir o papel do esp como SLAVE na configuração: esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);

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

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
 char a[32];
 int b;
 float c;
 String d;
 bool e;
} struct_message;
struct_message myData;
// callback when data is received
void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
 memcpy(&myData, incomingData, sizeof(myData));
 Serial.print("Bytes received: ");
 Serial.println(len);
 Serial.print("Char: ");
 Serial.println(myData.a);
 Serial.print("Int: ");
 Serial.println(myData.b);
 Serial.print("Float: ");
 Serial.println(myData.c);
 Serial.print("String: ");
 Serial.println(myData.d);
 Serial.print("Bool: ");
 Serial.println(myData.e);
 Serial.println();
}
void setup() {
 // Initialize 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("Error initializing ESP-NOW");
   return;
 }
 Serial.print(F("\nReciever initialized : "));
 Serial.println(WiFi.macAddress());
 // Define receive function
 esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
 esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
}

Quando carregar o código pela primeira vez, observe atentamente a mensagem de configuração que contém o endereço MAC do recetor. Deve introduzi-lo no código do transmissor para assegurar o emparelhamento e a comunicação com êxito.

Resultados

Uma vez definido o endereço MAC do cartão recetor e carregados os códigos em cada cartão, a comunicação é estabelecida e a estrutura é enviada e desencriptada corretamente.

Bónus: Comunicação bidirecional entre dois ESP8266

Já vimos como enviar dados de um cartão para outro utilizando o protocolo ESP-NOW. Vamos agora ver como, modificando ligeiramente os códigos, podemos obter uma comunicação bidirecional.

Código Transceiver

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

const char nom[10]="Master"; //or slave
uint8_t broadcastAddress[] = {0xDC, 0x4F, 0x22, 0x58, 0xD2, 0xF5};// REPLACE WITH OTHER STATION MAC ADDRESS

// Structure example to send data
// Must match the receiver structure
typedef struct struct_message {
  char a[32];
  int b;
  bool c;
} struct_message;
struct_message dataSent;
struct_message dataRcv;

unsigned long previousTime=0;

// callbacks for sending and receiving data
void OnDataSent(uint8_t *mac_addr, uint8_t status) {
  Serial.print("\r\n"+String(nom)+" packet sent:\t");
  Serial.println(status == 0 ? "Delivery Success" : "Delivery Fail");
}

void OnDataRecv(uint8_t * mac, uint8_t *incomingData, uint8_t len) {
  memcpy(&dataRcv, incomingData, sizeof(dataRcv));
  Serial.print("\r\nBytes received: ");
  Serial.println(len);
  Serial.print("From: ");
  Serial.println(dataRcv.a);
  Serial.print("Sensor: ");
  Serial.println(dataRcv.b);
  Serial.print("Status: ");
  Serial.println(dataRcv.c);
  Serial.println();
}
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_CONTROLLER); //ESP_NOW_ROLE_SLAVE if slave
  esp_now_register_send_cb(OnDataSent);
  esp_now_register_recv_cb(OnDataRecv);

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

void loop() {
  if((millis() -previousTime)>1000){
    // Set values to send
    strcpy(dataSent.a, nom);
    dataSent.b = random(100, 200);
    dataSent.c = false;
  
    // Send message via ESP-NOW
    uint8_t result = esp_now_send(broadcastAddress, (uint8_t *) &dataSent, sizeof(dataSent));
  
    previousTime=millis();
  }
}

N.B.: Para obter o mesmo código para o emissor e o recetor, utilizamos a mesma estrutura de dados para as mensagens enviadas e recebidas. É possível definir estruturas diferentes consoante a origem da mensagem. No entanto, é necessário ter em conta que o cartão recetor deve conhecer a estrutura da mensagem recebida para a poder decifrar.

Para passar de um código MASTEr para um código SLAVE, é necessário alterar o código:

  • nome do nome da estação[10] (Opcional)
  • argumento para a função esp_now_set_self_role
  • argumento para a função esp_now_add_peer

Resultados

Utilizando o mesmo código com algumas ligeiras modificações, é possível estabelecer uma comunicação bidirecional entre dois ESP8266.

Fontes

How useful was this post?

Click on a star to rate it!

Average rating 5 / 5. Vote count: 2

No votes so far! Be the first to rate this post.

As you found this post useful...

Follow us on social media!

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?