Olá, como estão? No post passado falamos sobre o ESP32 LoRa e a Rede LoRa, caso não tenha lido clique aqui, nele demos um exemplo de uso, um alarme de incêndio florestal. Entretanto caso quisesse supervisionar, porém você está em outra cidade ou fora do alcance do sinal LoRa. Nesse caso podemos utilizar a internet ao nosso favor, utilizando a rede LoRa com WiFi já que o ESP32 LoRa tem conectividade com outros dois tipos de rede sendo elas Bluetooth e WiFi.
Componentes Utilizados
Funcionamento do Projeto WiFi com LoRa
Não iremos abordar muito afundo referente a WiFi nem LoRa pois já tivemos posts focados neles. Nesse projeto iremos utilizar a mesma lógica que utilizamos nos projetos de WiFi e iremos incrementar o LoRa que vimos no post passado, para assim poder utilizar as duas ao nosso favor.
Montagem do Projeto WiFi com LoRa
Então agora iremos utilizar o mesmo circuito do post passado.
Contudo segue abaixo uma imagem que demonstrando a montagem do circuito.
Diagrama Esquemático do Projeto WiFi com LoRa
Preparando a Arduíno IDE
Antes de mais nada na Arduíno IDE clique em Preferências e cole o link abaixo em “URLs Adicionais para Gerenciadores de Placas “e dê um OK.
URL: https://dl.espressif.com/dl/package_esp32_index.json
Em seguida, clique em Ferramentas -> Placas -> Gerenciador de placas, pesquise ESP32, selecione e clique em instalar.
Logo após ser instalado, vá em Ferramentas -> Placas e selecione a placa Heltec WIFI LoRa 32(v2).
Assim que selecionar a placa clique em Ferramentas -> Gerenciar Bibliotecas, pesquise heltec, selecione Heltec ESP32 Dev-Boards.
Assim que selecionar a placa clique em Ferramentas -> Gerenciar Bibliotecas, pesquise heltec, selecione Heltec ESP32 Dev-Boards.
Código-fonte do Projeto WiFi com LoRa
Então agora iremos programar 2 ESP32 LoRa, um deles sendo o Sender o que envia os “pacotes”, e Reciver o que recebe os “pacotes”.
Programação Sender
Contudo o código do Sender foi dividido em três funções e dois arquivos. Entretanto sendo um arquivo o código e outro a imagem.
//Biblioteca -----------------------------------------------------------------------------------------
#include <heltec.h> // Responsável pelo display e LoRa
#include <DHT.h> // Responsável pelo DHT
#include <DHT_U.h> // Responsável pelo DHT
#include "images.h" // Responsável pela imagem
//LoRa - Variáveis Globais e Define ------------------------------------------------------------------
#define BAND 915E6 // Frequência de banda
#define KEY 0xF3 // Chave para receber pacote
//Variáveis Globais ----------------------------------------------------------------------------------
unsigned int counter = 0; // Contador de pacotes
float temp = 0; // Temperatura
float umid = 0; // Umidade
//DHT11 - Variáveis Globais e Define -----------------------------------------------------------------
#define DHTPIN 32 // Define o pino
#define DHTTYPE DHT11 // Define o sensor de temperatura
DHT dht(DHTPIN,DHTTYPE); // Criando um objeto dht
//Função Auxiliares ----------------------------------------------------------------------------------
void logo(); // Responsável por imprimir a logo
//Setup ----------------------------------------------------------------------------------------------
void setup(){
dht.begin(); // Inicializa o DHT11
//Abaixo inicializa Display, LoRa, Serial, PABOOST, BAND
Heltec.begin(true, true, true, true, BAND);
LoRa.setSyncWord(KEY); // Chave para receber o pacote
Heltec.display->init(); // Inicializa o display
Heltec.display->flipScreenVertically(); // Vira na vertical
Heltec.display->setFont(ArialMT_Plain_10); //Escolhe a fonte
logo(); // Chama função que imprime logo
Heltec.display->drawString(0, 0, "ESP32 LoRa Iniciou"); // Escreve que foi Inicializado
Heltec.display->drawString(0, 11, "com Sucesso!");
Heltec.display->display();
delay(1000); // Espera 1s
}
//Void -----------------------------------------------------------------------------------------------
void loop(){
temp = dht.readTemperature(); // Leitura da Temperatura
umid = dht.readHumidity(); // Leitura da Humidade
Heltec.display->clear(); // Limpa o display
Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); // Alinha o texto na esquerda
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
Heltec.display->drawString(0, 0, "Envio do Pacote: "); // Imprime informação do pacote
Heltec.display->drawString(90, 0, String(counter)); // Imprime numero do pacote
Heltec.display->drawString(0, 11, "Temperatura: " + String(temp)); // Imprime informação
Heltec.display->drawString(0, 22, "Umidade: " + String(umid)); // Imprime informação da umidade
Heltec.display->display();
/* LoRa.setTxPower(txPower,RFOUT_pin);
* txPower -- 0 ~ 20
* RFOUT_pin could be RF_PACONFIG_PASELECT_PABOOST ou RF_PACONFIG_PASELECT_RFO
* - RF_PACONFIG_PASELECT_PABOOST -- LoRa single saida via PABOOST, maxima saida 20dBm
* - RF_PACONFIG_PASELECT_RFO -- LoRa single saida via RFO_HF / RFO_LF, maxima saida 14dBm */
//Envio dos Pacotes
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("p"); // Informa que ira enviar o pacote
LoRa.print(counter); // Envia informação do pacote
LoRa.endPacket(); // Fecha o pacote
delay(10); // Espera 0,01s
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("t"); // Informa o envio da temperatura
LoRa.print(temp); // Envia informação da temperatura
LoRa.endPacket(); // Fecha o pacote
delay(10); // Espera 0,01s
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("u"); // Informa o envio da humidade
LoRa.print(umid); // Envia informação da humidade
LoRa.endPacket(); // Fecha o pacote
counter++;
digitalWrite(LED, HIGH); // Acende o LED da placa
delay(500); // Espera 0,5s
digitalWrite(LED, LOW); // Apaga o LED da placa
delay(500); // Espera 0,5s
}
//Logo -----------------------------------------------------------------------------------------------
void logo(){
Heltec.display->clear(); // Limpa o display
Heltec.display->drawXbm(0,10,logo_width,logo_height,logo_bits); // Imprime imagem
Heltec.display->display();
delay(1500); // Espera 1,5s
Heltec.display->clear(); // Limpa o display
}
Vamos dar uma olhada mais de perto no código:
Incluindo Bibliotecas
Primeiramente temos que incluir as bibliotecas que usamos em nosso projeto.
//Biblioteca -----------------------------------------------------------------------------------------
#include <heltec.h> // Responsável pelo display e LoRa
#include <DHT.h> // Responsável pelo DHT
#include <DHT_U.h> // Responsável pelo DHT
#include "images.h" // Responsável pela imagem
Definições LoRa
Em seguida definimos a frequência e a chave (para garantir o recebimento receba apenas pacotes de seu remetente, para pode-se definir uma palavra de sincronização (entre 0 a 0xFF)) que usaremos no LoRa.
//LoRa - Variáveis Globais e Define ------------------------------------------------------------------
#define BAND 915E6 // Frequência de banda
#define KEY 0xF3 // Chave para receber pacote
Variáveis Globais
Logo após declaramos as variáveis globais que será o contador de pacotes, temperatura e umidade.
//Variáveis Globais ----------------------------------------------------------------------------------
unsigned int counter = 0; // Contador de pacotes
float temp = 0; // Temperatura
float umid = 0; // Umidade
Definições DHT11
Então definimos o pino e o tipo do DHT (no nosso caso é o DHT11).
//DHT11 - Variáveis Globais e Define -----------------------------------------------------------------
#define DHTPIN 32 // Define o pino
#define DHTTYPE DHT11 // Define o sensor de temperatura
DHT dht(DHTPIN,DHTTYPE); // Criando um objeto dht
Funções Auxiliares
Logo após declaramos 1 função auxiliar que usamos no projeto.
//Funções Auxiliares ---------------------------------------------------------------------------------
void logo(); // Responsável por imprimir a logo
Funções Setup
No setup primeiramente iremos inicializar o DHT e heltec com o display ligado, LoRa ligado, Serial ligado, PABOOST e com a frequência. Logo após isso sincronizamos o LoRa com a nossa chave.
//Setup ----------------------------------------------------------------------------------------------
void setup(){
dht.begin(); // Inicializa o DHT11
//Abaixo inicializa Display, LoRa, Serial, PABOOST, BAND
Heltec.begin(true, true, true, true, BAND);
LoRa.setSyncWord(KEY); // Chave para receber o pacote
Em seguida inicializamos também o display, viramos na vertical e escolhemos a fonte juntamente com o tamanho e chamamos a função para imprimir a logo no display. Logo após isso escrevemos no display que o ESP32 LoRa inicializou e esperamos 1s.
Heltec.display->init(); // Inicializa o display
Heltec.display->flipScreenVertically(); // Vira na vertical
Heltec.display->setFont(ArialMT_Plain_10); //Escolhe a fonte
logo(); // Chama função que imprime logo
Heltec.display->drawString(0, 0, "ESP32 LoRa Iniciou"); // Escreve que foi Inicializado
Heltec.display->drawString(0, 11, "com Sucesso!");
Heltec.display->display();
delay(1000); // Espera 1s
}
Funções Loop
Então agora na função loop, iremos armazenar a temperatura e umidade lida pelo DHT11. Logo depois limpamos o display e imprimimos todas as informações nele. Logo após imprimir, criamos os pacotes, cada pacote enviamos uma letra como referência e enviamos a informação. Então no total enviamos 3 pacotes.
//Void -----------------------------------------------------------------------------------------------
void loop(){
temp = dht.readTemperature(); // Leitura da Temperatura
umid = dht.readHumidity(); // Leitura da Humidade
Heltec.display->clear(); // Limpa o display
Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); // Alinha o texto na esquerda
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
Heltec.display->drawString(0, 0, "Envio do Pacote: "); // Imprime informação do pacote
Heltec.display->drawString(90, 0, String(counter)); // Imprime numero do pacote
Heltec.display->drawString(0, 11, "Temperatura: " + String(temp)); // Imprime informação
Heltec.display->drawString(0, 22, "Umidade: " + String(umid)); // Imprime informação da umidade
Heltec.display->display();
/* LoRa.setTxPower(txPower,RFOUT_pin);
* txPower -- 0 ~ 20
* RFOUT_pin could be RF_PACONFIG_PASELECT_PABOOST ou RF_PACONFIG_PASELECT_RFO
* - RF_PACONFIG_PASELECT_PABOOST -- LoRa single saida via PABOOST, maxima saida 20dBm
* - RF_PACONFIG_PASELECT_RFO -- LoRa single saida via RFO_HF / RFO_LF, maxima saida 14dBm */
//Envio dos Pacotes
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("p"); // Informa que ira enviar o pacote
LoRa.print(counter); // Envia informação do pacote
LoRa.endPacket(); // Fecha o pacote
delay(10); // Espera 0,01s
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("t"); // Informa o envio da temperatura
LoRa.print(temp); // Envia informação da temperatura
LoRa.endPacket(); // Fecha o pacote
delay(10); // Espera 0,01s
LoRa.beginPacket(); // Cria pacote
LoRa.setTxPower(14,RF_PACONFIG_PASELECT_PABOOST);
LoRa.print("u"); // Informa o envio da humidade
LoRa.print(umid); // Envia informação da humidade
LoRa.endPacket(); // Fecha o pacote
Continuação Função Loop
Contudo como foi enviado o pacote acrescentamos +1 no contador e para sinalizar piscamos 1 vez o LED.
counter++;
digitalWrite(LED, HIGH); // Acende o LED da placa
delay(500); // Espera 0,5s
digitalWrite(LED, LOW); // Apaga o LED da placa
delay(500); // Espera 0,5s
}
Função Logo
Então agora na função logo, será onde iremos limpar a tela e desenhamos a logo.
//Logo -----------------------------------------------------------------------------------------------
void logo(){
Heltec.display->clear(); // Limpa o display
Heltec.display->drawXbm(0,10,logo_width,logo_height,logo_bits); // Imprime imagem
Heltec.display->display();
delay(1500); // Espera 1,5s
Heltec.display->clear(); // Limpa o display
}
E assim finalizamos todo código do Sender.
Programação Reciver
Contudo código do Reciver também foi dividido em cinco funções e dois arquivos. Entretanto sendo um arquivo o código e outro a imagem.
//Biblioteca ------------------------------------------------------------------------------------------
#include <WiFi.h> // Responsável pelo WiFi
#include <heltec.h> // Responsável pelo display e LoRa
#include "images.h" // Responsável pelo imagem
//LoRa ------------------------------------------------------------------------------------------------
#define BAND 915E6 // Frequência de banda
#define KEY 0xF3 // Chave para receber pacote
//WiFi ------------------------------------------------------------------------------------------------
const char* SSID = "<NOME-DA-REDE>"; // Nome da rede WiFi
const char* password = "<SENHA-DA-REDE>"; // Senha do WiFi
WiFiServer server(80); // Declaração do servidor junto a sua porta
//Variáveis Globais -----------------------------------------------------------------------------------
String rssi = "RSSI --"; // Sinal
String packSize = "--"; // Tamanho do Pacote
String packet; // Pacote
String temp; // Temperatura
String umid; // Umidade
//Função Auxiliares -----------------------------------------------------------------------------------
void logo(); // Responsável por imprimir a logo
void LoRaData(); // Responsável por imprimir no display
void cbk(int packetSize); // Responsável pelas informações
//Setup -----------------------------------------------------------------------------------------------
void setup() {
//Abaixo inicializa Display, LoRa, Serial, PABOOST, BAND
Heltec.begin(true, true, true, true, BAND);
LoRa.setSyncWord(KEY); // Chave para receber o pacote
Heltec.display->init(); // Inicializa o display
Heltec.display->flipScreenVertically(); // Vira na vertical
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
logo(); // Chama função que imprime logo
//WiFi
WiFi.begin(SSID, password); // Tenta se conectar no WiFi
while (WiFi.status() != WL_CONNECTED) { // Verifica se a Conexão foi realizada
delay(500); // Espera 0,5s
}
Serial.println(WiFi.localIP()); // Mostra o IP do ESP32
server.begin(); // Inicia o servidor
Heltec.display->drawStri ng(0, 0, "Esperando Pacote..."); // Escreve que foi Inicializado
Heltec.display->display();
delay(1000); // Espera 1s
LoRa.receive(); // Recebe Informação do LoRa
}
//Loop ------------------------------------------------------------------------------------------------
void loop() {
int packetSize = LoRa.parsePacket(); // Armazena a informação
if (packetSize) { cbk(packetSize); } // Chama a função para armazenar
delay(10); // Espera 0,1s
WiFiClient cliente = server.available();
if(cliente){
Serial.println("Novo Cliente");
String currentLine=""; // Declara variável vazia
while(cliente.connected()){ // Faz loop enquanto tiver cliente conectado
if(cliente.available()){ // Verifica se tem algum dado sendo passado
char c = cliente.read(); // Atribui a C as informações do cliente
if(c == '\n'){
if(currentLine.length() == 0){
cliente.println("HTTP/1.1 200 OK"); // Retorna para o Cliente que a solicitação dele deu certo
cliente.println("Content-type:text/html"); // Informa o iremos fazer um HTML
cliente.println("Connection: close");
cliente.println("");
//HTML
cliente.println("<!DOCTYPE html><html lang=\"pt-br\">");
cliente.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
cliente.println("<title>ESP32 LoRa - WIFI</title>");
//CSS
cliente.println("<style>html { background-color: #edf2f9; font-size: 20px; font-family: cursive; display: inline-block; margin: 0px auto; text-align: center;}");
cliente.println(".card { background-color: white; margin: 10px; padding: 10px; border-radius: 10px; width: 50%; display: flex;}");
cliente.println(".text { width: 70%;}");
cliente.println(".image { padding-top: 10%;}");
cliente.println("#grid { display: inline-flex;}</style>");
cliente.println("");
//Body
cliente.println("<body><h1>ESP32 LoRa - Web Server</h1>");
cliente.println("<div id=\"grid\">");
//Pacote
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Pacote: ");
cliente.print(packet);
cliente.println("</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://cdn.icon-icons.com/icons2/1465/PNG/512/724package_100522.png\" width=\"50px\"></div></div>");
//Temperatura
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Temperatura: ");
cliente.print(temp);
cliente.println(" C</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://1.bp.blogspot.com/-ZlYO13BMP-Y/WTRMcflEZ9I/AAAAAAAAXKM/ihxY2eyfZ1E6iRaBxof4RX54EbxXhJZMwCLcB/s1600/over_temperature_80_85.png\" width=\"50px\"></div></div>");
//Umidade
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Umidade: ");
cliente.print(umid);
cliente.println("%</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://cdn-icons-png.flaticon.com/512/728/728093.png\" width=\"50px\"></div></div>");
cliente.println("</body></html>"); //Finialização do body e HTML
cliente.println();
break;
} else{
currentLine = ""; // Limpa a variável
}
} else if(c != '\r'){ // Indica retorno atribui o C a currentLine
currentLine += c;
}
}
}
cliente.stop(); // Desconecta do Servidor
Serial.println("Cliente Desconectou.");
Serial.println("");
}
}
//Logo ------------------------------------------------------------------------------------------------
void logo(){
Heltec.display->clear(); // Limpa o display
Heltec.display->drawXbm(0,10,logo_width,logo_height,logo_bits);
Heltec.display->display();
delay(1500); // Espera 1,5s
Heltec.display->clear(); // Limpa o display
}
//LoRaData --------------------------------------------------------------------------------------------
void LoRaData(){
Heltec.display->clear(); // Limpa o display
Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); // Alinha o texto na esquerda
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
Heltec.display->drawString(0, 0, rssi + " dBm"); // Imprime informação do sinal
Heltec.display->drawString(0 , 13 , "Received "+ packSize + " bytes"); // Imprime tamanho
Heltec.display->drawString(0 , 26, "Pacote: " + packet); // Imprime pacote
Heltec.display->drawString(0 , 39, "Temperatura: "+ temp + "°C"); // Imprime temperatura
Heltec.display->drawString(0 , 52 , "Umidade: "+ umid + "%"); // Imprime umidade
Heltec.display->display();
}
//cbk -------------------------------------------------------------------------------------------------
void cbk(int packetSize) {
packSize = String(packetSize,DEC);
char l = (char) LoRa.read(); // Pega a primeira letra
if(l == 'p'){ // Verifica qual é a letra
packet = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
packet += (char) LoRa.read(); // Armazena o valor do Pacote
}
rssi = "RSSI " + String(LoRa.packetRssi(), DEC);
}
else if(l == 't'){
temp = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
temp += (char) LoRa.read(); // Armazena o valor da Temperatura
}
}
else if(l == 'u'){
umid = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
umid += (char) LoRa.read(); // Armazena o valor da Humidade
}
}
LoRaData(); // Chama função para imprimir no display
}
Vamos dar uma olhada mais de perto no código:
Incluindo Bibliotecas
Primeiramente temos que incluir as bibliotecas que usamos em nosso projeto.
//Biblioteca -----------------------------------------------------------------------------------------
#include <WiFi.h> // Responsável pelo WiFi
#include <heltec.h> // Responsável pelo display e LoRa
#include "images.h" // Responsável pelo imagem
Definições LoRa
Em seguida definimos a frequência e a chave (para garantir o recebimento receba apenas pacotes de seu remetente, para pode-se definir uma palavra de sincronização (entre 0 a 0xFF)) que usaremos no LoRa.
//LoRa -----------------------------------------------------------------------------------------------
#define BAND 915E6 // Frequência de banda
#define KEY 0xF3 // Chave para receber pacote
Definições WiFi
Logo após isso declaramos duas constantes o SSID (nome da rede wifi) e password (senha da rede), também inicializamos um objeto chamado server.
//WiFi -----------------------------------------------------------------------------------------------
const char* SSID = "<NOME-DA-REDE>"; // Nome da rede WiFi
const char* password = "<SENHA-DA-REDE>"; // Senha do WiFi
WiFiServer server(80); // Declaração do servidor junto a sua porta
Variáveis Globais
Então declaramos as variáveis globais que será o contador de pacotes, temperatura, umidade e sinal.
//Variáveis Globais ----------------------------------------------------------------------------------
String rssi = "RSSI --"; // Sinal
String packSize = "--"; // Tamanho do Pacote
String packet; // Pacote
String temp; // Temperatura
String umid; // Umidade
Funções Auxiliares
Logo após declaramos 3 funções auxiliares que usamos no projeto.
//Função Auxiliares ----------------------------------------------------------------------------------
void logo(); // Responsável por imprimir a logo
void LoRaData(); // Responsável por imprimir no display
void cbk(int packetSize); // Responsável pelas informações
Funções Setup
Então agora na função setup, primeiramente iremos inicializar o heltec com o display, LoRa, Serial, PABOOST e sincronizamos o LoRa. Em seguida inicializamos também o display, viramos na vertical e escolhemos a fonte juntamente com o tamanho e chamamos a função para imprimir a logo.
//Setup ----------------------------------------------------------------------------------------------
void setup() {
//Abaixo inicializa Display, LoRa, Serial, PABOOST, BAND
Heltec.begin(true, true, true, true, BAND);
LoRa.setSyncWord(KEY); // Chave para receber o pacote
Heltec.display->init(); // Inicializa o display
Heltec.display->flipScreenVertically(); // Vira na vertical
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
logo(); // Chama função que imprime logo
Logo após inicializamos o wifi com o SSID e o password, também inicializamos o objeto server. Então escrevemos no display “Esperando Pacote…”, esperamos 1s e recebemos informação do LoRa.
//WiFi
WiFi.begin(SSID, password); // Tenta se conectar no WiFi
while (WiFi.status() != WL_CONNECTED) { // Verifica se a Conexão foi realizada
delay(500); // Espera 0,5s
}
Serial.println(WiFi.localIP()); // Mostra o IP do ESP32
server.begin(); // Inicia o servidor
Heltec.display->drawStri ng(0, 0, "Esperando Pacote..."); // Escreve que foi Inicializado
Heltec.display->display();
delay(1000); // Espera 1s
LoRa.receive(); // Recebe Informação do LoRa
}
Funções Loop
Em seguida na função loop armazenamos a informação que chegou pelo LoRa e chama a função cbk. Logo após verificamos se algum cliente se conectou, caso tenha criamos um loop até que o cliente se desconecte. Então verificamos se tem algum dado sendo passado, lê as informações do cliente e atribui a c. Em seguida verificamos se c é igual a “\n” se for verdadeiro, ele retorna ao cliente que a solicitação foi concluída com sucesso. Logo depois retornarmos uma pagina HTML para o cliente. Entretanto caso seja falso, realizamos outra verificação se é diferente de “\r” incrementamos C em currentLine. Contudo quando o cliente se desconectar, nos desconectamos o cliente do server e imprimimos no serial.
//Loop -----------------------------------------------------------------------------------------------
void loop() {
int packetSize = LoRa.parsePacket(); // Armazena a informação
if (packetSize) { cbk(packetSize); } // Chama a função para armazenar
delay(10); // Espera 0,1s
WiFiClient cliente = server.available();
if(cliente){
Serial.println("Novo Cliente");
String currentLine=""; // Declara variável vazia
while(cliente.connected()){ // Faz loop enquanto tiver cliente conectado
if(cliente.available()){ // Verifica se tem algum dado sendo passado
char c = cliente.read(); // Atribui a C as informações do cliente
if(c == '\n'){
if(currentLine.length() == 0){
cliente.println("HTTP/1.1 200 OK"); // Retorna para o Cliente que a solicitação dele deu certo
cliente.println("Content-type:text/html"); // Informa o iremos fazer um HTML
cliente.println("Connection: close");
cliente.println("");
//HTML
cliente.println("<!DOCTYPE html><html lang=\"pt-br\">");
cliente.println("<head><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">");
cliente.println("<title>ESP32 LoRa - WIFI</title>");
//CSS
cliente.println("<style>html { background-color: #edf2f9; font-size: 20px; font-family: cursive; display: inline-block; margin: 0px auto; text-align: center;}");
cliente.println(".card { background-color: white; margin: 10px; padding: 10px; border-radius: 10px; width: 50%; display: flex;}");
cliente.println(".text { width: 70%;}");
cliente.println(".image { padding-top: 10%;}");
cliente.println("#grid { display: inline-flex;}</style>");
cliente.println("");
//Body
cliente.println("<body><h1>ESP32 LoRa - Web Server</h1>");
cliente.println("<div id=\"grid\">");
//Pacote
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Pacote: ");
cliente.print(packet);
cliente.println("</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://cdn.icon-icons.com/icons2/1465/PNG/512/724package_100522.png\" width=\"50px\"></div></div>");
//Temperatura
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Temperatura: ");
cliente.print(temp);
cliente.println(" C</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://1.bp.blogspot.com/-ZlYO13BMP-Y/WTRMcflEZ9I/AAAAAAAAXKM/ihxY2eyfZ1E6iRaBxof4RX54EbxXhJZMwCLcB/s1600/over_temperature_80_85.png\" width=\"50px\"></div></div>");
//Umidade
cliente.println("<div class=\"card\"><div class=\"text\">");
cliente.print("<p>Umidade: ");
cliente.print(umid);
cliente.println("%</p>");
cliente.println("</div><div class=\"image\"><img src=\"https://cdn-icons-png.flaticon.com/512/728/728093.png\" width=\"50px\"></div></div>");
cliente.println("</body></html>"); //Finialização do body e HTML
cliente.println();
break;
} else{
currentLine = ""; // Limpa a variável
}
} else if(c != '\r'){ // Indica retorno atribui o C a currentLine
currentLine += c;
}
}
}
cliente.stop(); // Desconecta do Servidor
Serial.println("Cliente Desconectou.");
Serial.println("");
}
}
Função Logo
Então na função logo, limpamos o display e desenhamos a logo.
//Logo -----------------------------------------------------------------------------------------------
void logo(){
Heltec.display->clear(); // Limpa o display
Heltec.display->drawXbm(0,10,logo_width,logo_height,logo_bits);
Heltec.display->display();
delay(1500); // Espera 1,5s
Heltec.display->clear(); // Limpa o display
}
Função LoRa Data
Logo após temos a função LoRaData, limpamos o display e escrevemos todas as informações sobre sinal, tamanho do pacote, numero do pacote, temperatura e umidade nele.
//LoRaData -------------------------------------------------------------------------------------------
void LoRaData(){
Heltec.display->clear(); // Limpa o display
Heltec.display->setTextAlignment(TEXT_ALIGN_LEFT); // Alinha o texto na esquerda
Heltec.display->setFont(ArialMT_Plain_10); // Escolhe a fonte
Heltec.display->drawString(0, 0, rssi + " dBm"); // Imprime informação do sinal
Heltec.display->drawString(0 , 13 , "Received "+ packSize + " bytes"); // Imprime tamanho
Heltec.display->drawString(0 , 26, "Pacote: " + packet); // Imprime numero do pacote
Heltec.display->drawString(0 , 39, "Temperatura: "+ temp + "°C"); // Imprime temperatura
Heltec.display->drawString(0 , 52 , "Umidade: "+ umid + "%"); // Imprime umidade
Heltec.display->display();
}
Função cbk
Agora na função cbk, é um pouquinho mais complexo pois primeiramente iremos armazenar em packSize a string em decimal. Em seguida lemos a primeira letra do pacote para que assim possamos saber sobre a qual pacote se refere. Logo após fazemos uma verificação se a primeira letra é “p”. Entretanto se for conseguimos identificar que o pacote enviado é referente ao número do pacote. Então sabendo disso limpamos a variável packet e fazemos um for para armazenar letra por letra no pacote.
//cbk ------------------------------------------------------------------------------------------------
void cbk(int packetSize) {
packSize = String(packetSize,DEC);
char l = (char) LoRa.read(); // Pega a primeira letra
if(l == 'p'){ // Verifica qual é a letra
packet = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
packet += (char) LoRa.read(); // Armazena o valor do Pacote
}
rssi = "RSSI " + String(LoRa.packetRssi(), DEC);
}
Continuação da Função cbk
Entretanto caso não seja iremos realizar novamente o mesmo procedimento para os demais. Após isso podemos chamar a função LoRaData para assim possamos imprimir as informações no display.
else if(l == 't'){
temp = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
temp += (char) LoRa.read(); // Armazena o valor da Temperatura
}
}
else if(l == 'u'){
umid = ""; // Limpa a variável
for (int i = 1; i < packetSize; i++){
umid += (char) LoRa.read(); // Armazena o valor da Humidade
}
}
LoRaData(); // Chama função LoRaData()
}
E assim finalizamos todo código do Reciver.
Arquivo images.h
#define logo_width 124
#define logo_height 44
const unsigned char logo_bits[] = {
0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0xA0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x90,
0x4A, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x10, 0x20, 0x01, 0x42, 0x00, 0xE0, 0x0F, 0xE0, 0x0F, 0xE0,
0x0F, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x4A, 0x0A, 0x48, 0x12, 0x00, 0xE0,
0x0F, 0xE0, 0x0F, 0xE0, 0x07, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x0A, 0x00,
0x44, 0x05, 0x00, 0xC0, 0x0F, 0xF0, 0x0F, 0xF0, 0x07, 0x00, 0xF8, 0x03,
0x00, 0x40, 0x50, 0x55, 0x21, 0x90, 0x00, 0xC0, 0x1F, 0xF0, 0x1F, 0xF0,
0x07, 0x00, 0xF8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x48, 0x86, 0x01, 0xC0,
0x1F, 0xF0, 0x1F, 0xF0, 0x03, 0x00, 0xF8, 0x03, 0x80, 0x07, 0x01, 0x00,
0x00, 0x10, 0x00, 0x80, 0x1F, 0xF8, 0x1F, 0xF0, 0x03, 0x00, 0xF8, 0x01,
0x80, 0xFC, 0xFF, 0xF1, 0x07, 0x12, 0x00, 0x80, 0x1F, 0xF8, 0x3F, 0xF8,
0x03, 0x00, 0xF8, 0x01, 0x80, 0xFC, 0x7F, 0xFC, 0x1F, 0x48, 0x00, 0x80,
0x1F, 0xF8, 0x3F, 0xF8, 0x01, 0x00, 0xF8, 0x03, 0x80, 0x87, 0x7F, 0xAE,
0x36, 0x54, 0x00, 0x00, 0x1F, 0xFC, 0x3E, 0xF8, 0x01, 0x00, 0xF8, 0x03,
0x00, 0x80, 0x3F, 0x93, 0xE4, 0x00, 0x00, 0x00, 0x0F, 0x7C, 0x7E, 0xFC,
0x01, 0x00, 0xF8, 0x01, 0x00, 0x80, 0x9C, 0x91, 0xCC, 0x04, 0x00, 0x00,
0x0F, 0x7C, 0x7C, 0xFC, 0x00, 0x00, 0xF8, 0x03, 0x00, 0x00, 0x9A, 0xFF,
0xFF, 0x51, 0x02, 0x00, 0x0F, 0x7E, 0x7C, 0xFC, 0x00, 0x00, 0xF8, 0x01,
0x02, 0x00, 0xDB, 0x88, 0x10, 0x41, 0x00, 0x00, 0x06, 0x3E, 0xFC, 0xFE,
0xF0, 0x03, 0xF8, 0x03, 0x4E, 0x2A, 0x48, 0x88, 0x10, 0x11, 0x09, 0x00,
0x06, 0x3F, 0xFC, 0x7E, 0xF0, 0x03, 0xF8, 0x01, 0xF9, 0xFF, 0x4F, 0x88,
0x10, 0x13, 0x08, 0x00, 0x02, 0x3F, 0xF8, 0x7E, 0xF0, 0x03, 0xF8, 0x03,
0xFB, 0xFF, 0xCC, 0xDF, 0x57, 0x83, 0x01, 0x00, 0x00, 0x1F, 0xF8, 0x7F,
0xF0, 0x07, 0xFC, 0x01, 0x0E, 0x00, 0xC9, 0xA9, 0x75, 0x53, 0x1A, 0x00,
0x80, 0x1F, 0xF0, 0x3F, 0xF0, 0xEF, 0xFE, 0x03, 0x00, 0x00, 0x4B, 0x88,
0x10, 0x03, 0x00, 0x00, 0x80, 0x1F, 0xF0, 0x3F, 0xF0, 0xFF, 0xFF, 0x01,
0xC0, 0x1B, 0xC8, 0x88, 0x10, 0x43, 0x02, 0x00, 0x80, 0x0F, 0xF0, 0x3F,
0xF0, 0xFF, 0xFF, 0x01, 0x40, 0xFE, 0xCE, 0x88, 0x88, 0x21, 0x08, 0x00,
0x80, 0x0F, 0xE0, 0x1F, 0xE0, 0xFF, 0xFF, 0x00, 0xC0, 0xFE, 0x9F, 0xFF,
0xFF, 0x01, 0x02, 0x00, 0xC0, 0x0F, 0xE0, 0x1F, 0xC0, 0xFF, 0x7F, 0x00,
0x80, 0x83, 0x9F, 0x91, 0xC9, 0x60, 0x00, 0x00, 0xC0, 0x06, 0xC0, 0x1B,
0x00, 0xFF, 0x1F, 0x00, 0x00, 0x80, 0x3F, 0x93, 0x64, 0x08, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB8, 0x7F, 0xAE,
0x76, 0xC2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xE4, 0xFF, 0xFC, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0xFF, 0xF1, 0x07, 0x0A, 0x00, 0x48,
0x92, 0x24, 0x49, 0x52, 0xAA, 0xAA, 0xAA, 0x0A, 0x00, 0x38, 0x00, 0x00,
0x00, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x60, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x11, 0x88, 0x00, 0x52, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x49, 0x12,
0x4A, 0x04, 0x00, 0x48, 0x24, 0x45, 0x54, 0x42, 0x48, 0x12, 0x91, 0x00,
0x00, 0x00, 0x04, 0xA0, 0x52, 0x0A, 0x00, 0x20, 0x96, 0x08, 0x42, 0x22,
0x49, 0x83, 0x08, 0x02, 0x00, 0x00, 0x50, 0x06, 0x08, 0x20, 0x00, 0xC8,
0x10, 0x65, 0x55, 0x44, 0x09, 0x5A, 0xD2, 0x04, 0x00, 0x00, 0x04, 0x50,
0x42, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xA0, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, };
Observação do Projeto WiFi com LoRa
Do mesmo modo caso você queira colocar uma imagem também, você irá precisar dimensionar ela para 128 x 58 no máximo podendo ser menor. Contudo você pode estar entrando no paint para fazer isso.
Logo após isso acessamos o site da online-utility e importamos a imagem que redimensionamos. Em seguida mudamos de .xbm para .h e colocamos na pasta do nosso código.
Entretanto também indicamos que quando for fazer o HTML utilize o Visual Studio Code.
Resultado do Projeto WiFi com LoRa
Esse foi o resultado obtido com nosso projeto.
Agradecemos sua Presença
Por fim, espero que tenham gostado e aprendido. Compartilhe com seus colegas e deixe um comentário de qual projeto deveria ser o próximo aqui no Blog da WJ Componentes!!
Enfim estarei deixando o arquivo Arduíno, software e sites utilizados e deixarei os arquivos os Fritzing dos componentes.
Fique à vontade para tirar suas dúvidas nos comentários.
Software e Sites Utilizados
GitHub das Bibliotecas Utilizadas
Post Relacionados
Posts mais Recentes
- Programando Relé RF 4331 -Instruções de emparelhamento do modo de alternância Modo de… Leia mais: Programando Relé RF 433
- Acionando motor DC por meio do pino “Touch” do ESP-32Neste projeto, vamos explorar uma aplicação ainda mais dinâmica e… Leia mais: Acionando motor DC por meio do pino “Touch” do ESP-32
- Acendendo led RGB por meio do pino “Touch” do ESP-32No último post, exploramos o fascinante mundo dos pinos touch… Leia mais: Acendendo led RGB por meio do pino “Touch” do ESP-32
- Utilizando os Pinos touch do ESP32Nesse projeto Vamos aprender a usar os pinos touch´s do… Leia mais: Utilizando os Pinos touch do ESP32
- Como Programar e Localizar o Endereço de uma Tela OLED I2C com Arduinoeste guia, vou levá-lo através dos passos para programar uma… Leia mais: Como Programar e Localizar o Endereço de uma Tela OLED I2C com Arduino
Julio Cesar Bonow Manoel
Cursando Engenharia da Computação pelo Centro Universitário Facens e atua no desenvolvimento de projetos na WJ Componentes. Participante da equipe de robótica Omegabotz.
Deixe um comentário