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.
Mostrando postagens com marcador Embarcados. Mostrar todas as postagens
Mostrando postagens com marcador Embarcados. Mostrar todas as postagens

domingo, 21 de junho de 2020

Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs + PCI

Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs + PCI

Olá a Todos!!!

Hoje em dia, todos nós estamos envolvidos com circuitos de automação, disparos remoto, controle de cargas remotamente e etc, e sempre utilizamos o velho e conhecido Relê, seja ele Relê de contato, utilizando bobinas com contatos de fechamento metálico, ou com os mais avançados "caros" Relê de Estado Sólidos, mas para controlar uma carga de potência em 220V, com níveis de controle diferentes com o seu microcontrolador isolado da rede de energia, podemos dizer que não é tão simples de encontrar um módulo para dimerização e controle de carga controlado por Microcontroladores com um custo baixo. Foi pensando nisso que estamos a apresentar esse pequeno circuito que pode controlar eficientemente a; luminosidade de uma lâmpada incandescente,  velocidade de um motor elétrico, temperatura de uma estufa, secador de cabelos ou qualquer outro eletrodoméstico elétrico que pode ser controlado através de um dimmer. Todo esse controle se dar ao uso de um microcontrolador que pode ser um ESP8266, ESP32, Arduíno, PIC ou qualquer outro Microcontrolador que você tiver utilizando, que controla o módulo de potência baseado em um TRIAC
O TRIAC é acionado através de um DIAC que conduz à partir de uma tensão de 28V, ele é quem controla o ângulo de condução do TRIAC, disparando-o em diversos pontos do sinal senoidal da rede de energia sendo assim possível aplicar potências diferentes na carga controlada.
Para controlar o disparo do TRIAC, é usado um circuito RC, de maneira que a modificação dessa resistência, dispara o TRIAC em pontos de semiciclos de energia da rede. 
Para conseguirmos modificarmos a resistência controlando por um Microcontrolador, implementamos um divisor somador com 3 resistores diferentes que são conectados através de um opto-acoplador, e é através desse conjunto de resistores que formamos o Req pelo qual podemos controlar o circuito RC de retardo onde Req setada no máximo valor, o tempo de carga de C1 até o disparo do DIAC é maior, pela qual ocorre um tempo maior do semiciclo da energia da rede fazendo com que a carga tenha uma menor potência, já com Req na posição mínimo a carga de C1 é rápida e o disparo do DIAC ocorre no início do semiciclo, tornando a potência da carga no máximo, sendo assim, podemos controlar a potência máxima e mínima na carga. E vale salientar que quando utilizamos esse circuito para controlar motores, ele corta uma parte do semiciclo, mantendo a tensão em 220V, o que significa que o torque de um motor se mantém mesmo sendo controlado em baixa velocidade, o que o assemelha ao motor DC controlado por PWM.

Na figura 2, temos o diagrama esquemático do circuito de Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs com TRIAC TIC246, utilizamos 3 portas digitais do Arduíno, D9, D10, D11 para controlar o circuito de potência, foi utilizado resistores em série para controle de corrente no entre a saída digital do Arduíno (5V), e o Opto-acoplador, que utiliza um LED Infra-vermelho interiormente, e sabemos que se aplicarmos uma tensão de 5V direto no LED, ele irá queimar. O Opto-acoplador que utilizamos foi um MOC3021, mas, você pode está substituindo pelos  MOC3020, MOC3021, MOC3022, MOC3023, OPI3020, OPI3021, OPI3022, OPI3023, MCP3020, MCP3021, MCP3022, GE3020, GE3021, GE3022, GE3023, todos são compatíveis.
Fig. 2 - Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs
As séries de Opto-acopladores MOCs são dispositivos de driver TRIAC isolados opticamente. Esses dispositivos contêm um diodo emissor de infravermelho GaAs e um comutador bilateral de silício ativado por luz, que funciona como um TRIAC. Eles são projetados para interface entre controles eletrônicos e TRIACs de potência para controlar cargas resistivas e indutivas para operações de 115 ou 220 VCA.
E é através desse fechamento que conseguimos diminuir a resistência que colocamos em seus terminais, e baixamos a queda de tensão que ocorre através dessa resistência e assim, aumentamos a carga em C1, e o disparo do DIAC ocorre no início do semiciclo, aumentando a potência da carga.

