Recents in Beach


Receba o meu conteĂșdo GRATUITAMENTE


ESP-NOW: WiFi com 3x mais alcance


Utilizando o protocolo ESP-NOW para fazer pontes entre mĂșltiplos ESP32, chegamos a um WiFi com 3x mais alcance, ou seja, 480 metros de distĂąncia. Alcançamos essa rede sem fio de 2,4 GHz com as antenas embutidas do ESP32. No nosso projeto de hoje, portanto, um ESP32 irĂĄ fazer a leitura de um pino e enviar o valor para outro ESP32. Esse outro ESP32 irĂĄ receber este valor e alterar a saĂ­da do pino e enviar este valor para um prĂłximo ESP32. O prĂłximo ESP32 irĂĄ fazer a mesma coisa e repassar para o prĂłximo ESP32. Resumindo, montei um controle remoto com duas bridges (pontes) no meio.



Para este projeto, fizemos um software que envia os valores que selecionarmos para inĂșmeros ESP32. Nosso exemplo utiliza quatro chips, mas vocĂȘ pode utilizar quantos desejar, pois este protocolo Ă© muito rĂĄpido. Quero destacar que, este esquema nĂŁo Ă© para fazer link de internet, mas, sim, para automação, ou seja, para enviar bit de controle, mesmo embora esse protocolo seja bem mais rĂĄpido que LoRa.

ESP32 Pinout

Pinout do ESP32


Comunicação

Comunicação

Como vocĂȘ vĂȘ na imagem:
1Âș: Master faz a leitura do pino e envia.
2Âș: O prĂłximo ESP32, Slave 1, recebe, muda o valor do pino e envia para o prĂłximo.
3Âș: O prĂłximo ESP32, Slave 2, recebe, muda o valor do pino e envia para o prĂłximo.
4Âș: Por fim, o quarto ESP32, Slave 3, recebe e muda o valor do pino.

Esp32EspNowSendReceive.ino

Em primeiro lugar, nós vamos incluir as bibliotecas ESP-NOW e WiFi. Vamos ainda definir o pino 2 para fazer a leitura e envio do valor, bem como o canal 1 para a conexão. Aponto que, se o Master estiver definido, serå compilado o Master.ino. Do contrårio, serå compilado o Slave.ino. Por fim, crio um objeto que é o peer, o qual vai guardar o endereço.

//Libs do espnow e wifi
#include <esp_now.h>
#include <WiFi.h>

//Pino utilizado para leitura
//e que serĂĄ enviado o valor
#define PIN 2

//Canal usado para conexĂŁo
#define CHANNEL 1

//Se MASTER estiver definido 
//o compilador irĂĄ compilar o Master.ino
//Se quiser compilar o Slave.ino remova ou
//comente a linha abaixo
#define MASTER

//Estrutura com informaçÔes
//sobre o prĂłximo peer
esp_now_peer_info_t peer;

Esp32EspNowSendReceive.ino – modeStation

Aqui temos a função que inicializa o modo station. Expliquei bastante sobre esse assunto no ESP32 com protocolo ESP-NOW. Ainda nesta etapa, nĂłs mostramos no monitor serial o Mac Address do ESP quando em modo station.

//Função para inicializar o modo station
void modeStation(){
    //Colocamos o ESP em modo station
    WiFi.mode(WIFI_STA);
    //Mostramos no Monitor Serial o Mac Address 
    //deste ESP quando em modo station
    Serial.print("Mac Address in Station: "); 
    Serial.println(WiFi.macAddress());
}

Esp32EspNowSendReceive.ino - InitESPNow

Tratamos nesta parte do código sobre a função de inicialização do ESP-NOW.

//Função de inicialização do ESPNow
void InitESPNow() {
    //Se a inicialização foi bem sucedida
    if (esp_now_init() == ESP_OK) {
        Serial.println("ESPNow Init Success");
    }
    //Se houve erro na inicialização
    else {
        Serial.println("ESPNow Init Failed");
        ESP.restart();
    }
}

Esp32EspNowSendReceive.ino – addPeer

Através do endereço MAC, adicionamos aqui um novo peer. Além disso, informamos o canal e adicionamos também o slave.

