sexta-feira, 31 de janeiro de 2020

ESP-NOW no NINA W102

NINA W102 RODANDO ESP-NOW (ARDUINO)

O objetivo deste BLOG é dar uma ideia geral de como fazer o módulo NINA W102 rodar o protocolo ESP-NOW. Baseado no blog de Rui Santos, porém testado no W102. 

https://randomnerdtutorials.com/esp-now-esp32-arduino-ide/



ESP-NOW


O ESP-NOW é outro protocolo desenvolvido pela Espressif, que permite que vários dispositivos se comuniquem sem usar o Wi-Fi. O protocolo é semelhante à conectividade sem fio de 2,4 GHz de baixa potência, geralmente implantada em mouses sem fio. Portanto, o emparelhamento entre dispositivos é necessário antes da comunicação. Após o emparelhamento, a conexão é segura e ponto a ponto, sem a necessidade de handshake.

Recursos

O ESP-NOW suporta os seguintes recursos:
• Comunicação unicast 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 do aplicativo de sucesso ou falha na transmissão.

A tecnologia ESP-NOW também possui as seguintes limitações:

• A transmissão não é suportada.
• Pares criptografados limitados. No máximo 10 pares criptografados são suportados no Station modo; 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

Dúvida clássica

O ESP_NOW ele é um protocolo de comunicação entre placas ESP32 , ela funciona numa metodologia onde vários slaves (placas escravas) podem mandar informações para uma única placa mestra (placa master), inicialmente a exigência que existe é que as placas escravas tenham setados em seu código fonte o endereço MAC da placa master, que é onde os dados devem ser enviados.

Como elas se comunicam através do MAC utilizando uma conexão Ponto a Ponto, ela não tem necessidade de utilizar o Protocolo TCP/IP, mas existe um porém, caso a placa master necessite estar conectada à uma rede WiFi para acessar um webservice ou algo do tipo, as placas slaves precisam estar sintonizadas no mesmo canal wifi que a placa master estiver usando.

No caso elas se comunicam estando ambas em configuração de estação wifi, então todas devem estar sintonizadas no mesmo canal.

Um exemplo, se for necessário fazer várias placas enviarem dados para uma única placa mestra, os dados serão enviados sem problema nenhum apenas fornecendo o MAC da placa mestra, porém, caso a placa mestra necessite estar conectada à internet enquanto recebe esses dados das outras placa, ai sim todas elas precisam estar em sintonia.

Tive um problema semelhante no TCC, resolvi este problema setando o SSID da rede WiFi na placa escrava e efetuando um Scan em todas as redes próximas, no momento em que o slave detectar aquela rede, ele configura para si mesmo o mesmo canal.

"Jardel Dos Santos" - Aluno BCC Furb


ÓTIMO LINK SOBRE ESP-NOW

Introdução ao ESP-NOW (W102 COM ARDUINO)


Aprenda a usar o ESP-NOW para trocar dados entre placas W102 programadas com o Arduino IDE. O ESP-NOW é um protocolo de comunicação sem conexão desenvolvido pela Espressif que possui transmissão de pacotes curtos. Este protocolo permite que vários dispositivos se comuniquem sem usar o Wi-Fi.

Vamos programar o W102 usando o Arduino IDE, portanto, antes de prosseguir com este tutorial, você deve ter o complemento W102 instalado no seu Arduino IDE. 

Apresentando o ESP-NOW


Depois de emparelhar um dispositivo, a conexão é persistente. Em outras palavras, se de repente uma de suas placas perder energia ou redefinir, quando reiniciar, ela se conectará automaticamente ao seu par para continuar a comunicação.
Em palavras simples, o ESP-NOW é um protocolo de comunicação rápido que pode ser usado para trocar pequenas mensagens (até 250 bytes) entre placas W102.
O ESP-NOW é muito versátil e você pode ter comunicação unidirecional ou bidirecional em diferentes configurações.

Comunicação unidirecional ESP-NOW