Por utilizarmos 3 resistores em série/ponte, conseguimos 8 combinações de resistências diferentes, e na figura 3 temos a tabela para verdade para seguirmos e podermos programar as combinações sequenciadas nas portas do Arduíno.

Fig 3 - Tabela Verdade Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs
A potência total da carga que podemos colocar em nosso circuito, só dependerá unicamente do tipo de TRIAC que você vai utilizar, em nossa montagem, fizemos com o TIC246, por ser um TRIAC que suporta até 16 Amperes, o que é uma carga muitíssimo grande, se falamos de carga residencial, no entanto existem diversos tipos de TRIACs para ser utiliazdos, deixamos alguns dos mais conhecidos e fácil de se encontrar no mercado para você poder utilizar de acordo com o seu projeto: TIC116 para 6A, TIC226 ou BT137 para 8A, TIC236 para 12A, TIC246 para 16A.

Lista de Materiais

T1 -------------------------- Triac de Potência TIC246D ou substituto *ver texto*
D1 -------------------------- Diodos DIAC DB3 ou substituto
D4 -------------------------- Ponte retificadora KBPC5010 - 100V, 50A
U1, U2, U3 --------------- Opto-acoplador MOC3021 ou substituto *ver texto*
R1 -------------------------- Resistor 47Ω 1/4W  (amarelo, violeta, preto)
R2 -------------------------- Resistor 6.8KΩ 1/4W  (verde, cinza, vermelho)
R3 -------------------------- Resistor 47KΩ 1/4W  (amarelo, violeta, laranja)
R4 -------------------------- Resistor 100KΩ 1/4W  (marrom, preto, amarelo)
R5 -------------------------- Resistor 220KΩ 1/4W  (vermelho, vermelho, amarelo)
C1 -------------------------- Capacitor Poliéster / Cerâmico 0.22uF ou 220nF
C2 -------------------------- Capacitor Poliéster / Cerâmico 0.12uF ou 120nF
J1 --------------------------- Conector Barra Macho 4 pinos
P1, P2 ---------------------- Terminal Kre Block Borne Conector Duplo 2 Vias
Diversos ------------------- Placa Circuito Impresso, estanho, fios, etc.

Download:

Estamos dispondo para Download o link com os arquivos para impressão da placa de circuito impresso, são eles: Gerber, PDF layout, webp, tudo isso com link direto para o Mega.
Fig 4 - PCI - Controle de potência de carga 110/220Vac. Controlado por: ESPs Arduínos ou PICs

Link Direto: Arquivos, Layout PCB, PDF, GERBER

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

terça-feira, 28 de abril de 2020

Como saber, obter, pegar o MAC Address do NodeMCU ESP8266 e ESP32 na IDE Arduíno

Como saber, obter, pegar o MAC Address do NodeMCU ESP8266 e ESP32 na IDE Arduíno

Olá a Todos!!!


No Post de hoje, faremos um guia rápido de como saber, obter, pegar, o endereço MAC do NodeMCU ESP8266 ou ESP32 utilizando a IDE Arduíno. 
O endereço MAC "Media Access Control" ou (Controle de Acesso de Mídia) que muitas vezes é entendido por ""Machine Access Control" ou (Controle de Acesso a Máquinas), isso quando referido a maquinas mesmo, eles são endereços de hardware exclusivo que identificam um adaptador de rede, sendo assim jamais teremos dois dispositivos com mesmo Endereço MAC.
O endereço MAC é formado por um conjunto de 6 bytes, sendo cada byte representado por dois algarismos na forma hexadecimal, como por exemplo: "00:38:0F:2V:5M:7L".

O código

O código é bastante simples, inicializa incluindo a biblioteca ESP8266WiFi.h.
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>#include <user_interface.h>
}

Que é a biblioteca que ativa o módulo WiFi, seguido da inclusão da biblioteca espnow.h, com a diretriz de encaminhamento extern "C", que informa ao software o caminho para a biblioteca do ESP8266 ou ESP32.

