ESP32 LORA: Gas Sensor, Humidity, and Temperature by SMS – Part 2
by Fernando Koyanagi in Circuits > Microcontrollers
4142 Views, 14 Favorites, 0 Comments
ESP32 LORA: Gas Sensor, Humidity, and Temperature by SMS – Part 2
Continuing the subject we discussed last Friday, in today’s article and video we return to the creation of extremely useful devices for your home or workplace, in regard to the Internet of Things. As we have shown, you can use safety sensors that involve gas, temperature, and humidity (just as examples), with an ESP32 LORA. This enables you to set up an alarm that sends an SMS message to your smartphone, in the unfortunate event of a gas leak, as an example.
In the first part of this video: ESP32 LORA: Gas Sensor, Humidity, and Temperature by SMS – Part 1, we use an MQ2 gas sensor module and a DHT22 (AM2302) temperature and humidity sensor. As you can see in the image below, both are read by the first ESP32 LORA, which will function as the Sender. It will then send an alert to the second ESP32 LORA, which will be the Receiver, in case there is any intercurrence.
Via UART, the Receiver will send the information to the Arduino Nano. Via SPI, this makes cable communication the internal network, making you independent from a 2.4 WiFi network. Then, from the communication with the Server, this activates a gateway that will send an SMS to your cell phone.
Now, in this third and last part, we will do a brief review of the prototype's operation with ESP32 LORA. We will start with the .INO code of the Receiver, as well as the Arduino Nano.
Receiver - Organization of the Code
1. Setup
2. Loop
2.1. readPacket: Function responsible for reading the bytes of the received packet, and the assigning to a String.
2.1.1. showDisplay: Function responsible for displaying a message on the display, with the fonts and alignments already configured.
2.1.2. Alarm: Function responsible for activating the buzzer for 1 second.
Receiver Code [Includes and Defines]
So, similarly to the Sender, we will include the libraries and make the pin definition at the beginning of the RECEIVED code. Also, let's select the radio frequency, add parameters, and point details of the data packet and buzzer.
#include <SPI.h> //serial peripheral interface (SPI) library #include <LoRa.h> //wifi lora library #include <Wire.h> //communication i2c library #include "SSD1306.h" //display communication library // Pins definition #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 //Radio frequency, we can still use: 433E6, 868E6, 915E6 //parameters: address,SDA,SCL SSD1306 display(0x3c, 4, 15); //display object String packSize; //variable used to receive the size of package converted in string String packet; //variable used to receive the package const int buzzerpin = 13; //buzzer
Receiver Code [Setup]
In the Setup, we will initialize the serial, and configure the buzzer and display operation.
void setup()
{
//initialize the Serial with 9600b per second
Serial.begin(9600);
//configures buzzer as output
pinMode(buzzerpin, OUTPUT);
//configures oled pins as output
pinMode(16,OUTPUT);
//reset oled
digitalWrite(16, LOW);
//waits 50ms
delay(50);
//while the oled is on, GPIO16 must be HIGH
digitalWrite(16, HIGH);
//initializes the display
display.init();
//flip vertically the display
display.flipScreenVertically();
//set display font
display.setFont(ArialMT_Plain_10);
//waits 1500ms
delay(1500);Then, we start the serial with LORA, configure the pins that will be used by the library, and initialize the LORA with the specific frequency. We will enable it to receive data.
//clear the display
display.clear();
//initializes serial interface
SPI.begin(SCK,MISO,MOSI,SS);
//set Lora pins
LoRa.setPins(SS,RST,DI00);
//initializes the lora, seting the radio frequency
if (!LoRa.begin(BAND))
{
//draw in the position 0,0 the message in between quotation marks
display.drawString(0, 0, "Starting LoRa failed!");
//turns on the LCD display
display.display();
//do nothing forever
while (1);
}
//sets lora as receiver
LoRa.receive();
}Receiver Code [Loop]
Here in the Loop, we make new definitions on the display.
void loop()
{
//clear display
display.clear();
//set the text alignment to left
display.setTextAlignment(TEXT_ALIGN_LEFT);
//sets the text font
display.setFont(ArialMT_Plain_16);
//draw in the position 0,0 the message in between quotation marks
display.drawString(0, 0, "Running...");
//turns on the LCD display
display.display();
//parsePacket: check if a packet was received
int packetSize = LoRa.parsePacket();
//if a packet was received
if (packetSize)
{
//reads byte to byte and concatenates to string "packet"
readPacket(packetSize);
}
//waits 10ms
delay(10);
}Receiver Code [readPacket]
We define the function that deals with the reception of package contents, display date in the display, and the firing of the buzzer.
//reads byte to byte and concatenates to string "packet"
void readPacket(int packetSize)
{
//sets string to ""
packet ="";</p><p> //reads byte to byte and concatenates to string "packet"
for (int i = 0; i < packetSize; i++)
{
packet += (char) LoRa.read();
}
// if the received message contains "alarm", then turns on the buzzer
if(strstr(packet.c_str(),"ALARM")!=NULL)
{
//shows packet to the serial
Serial.println(packet);
//shows 'gas detected' to the serial
showDisplay("Gas Detected!");
//turns on the buzzer
alarm();
}
}Receiver Code [alarm and ShowDisplay]
In this part of the code, we deal with the activation of the alarm, as well as the display data related to this measurement in the display.
void alarm()
{
//turns on the buzzer
digitalWrite(buzzerpin, HIGH);
//waits 1s
delay(1000);
//turns off the buzzer
digitalWrite(buzzerpin, LOW);
}
void showDisplay(String msg)
{
//clear display
display.clear();
//set the text alignment to left
display.setTextAlignment(TEXT_ALIGN_LEFT);
//sets the text font
display.setFont(ArialMT_Plain_16);
//draw in the position 0,25 the message in between quotation marks
display.drawString(0 , 25 , msg);
//turns on the LCD display
display.display();
}Arduino Nano – Code Organization
In this project, we use the Arduino as a kind of bridge.
Setup - startEthernet: Function responsible for initiating the Ethernet client connection.
Loop - splitString: Function responsible for "removing" the values of humidity and temperature of the string received by the serial.
Arduino Code [Includes and Defines]
First, let's include the SPI lib, as well as the Ethernet library for the ENC28J60 module. We work with the configuration of the LEDs, the structure to house the MAC Address, and the SMS sending gateway, as well as the IP of the network destined for the Ethernet module. We identify the internal network and the Client object. We use a Flag, which allows only one message to be sent.
#include <SPI.h> //Serial Peripheral Interface (SPI) library
#include <UIPEthernet.h> //Ethernet ENC28J60 module library
#define GREENLED 7 //green led pin
#define REDLED 8 //red led pin
//mac address (1,2,3,4,5) to ethernet configuration
uint8_t mac[6] = {0x00,0x01,0x02,0x03,0x04,0x05};
//sms sender gateway
char gateway[] = "111.11.111.1";
//network ip to the ethernet module (conected with cable)
IPAddress ip(111,11,111,11);
//Ethernet object to client conections
EthernetClient client;
//Humidity and Temperature
String H,T;
//Flag that allows only one message to be sent
bool messageSent = false;Arduino Code [Setup]
Again, we will initialize the serial, define the pins, and configure the Ethernet client.
void setup()
{
//initialize the Serial with 9600b per second
Serial.begin(9600);</p><p> //while the serial is not started, wait
while (!Serial);</p><p> //show message
Serial.println("Serial ok");
//set the green led pin as output
pinMode(GREENLED,OUTPUT);
//set the red led pin as output
pinMode(REDLED,OUTPUT);</p><p> //function responsible for initializing and connecting the ethernet client
Ethernet.begin(mac, ip);
//give to Ethernet Shield a second to be initialize
delay(1000);
//light up green led
digitalWrite(GREENLED,HIGH);
}We have determined that the green LED should flash if Ethernet is not initialized.
else<br> {
Serial.println("Connecting failed...");
digitalWrite(GREENLED,HIGH);
delay(500);
digitalWrite(GREENLED,LOW);
delay(500);
digitalWrite(GREENLED,HIGH);
delay(500);
digitalWrite(GREENLED,LOW);
}Arduino Code [startEthernet]
In this part, we will configure the Ethernet client network data and the messages to be displayed on the display.
//function responsible for initializing and connecting the ethernet client Ethernet.begin(mac, ip); //give to Ethernet Shield a second to be initialize delay(1000);
Arduino Code [Loop]
In the Loop, we check if there is available data sent by the serial. Also, we verify that the client is connected.
void loop()
{
//if serial data exists
if(Serial.available())
{</p><p>if (client.connected() && client.available()) <br> {
char c = client.read();
Serial.print(c);
}</p><p> //if client disconnected
if (!client.connected())
{
//stop client
client.stop();
delay(1);
}
}If the client is connected, it reads the message sent by the serial.
//read the message
String msg = Serial.readString();
//if the substring "ALARM" exists in the message and the message has no sent yet
if(strstr(msg.c_str(),"ALARM")!=NULL && !messageSent)
{
//split the message and obtains the humidity and temperature values
splitString(msg);</p><p> Serial.println("Packet: "+msg);
if (client.connect(gateway, 80))
{
//shows message
Serial.println("connected");
//send sms
client.println("GET /script/sms/my_script_sms.php?humidity="+H+"&temperature="+T+" HTTP/1.1");
client.println("Host: 111.11.111.1");
client.println();
//shows message
Serial.println("Message sent!");
//light up red led to indicate the message has been sent
digitalWrite(REDLED,HIGH);</p><p>//set true to flag, it blocks multiples sends
messageSent = true;
}
}In the case that the client is disconnected, the disconnection will be signaled and the green LED will be erased.
//if client disconnected
if (!client.connected())
{
//stop client
client.stop();
delay(1);
}
}Arduino Code [splitString]
In this function, we assign the values to variables such as humidity and temperature, for example.
//Message example: ALARM|30.12|27.82°C<br>//split the message, obtaining the H and T values
void splitString(String msg)
{
//sets strings to ""
H = T = "";
int i;
//finds the delimiter "|" and ignores the "ALARM" substring
for(i=0; i< msg.length() && msg.charAt(i)!='|'; i++);
i++;
//finds the next delimiter obtaining the humidity value
while(i< msg.length() && msg.charAt(i)!='|')
{
H+=msg.charAt(i);
i++;
}
i++;
//finds the "°" symbol obtaining the temperature value
while(i< msg.length() && msg.charAt(i)!='°')
{
T+=msg.charAt(i);
i++;
}
}SMS Messaging Script
* You need an SMS gateway for the script to work! Why did I choose to use a PHP script? Because, regardless if you want to send SMS, call, send email, among others, you take your data and put it on a SQL database. This is your base, so you won’t need to pay for a company, as you’ll have a rented server, which is cheaper. It’s possible to store many terabytes of information for cheap.
It’s important to point out that Gateway-SMS is a company that I pay for sending messages, and this can be per month or per unit.
I also remind you that you’ll need to make two changes in this code to make this assembly: in the customer ID that you’ll receive from the company that manages SMS sending and in the mobile number where you’ll put your telephone number.
<?php</p><p><?php <br-->$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);
?>SMS Gateway
This is the Gateway company I use. It guarantees the sending of the message to the operator.
Se more on my site: www.fernandok.com