Introduction: ESP32 Lora Thingspeak Gateway With Sensor Node

in this IoT Project, I designed ESP32 LoRa Gateway & also ESP32 LoRa Sensor Node to monitor the sensor reading wirelessly from a few kilometer distances. The sender will read the humidity and temperature data using DHT11 Sensor. Then it transmits the data via LoRa Radio. The data is received by the receiver module. The receiver will then send the data to Thingspeak Server after a certain interval.

Step 1: Components Required

1. ESP32 Board - 2

2. Lora Module SX1278/SX1276

3. DHT11 Humidity Temperature Sensor

4. Breadboard

5. Connecting Jumper Wires

Step 2: Installing the Required Libraries

We need to install different libraries first:

1. DHT11 Library

2. LoRa Library

Step 3: ESP32 LoRa Thingspeak Gateway

Now let us see the sender and receiver circuit for building ESP32 LoRa Gateway & Sensor Node. I assembled both the circuit on a breadboard. You can make it on PCB if you want.

Here is an ESP32 LoRa Module SX1278 Gateway Circuit. This part work as a Receiver. The humidity and temperature data is received using LoRa Radio & uploaded to Thingspeak Server.

Step 4: ESP32 LoRa Sensor Node

Here is an ESP32 LoRa Sensor Node Circuit with DHT11 Sensor. This part work as a transmitter. The humidity and temperature data is read by DHT11 Humidity Temperature Sensor and transmitted using LoRa Radio.

Step 5: Setting Up Thingspeak

In order to Monitor the Sensor Data on Thingspeak Server, you first need to Setup the Thingspeak. To set up the Thingspeak Server, visit https://thingspeak.com/. Create an account or simply sign in if you created the account earlier. Then create a new channel with the following details.

Step 6: Gateway Code

#include 
 
//Libraries for LoRa
#include 
#include 
 
//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 = "Wifi SSID"; // replace with your wifi ssid and wpa2 key
const char *password = "Password";
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);
}

Step 7: Sensor Node Code

#include 
#include 
 
//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);
}

Step 8: Monitor Data on Thingspeak Server

Once the code is uploaded, you can open the Serial Monitor on both the Gateway & Sensor Node Circuit. You will data send and received if the code is correct. Now you can visit Thingspeak Private View. There you can see the data for Packet Number, Temperature, Humidity & Gateway is uploaded after the interval of 15 seconds.

Step 9: References