LoRa Transciever Code
LoRa Transciever Code
#include <SPI.h>
#include <LoRa.h>
#include <Adafruit_Sensor.h>
#include "Adafruit_BME680.h"
#include <Wire.h>
//----------------------------------------
Adafruit_BME680 bme; // I2C
//Uncomment Slave1 Address if code is getting compiled in Node1 and others are commented. Same for all Nodes
//byte LocalAddress = 0x02; //--> address of this device (Slave 1).
//byte LocalAddress = 0x03; //--> address of this device (Slave 2).
//byte LocalAddress = 0x04; //--> address of this device (Slave 3).
//---------------------------------------- Checks whether the incoming data or message for this device.
if (recipient != LocalAddress) {
Serial.println();
Serial.println("!"); //--> "!" = This message is not for me.
//Serial.println("This message is not for me.");
void Processing_incoming_data() {
// Fill in the "Message" variable with the value of humidity, temperature and the last state of the LED.
Message = String(Temperature) + "," + String(Humidity) + "," + String(Pressure) + "," + String(Gas) + "," + String(Altitude) + "," +
String(m4) + "," + String(m7) + "," + String(sd);
Serial.println();
Serial.println("Tr to : 0x" + String(Destination_Master, HEX));
Serial.println("Message: " + Message);
Serial.println();
Serial.println(F("Restart LoRa..."));
Serial.println(F("Start LoRa init..."));
if (!LoRa.begin(433E6)) { // initialize ratio at 915 or 433 MHz
Serial.println(F("LoRa init failed. Check your connections."));
while (true); // if failed, do nothing
}
Serial.println(F("LoRa init succeeded."));
Serial.begin(115200);
// Calls the Rst_LORA() subroutine.
Rst_LORA();
if (!bme.begin()) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
while (1);
}
//---------------------------------------- Millis / Timer to update the temperature and humidity values from the DHT11 sensor every 2
seconds (see the variable interval_UpdateDHT11).
unsigned long currentMillis_UpdateBME = millis();
// Check if any reads failed and exit early (to try again).
if (isnan(Temperature) || isnan(Humidity)) {
Serial.println(F("Failed to read from BME sensor!"));
return;
}
}
Count_to_Rst_LORA++;
if (Count_to_Rst_LORA > 30) {
LoRa.end();
Rst_LORA();
}
}
//---------------------------------------- parse for a packet, and call onReceive with the result:
onReceive(LoRa.parsePacket());
//----------------------------------------
#include <SPI.h>
#include <LoRa.h>
#include <Wire.h>
#include <WiFi.h>
#include <ArduinoOTA.h>
#include <WiFiClientSecure.h>
#include <AsyncTCP.h>
#include "html.h"
#include <ESPAsyncWebServer.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <RTClib.h>
//---------------------------------------- Declaration for an SSD1306 display connected to I2C (SDA, SCL pins).
//----------------------------------------
RTC_DS3231 rtc;
//---------------------------------------- LoRa Pin / GPIO configuration.
#define ss 10
#define rst 9
#define dio0 2
AsyncWebServer server(80);
AsyncEventSource events("/events");
//----------------------------------------
//----------------------------------------
//----------------------------------------
//---------------------------------------- Variable declaration to get temperature and humidity values received from Slaves.
float Humd[3];
float Temp[3];
float Pres[3];
float Gas[3];
float Alt[3];
int MQ4[3];
int MQ7[3];
int SD[3];
char timestamp[20];
//----------------------------------------
String GAS_ID;
byte Slv = 0;
// Declare a variable as a counter to update the OLED LCD display if there is no incoming message from the slaves.
byte Count_OLED_refresh_when_no_data_comes_in = 0;
byte SL_Address;
byte Count_to_Rst_LORA = 0;
WiFiClientSecure client;
if(var == "TEMPERATURE1"){
return String(Temp[0]);
return String(Humd[0]);
return String(Pres[0]);
return String(Gas[0]);
return String(SD[0]);
return String(MQ4[0]);
return String(MQ7[0]);
return String(Temp[1]);
return String(Humd[1]);
return String(Pres[1]);
return String(Gas[1]);
return String(Alt[1]);
return String(SD[1]);
return String(MQ4[1]);
return String(MQ7[1]);
return String();
//____________________________
//----------------------------------------
SL_Address = sender;
Incoming = "";
while (LoRa.available()) {
Incoming += (char)LoRa.read();
//----------------------------------------
Count_to_Rst_LORA = 0;
Count_OLED_refresh_when_no_data_comes_in = 0;
if (incomingLength != Incoming.length()) {
Serial.println();
Serial.println("er"); //--> "er" = error: message length does not match length.
}
//----------------------------------------
//---------------------------------------- Checks whether the incoming data or message for this device.
if (recipient != LocalAddress) {
Serial.println();
//----------------------------------------
Serial.println();
//----------------------------------------
Processing_incoming_data();
//____________________________
void Processing_incoming_data() {
//---------------------------------------- Conditions for processing data or messages from Slave 1 (ESP32 Slave 1).
if (SL_Address == Destination_ESP32_Slave_1) {
//----------------------------------------
//---------------------------------------- Conditions for processing data or messages from Slave 2 (ESP32 Slave 2).
if (SL_Address == Destination_ESP32_Slave_2) {
//----------------------------------------
//----------------------------------------
/* if (SL_Address == Destination_ESP32_Slave_3) {
} */
Update_OLED_Display();
//____________________________
void Update_OLED_Display() {
if ( SL_Address == 0x02 ) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.print("Node1:");
display.setTextSize(1);
display.setCursor(45,0);
display.print(WiFi.localIP());
display.setTextSize(1);
display.setCursor(0, 20);
display.print("Time:");
display.print(timestamp);
display.setCursor(0, 35);
display.print("Temp:");
display.print(Temp[0]);
display.setCursor(60, 35);
display.print(",Hum:");
display.print(Humd[0]);
display.setCursor(0, 50);
display.print("Alt:");
display.print(Alt[0]);
display.display();
delay(1000);
if ( SL_Address == 0x03 ) {
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.print("Node2:");
display.setTextSize(1);
display.setCursor(45,0);
display.print(WiFi.localIP());
display.setTextSize(1);
display.setCursor(0, 20);
display.print("Time:");
display.print(timestamp);
display.setCursor(0, 35);
display.print("Temp:");
display.print(Temp[1]);
display.setCursor(60, 35);
display.print(",Hum:");
display.print(Humd[1]);
display.setCursor(0, 50);
display.print("Alt:");
display.print(Alt[1]);
display.display();
delay(1000);
display.clearDisplay();
display.setTextSize(1);
display.setCursor(0,0);
display.print("Node3:");
display.setTextSize(1);
display.setCursor(45,0);
display.print(WiFi.localIP());
display.setTextSize(1);
display.setCursor(0, 20);
display.print("Temp:");
display.print(Temp[2]);
display.setCursor(60, 20);
display.print(",Hum:");
display.print(Humd[2]);
display.setCursor(0, 35);
display.print("Pre:");
display.print(Pres[2]);
display.setCursor(60, 35);
display.print(",Gas:");
display.print(Gas[2]);
display.setCursor(0, 50);
display.print("Alt:");
display.print(Alt[2]);
display.setCursor(60, 50);
display.print(",MQ4:");
display.print(MQ4[2]);
display.setCursor(0, 65);
display.print("MQ7:");
display.print(MQ7[2]);
display.setCursor(40, 65);
display.print("SD:");
display.print(SD[2]);
display.display();
delay(1000);
}*/
Incoming = "";
//____________________________
void Getting_data_for_the_first_time() {
Serial.println();
while(true) {
previousMillis_SendMSG = currentMillis_SendMSG;
Slv++;
if (Slv > 3) {
Slv = 0;
Serial.println();
break;
Message = "N,N";
//::::::::::::::::: Condition for sending message / command data to Slave 1 (ESP32 Slave 1).
if (Slv == 1) {
Serial.println();
sendMessage(Message, Destination_ESP32_Slave_1);
//:::::::::::::::::
//::::::::::::::::: Condition for sending message / command data to Slave 2 (ESP32 Slave 2).
if (Slv == 2) {
Serial.println();
sendMessage(Message, Destination_ESP32_Slave_2);
//:::::::::::::::::
/* if (Slv == 3) {
Serial.println();
sendMessage(Message, Destination_ESP32_Slave_3);
}*/
//---------------------------------------- parse for a packet, and call onReceive with the result:
onReceive(LoRa.parsePacket());
//----------------------------------------
//----------------------------------------
//____________________________
//____________________________ String function to process the data received
int found = 0;
int strIndex[] = { 0, -1 };
found++;
strIndex[0] = strIndex[1] + 1;
//____________________________
void Rst_LORA() {
Serial.println();
Serial.println("Restart LoRa...");
Count_to_Rst_LORA = 0;
//____________________________
void setup() {
Serial.begin(115200);
if (!rtc.begin()) {
rtc.adjust(DateTime(F(_DATE), F(TIME_))); // Uncomment this line to set the RTC to the time this sketch was compiled
//rtc.adjust(DateTime(2024, 7, 8, 4, 29, 0)); // Set to specific time: YYYY, MM, DD, HH, MM, SS
// But on my 128x64 module the 0x3D address doesn't work. What works is the 0x3C address.
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
//----------------------------------------
//----------------------------------------
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(WHITE);
display.setCursor(32, 15);
display.println("ESP32 LORA");
display.setCursor(17, 35);
display.println("WEATHER STATION");
display.display();
//----------------------------------------
delay(2000);
//---------------------------------------- Clears the values of the Temp and Humd array variables for the first time.
Temp[i] = 0.00;
Humd[i] = 0.00;
Pres[i] = 0.00;
Gas[i] = 0.00;
Alt[i] = 0.00;
MQ4[i] = 0;
MQ7[i] = 0;
SD[i] = 0;
//----------------------------------------
// Calls the Update_OLED_Display() subroutine.
Update_OLED_Display();
delay(1000);
Rst_LORA();
Getting_data_for_the_first_time();
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.print("Connecting to WiFi");
Serial.print(".");
delay(250);
Serial.println("");
Serial.println(WIFI_SSID);
Serial.println(WiFi.localIP());
Serial.println();
ArduinoOTA.begin();
client.setInsecure();
});
events.onConnect([](AsyncEventSourceClient *client){
if(client->lastId()){
});
server.addHandler(&events);
server.begin();
//____________________________
//____________________________ VOID LOOP
void loop() {
ArduinoOTA.handle();
previousMillis_SendMSG = currentMillis_SendMSG;
//::::::::::::::::: The condition to update the OLED LCD if there is no incoming message from all slaves.
Count_OLED_refresh_when_no_data_comes_in++;
if (Count_OLED_refresh_when_no_data_comes_in > 5) {
Count_OLED_refresh_when_no_data_comes_in = 0;
Processing_incoming_data();
//:::::::::::::::::
Slv++;
//:::::::::::::::::
//::::::::::::::::: Condition for sending message / command data to Slave 1 (ESP32 Slave 1).
if (Slv == 1) {
Serial.println();
Temp[0] = 0.00;
Humd[0] = 0.00;
Pres[0] = 0.00;
Gas[0] = 0.00;
Alt[0] = 0.00;
MQ4[0] = 0;
MQ7[0] = 0;
SD[0] = 0;
sendMessage(Message, Destination_ESP32_Slave_1);
//:::::::::::::::::
//::::::::::::::::: Condition for sending message / command data to Slave 2 (ESP32 Slave 2).
if (Slv == 2) {
Serial.println();
Temp[1] = 0.00;
Humd[1] = 0.00;
Pres[1] = 0.00;
Gas[1] = 0.00;
Alt[1] = 0.00;
MQ4[1] = 0;
MQ7[1] = 0;
SD[1] = 0;
sendMessage(Message, Destination_ESP32_Slave_2);
//:::::::::::::::::
//:::::::::::::::::
/* if (Slv == 3) {
Serial.println();
Temp[2] = 0.00;
Humd[2] = 0.00;
Pres[2] = 0.00;
Gas[2] = 0.00;
Alt[2] = 0.00;
MQ4[2] = 0;
MQ7[2] = 0;
SD[2] = 0;
sendMessage(Message, Destination_ESP32_Slave_3);
} */
//----------------------------------------
previousMillis_RestartLORA = currentMillis_RestartLORA;
Count_to_Rst_LORA++;
LoRa.end();
Rst_LORA();
}
}
events.send("ping",NULL,millis());
events.send(String(Temp[0]).c_str(),"Temperature1",millis());
events.send(String(Humd[0]).c_str(),"Humidity1",millis());
events.send(String(Pres[0]).c_str(),"Pressure1",millis());
events.send(String(Gas[0]).c_str(),"Gas1",millis());
events.send(String(Alt[0]).c_str(),"Altitude1",millis());
events.send(String(SD[0]).c_str(),"SoundValue1",millis());
events.send(String(MQ4[0]).c_str(),"Methane1",millis());
events.send(String(MQ7[0]).c_str(),"Monoxide1",millis());
events.send(String(Temp[1]).c_str(),"Temperature2",millis());
events.send(String(Humd[1]).c_str(),"Humidity2",millis());
events.send(String(Pres[1]).c_str(),"Pressure2",millis());
events.send(String(Gas[1]).c_str(),"Gas2",millis());
events.send(String(Alt[1]).c_str(),"Altitude2",millis());
events.send(String(SD[1]).c_str(),"SoundValue2",millis());
events.send(String(MQ4[1]).c_str(),"Methane2",millis());
events.send(String(MQ7[1]).c_str(),"Monoxide2",millis());
/* events.send(String(Temp[2]).c_str(),"Temperature3",millis());
events.send(String(Humd[2]).c_str(),"Humidity3",millis());
events.send(String(Pres[2]).c_str(),"Pressure3",millis());
events.send(String(Gas[2]).c_str(),"Gas3",millis());
events.send(String(Alt[2]).c_str(),"Altitude3",millis());
events.send(String(SD[2]).c_str(),"SoundValue3",millis());
events.send(String(MQ4[2]).c_str(),"Methane3",millis());
events.send(String(MQ7[2]).c_str(),"Monoxide3",millis());
*/
lastTime = millis();
//----------------------------------------
delay(60000);
onReceive(LoRa.parsePacket());
//----------------------------------------
//____________________________
void sendData(String GAS_ID,float a,float b,float c,float d,float e,int f,int g,int h) {
Serial.println("==========");
Serial.print("connecting to ");
Serial.println(host);
if (!client.connect(host, httpsPort)) {
Serial.println("connection failed");
return;
//----------------------------------------
String url = "/macros/s/" + GAS_ID + "/exec?param1=" + string_param1 + "¶m2=" + string_param2 + "¶m3=" + string_param3 +
"¶m4=" + string_param4 + "¶m5=" + string_param5 + "¶m6=" + string_param6 + "¶m7=" + string_param7 + "¶m8=" +
string_param8;
Serial.println(url);
"User-Agent: BuildFailureDetectorESP8266\r\n" +
"Connection: close\r\n\r\n");
Serial.println("request sent");
//----------------------------------------
while (client.connected()) {
if (line == "\r") {
Serial.println("headers received");
break;
if (line.startsWith("{\"state\":\"success\"")) {
Serial.println("esp8266/Arduino CI successfull!");
} else {
Serial.println(line);
Serial.println("closing connection");
Serial.println("==========");
Serial.println();
//----------------------------------------
client.stop();
Dashboard Code:
Open a new tab add the below code, save it with “html.h” as file name and link it to the main LoRa Receiver code using the include property to get a webserver page for
displaying data on Dashboards
function doGet(e) {
Logger.log( JSON.stringify(e) );
var result = 'Ok';
if (e.parameter == 'undefined') {
result = 'No Parameters';
}
else {
var sheet_id = 'Spreadsheet I’d to be placed here';
var sheet = SpreadsheetApp.openById(sheet_id).getActiveSheet();
var newRow = sheet.getLastRow() + 1;
var rowData = [];
var Curr_Date = new Date();
rowData[0] = Curr_Date; // Date in column A
var Curr_Time = Utilities.formatDate(Curr_Date, "Asia/Kolkata", 'HH:mm:ss');
rowData[1] = Curr_Time; // Time in column B
for (var param in e.parameter) {
Logger.log('In for loop, param=' + param);
var value = stripQuotes(e.parameter[param]);
Logger.log(param + ':' + e.parameter[param]);
switch (param) {
case 'param1':
rowData[2] = value;
result = 'Temperature Written on column C';
break;
case 'param2':
rowData[3] = value;
result += ' ,Humidity Written on column D';
break;
case 'param3':
rowData[4] = value;
result += 'Pressure Written on column E';
break;
case 'param4':
rowData[5] = value;
result += 'Gas Written on column F';
break;
case 'param5':
rowData[6] = value;
result += 'Altitude Written on column G';
break;
case 'param6':
rowData[7] = value;
result += 'Methane Written on column H';
break;
case 'param7':
rowData[8] = value;
result += 'Monoxide Written on column I';
break;
case 'param8':
rowData[9] = value;
result += 'Sound Written on column J';
break;
default:
result = "unsupported parameter";
}
}
Logger.log(JSON.stringify(rowData));
var newRange = sheet.getRange(newRow, 1, 1, rowData.length);
newRange.setValues([rowData]);
}
return ContentService.createTextOutput(result);
}
function stripQuotes( value ) {
return value.replace(/^["']|['"]$/g, "");
}