🌐 Idioma / Language: Português Português English English Español Español

quinta-feira, 23 de janeiro de 2020

Controlando LEDs com dois ESP8266 utilizando Protocolo ESP-NOW


Olá a Todos!

No post de hoje, faremos a comunicação entre dois ESP8266, uma conexão direta sem roteadores executando a conexão, acionaremos duas cargas, que serão simuladas utilizando dois LEDs, e utilizaremos o protocolo de comunicação ESP-NOW. 

Essa protocolo foi desenvolvido pela fabricante chinesa ESPRESSIF. Esse protocolo tem sido bastante utilizado em muitos Gadgets como: Mouses sem fios, teclados sem fio, sensores de incêndios Wireless, controles remotos, etc. por ter uma conexão rápida e direta e com pouco consumo de energia.

Se você não conhece esse protocolo, ou deseja saber mais sobre ele, recomendamos a você dar uma olhadinha em nosso POST que explica o código detalhando por etapas e cada parte dos processos do código:

O que faremos é, utilizar a biblioteca espnow.h, sendo uma biblioteca desenvolvida para ESP8266, e o motivo é bastante simples, uma grande maioria de pessoas têm o ESP8266, e códigos utilizando a biblioteca espnow.h que é a biblioteca utilizada no ESP8266, são bastante difíceis.

O mais comum de se encontrar são códigos que utilizam a biblioteca esp-now.h biblioteca utilizada no ESP32, mas, a grande maioria ainda utiliza o ESP8266 assim como eu, tenho o ESP32, mas utilizo mais o ESP8266.

O que precisaremos!

  • Precisaremos ter instalado a biblioteca espnow.h na IDE Arduíno. Se você não o fez, ou estar em dúvidas se já está instalado, confere no nosso post, como instalar a biblioteca espnow.h na IDE Arduíno. 
  • 2 - ESP8266
  • 4 - LEDs “2 opcionais
  • 2 - Chave Micro-Switch
  • Protoboards, Fios rabichos, etc.

A montagem é bastante simples, teremos apenas dois LEDs no Circuito Receiver, e duas Micro-Chaves com Dois LEDs no Circuito Controle.

No Circuito Controle, os LEDs estão ligados nas GPIOs: D2 e D3, e as Micro-Chaves estão ligados nas GPIOs D1 e D4, você pode está modificando essas GPIOs, para o mais adequado em seu projeto, não fará diferença alguma se mudarmos, só não podemos esquecer de ligá-la na porta correta e modificar o código na (Sketch).

No Circuito Receiver, os LEDs estão ligados nas GPIOs: D0 e D1, como já mencionado acima, você pode também estar modificando conforme o seu projeto. Logo abaixo temos os dois códigos para completos para você poder acompanhar.

Código do Circuito Controle

//=================================================================================================//
// MASTER                                                                                          //
// Controlling LEDs with Two ESP8266 Uses ESP-NOW Protocol                                         //
// Edited and Adapted by: Engineer Jemerson Marques, On: 22.12.2019 - FVM Learning website         //
// Available at: https://www.fvml.com.br and on Youtube channel                                    //
// https://www.youtube.com/c/FVMLearning - I hope you have fun - Good luck                         //
//-------------------------------------------------------------------------------------------------//

#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
// This is the slave MAC Address which receives the data
 uint8_t mac[] = {0x5C, 0xCF, 0x7F, 0x4C, 0x82, 0x5C}; //AP MAC SLAVE'S ADDRESS

  #define WIFI_CHANNEL 4
  int prevstate_1 = LOW;
  int prevstate_2 = LOW;

// Data structure, must be the same for the slave

struct __attribute__((packed))DataStruct {
  char text[32];
};
    DataStruct button_1;
    DataStruct button_2;

