Dando continuidade ao assunto
que tratamos na última sexta-feira, no vídeo e no artigo de hoje vamos retomar
a possibilidade de criar dispositivos bastante uteis no que diz respeito à
Internet das Coisas. Utilizando o nosso exemplo, você poderá usar sensores
destinados à segurança, envolvendo gás, temperatura e umidade, por exemplo, com
um ESP32 Lora. Estes vão te possibilitar a montagem de um alarme que vai enviar
mensagem SMS para o seu smartphone em caso de algum tipo de problema, como um
vazamento de gás, por exemplo.
Na 1ª parte deste vídeo: ESP32 LORA: SENSOR DE GÁS, UMIDADE E TEMPERATURA POR SMS - Pt1, utilizamos, então, um módulo sensor de gás MQ2 e um sensor
de temperatura e umidade DHT22 (AM2302). Como você pode ver na imagem abaixo, ambos
são lidos por um primeiro ESP32 Lora, que funcionará como Sender, e enviará
alerta para um segundo ESP32 Lora, que estará como Receiver, caso haja alguma
intercorrência.
Via UART, o Receiver vai
mandar as informações para o Arduino Nano, que via SPI faz comunicação de cabo
como a rede interna, te deixando independente da um rede WiFi 2.4. Então, a
partir da comunicação com o Server, este ativa um gateway que vai enviar um SMS
para o seu celular.
Agora, nesta 3ª e última
parte, vamos fazer uma breve revisão do funcionamento do protótipo com ESP32
Lora e partiremos para o código .INO do Receiver, bem como do Arduino Nano.
Código Receiver
Receiver – Organização do código
1. Setup
2. Loop
2.1. readPacket: Função responsável por ler
os bytes do pacote recebido e atribuir para uma String.
2.1.1. showDisplay: Função responsável por exibir
uma mensagem no display com as fontes e alinhamentos já configurados.
2.1.2. Alarm: Função
responsável por ativar o buzzer durante 1 segundo.
Código Receiver[Includes e Defines]
Assim, como no Sender, neste
início do código do Receiver, vamos incluir as bibliotecas e fazer a definição
dos pinos. Ainda, vamos selecionar a frequência de rádio, adicionar parâmetros e
apontar detalhes do pacote de dados e do buzzer.
#include <SPI.h> //responsável pela comunicação serial #include <LoRa.h> //responsável pela comunicação com o WIFI Lora #include <Wire.h> //responsável pela comunicação i2c #include "SSD1306.h" //responsável pela comunicação com o display // Definição dos pinos #define SCK 5 // GPIO5 -- SX127x's SCK #define MISO 19 // GPIO19 -- SX127x's MISO #define MOSI 27 // GPIO27 -- SX127x's MOSI #define SS 18 // GPIO18 -- SX127x's CS #define RST 14 // GPIO14 -- SX127x's RESET #define DI00 26 // GPIO26 -- SX127x's IRQ(Interrupt Request) #define BAND 433E6 //Frequencia do radio - podemos utilizar ainda : 433E6, 868E6, 915E6 //parametros: address,SDA,SCL SSD1306 display(0x3c, 4, 15); //construtor do objeto que controlaremos o display String packSize; //tamanho do pacote convertido em String String packet; //pacote recebido const int buzzerpin = 13; //buzzer
Código Receiver [Setup]
No Setup, vamos inicializar a
serial, configurar o buzzer e o funcionamento do display.
void setup() { //inicia serial com 9600 bits por segundo Serial.begin(9600); //configura buzzer como saída pinMode(buzzerpin, OUTPUT); //configura RST do oled como saida pinMode(16,OUTPUT); //reseta o OLED digitalWrite(16, LOW); //aguarda 50ms delay(50); //enquanto o OLED estiver ligado, GPIO16 deve estar HIGH digitalWrite(16, HIGH); //inicializa display display.init(); //inverte a tela verticalmente (de ponta cabeça) display.flipScreenVertically(); //configura a fonte do display display.setFont(ArialMT_Plain_10); //aguarda 1500ms delay(1500);
Na sequência, iniciamos a
serial com o Lora, configuramos os pinos que serão utilizados pela biblioteca e
inicializamos o Lora com a frequência específica. Habilitamos o mesmo para
receber dados.
//limpa display display.clear(); //inicia a comunicação serial com o Lora SPI.begin(SCK,MISO,MOSI,SS); //configura os pinos que serão utlizados pela biblioteca (deve ser chamado antes do LoRa.begin) LoRa.setPins(SS,RST,DI00); //inicializa o Lora com a frequencia específica. if (!LoRa.begin(BAND)) { //escreve na pos 0,0 a mensagem em aspas display.drawString(0, 0, "Starting LoRa failed!"); //exibe no display display.display(); //deixa em loop infinito até que o ESP seja reiniciado while (1); } //habilita o Lora para receber dados LoRa.receive(); }
Código Receiver [Loop]
Aqui no Loop, fazemos novas
definições sobre o display.
void loop() { //limpa display display.clear(); //configura alinhamento de texto à esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //configura fonte do texto display.setFont(ArialMT_Plain_16); //escreve na pos 0,10 a mensagem entre aspas display.drawString(0, 0, "Running..."); //exibe no display display.display(); //parsePacket: checa se um pacote foi recebido //retorno: tamanho do pacote em bytes. Se retornar 0 (ZERO) nenhum pacote foi recebido int packetSize = LoRa.parsePacket(); //caso tenha recebido pacote if (packetSize) { //chama a função responsável por recuperar o conteúdo do pacote recebido readPacket(packetSize); } //aguarda 10ms delay(10); }
Código Receiver [readPacket]
Definimos a função que trata
do recebimento de conteúdo do pacote, exibição de dados no display e disparo do
buzzer.
//função responsável por recuperar o conteúdo do pacote recebido //parametro: tamanho do pacote (bytes) void readPacket(int packetSize) { //deixa string com valor vazio packet =""; //lê byte a byte do pacote e atribui à string "packet" for (int i = 0; i < packetSize; i++) { packet += (char) LoRa.read(); //recupera o dado recebido e concatena na variável "packet" } //se a mensagem recebida contem "alarm", então soa o buzzer if(strstr(packet.c_str(),"ALARM")!=NULL) { //exibe pacote Serial.println(packet); //exibe no display showDisplay("Gas Detected!"); //soa o buzzer alarm(); } }
Código Receiver [alarm e showDisplay]
Nesta parte do código,
tratamos da ativação do alarme, bem como a exibição de dados relacionados a
esta medida no display.
void alarm() { //ativa buzzer digitalWrite(buzzerpin, HIGH); //aguarda 1 segundo delay(1000); //desativa buzzer digitalWrite(buzzerpin, LOW); } //exibe mensagem recebida como parâmetro void showDisplay(String msg) { //limpa o display display.clear(); //configura alinhamento de texto à esquerda display.setTextAlignment(TEXT_ALIGN_LEFT); //configura fonte do texto display.setFont(ArialMT_Plain_16); //escreve na pos 0,25 a mensagem display.drawString(0 , 25 , msg); //exibe no display display.display(); }
Código Arduino Nano
Arduino – Organização do código
Neste nosso projeto,
utilizamos o arduino como uma espécie de ponte.
Setup – startEthernet: Função
responsável por iniciar a conexão do client ethernet.
Loop – splitString: Função
responsável por “retirar” os valores de umidade e temperatura da string
recebida pela serial.
Código Arduino[Includes e Defines]
Primeiramente vamos incluir a
lib SPI, assim como a biblioteca Ethernet para o módulo ENC28J60. Abordamos a
configuração dos leds, da estrutura para abrigar o MAC Address, gateway de
envio de SMS, bem como IP da rede destinada ao módulo Ethernet. Identificamos a
rede interna e o objeto Client. Utilizamos uma Flag, que permite apenas um
envio de mensagem.
#include <SPI.h> //lib para a Serial Peripheral Interface (SPI) #include <UIPEthernet.h> //lib Ethernet para o módulo ENC28J60 #define GREENLED 7 //pino led verde #define REDLED 8 //pino led vermelho //endereço mac (1,2,3,4,5) para a configuração ethernet uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05}; //gateway de envio de SMS char gateway[] = "111.11.111.1"; //ip da rede destinado ao módulo ethernet (conectado por cabo) IPAddress ip(111,11,111,11); //objeto Ethernet para conexões de clientes EthernetClient client; //Humidade e Temperatura String H,T; //Flag que permite apenas um envio de mensagem //O envio fica dentro do "loop()" , assim que o arduino recebe dados na porta serial ele envia a mensagem //Caso esta flag não exista, um número descontrolado de mensagens será enviado bool messageSent = false;
Código Arduino[Setup]
Novamente vamos inicializar a
serial e definir os pinos, além de configurar o client ethernet.
void setup() { //inicializa Serial com 9600 bits por segundo Serial.begin(9600); //enquanto a serial não for inicializada, aguarda while (!Serial); //exibe mensagem Serial.println("Serial ok"); //define pino do led verde como saída pinMode(GREENLED,OUTPUT); //define pino do led vermelho como saída pinMode(REDLED,OUTPUT); //inicializa e configura o client ethernet if(startEthernet()) { //acende o led verde digitalWrite(GREENLED,HIGH); }
Definimos que o led verde
deverá piscar caso a ethernet não seja inicializada.
else { //se a ethernet não for inicializada //pisca led vermelho digitalWrite(GREENLED,HIGH); delay(500); digitalWrite(GREENLED,LOW); delay(500); digitalWrite(GREENLED,HIGH); delay(500); digitalWrite(GREENLED,LOW); } }
Código Arduino[startEthernet]
Nesta parte, vamos configurar
os dados de rede do cliente ethernet e as mensagens a serem exibidas no
display.
//Obs: As exibições na serial (Serial.println) são apenas para verificações, ao serem retiradas do código não mudarão o funcionamento do protótipo //função responsável por inicializar e conectar o client ethernet //este booleano pode ser retirado! pois sempre retornará true bool startEthernet() { //configura dados de rede Ethernet.begin(mac, ip); //dá ao Ethernet Shield um segundo para inicializar delay(1000); return true; }
Código Arduino[Loop]
No Loop, verificamos se
existem dados disponíveis enviados pela serial. Ainda, verificamos se o cliente
está conectado.
void loop() { //se existem dados enviados pela serial if(Serial.available()) { if (client.connected() && client.available()) { char c = client.read(); Serial.print(c); } //se o client está desconectado if (!client.connected()) { //desconecta client client.stop(); delay(1); } }
Caso o cliente esteja
conectado, este lê mensagem enviada pela serial.
//lê mensagem enviada pela serial String msg = Serial.readString(); //se na mensagem existir a palavra "ALARM" e o SMS ainda não estiver sido enviado if(strstr(msg.c_str(),"ALARM")!=NULL && !messageSent) { //"desmembra" mensagem e atribui para as variáveis os valores de Humidade e Temperatura splitString(msg); Serial.println("Packet: "+msg); if (client.connect(gateway, 80)) { //exibe mensagem Serial.println("connected"); //envia sms client.println("GET /script/sms/meu_script_sms.php?umidade="+H+"&temperatura="+T+" HTTP/1.1"); client.println("Host: 111.11.111.1"); client.println(); //exibe mensagem enviada Serial.println("Message sent!"); //sinaliza que enviou acendendo o led vermelho digitalWrite(REDLED,HIGH); //atribui true para a flag, evitando múltiplos envios messageSent = true; } }
Já no caso do cliente estar
desconectado, será sinalizada a desconexão e o led verde será apagado.
//se o client está desconectado if (!client.connected()) { //desconecta client client.stop(); delay(1); }
Código Arduino[splitString]
Nesta função, atribuímos os
valores às variáveis, como umidade e temperatura, por exemplo.
//Exemplo de mensagem: ALARM|30.12|27.82°C //"desmembra" mensagem atribuindo os valores às variáveis void splitString(String msg) { //inicia variáveis com vazio H = T = ""; int i; //percorre string até encontrar o delimitador pipe "|" for(i=0; i< msg.length() && msg.charAt(i)!='|'; i++); i++; //percorre string até o próximo delimitador atribuindo valor de humidade while(i< msg.length() && msg.charAt(i)!='|') { H+=msg.charAt(i); i++; } i++; //percorre string até o símbolo "°" atribuindo valor de temperatura while(i< msg.length() && msg.charAt(i)!='°') { T+=msg.charAt(i); i++; } }
Script de envio de Mensagens SMS
*É preciso um gateway de SMS
para que o script funcione! Por que eu escolhi utilizar um script PHP? Porque,
independentemente se você quer mandar SMS, fazer ligação, mandar e-mail, entre
outros, você pega os seus dados e joga em uma base SQL. Essa base é sua, então,
você não vai precisar ficar pagando para uma empresa, pois vai ter um servidor
alugado, o que sai mais barato. É possível armazenar muitos Terabytes de
informação pagando pouco.
Destaco que o Gateway-SMS é
uma empresa que eu pago pelo envio de mensagens, isso por mensalidade ou por
unidade.
Lembro ainda que
obrigatoriamente você terá que fazer duas alterações neste código para realizar
essa montagem: no ID de cliente que você vai receber da empresa que administra
o envio de SMSs e no número de celular, onde você vai preencher o seu número de
telefone.
<?php $umidade = $_GET['umidade']; $temperatura = $_GET['temperatura']; header ('Content-type: text/html; charset=UTF-8'); function post_to_url($url, $data) { $fields = http_build_query($data); $post = curl_init(); $url = $url.'?'.$fields; curl_setopt($post, CURLOPT_URL, $url); curl_setopt($post, CURLOPT_POST, 1); curl_setopt($post, CURLOPT_POSTFIELDS, $fields); $result = curl_exec($post); if($result == false) { die('Curl error: ' . curl_error($post)); } curl_close($post); } $url = "https://GateWay-SMS"; $data = array ( 'content' => 'Gás detectado!!!Umidade do ar:'.$umidade.' -Temperatura:'.$temperatura.' C', 'sender' => 'ID', 'receivers' => '18900000000' ); post_to_url($url, $data); ?>
Gateway SMS
Essa é a empresa de Gateway que utilizo: https://sms.comtele.com.br/. Ela garante o envio da mensagem até a operadora.
Faça o download dos arquivos:
6 Comentários
Bom dia Fernando!
ResponderExcluirUm dúvida... Você já conseguiu usar um modulo SD card que é SPI junto com o Lora?
Lora usa SPI pra transmissão e a ativação do SS é feito pela biblioteca....está difícil alterar as coisas! Tem alguma luz pra me ajudar?
O contato contato@fernandok.com... É mais trocar uma idéia por lá? :D
ExcluirEsta com erro o link de download do arquivo .INO
ResponderExcluirOlá, Hugo.
ExcluirAtualizamos o link. Pode tentar novamente, por favor?
Abraço
Fernando, você chegou a tentar ligar o ENC28J60 diretamente no ESP32 sem passar pelo Arduino Nano?
ResponderExcluirolá, estou a ter computação ubíqua e Internet das coisas, e os teu vídeos estão a decepar todas as minhas duvidas, sou um fan seu.
ResponderExcluir