FVM Learning

Nosso maior compromisso é compartilhar conhecimentos, somos simples mas não simplórios, astuto mas não pacóvio, nos posicionamos empenhados em mostrar o caminho para desmistificação do opróbrio em legítima defesa do conhecimento compartilhado. Eng. Jemerson Marques.

quinta-feira, 23 de janeiro de 2020

Controlando LEDs com dois ESP8266 utilizando Protocolo ESP-NOW

ESP-NOW - Controlando LEDs com dois ESP8266 utilizando Protocolo ESP-NOW

Olá a Todos!!!

No post de hoje, iremos fazer a comunicação entre dois ESP8266, uma conexão direta sem roteadores executando a conexão, iremos acionar duas cargas, que serão simuladas utilizando dois LEDs, 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 à 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 é ESP-NOW - E como Funciona? - Código exemplo explicado!!!

O que iremos fazer é, utilizar a biblioteca espnow.h, que é uma biblioteca desenvolvida para ESP8266, e o motivo é bastante simples, uma grande maioria de pessoas teem 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 utilizam o ESP8266 assim como eu, tenho o ESP32, mas utilizo mais o ESP8266.

O que vamos precisar

  • 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, ficando teremos apenas dois LEDs no Receiver, e duas Chaves com Dois LEDs no Controle.
No Controle, os LEDs estão ligados nas GPIOs: D2 e D3, e as MicroSwitchs estão ligados nas GPIOs D1 e D4, você pode está modificando essas GPIOs, para o que mais se adeque em seu projeto, não vai fazer diferença alguma se mudarmos, só não podemos esquecer de ligá-la na porta correta e modificar na Sketch.
No Receiver, os LEDs estão ligados nas GPIOs: D0 e D1, como já mencionado acima, você pode também estar modificando diacordo com o seu projeto. Logo abaixo temos os dois códigos para completos para você poder acompanhar.

Código do 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 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 Controle como do Receiver, nós aconselhamos a 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.

Click no Botão abaixo para baixar os arquivos: 

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


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

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

Se inscreva no nosso Blog!!! Click Aqui FVM Learning!!!

Forte abraço.

Deus vos Abençoe

Shalom


26 comentários:

  1. 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.

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

    ResponderExcluir
  3. é 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...

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  4. 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 .

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  5. 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 .

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  6. Obrigado logo que poder vou testar

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  7. 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 .

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  8. 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

    ResponderExcluir
    Respostas
    1. 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.

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

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

    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  10. 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.


    ResponderExcluir
    Respostas
    1. 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.

      Excluir
  11. 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

    ResponderExcluir
    Respostas
    1. Olá!!!
      O protoclo ESP NOW, não tem "master" "slave" eles podem ser ambos ao mesmo tempo, por esse motivo podemos sim, temos aqui em nosso site e no nosso canal do youtube um projeto desse jeito, pelo qual o "master" envia sinais para o "slave" e vice-versa.
      Obrigado por estar conosco!!!
      Lhes convido a se inscrever também em nosso canal no YouTube, isso nos ajuda bastante a darmos prosseguimento ao nosso trabalho, e não lhes custa nada, não é? https://www.youtube.com/channel/UCnaAKKkyhX7LY2ZYIff-qug
      Forte abraço.

      Excluir
  12. 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!

    ResponderExcluir
    Respostas
    1. Olá!!!
      O ESP32 tem um protocolo diferente, não são iguais, para o ESP8266 utilizamos a biblioteca espnow.h, e para o ESP32, utilizamos a biblioteca ESP-NOW.h, eles tem fundamentos diferentes em seus códigos, não podemos utilizar a mesma estrutura de código para ambos.
      Obrigado por estar conosco!!!
      Lhes convido a se inscrever também em nosso canal no YouTube, isso nos ajuda bastante a darmos prosseguimento ao nosso trabalho, e não lhes custa nada, não é? https://www.youtube.com/channel/UCnaAKKkyhX7LY2ZYIff-qug
      Forte abraço.

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

    ResponderExcluir
    Respostas
    1. Olá @LIEBSON HENRIQUE
      A biblioteca espnow.h, já vem instalada na IDE Arduíno mais atuais, veja se a sua IDE é a mais atualizada, depois nos dê o feedback.
      Obrigado por estar conosco!!!
      Lhes convido a se inscrever também em nosso canal no YouTube, isso nos ajuda bastante a darmos prosseguimento ao nosso trabalho, e não lhes custa nada, não é? https://www.youtube.com/channel/UCnaAKKkyhX7LY2ZYIff-qug
      Forte abraço.

      Excluir
  14. 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

    ResponderExcluir
    Respostas
    1. Hello @DORDALMA
      Thank you for your "translation" cooperation.
      Thank you for being with us !!!
      I invite you to subscribe to our YouTube channel as well, it helps us a lot to continue our work, and it doesn't cost them anything, does it? https://www.youtube.com/channel/UCnaAKKkyhX7LY2ZYIff-qug
      My best regard.

      Excluir