//Função que adiciona um novo peer
//através de seu endereço MAC
void addPeer(uint8_t *peerMacAddress){
    //Informamos o canal
    peer.channel = CHANNEL;
    //0 para nĂŁo usar criptografia ou 1 para usar
    peer.encrypt = 0;
    //Copia o endereço do array para a estrutura
    memcpy(peer.peer_addr, peerMacAddress, 6);
    //Adiciona o slave
    esp_now_add_peer(&peer);
}

Esp32EspNowSendReceive.ino – send

Temos nesta parte a função que irå enviar o valor para o peer que tenha o MAC Address especificado. Trabalhamos com as possibilidades de envio bem sucedido e também de erro.

//Função que irå enviar o valor para 
//o peer que tenha o mac address especificado
void send(const uint8_t *value, uint8_t *peerMacAddress){
    esp_err_t result = esp_now_send(peerMacAddress, value, sizeof(value));
    Serial.print("Send Status: ");
    //Se o envio foi bem sucedido
    if (result == ESP_OK) {
        Serial.println("Success");
    }
    //Se aconteceu algum erro no envio
    else {
        Serial.println("Error");
    }
}

Master.ino

Aqui temos o #ifdef MASTER, que apenas irå compilar se o Master estiver definido na diretiva de compilação. Incluímos nesta parte o MAC Address para o qual enviaremos os dados.

//Apenas irĂĄ compilar se MASTER estiver definido
 #ifdef MASTER

//Mac Address do peer para o qual iremos enviar os dados
uint8_t peerMacAddress[] = {0x24, 0x0A, 0xC4, 0x0E, 0x3F, 0xD0};

Master.ino – setup

Vamos chamar as funçÔes de inicializam o modo station e o ESP-NOW, adicionar o peer, registrar o callback e executar a função onDataSent. Por fim, colocamos o pino em modo de leitura, a qual é feita e os dados enviados.

void setup() {
  Serial.begin(115200);

  //Chama a função que inicializa o modo station
  modeStation();

  //Chama a função que inicializa o ESPNow
  InitESPNow();

  //Adiciona o peer
  addPeer(peerMacAddress);

  //Registra o callback que nos informarĂĄ 
  //sobre o status do envio.
  //A função que serå executada é onDataSent
  //e estĂĄ declarada mais abaixo
  esp_now_register_send_cb(OnDataSent);
  
  //Colocamos o pino em modo de leitura
  pinMode(PIN, INPUT);

  //LĂȘ o valor do pino e envia
  readAndSend();
}

Master.ino - readAndSend

Temos aqui a readAndSend, que é a função responsåvel pela leitura do pino e o envio do valor para o peer.

//Função responsåvel pela
//leitura do pino e envio
//do valor para o peer
void readAndSend(){
  //LĂȘ o valor do pino
  uint8_t value = digitalRead(PIN);
  //Envia o valor para o peer
  send(&value, peerMacAddress);
}

Master.ino – OnDataSent

JĂĄ OnDataSent Ă© a função que serve de callback para nos avisar sobre a situação do envio que fizemos. Lembrando que, quando recebemos o resultado do Ășltimo envio jĂĄ podemos ler e enviar novamente.

//Função que serve de callback para nos avisar
//sobre a situação do envio que fizemos
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");

  //Quando recebemos o resultado do Ășltimo envio
  //jĂĄ podemos ler e enviar novamente
  readAndSend();
}

Master.ino – loop

No Loop, nĂŁo precisamos fazer nada, pois sempre que recebemos o feedback do envio atravĂ©s da função OnDataSent nĂłs enviamos os dados novamente, fazendo com que os dados estejam sempre sendo enviados em sequĂȘncia.

//NĂŁo precisamos fazer nada no loop
//pois sempre que recebemos o feedback
//do envio através da função OnDataSent
//nĂłs enviamos os dados novamente,
//fazendo com que os dados estejam sempre
//sendo enviados em sequĂȘncia
void loop() {
}
#endif

Slave.ino

Iniciando o cĂłdigo do Slave, destacamos que apenas irĂĄ compilar se Master nĂŁo estiver definido. No caso de compilarmos como Slave, temos, entĂŁo, o Mac Address do peer para o qual iremos enviar os dados.

//Apenas irĂĄ compilar se MASTER nĂŁo estiver definido
#ifndef MASTER

//Mac Address do peer para o qual iremos enviar os dados
uint8_t peerMacAddress[6] = {0x24, 0x0A, 0xC4, 0x0E, 0x46, 0xCC};

