A variety of communication methods for interaction amongst IoT devices have been available in recent years. Wi-Fi Technology and Bluetooth modules are the most common. They do, however, have several drawbacks, such as restricted range, limited entry points, and high power consumption. Semtech has introduced LoRa technology to address all of these issues. The device can run for a year on a single battery.
So, in this IoT project, we’ll create an ESP32 LoRa Gateway as well as an ESP32 LoRa Sensor Node to wirelessly monitor sensor readings from a few kilometers away. The DHT11 Sensor will be used by the transmitter to read the humidity and temperature data. The data is then transmitted over LoRa Radio. The receiver module receives the data. After a specific interval, the receiver will send the data to Thingspeak Server.
Components Required:
- ESP32 ESP-32S Development Board (ESP-WROOM-32)
- SX1278/76 Lora Module
- DHT11 Humidity Temperature Sensor
Installing the Required Libraries
For the project to program the ESP32 Board with the Arduino IDE, several libraries are necessary.
1. DHT11 Library
Any temperature humidity sensor is required to read the temperature and humidity. The best and cheapest sensor for this is the DHT11. For that, we’ll need to install the DHT11 Library. Add the library to the Arduino IDE by downloading it from the link below.
2. LoRa Library
For sending and receiving data over LoRa radios, we’ll need an Arduino library. Semtech SX1276, SX1277, SX1278, SX1279, as well as HopeRF RFM95W, RFM96W, and RFM98W, are supported by the library.
Circuit: ESP32 LoRa Thingspeak Gateway with LoRa Sensor Node
Let’s look at the sender and receiver circuits for the ESP32 LoRa Gateway and Sensor Node now. I built both circuits on a breadboard. If you like, you can build it on a PCB.
ESP32 LoRa Sensor Node
An ESP32 LoRa Sensor Node Circuit with a DHT11 Sensor is shown below. This component serves as a transmitter. The DHT11 Humidity Temperature Sensor reads the humidity and temperature data and transmits it over LoRa Radio.
The connection is fairly simple. Similarly connect the Lora SX1278 & ESP32 as follows.
ESP32 PINS | SX1278 PINS |
GND | GND |
3.3V | VCC |
D5 | NSS |
D23 | MOSI |
D19 | MISO |
D18 | SCK |
D14 | RST |
D2 | DIO0 |
Similarly connect the DHT11 digital input pin to GPIO4 of ESP32. Connect its VCC to 3.3V & GND to GND of ESP32.
ESP32 LoRa Thingspeak Gateway
This is an SX1278 Gateway Circuit for the ESP32 LoRa Module. This component serves as a receiver. The data on humidity and temperature is received via LoRa Radio and uploaded to the Thingspeak Server.
The ESP32 & LoRa SX1278 connection same as above.
Setting Up Thingspeak
You must first configure Thingspeak before you can monitor sensor data on the server. To set up the Thingspeak Server, visit https://thingspeak.com/. Create an account, or simply login in if you already have one. Then make a new channel with the following information.
ESP32 LoRa Sensor Node Code
On a breadboard, connect the Sensor Node Circuit together. In the ESP32 Board, copy and paste the code below. Before uploading, make sure the LoRa frequency is set to the correct frequency for your location.
#define BAND 433E6 //433E6 for Asia, 866E6 for Europe, 915E6 for North America |
//Libraries for LoRa #include <SPI.h> #include <LoRa.h> //Libraries for LoRa #include “DHT.h” #define DHTPIN 4 //pin where the dht11 is connected DHT dht(DHTPIN, DHT11); //define the pins used by the LoRa transceiver module #define ss 5 #define rst 14 #define dio0 2 #define BAND 433E6 //433E6 for Asia, 866E6 for Europe, 915E6 for North America //packet counter int readingID = 0; int counter = 0; String LoRaMessage = “”; float temperature = 0; float humidity = 0; //Initialize LoRa module void startLoRA() { LoRa.setPins(ss, rst, dio0); //setup LoRa transceiver module while (!LoRa.begin(BAND) && counter < 10) { Serial.print(“.”); counter++; delay(500); } if (counter == 10) { // Increment readingID on every new reading readingID++; Serial.println(“Starting LoRa failed!”); } Serial.println(“LoRa Initialization OK!”); delay(2000); } void startDHT() { if (isnan(humidity) || isnan(temperature)) { Serial.println(“Failed to read from DHT sensor!”); return; } } void getReadings(){ humidity = dht.readHumidity(); temperature = dht.readTemperature(); Serial.print(F(“Humidity: “)); Serial.print(humidity); Serial.print(F(“% Temperature: “)); Serial.print(temperature); Serial.println(F(“°C “)); } void sendReadings() { LoRaMessage = String(readingID) + “/” + String(temperature) + “&” + String(humidity) ; //Send LoRa packet to receiver LoRa.beginPacket(); LoRa.print(LoRaMessage); LoRa.endPacket(); Serial.print(“Sending packet: “); Serial.println(readingID); readingID++; Serial.println(LoRaMessage); } void setup() { //initialize Serial Monitor Serial.begin(115200); dht.begin(); startDHT(); startLoRA(); } void loop() { getReadings(); sendReadings(); delay(500); } |
ESP32 LoRa Gateway Code
You can now copy the code below and upload it to the ESP32 Board as the Gateway code. Make modifications to the WiFi SSID, Password, and Thingspeak API Key in the code below.
String apiKey = “14K8UL2QEK8BTHN6”; // Enter your Write API key from ThingSpeak const char *ssid = “Alexahome”; // replace with your wifi ssid and wpa2 key const char *password = “12345678”; |
// Import Wi-Fi library #include <WiFi.h> //Libraries for LoRa #include <SPI.h> #include <LoRa.h> //define the pins used by the LoRa transceiver module #define ss 5 #define rst 14 #define dio0 2 #define BAND 433E6 //433E6 for Asia, 866E6 for Europe, 915E6 for North America // Replace with your network credentials String apiKey = “14K8UL2QEK8BTHN6”; // Enter your Write API key from ThingSpeak const char *ssid = “Alexahome”; // replace with your wifi ssid and wpa2 key const char *password = “12345678”; const char* server = “api.thingspeak.com”; WiFiClient client; // Initialize variables to get and save LoRa data int rssi; String loRaMessage; String temperature; String humidity; String readingID; // Replaces placeholder with DHT values String processor(const String& var){ //Serial.println(var); if(var == “TEMPERATURE”) { return temperature; } else if(var == “HUMIDITY”) { return humidity; } else if (var == “RRSI”) { return String(rssi); } return String(); } void setup() { Serial.begin(115200); int counter; //setup LoRa transceiver module LoRa.setPins(ss, rst, dio0); //setup LoRa transceiver module while (!LoRa.begin(BAND) && counter < 10) { Serial.print(“.”); counter++; delay(2000); } if (counter == 10) { // Increment readingID on every new reading Serial.println(“Starting LoRa failed!”); } Serial.println(“LoRa Initialization OK!”); delay(2000); // Connect to Wi-Fi network with SSID and password Serial.print(“Connecting to “); Serial.println(ssid); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(2000); Serial.print(“.”); } // Print local IP address and start web server Serial.println(“”); Serial.println(“WiFi connected.”); Serial.println(“IP address: “); Serial.println(WiFi.localIP()); } // Read LoRa packet and get the sensor readings void loop() { int packetSize = LoRa.parsePacket(); if (packetSize) { Serial.print(“Lora packet received: “); while (LoRa.available()) // Read packet { String LoRaData = LoRa.readString(); Serial.print(LoRaData); int pos1 = LoRaData.indexOf(‘/’); int pos2 = LoRaData.indexOf(‘&’); readingID = LoRaData.substring(0, pos1); // Get readingID temperature = LoRaData.substring(pos1 +1, pos2); // Get temperature humidity = LoRaData.substring(pos2+1, LoRaData.length()); // Get humidity } rssi = LoRa.packetRssi(); // Get RSSI Serial.print(” with RSSI “); Serial.println(rssi); } if (client.connect(server, 80)) // “184.106.153.149” or api.thingspeak.com { String postStr = apiKey; postStr += “&field1=”; postStr += String(readingID); postStr += “&field2=”; postStr += String(temperature); postStr += “&field3=”; postStr += String(humidity); postStr += “&field4=”; postStr += String(rssi); postStr += “\r\n\r\n\r\n\r\n”; client.print(“POST /update HTTP/1.1\n”); client.print(“Host: api.thingspeak.com\n”); client.print(“Connection: close\n”); client.print(“X-THINGSPEAKAPIKEY: ” + apiKey + “\n”); client.print(“Content-Type: application/x-www-form-urlencoded\n”); client.print(“Content-Length: “); client.print(postStr.length()); client.print(“\n\n”); client.print(postStr); } //delay(30000); } |
Monitoring Sensor Data on Thingspeak Server
You can open the Serial Monitor on both the Gateway and Sensor Node Circuits once the code has been uploaded. If the code and connections are correct, you should see the following output.
Thingspeak Private View is now available for viewing. After a 15-second period, the data for Packet Number, Temperature, Humidity, and Gateway is uploaded there. You can adjust the timing of the data retrieval by changing the delay function in the code.