Depois já se entra no void setup.
void setup() {
  Serial.begin(115200); Serial.println();
  Serial.println("Starting fvm learning, get mac address");
Iniciamos o Serial com a função Serial.begin(115200), decorrido da velocidade do Bounce da comunicação entre o módulo e o computador na porta serial. Depois já imprimimos uma mensagem vazia, só para pular uma linha, logo após, imprimimos a mensagem de inicialização, "Inicializando o fvm leaning, obter endereço mac".

Logo esse código imprime dois tipos de Endereços Mac, O Mac Address AP "Access Point"  e o Mac Address STA "Station".
  Serial.print("This node AP mac: ");   Serial.println(WiFi.softAPmacAddress());  Serial.print("This node STA mac: ");   Serial.println(WiFi.macAddress());}

E fechamos aqui todo o código, pois como podemos visualizar, no void loop, não ha atividades alguma.
void loop() {

}
Logo abaixo temos todo o código, não ha necessidade de fazer-se nenhuma mudança, é só você copiar o código abaixo e colar na sua IDE Arduíno, ou se preferir, você pode estar baixando pelo link de Download logo abaixo do código, "Recomendável".
//==================================================================================//
// Getting Mac Address from NodeMCU ESP8266 on IDE Arduino                          //
// Created by: Engineer Jemerson Marques, On: 21.01.2019 - FVM Learning website     //
// Available at: https://www.fvml.com.br                                            //
// 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>
}

//===================================================================================
void setup() {
  Serial.begin(115200); Serial.println();
  Serial.println("Starting fvm learning get mac address");  Serial.print("This node AP mac: ");   Serial.println(WiFi.softAPmacAddress());  Serial.print("This node STA mac: ");   Serial.println(WiFi.macAddress());}

//===================================================================================
void loop() {

}
//================================ www.fvml.com.br ===================================
Muitas vezes quando copiamos o código direto do navegador, ocorre troca de caracteres, dando assim erros no código, por isso recomendamos e disponibilizamos um link direto para baixar.

Click no Botão abaixo para baixar os arquivos: 


Logo depois de ter baixado, abra o código baixado na sua IDE Arduíno, coloque o cabo USB do NodeMCU no seu computador, sete a porta que você colocou, e faça o Upload do código.
Quando o upload do código terminar, abra o Serial Monitor e lá você irá encontrar os Endereços Mac do seu NodeMCU ESP8266 ou ESP32

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

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


segunda-feira, 13 de janeiro de 2020

O que é ESP-NOW - E como Funciona? - Código exemplo explicado!!!

O que é ESP-NOW - E como Funciona? Código exemplo explicado!!!

Olá a Todos!!!

No Post de hoje, iremos abordar um assunto de suma importância para quem trabalha, desenvolve, ou projeta circuitos para automação e controle IoT da vida... Iremos entender melhor o Protocolo ESP-NOW. Para quem já está no contexto, sabe que existem vários tipos de protocolos abordados sobre os ESPs, seja ESP32ESP8266 ou ESP8285
O ESP-NOW é mais um protocolo desenvolvido pela empresa Chinesa Espressif Sistemas, e permite que vários dispositivos se comuniquem entre si sem utilizar a rede Wi-Fi padrão. 

O ESP-NOW permite um controle direto e de baixa latência, menor que 10ms, podendo controlar vários dispositivos inteligentes tais como, luzes, dispositivos remotos, controles sem fios e etc, sem a necessidade de conexão com um roteador. Este método é eficiente em termos de economia de energia e conveniente para ser utilizado em dispositivos que trabalhe com pilhas ou baterias, como controles remotos, sensores de incêndio wireless, joystick sem fio e etc.
O protocolo é semelhante à conectividade sem fio de baixa potência de 2,4 GHz que é frequentemente implantada em mouses e teclados sem fio. Assim, o emparelhamento entre dispositivos é necessário antes de sua comunicação. Após o emparelhamento, a conexão é segura e ponto-a-ponto, sem necessidade de uma rede de apoio, e com uma velocidade de conexão surpreendentemente rápida. 
Com o protocolo ESP-Now, o usuário pode implementar dispositivos controladores de baixíssima energia para se comunicar com dispositivos clientes; tais dispositivos de controle podem ter duração de bateria dependendo do tipo de uso de vários anos.

