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


18 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