ESP32 LORA: Gas Sensor, Humidity, and Temperature by SMS – Part 2
by Fernando Koyanagi in Circuits > Microcontrollers
3929 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