Por exemplo, na comunicação unidirecional, você pode ter cenários como este:
  • Uma placa W102 enviando dados para outra placa W102
Essa configuração é muito fácil de implementar e é ótimo enviar dados de uma placa para outra, como leituras do sensor ou comandos ON e OFF para controlar os GPIOs.



  • Um W102 "mestre" enviando dados para vários "escravos" do W102
Uma placa W102  enviando comandos iguais ou diferentes para diferentes placas W102. Essa configuração é ideal para criar algo como um controle remoto. Você pode ter várias placas W102 espalhadas pela casa que são controladas por uma placa principal do W102.





  • Um "escravo" do W102 recebendo dados de vários "mestres"
Essa configuração é ideal se você deseja coletar dados de vários nós de sensores em uma placa W102. Isso pode ser configurado como um servidor da web para exibir dados de todas as outras placas, por exemplo.




Nota: na documentação do ESP-NOW não existem “remetente / mestre” e “receptor / escravo”. Cada quadro pode ser um remetente ou receptor. No entanto, para manter as coisas claras, usaremos os termos "remetente" e "destinatário" ou "mestre" e "escravo".

Comunicação bidirecional ESP-NOW

Com o ESP-NOW, cada placa pode ser um remetente e um destinatário ao mesmo tempo. Assim, você pode estabelecer uma comunicação bidirecional entre placas.
Por exemplo, você pode ter duas placas se comunicando.
Você pode adicionar mais placas a essa configuração e ter algo parecido com uma rede (todas as placas W102 se comunicam).

Em resumo, o ESP-NOW é ideal para construir uma rede na qual você pode ter várias placas W102 trocando dados entre si.

W102: Obtendo o endereço MAC da placa

Para se comunicar via ESP-NOW, você precisa saber o endereço MAC do receptor W102 . É assim que você sabe para qual dispositivo enviará as informações.
Cada W102 possui um endereço de MAC exclusivo e é assim que identificamos cada placa para enviar dados usando o ESP-NOW 
Para obter o endereço MAC da sua placa, carregue o código a seguir.
 #include "WiFi.h" void setup(){ Serial.begin(115200); WiFi.mode(WIFI_MODE_STA); Serial.println(WiFi.macAddress()); } void loop(){ } 
#include "WiFi.h"
 
void setup(){
  Serial.begin(115200);
  WiFi.mode(WIFI_MODE_STA);
  Serial.println(WiFi.macAddress());
}
 
void loop(){

}
Após o upload do código, abra o Serial Monitor a uma taxa de transmissão de 115200 e pressione o botão W102 RST / EN. O endereço MAC deve ser impresso da seguinte maneira:




ESP-NOW ESP32 Obtendo o endereço MAC da placa
Salve o endereço MAC da placa, pois você precisará enviar dados para a placa correta via ESP-NOW.

Comunicação ponto a ponto unidirecional ESP-NOW

Para começar com a comunicação sem fio ESP-NOW, criaremos um projeto simples que mostra como enviar uma mensagem de um W102 para outro. Um W102 será o "remetente" e o outro W102 será o "receptor".




Enviaremos uma estrutura que contém uma variável do tipo char , int , float , String e boolean . Em seguida, você pode modificar a estrutura para enviar os tipos de variáveis ​​adequados ao seu projeto (como leituras do sensor ou variáveis ​​booleanas para ativar ou desativar algo).
Para um melhor entendimento, chamaremos "remetente" para W102 # 1 e "receptor" para W102 # 2.
Aqui está o que devemos incluir no esboço do remetente:
  1. Inicialize o ESP-NOW;
  2. Registrar uma função de retorno de chamada ao enviar dados - a função OnDataSent será executada quando uma mensagem for enviada. Isso pode nos dizer se a mensagem foi entregue com êxito ou não;
  3. Adicione um dispositivo de mesmo nível (o receptor). Para isso, você precisa saber o endereço MAC do receptor;
  4. Envie uma mensagem para o dispositivo ponto.