Slave.ino – setup

No Setup do Slave, novamente vamos chamar as funçÔes que inicializam o modo station e o ESP-NOW, adicionar o peer e registrar o callback. A novidade é que, desta vez, temos dois callbacks. Então, vamos executar a função onDataRecv, que informarå que recebemos os dados, bem como a função onDataSent, que informarå sobre o status do envio de dados. Por fim, colocamos o pino em modo de saída.

void setup() {
  Serial.begin(115200);

  //Chama a função que inicializa o modo station
  modeStation();

  //Chama a função que inicializa o ESPNow
  InitESPNow();

  //Adiciona o peer
  addPeer(peerMacAddress);

  //Registra o callback que nos informarĂĄ
  //que recebemos dados.
  //A função que serå executada
  //Ă© onDataRecv e estĂĄ declarada mais abaixo
  esp_now_register_recv_cb(onDataRecv);

  //Registra o callback que nos informarĂĄ 
  //sobre o status do envio.
  //A função que serå executada
  //Ă© onDataSent e estĂĄ declarada mais abaixo
  esp_now_register_send_cb(onDataSent);

  //Colocamos o pino como saĂ­da
  pinMode(PIN, OUTPUT);
}

Slave.ino – onDataRecv

Esta função onDataRecv serve de callback, sendo que, toda vez que houver o envio, ela vai chamar a função send(value, peerMacAddress);, isso para enviar o valor lido para o próximo ESP.

//Função que serve de callback para nos avisar
//que recebemos dados
void onDataRecv(const uint8_t *mac_addr, const uint8_t *value, int len) {
  //Coloca o valor recebido na saĂ­da do pino
  digitalWrite(PIN, *value);
  //Envia o valor lido para o prĂłximo esp
  //Se este for o Ășltimo, comente esta linha antes de compilar
  send(value, peerMacAddress);
}

Slave.ino – onDataSent

Jå esta função serve de callback para nos avisar sobre a situação do envio que fizemos.

//Função que serve de callback para nos avisar
//sobre a situação do envio que fizemos
void onDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
  Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Success" : "Fail");
}

Slave.ino – loop

Novamente, nĂŁo precisamos fazer nada no Loop, pois nĂłs enviamos os dados assim que recebemos do outro ESP pelo callback.

//NĂŁo precisamos fazer nada no loop
//nĂłs enviamos os dados assim que 
//recebemos do outro esp pelo callback
void loop() {
}
#endif




Faça o download dos arquivos:



Postar um comentĂĄrio

7 ComentĂĄrios

  1. Olå Fernando, estou curtindo muito os seus vídeos, gostaria de saber se é possível criar uma comunicação com os esp01 com rede MESH?....Parabéns pelos vídeos!!!

    ResponderExcluir
  2. OlĂĄ fernando, onde consigo esta biblioteca esp_now.h?

    ResponderExcluir
    Respostas
    1. OlĂĄ, Lucas.
      Na verdade, ela jĂĄ deveria vir quando se instala o ESP32 com o board manager do Arduino. Tecnicamente Ă© sĂł instalar isso que funciona.
      Sugiro para vocĂȘ este vĂ­deo “ESP32: Como instalar na IDE do Arduino”, que estĂĄ no link: https://youtu.be/_4igHlpnlLI
      Abraço

      Excluir
    2. Opå, uma pergunta, consigo utilizar o ESP_NOW com o ESP01? me parece que sim né? neste caso onde acho o esp_now.h? Obrigado e parabéns pelos videos.

      Excluir
  3. Boa tarde Fernando...
    Como faço para adicionar um slave esp8266, tentei adicionar um outro nodemcu e/ou esp01 mas da erro ao compilar o código!

    ResponderExcluir
  4. OlĂĄ Fernando, existe alguma biblioteca para esp32 equivalente a keyboard.h do arduino?

    ResponderExcluir
  5. Seus tutoriais me ajudam demais, sou muito agradecido pelos seus trabalhos. SĂł uma coisa, esses links dos arquivos estao inacessiveis ou com dificuldade de acesso, ta em HTTP sem criptografia, o chrome ou outros navegadores fica reclamando.. enfim se tiver outra forma de baixar serei eternamente grato! sugestĂŁo criar um GitHub.

    ResponderExcluir