//=====================================================================================================
void setup() {
  pinMode(D1, INPUT_PULLUP);
  pinMode(D4, INPUT_PULLUP);
  pinMode(D2, OUTPUT);
  pinMode(D3, OUTPUT);

  Serial.begin(115200); Serial.println();
  Serial.println("Starting EspnowController.ino");
  WiFi.mode(WIFI_STA); // Station mode for esp-now controller
  WiFi.disconnect();
  Serial.printf("This mac: %s, ", WiFi.macAddress().c_str());
  Serial.printf("slave mac: %02x%02x%02x%02x%02x%02x", mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
  Serial.printf(", channel: %i\n", WIFI_CHANNEL);
  if (esp_now_init() != 0)
  {
    Serial.println("*** ESP_Now initialization failed");
  }
  esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);
  esp_now_add_peer(mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);
  strcpy(button_1.text, "Button 01 pressed");
  strcpy(button_2.text, "Button 02 pressed");
  Serial.println("Setup finished");
}

//======================================================================================================

void loop() {
  sendData();
}

//======================================================================================================
void sendData() {

  int currentstate_1 = digitalRead(D4);
  if (prevstate_1 != currentstate_1) {
    if (currentstate_1 == LOW) {
      uint8_t bs[sizeof(button_1)];
      memcpy(bs, &button_1, sizeof(button_1));
      esp_now_send(mac, bs, sizeof(button_1));
      Serial.println(button_1.text);
      digitalWrite(D2, !digitalRead(D2));
    }
  } prevstate_1 = currentstate_1;

  int currentstate_2 = digitalRead(D1);
  if (prevstate_2 != currentstate_2) {
    if (currentstate_2 == LOW) {
      uint8_t bs[sizeof(button_2)];
      memcpy(bs, &button_2, sizeof(button_2));
      esp_now_send(mac, bs, sizeof(button_2));
      Serial.println(button_2.text);
      digitalWrite(D3, !digitalRead(D3));
    }
  } prevstate_2 = currentstate_2;
}

//========================================== www.fvml.com.br ===========================================

Código do Circuito Receiver

//=================================================================================================//
// SLAVE                                                                                          //
// Controlling LEDs with Two ESP8266 Uses ESP-NOW Protocol                                         //
// Edited and Adapted by: Engineer Jemerson Marques, On: 22.12.2019 - FVM Learning website         //
// Available at: https://www.fvml.com.br and on Youtube channel                                    //
// https://www.youtube.com/c/FVMLearning - I hope you have fun - Good luck                         //
//-------------------------------------------------------------------------------------------------//

#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>#include <user_interface.h>
}
 uint8_t mac[] = {0x5C, 0xCF, 0x7F, 0x4C, 0x82, 0x5C}; //AP MAC SLAVE'S ADDRESS

//=====================================================================================================
  int Led1 = D0;
  int Led2 = D1;

void initVariant() {
  WiFi.mode(WIFI_AP);
  wifi_set_macaddr(SOFTAP_IF, &mac[0]);
}

//=====================================================================================================

#define WIFI_CHANNEL 4
// Must match the controller structstruct __attribute__((packed))DataStruct {
  char text[32];
unsigned int time;};

DataStruct receivedData;
//=====================================================================================================
void setup() {
  Serial.begin(115200); Serial.println();
  Serial.println("Starting EspnowSlave.ino");  Serial.print("This node AP mac: "); Serial.println(WiFi.softAPmacAddress());  Serial.print("This node STA mac: "); Serial.println(WiFi.macAddress());  pinMode(Led1, OUTPUT);
  pinMode(Led2, OUTPUT);

  if (esp_now_init() != 0){
    Serial.println("*** ESP_Now init failed");    while (true) {};
  }
  esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);
  esp_now_register_recv_cb(receiveCallBackFunction);
  Serial.println("End of setup - waiting for messages");}

//======================================================================================================

void loop() {
}

//======================================================================================================
void receiveCallBackFunction(uint8_t *senderMac, uint8_t *incomingData, uint8_t len) {
  memcpy(&receivedData, incomingData, sizeof(receivedData));

  String DataCompare = String(receivedData.text);

  if(DataCompare == "Button 01 pressed"){
  digitalWrite(Led1, !digitalRead(Led1));
  Serial.println(" Message = " + DataCompare);
 }
  if(DataCompare == "Button 02 pressed"){
  digitalWrite(Led2, !digitalRead(Led2));
  Serial.println(" Message = " + DataCompare);
   
  }
}