O que é o Protocolo ESP-NOW

O protocolo ESP-NOW é um protocolo de comunicação M2M (Machine To Machine) ou seja, é a comunicação entre ESPs8266 (mestre e esclavo) ou mesmo, ambos os seguimentos, devido ao protocolo ESP-NOW ter também os modos de Mestre/Escravo cujo o dispositivo podem se tornar mestre e escravo ao mesmo tempo, que interagem entre si, podendo responderem ambos comandos enviados por outro ESP, e ainda podendo responder não só ponto à ponto, mas, um ESP Mestre/Escravo pode responder ou enviar comandos para outros ESPs escravos, mestres, ou mestre/escravo.

Recursos do protocolo ESP-NOW

  • Comunicação Uni-cast criptografada e não criptografada.
  • Dispositivos pares criptografados e não criptografados.
  • Carga útil de até 250 bytes.
  • A função de retorno de chamada de envio que pode ser configurada para informar a camada de aplicação o sucesso ou falha na transmissão.

Limitações do protocolo ESP-NOW

  • Não Suporta BroadCast
  • Pares criptografados limitados.
  • No máximo 10 pares criptografados são suportados no modo Station; 6 no máximo no modo SoftAP ou SoftAP + Station. Vários pares não criptografados são suportados, no entanto, seu número total deve ser menor que 20, incluindo pares criptografados.
  • A carga útil é limitada a 250 bytes.

Como funciona o protocolo ESP-NOW

O funciona com um protocolo de comunicação WI-FI sem conexão, definido pelo Espressif. No ESP-NOW, os dados do aplicativo são encapsulados em um quadro de ação específico do fornecedor e depois transmitidos de um dispositivo WI-FI para outro sem conexão. A CTR com o protocolo CBC-MAC (CCMP) é usada para proteger o quadro de ação por segurança.
Iremos exemplificar o funcionamento do protocolo ESP-NOW dando um exemplo de comunicação básico, nesse exemplo iremos utilizar um par de NodeMCU ESP8266 pelo qual iremos enviar dados para um outro NodeMCU ESP8266, e iremos explicar o código por partes para que possamos entender melhor o funcionamento dessa comunicação.
Começaremos pelo biblioteca espnow.h que será utilizada para estabelecer a comunicação entre os ESP8266, será essa biblioteca que iremos utilizar em nosso exemplo, as funções intrínsecas na biblioteca espnow.h utilizados para execução das comunicações são bastante abrangentes, no entanto iremos centralizar nas principais funções seguindo um exemplo de comunicação entre dois NodeMCU, que irá estabelecer uma comunicação entre eles e um dos ESP8266 irá acionar um botão e o outro receberá essa informação e irá acender o LED.

Inicializando ESP-NOW

O primeiro passo para fazer essa comunicação entre os ESPs8266 é inicializar a biblioteca, existem duas bibliotecas mais conhecidas desenvolvidas para ESPs, a primeira é a biblioteca: esp_now.h, que é uma biblioteca desenvolvida para ser utilizada com ESP32. e a outra é biblioteca espnow.h, essa é uma biblioteca desenvolvida para ser utilizada com o ESP8266 e é a biblioteca que iremos utilizar em nosso exemplo.

Código ESP-NOW do "Master"

O termo utilizado "Master" na verdade é uma atribuição que fazemos para determinar qual será o ESP que irá "comandar" digo "entre aspas" pois todos os ESPs estão em modo STA "Station", que nesse caso ambos podem ser "Master" não ha distinção entre ambos, então utilizamos a atribuição só para termos base e entendermos melhor os códigos.
Nas primeiras linhas - iniciaremos o código chamando as bibliotecas que são pertinentes para o uso com o ESP8266:
8
9
10
11
#include <ESP8266WiFi.h>                                      
extern "C" {
#include <espnow.h>
}

