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