No lado do receptor, o esboço deve incluir:
  1. Inicialize o ESP-NOW;
  2. Registre-se para uma função de recebimento de retorno de chamada ( OnDataRecv ). Esta é uma função que será executada quando uma mensagem for recebida.
  3. Dentro dessa função de retorno de chamada, salve a mensagem em uma variável para executar qualquer tarefa com essas informações.
O ESP-NOW trabalha com funções de retorno de chamada que são chamadas quando um dispositivo recebe uma mensagem ou quando uma mensagem é enviada (você obtém se a mensagem foi entregue com êxito ou se falhou).

Funções úteis do ESP-NOW

Aqui está um resumo das funções essenciais do ESP-NOW:




Nome e Descrição da Função
esp_now_init () Inicializa o ESP-NOW. Você deve inicializar o Wi-Fi antes de inicializar o ESP-NOW.
esp_now_add_peer () Chame essa função para emparelhar um dispositivo e passar como argumento o endereço MAC de mesmo nível.
esp_now_send () Envie dados com o ESP-NOW.
esp_now_register_send_cb () Registra uma função de retorno de chamada que é acionada ao enviar dados. Quando uma mensagem é enviada, uma função é chamada - essa função retorna se a entrega foi bem-sucedida ou não.
esp_now_register_rcv_cb () Registra uma função de retorno de chamada que é acionada ao receber dados. Quando os dados são recebidos via ESP-NOW, uma função é chamada.

Para obter mais informações sobre essas funções, leia 

https://demo-dijiudu.readthedocs.io/en/latest/api-reference/wifi/esp_now.html

Sketch do Remetente W102 (ESP-NOW)
Aqui está o código para a placa remetente W102. Copie o código para o seu Arduino IDE, mas não o carregue ainda. Você precisa fazer algumas modificações para que funcione para você.

/* Rui Santos Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files. The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. */ #include <esp_now.h> #include <WiFi.h> // REPLACE WITH YOUR RECEIVER MAC Address uint8_t broadcastAddress[] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; // Structure example to send data // Must match the receiver structure typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; // Create a struct_message called myData struct_message myData; // callback when data is sent void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); } void setup() { // Init Serial Monitor Serial.begin(115200); // Set device as a Wi-Fi Station WiFi.mode(WIFI_STA); // Init ESP-NOW if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } // Once ESPNow is successfully Init, we will register for Send CB to // get the status of Trasnmitted packet esp_now_register_send_cb(OnDataSent); // Register peer esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; peerInfo.encrypt = false; // Add peer if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } } void loop() { // Set values to send strcpy(myData.a, "THIS IS A CHAR"); myData.b = random(1,20); myData.c = 1.2; myData.d = "Hello"; myData.e = false; // Send message via ESP-NOW esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } delay(2000); }
Como o código funciona
Primeiro, inclua as bibliotecas esp_now.he WiFi.h.
 #include <esp_now.h> #include <WiFi.h> 
Na próxima linha, você deve inserir o endereço MAC do receptor W102.
 uint8_t broadcastAddress[] = {0x30, 0xAE, 0xA4, 0x07, 0x0D, 0x64}; 
No nosso caso, o endereço MAC do receptor é: 30: AE: A4: 07: 0D: 64 , mas você precisa substituir essa variável pelo seu próprio endereço MAC.
Em seguida, crie uma estrutura que contenha o tipo de dados que queremos enviar. Chamamos essa estrutura de struct_message e ela contém 5 tipos diferentes de variáveis. Você pode alterar isso para enviar os tipos de variáveis ​​desejados.
 typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; 
Em seguida, crie uma nova variável do tipo struct_message chamada myData que armazenará os valores das variáveis.
 struct_message myData; 
Em seguida, defina a função OnDataSent () . Esta é uma função de retorno de chamada que será executada quando uma mensagem for enviada. Nesse caso, essa mensagem simplesmente imprime se a mensagem foi entregue com êxito ou não.
 void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { Serial.print("\r\nLast Packet Send Status:\t"); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); } 