//========================================== www.fvml.com.br ===========================================
Logo abaixo temos um link com os arquivos dos códigos do Circuito Controle como do Circuito Receiver

Recomendamos você baixar e não copiar no código acima, pois pode vir com algum erro de acentuação ou qualquer outra coisa, então disponibilizamos o link para baixar.

Clique no Link Abaixo Para Descarregar os arquivos:

 

Você pode também está acompanhando esse post em nosso canal do YouTube, é uma forma de você acompanhar o funcionamento do mesmo.

Pessoal, o trabalho é grande, escrever, montar, testar, elaborar a PCI, armazenar para baixar, tudo isso dá muito trabalho, e nada cobramos por isso!

Então nos ajude a divulgar nosso trabalho, compartilha nas redes sociais, Facebook, Instagram, nos grupos de WhatsAppuma simples atitude sua, faz com que cresçamos juntos e melhoremos o nosso trabalho!

E por hoje é só, espero que tenham gostado!

Qualquer dúvida, digita nos comentários que logos estaremos respondendo.

Se inscreva no nosso BlogClique Aqui — FVM Learning!

Forte abraço.

Deus vos Abençoe
Shalom!

26 comentários:

Eder disse...

Muito obrigado amigo pelos ótimos videos, poderia fazer videos com o esp32. Ensine a enviar dados do Esp32 para nuvem e visualizar através de um site como o Thingspeak ou Ubdots por exemplo.

FVML disse...

Olá @EDER
Aos poucos estaremos iniciando vários projetos com o ESP32, estamos nos organizando.
Forte abraço.

Unknown disse...

é vc ja fez videos melhores .... Pecou muito na falta de explicação da esquematica de montagem... falto desenhos ilustrativos para quem não manja bem de eletrônica.
mais lendo o codigo da pra saber como ligar...

FVML disse...

Olá!!!!
Na verdade você mesmo já respondeu sua própria indagação.
Você conseguiu ler o código e saber as portas utilizadas.
Na verdade, é que quem está a fazer projetos com ESPs, tem no mínimo o conhecimento básico de eletrônica, e as ligações só são leds GND + PORTA. Bastante simples, por isso não vimos necessidade de colocar algum "Diagrama esquemático", mas... absorvemos o seu questionamento, e nas próximas iremos colocar um diagrama esquemático.
Obrigado pelo se comentário.
Forte abraço.

manuela disse...

ola ;muito bom este seu video .
parabéns pela pagina muito bons exemplos .
entretanto estou a tentar fazer como o emissor deste circuito mande o sinal dos botes para mais de um salve mas não estou conseguindo .
será que me pode dar umas luzes .

Unknown disse...

ola,já consegui modificar o código de maneira a dar para comunicar com vários esp .
depois se alguém precisar e só pedir .
mas tenho estado a tentar modificar também o código de forma a que esse funcione de modo pus_boton , ou seja que em vez de mudar o estados do rele que o faça ligar e logo depois desligar tipo como o botão das campainhas .
mais um vez obrigado pelo bom trabalho .

FVML disse...

Olá @MANUELA
Na verdade é bastante simples, você pode está utilizando mais de que um "receptor", o que precisas fazer é identificar o Mac Address e colocar no MASTER, para que ele envie o comando para o ESP que você deseja.
Exemplo:
Na função SendData();
Temos os dois botões que envia o comando para o ESP RECEIVER com o seu MAC Address.
Nessa função abaixo, você pode está direcionando para o ESP que você queira.
EXEMPLO:
Botão 1 envia para MAC1
esp_now_send(mac1, bs, sizeof(button_1));

Botão 2 envia para MAC2
esp_now_send(mac2, bs, sizeof(button_2));

E assim sucessivamente.

Abraços.

FVML disse...

Olá!!!
Na verdade é bastante simples você fazer isso, podes está alterando nessa função.