Na linha 13 - Temos o endereço Mac do Módulo ESP Slave, e é ele que irá receber os comandos, e acionará "as cargas" os LEDs. 
Na linha 14 - definimos o canal da transmissão WI-FI para o canal 4. 
E na linha 15 - temos uma variável tipo inteira para comutar o estado anterior do Led, já estamos determinando o estado de inicialização dela no nível baixo, LOW.
13
14
15
uint8_t mac[] = {0x36, 0x33, 0x33, 0x33, 0x33, 0x33};                               
#define WIFI_CHANNEL 4
int prevstate = LOW;

Na Linha 19 à 23 - temos a declaração das estruturas de controle de dados 1 e 2, que devem estar correspondidas com o ESP Slave, e deverá ser programado com as mesmas configurações. No primeiro parâmetro temos a estrutura de controle de dados 1, será o (buttonpressed) que corresponderá o pressionar do botão.
19
20
21
22
23
struct __attribute__((packed))                               
DataStruct {
char text[32];
};
DataStruct buttonpressed;

Na Linha 25 à 29 - Temos a estrutura de controle de dados 2, que será o (buttonreleased) que corresponderá quando soltarmos o botão.
25
26
27
28
29
struct __attribute__((packed)) 
DataStruct {
char text[32];
};
DataStruct2 buttonreleased;

Depois dos processos de declarações, estruturas, e inclusão de variáveis, entraremos no Void setup() onde iremos atribuir os parâmetros de pinagens, inicialização das funções, os modos com que o controlador irá funcionar, ou seja, uma configuração inicial geral.

Na Linha 32 - Iniciamos a função void setup()
Na linha 33 
- Declaramos a GPIO D1 como entrada, utilizando o parâmetro INPUT_PULLUP, que estabelece o resistor pullup interno, fazendo com que não precisemos colocar um resistor externo.
Na linha 34 - Declaramos a GPIO D0 como Saída, que será utilizada com o LED de indicação.
Na linha 35 - Temos a inicialização do Serial Monitor e o parâmero de velocidade de transferência de dados setada em (115200).

32
33
34
35
void setup() {                                            
   pinMode(D1,INPUT_PULLUP);
   pinMode(D0,OUTPUT);
   Serial.begin(115200);

Na Linha 37 - Iniciamos o modo em que o ESP irá trabalhar que no caso, estamos utilizando o Modo Station "STA", ambos os ESPs irão trabalhar com esse mesmo modo.
Na Linha 38 - Iniciamos a função que certifica de que nada irá estar conectado ao ESP antes de ele iniciar os parâmetros de transmissão ESP-NOW.
37
38
WiFi.mode(WIFI_STA);                                          
WiFi.disconnect();

Na Linha 39 - Utilizamos a função Serial.printf() para imprimir o endereço Mac do módulo Master ESP8266.
Na Linha 40 - Utilizamos a função Serial.printf() para imprimir o endereço Mac do Módulo Slave ESP8266.
Na Linha 41 Utilizamos a função Serial.printf() para imprimir o Canal utilizado para fazer a transmissão e recepção entre os módulos.
39
40
41
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);

Na Linha 42 - Faz-se uma comparação declarando uma condicional if, que verifica se a função esp_now_init(), que inicia o protocolo ESP-NOW, foi inicializada corretamente, essa função tem dois valores de retorno: 0 = Erro, e 1 = OK, então na comparação, analisa-se a função esp_now_init(), se o valor de retorno for igual a 1, a inicialização foi estabelecida com sucesso, se o valor de retorno for igual a 0, na próxima linha...
Na Linha 44 - Ele imprime no Serial Monitor a mensagem de falha na inicialização.
42
44
if (esp_now_init() != 0){
Serial.println("*** ESP_Now initialization failed");}

Na Linha 46 - Temos a função que determinará o modo de trabalho do ESP8266, que no nosso caso, estamos colocando-a como Master:
Existem ainda dois modos a mais que podem ser implementadas substituindo os parâmetros apropriados: 
ESP_NOW_ROLE_SLAVE  para coloca-lo no modo Slave.
ESP_NOW_ROLE_COMBO para coloca-lo no modo Master + Slave