Na configuração () , inicialize o monitor serial para fins de depuração:
 Serial.begin(115200); 
Defina o dispositivo como uma estação Wi-Fi:
 WiFi.mode(WIFI_STA); 
Inicialize o ESP-NOW:
 if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } 
Após inicializar com sucesso o ESP-NOW, registre a função de retorno de chamada que será chamada quando uma mensagem for enviada. Nesse caso, registramos a função OnDataSent () criada anteriormente.
 esp_now_register_send_cb(OnDataSent); 
Depois disso, precisamos emparelhar com outro dispositivo ESP-NOW para enviar dados. É o que fazemos nas próximas linhas:
 //Register peer esp_now_peer_info_t peerInfo; memcpy(peerInfo.peer_addr, broadcastAddress, 6); peerInfo.channel = 0; peerInfo.encrypt = false; //Add peer if (esp_now_add_peer(&peerInfo) != ESP_OK){ Serial.println("Failed to add peer"); return; } 
No loop () , enviaremos uma mensagem via ESP-NOW a cada 2 segundos (você pode alterar esse tempo de atraso).
Primeiro, definimos os valores das variáveis ​​da seguinte maneira:
 strcpy(myData.a, "THIS IS A CHAR"); myData.b = random(1,20); myData.c = 1.2; myData.d = "Hello"; myData.e = false; 
Lembre-se que myData é uma estrutura. Aqui atribuímos os valores que queremos enviar dentro da estrutura. Por exemplo, a primeira linha atribui um caractere, a segunda linha atribui um número Int aleatório, um Float, uma String e uma variável booleana.
Criamos esse tipo de estrutura para mostrar como enviar os tipos de variáveis ​​mais comuns. Você pode alterar a estrutura para enviar qualquer outro tipo de dados.
Por fim, envie a mensagem da seguinte maneira:
 esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &myData, sizeof(myData)); 
Verifique se a mensagem foi enviada com sucesso:
 if (result == ESP_OK) { Serial.println("Sent with success"); } else { Serial.println("Error sending the data"); } 
loop () é executado a cada 2000 milissegundos (2 segundos).
 delay(2000); 

Esboço do receptor W102 (ESP-NOW)

Carregue o seguinte código na placa receptora do W102 .