void receiveCallBackFunction(uint8_t *senderMac, uint8_t *incomingData, uint8_t len) {
memcpy(&receivedData, incomingData, sizeof(receivedData));

String DataCompare = String(receivedData.text);

AQUI VOCÊ PODE ESTAR MUDANDO O COMPARADOR:

if(DataCompare == "Button 01 pressed"){
digitalWrite(Led1, HIGH);
} else{ digitalWrite(Led1, LOW);

Serial.println(" Message = " + DataCompare);
}
if(DataCompare == "Button 02 pressed"){
digitalWrite(Led2, !digitalRead(Led2));
Serial.println(" Message = " + DataCompare);

}
}

Simples assim, lembrando a mudança só foi feita na chave um, verás que a dois ficará normalmente, se queres mudar faça o mesmo procedimento.
Abraço.

Unknown disse...

Obrigado logo que poder vou testar

Unknown disse...

ola mais uma vez.
será possível fazer um pequeno projecto deste mais em que o esp funcione em modo wifi e modo esp_now abordar este assunto seria muito bom para todos nos alem de ser um magnifico material para se falar e estudar .

FVML disse...

Olá!!!
É um ótimo tema para ser abordado...
No entanto, estamos com pouquíssimo tempo para executar projetos, então... sua sujestão está anotada.
Obrigado por estar conosco, aproveita e se inscreve em nosso canal do Youtube e aqui em nosso blog, isso nos ajuda bastante a darmos prosseguimento ao nosso trabalho, e não custa nada a você...
Forte abraço.

FVML disse...

Olá!!!
Por nada!!!
Obrigado por estar conosco, aproveita e se inscreve em nosso canal do Youtube e aqui em nosso blog, isso nos ajuda bastante a darmos prosseguimento ao nosso trabalho, e não lhe custa nada.
Forte abraço.

Milutin disse...

Olá e obrigado pelo exemplo fenomenal.
Eu uso o Google Tradutor, espero que possamos concordar.
Não posso usar este exemplo modificado, quando pressiono a tecla, ela permanece alta e não consigo quebrá-la.
p.s. no Código do Control quando inseri delay () para uma operação mais precisa e sem erros.

grandes cumprimentos e obrigado

Milutin disse...

Поздрав и хвала на феноменалном примеру.
Користим Гоогле Транслате, надам се да се можемо сложити.
Не могу да користим овај измењени пример, када притиснем тастер, он остаје висок и не могу да га прекинем.
пс у контролном коду када сам унео кашњење () за тачнији и безгрешан рад.

велики поздрав и хвала вам

Olgorofi disse...

Oi pessoal. Parabens pelo projeto.
Para o ESP8266-01 tive que alterar o sketch como segue:

