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.
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:
7 ComentĂĄrios
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!!!
ResponderExcluirOlĂĄ fernando, onde consigo esta biblioteca esp_now.h?
ResponderExcluirOlĂĄ, Lucas.
ExcluirNa 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
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.
ExcluirBoa tarde Fernando...
ResponderExcluirComo faço para adicionar um slave esp8266, tentei adicionar um outro nodemcu e/ou esp01 mas da erro ao compilar o código!
OlĂĄ Fernando, existe alguma biblioteca para esp32 equivalente a keyboard.h do arduino?
ResponderExcluirSeus 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