/*  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/esp-now-esp32-arduino-ide/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

#include <esp_now.h>
#include <WiFi.h>

// Structure example to receive data
// Must match the sender structure
typedef struct struct_message {
    char a[32];
    int b;
    float c;
    String d;
    bool e;
} struct_message;

// Create a struct_message called myData
struct_message myData;

// callback function that will be executed when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
  memcpy(&myData, incomingData, sizeof(myData));
  Serial.print("Bytes received: ");
  Serial.println(len);
  Serial.print("Char: ");
  Serial.println(myData.a);
  Serial.print("Int: ");
  Serial.println(myData.b);
  Serial.print("Float: ");
  Serial.println(myData.c);
  Serial.print("String: ");
  Serial.println(myData.d);
  Serial.print("Bool: ");
  Serial.println(myData.e);
  Serial.println();
}
 
void setup() {
  // Initialize Serial Monitor
  Serial.begin(115200);
  
  // Set device as a Wi-Fi Station
  WiFi.mode(WIFI_STA);

  // Init ESP-NOW
  if (esp_now_init() != ESP_OK) {
    Serial.println("Error initializing ESP-NOW");
    return;
  }
  
  // Once ESPNow is successfully Init, we will register for recv CB to
  // get recv packer info
  esp_now_register_recv_cb(OnDataRecv);
}
 
void loop() {

}
Como o código funciona

Da mesma forma que o remetente, comece incluindo as bibliotecas:

 #include <esp_now.h> #include <WiFi.h> 
Crie uma estrutura para receber os dados. Essa estrutura deve ser a mesma definida no esboço do remetente.
 typedef struct struct_message { char a[32]; int b; float c; String d; bool e; } struct_message; 
Crie uma variável struct_message chamada myData .
 struct_message myData; 
Crie uma função de retorno de chamada que será chamada quando o W102 receber os dados via ESP-NOW. A função é chamada onDataRecv () e deve aceitar vários parâmetros da seguinte maneira:
 void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) { 
Copiamos o conteúdo da variável de dados incomingData na variável myData .
 memcpy(&myData, incomingData, sizeof(myData)); 
Agora, a estrutura myData contém várias variáveis ​​dentro dos valores enviados pelo remetente W102. Para acessar a variável a , por exemplo, basta chamar myData.a .
Neste exemplo, simplesmente imprimimos os dados recebidos, mas em um aplicativo prático você pode imprimir os dados em uma tela, por exemplo.
  Serial.print("Bytes received: "); Serial.println(len); Serial.print("Char: "); Serial.println(myData.a); Serial.print("Int: "); Serial.println(myData.b); Serial.print("Float: "); Serial.println(myData.c); Serial.print("String: "); Serial.println(myData.d); Serial.print("Bool: "); Serial.println(myData.e); Serial.println(); } 
Na configuração () , inicialize o Serial Monitor.
 Serial.begin(115200); 
Defina o dispositivo como uma estação Wi-Fi.
 WiFi.mode(WIFI_STA); 
Inicialize o ESP-NOW:
 if (esp_now_init() != ESP_OK) { Serial.println("Error initializing ESP-NOW"); return; } 
Registre-se para uma função de retorno de chamada que será chamada quando os dados forem recebidos. Nesse caso, registramos a função OnDataRecv () que foi criada anteriormente.
 esp_now_register_recv_cb(OnDataRecv); 

Testando a comunicação ESP-NOW

Carregue o esboço do remetente na placa W102 do remetente e o esboço do receptor na placa W102 do receptor.
Agora, abra duas janelas IDE do Arduino. Um para o destinatário e outro para o remetente. Abra o Monitor serial para cada placa. Deve ser uma porta COM diferente para cada placa.
É isso que você deve colocar no lado do remetente.


Testando a comunicação ESP-NOW ESP32 com o remetente IDE do Arduino
E é isso que você deve colocar no lado do receptor. Observe que a variável Int muda entre cada leitura recebida (porque a definimos como um número aleatório no lado do remetente).




Testando a comunicação ESP-NOW ESP32 com o receptor Arduino IDE
Tentamos manter nossos exemplos o mais simples possível, para que você entenda melhor como tudo funciona. Existem mais funções relacionadas ao ESP-NOW que podem ser úteis em seus projetos, como: gerenciamento de pares, exclusão de pares, varredura de dispositivos escravos, etc ... Para um exemplo completo, no seu Arduino IDE, você pode ir para Arquivo> Exemplos> ESP32 > ESPNow e escolha um dos esboços de exemplo.

Esperamos que você tenha achado útil esta introdução ao ESP-NOW. Como um exemplo simples de introdução, mostramos como enviar dados como uma estrutura de um W102 para outro. A idéia é substituir os valores da estrutura por leituras de sensor ou estados GPIO, por exemplo.

Além disso, com o ESP-NOW, cada placa pode ser um remetente e receptor ao mesmo tempo, e uma placa pode enviar dados para várias placas e também receber dados de várias placas. Esses tópicos serão abordados em futuros tutoriais, portanto, fique atento.

DÚVIDAS

suporte@smartcore.com.br


REFERÊNCIAS
 

Sobre a SMARTCORE

A SmartCore fornece módulos para comunicação wireless, biometria, conectividade, rastreamento e automação.
Nosso portifólio inclui modem 2G/3G/4G/NB-IoT/Cat.M, satelital, módulos WiFi, Bluetooth, GNSS / GPS, Sigfox, LoRa, leitor de cartão, leitor QR code, mecanismo de impressão, mini-board PC, antena, pigtail, LCD, bateria, repetidor GPS e sensores.
Mais detalhes em www.smartcore.com.br