MASTER
void setup() {
pinMode(0, INPUT_PULLUP);//antes era D1 agora GPIO 0//
pinMode(2, INPUT_PULLUP);//antes era D4 agora GPIO 2//
//pinMode(D2, OUTPUT); /OCULTEI ESTA LINHA//
//pinMode(D3, OUTPUT); //OCULTEI ESTA LINHA//

//==========MUDADO NA PROXIMA SUB ROTINA=========

void sendData() {
int currentstate_1 = digitalRead(2); // ERA (D4)//
if (prevstate_1 != currentstate_1) {
if (currentstate_1 == LOW) {
uint8_t bs[sizeof(button_1)];
memcpy(bs, &button_1, sizeof(button_1));
esp_now_send(mac, bs, sizeof(button_1));
Serial.println(button_1.text);
//digitalWrite(D2, !digitalRead(D2));// OCULTEI ESTA LINHA
}
} prevstate_1 = currentstate_1;

int currentstate_2 = digitalRead(0); // ERA (D1)//
if (prevstate_2 != currentstate_2) {
if (currentstate_2 == LOW) {
uint8_t bs[sizeof(button_2)];
memcpy(bs, &button_2, sizeof(button_2));
esp_now_send(mac, bs, sizeof(button_2));
Serial.println(button_2.text);
//digitalWrite(D3, !digitalRead(D3));// OCULTEI ESTA LINHA
}
} prevstate_2 = currentstate_2;
}

====================NO SLAVE (RECEPTOR)========================

Nas definições inciais mudei o seguinte:


int Led1=0; // TROQUEI O D0 por 0 //
int Led2=2; //TROQUEI O D1 por 2 //

Testei e funcionou .
Boa sorte a todos.


FVML disse...

Olá @MILUTIN
Obrigado pelo comentário.
Na verdade ele já está dessa maneira, quando pressionamos a tecla, o LED fica em ALTA, e quando pressionamos novamente ele fica em BAIXA.
Se queres fazer de forma inversa. Podes está mudando no: void receiveCallBackFunction
Nessa parte aqui:

if(DataCompare == "Button 01 pressed"){
digitalWrite(Led1, HIGH);
Serial.println(" Message = " + DataCompare);
}
if(DataCompare == "Button 02 pressed"){
digitalWrite(Led2, HIGH);
Serial.println(" Message = " + DataCompare);

}

Nesse caso, o LED só acende enquanto o botão estiver pressionando.
Espero que seja isso o que você quer.
Forte abraço.

FVML disse...

Olá @MILUTIN
Obrigado pelo comentário.
Na verdade ele já está dessa maneira, quando pressionamos a tecla, o LED fica em ALTA, e quando pressionamos novamente ele fica em BAIXA.
Se queres fazer de forma inversa. Podes está mudando no: void receiveCallBackFunction
Nessa parte aqui:

if(DataCompare == "Button 01 pressed"){
digitalWrite(Led1, HIGH);
Serial.println(" Message = " + DataCompare);
}
if(DataCompare == "Button 02 pressed"){
digitalWrite(Led2, HIGH);
Serial.println(" Message = " + DataCompare);

}

Nesse caso, o LED só acende enquanto o botão estiver pressionando.
Espero que seja isso o que você quer.
Forte abraço.

FVML disse...

Olá @Olgorofi
Muitíssimo obrigado...
Que ótimo... e obrigado pelo FeedBack, é assim que nossa comunidade de código livre cresce, estamos sempre progredindo por esse motivo, compartilhamento de informações.
Forte abraço.

Unknown disse...

Boa noite, gostaria de saber se tem como enviar um sinal do slave para o master, por exemplo: um botão no slave que acende um led no master. obrigado

Unknown disse...

Olá Jemerson, parabens pelo video. Contudo gostaria de orientações sobre como utilizar as mesmas rotinas no ESP32. Pois inicialmente modifiquei os esp_now e o wifi.h contudo ainda me da alguns erros referentes ao esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER), teria como ajudar? Obrigado e Shalom!

Liebson Henrique disse...

Olá, poderia dizer onde encontro a biblioteca espnow.h por favor ?

DorDalma disse...

Hello @MILUTIN
Thanks for the comment.
In fact it is already that way, when we press the key, the LED is HIGH, and when we press it again it is LOW.
If you want to do it the other way around. Podes is changing at: void receiveCallBackFunction
In this part here:

if (DataCompare == "Button 01 pressed") {
digitalWrite (Led1, HIGH);
Serial.println ("Message =" + DataCompare);
}
if (DataCompare == "Button 02 pressed") {
digitalWrite (Led2, HIGH);
Serial.println ("Message =" + DataCompare);

}

In this case, the LED only lights up while the button is pressing.
I hope this is what you want.
Strong hug.

//////////////////////////


Still Led is being turned on when button is pressed. Any other work around needed to work this as a pull up led from reciver side

Gustavo disse...

Primeiro lugar parabéns pelo conteúdo aliás usei seu projeto em partes de um projeto que estou fazendo, sou novo com esp e tenho uma dúvida , no caso o master sempre faz a leitura de um pino e assim executa no slave mais no meu caso eu não preciso dessa leitura de pino que é feita no master eu preciso mandar uma informação pro slave acionar uma determinada carga mais só depois de um temporizador que está no master, queria saber como faço isso. Obrigado e forte abraço

marcio0408 disse...

Professor por favor da uma "luz" para usar esse código com ESP32.

E disse...

hello everyone, best regards, esp8266 now I want to make a transceiver that works like RF with 4 channel relay outputs with protocol, can you help me?

E disse...

hello everyone, best regards, esp8266 now I want to make a transceiver that works like RF with 4 channel relay outputs with protocol, can you help me?


pinteres ESP to ESP Communication