Na Linha 47 - Temos a função que adiciona os dados requeridos do Slave; Armazena o Endereço MAC; Seta o Modo de operação Módulo; Seta o Canal do Módulo; Seta a chave de 16 bytes necessária para a comunicação ESP-NOW; E seta o comprimento da chave, que deve ter 16 bytes
No nosso caso, estamos passando esses dois últimos parâmetros com NULL, e 0. Quando colocamos zero no ultimo parâmetro de retorno, isso quer dizer que a comunicação está OK.
Na Linha 48 - temos a função strcpy() que copia a string "Button pressed" e aponta para a fonte de destino a string tipo char "text" que está concatenada com a estrutura de dados buttonpressed.
Na Linha 49 - Temos a mesma função, o que difere é a string e para onde ela aponta.
46
47
48
49
50
esp_now_set_self_role(ESP_NOW_ROLE_CONTROLLER);                                             
esp_now_add_peer(mac, ESP_NOW_ROLE_SLAVE, WIFI_CHANNEL, NULL, 0);
strcpy(buttonpressed.text,"Button pressed");
strcpy(buttonreleased.text,"Button Released");
Serial.println("Setup finished");

Na Linha 54 - Entramos  na função void loop, que é a função que fica rodando todo o programa que estiver dentro dessa função, no nosso caso fizemos outra função dentro dela.
Na Linha 55 - Temos a função sendData, que constantemente fica analisando se houve o pressionar da chave Switch, e se sim, ele envia esses dados para o ESP Client.
54
55
void loop() {                                       
    sendData();

Na Linha 59 - Entramos  na função void sendData, que como já dito acima é responsável por verificar o pressionar do botão e enviar se caso foi pressionado ou solto.
Na Linha 60 - Declaramos uma variável "inttipo Inteira, que recebe a função digitalRead(D1), que ler se a chave Switch que está ligado na GPIO D1 foi pressionada, caso ela seja LOW ou HIGH, a variável currentstate recebe essa informação, e as mantém na sua memória.
59
60
void sendData() {                                       
  int currentstate = digitalRead(D1);

Na Linha 61 - Temos a função if, que faz um comparação lógica se a variável global, descrita no início do programa prevstate é diferente da variável currentstate que recebeu a leitura da GPIO D1. 
Na Linha 62 - Entramos em outro if dentro do if anterior, que faz uma comparação se o estado da variável currentstate é igual a HIGH ou LOW
61
62
if(prevstate != currentstate){                                 
  if(currentstate == HIGH){

Na Linha 63 -  Temos uma variável bs de 8 bits que recebe o operador sizeof que retorna o tamanho da string buttonpressed. e armazena na varável bs.
Na Linha 64 -  Temos a função memcpy padrão que armazena todo conteúdo que está dentro dela na memória.
63
64
uint8_t bs[sizeof(buttonpressed)];                               
  memcpy(bs, &buttonpressed, sizeof(buttonpressed));

Na Linha 65 - Temos a função que envia o pacote de dados para o ESP Salve que tenha o endereço MAC cadastrado no início do código, como já apresentado na Linha 6. 
Essa função é seguido de três parâmetros que vale a pena abordar:
1° Parâmetro: 
Endereço MAC  Se for NULL, o pacote será enviado para todos os endereços MAC gravados pelo ESP-NOW.
2° Parâmetro: 
Dados a ser enviado
3° Parâmetro: 
Tamanho dos dados
Na Linha 66 - Temos a já bastante conhecida função que imprime no serial monitor a string buttonpressed.
Na Linha 67 - Temos a também conhecida função que escreve na porta digital IO o estabelecido dentro da sua função com dois parâmetros (Porta, Estado).
65
66
67
esp_now_send(NULL, bs, sizeof(buttonpressed));                          
  Serial.println(buttonpressed.text);
  digitalWrite(D0, LOW);

Na Linha 68 - Temos a função else if que faz a comparação, só que desta vez, é para o movimento oposto, ou seja se o botão foi solto, ele armazena os dados se LOW ou HIGH
Na Linha 69 - Também temos a mesma variável bs de 8 bits que recebe o operador sizeof que retorna o tamanho da string buttonreleased. e armazena na varável bs.
Na Linha 70 Também temos a função memcpy padrão que armazena todo conteúdo que está dentro dela na memória.
Na Linha 71 Temos a função que envia o pacote de dados para o ESP Salve que tenha o endereço MAC cadastrado no início do código, como já apresentado na Linha 6. 
Na Linha 72 - Temos a já bastante conhecida função que imprime no serial monitor a string buttonreleased.
Na Linha 73 - Temos a também conhecida função que escreve na porta digital IO o estabelecido dentro da sua função com dois parâmetros (Porta, Estado).
Na Linha 75 - Temos a variável global prevstate recebendo uma nova atualização do ultimo estado da variável currentstate.
68
69
70
71
72
73
75
}else if(currentstate == LOW){                   
    uint8_t bs[sizeof(buttonreleased)];
    memcpy(bs, &buttonreleased, sizeof(buttonreleased));
    esp_now_send(NULL, bs, sizeof(buttonreleased));
  Serial.println(buttonreleased.text);
  digitalWrite(D0, HIGH);}
}prevstate = currentstate;

E aqui finalizamos a explicação básica do código ESP-NOW Master.

Código ESP-NOW do "Slave"

No Slave, iremos resumir, daremos explicações só nos parâmetros que não foram explicados no código do Master acima, para não ficar tão repetitivo.
Nas primeiras linhas - Assim como o Master iniciaremos o código chamando as bibliotecas que são específicas para o ESP8266, com a diferença que temos a biblioteca user_interface.h para se incluir, essa biblioteca é necessária para acessar os Timer`s. do ESP8266.
7
8
9
10
#include <ESP8266WiFi.h>                                      
extern "C" {
#include <espnow.h>
#include <user_interface.h>

Na Linha 17,18,19 - Temos uma função void initVariant(), que seta o endereço MAC Access Point do ESP8266, pelo MAC que você determina na String mac.
17
18
19
void initVariant() {                          
  WiFi.mode(WIFI_AP);
  wifi_set_macaddr(SOFTAP_IF, &mac[0]);


Na Linha 45 - Temos a função que determinará o modo de trabalho do ESP8266, que no nosso caso, estamos colocando-a como Slave.
Na Linha 46 - Temos a função de registro do CallBack que é responsável por  registrar as informações vinda do Master, com o argumento da função que será executada e está declarada dentro da função cb.
45
46
esp_now_set_self_role(ESP_NOW_ROLE_SLAVE);                             
esp_now_register_recv_cb(receiveCallBackFunction);



Na Linha 55 - Temos a função que recebe os dados vindo do ESP Controle, e que será utilizado para fazer o disparo do LED.
Na Linha 56 - Também temos a função memcpy padrão que armazena todo conteúdo que está dentro dela na memória.

Na Linha 62 - Temos a função que faz um flip-flop do Led1, ou seja, ele faz a leitura do estado do Led1 e determina seu estado inverso ao estado dele mesmo. Ou seja: cada vez que entra na função receiveCallBackFunction ele escreve o estado do Led1 ao seu estado anterior... uma vez liga, outra vez desliga.
55
56
62
void receiveCallBackFunction(uint8_t *senderMac, uint8_t *incomingData, uint8_t len) {         
  memcpy(&myData, incomingData, sizeof(myData));;
 digitalWrite(Led1, !digitalRead(Led1));



E aqui também termina as principais partes do código do Salve.

O código utilizado esta disponível para baixar no link direto logo abaixo, sinta-se à vontade para baixar e fazer suas próprias modificações.

Click Aqui para Baixar: 


Qualquer dúvida, ou sugestões ou mesmo correções, "a final de contas, somos todos eternos aprendizes", pode escrever nos comentários, e no que pudermos responder, faremos!!!

Se inscreva no nosso Blog!!! Click Aqui FVM Learning!!!
Forte abraço.

Deus vos Abençoe
Shalom