In this project, you’ll build a sensor monitoring system using a TTGO LoRa32 SX1276 OLED board that sends temperature, humidity and pressure readings via LoRa radio to an ESP32 LoRa receiver. The receiver displays the latest sensor readings on a web server.
With this project you’ll learn how to:
- Send sensor readings via LoRa radio between two ESP32 boards;
- Add LoRa and Wi-Fi capabilities simultaneously to your projects (LoRa + Web Server on the same ESP32 board);
- Use the TTGO LoRa32 SX1276 OLED board or similar development boards for IoT projects.
Recommended reading: TTGO LoRa32 SX1276 OLED Board: Getting Started with Arduino IDE
Watch the Video Demonstration
Watch the video demonstration to see what you’re going to build throughout this tutorial.
Project Overview
The following image shows a high-level overview of the project we’ll build throughout this tutorial.
- The LoRa sender sends BME280 sensor readings via LoRa radio every 10 seconds;
- The LoRa receiver gets the readings and displays them on a web server;
- You can monitor the sensor readings by accessing the web server;
- The LoRa sender and the Lora receiver can be several hundred meters apart depending on their location. So, you can use this project to monitor sensor readings from your fields or greenhouses if they are a bit apart from your house;
- The LoRa receiver is running an asynchronous web server and the web page files are saved on the ESP32 filesystem (LittleFS);
- The LoRa receiver also shows the date and time the last readings were received. To get date and time, we use the Network Time Protocol with the ESP32.
For an introduction to LoRa communication: what’s LoRa, LoRa frequencies, LoRa applications and more, read our Getting Started ESP32 with LoRa using Arduino IDE.
Parts Required
For this project, we’ll use the following components:
- TTGO LoRa32 SX1276 OLED board (2x): this is an ESP32 development board with a LoRa chip and a built-in OLED. You can use similar boards, or you can use an ESP32 + LoRa chip + OLED separately.
- BME280 temperature, humidity and pressure sensor. You should be able to modify this project to use any other sensor.
You’ll also need some jumper wires and a breadboard.
You can use the preceding links or go directly to MakerAdvisor.com/tools to find all the parts for your projects at the best price!
Preparing the Arduino IDE
To program the TTGO LoRa32 SX1276 OLED boards we’ll use Arduino IDE. To upload files to the ESP32 filesystem, we’ll use the ESP32 LittleFS filesystem uploader plugin.
So, before proceeding, you need to install the ESP32 boards and the ESP32 filesystem uploader plugin in your Arduino IDE.
Installing libraries
For this project, you need to install several libraries.
LoRa, BME280 and OLED Libraries
The following libraries can be installed through the Arduino Library Manager. Go to Sketch > Include Library> Manage Libraries and search for the library name.
- LoRa library: arduino-LoRa library by sandeep mistry
- OLED libraries: Adafruit_SSD1306 library and Adafruit_GFX library
- BME280 libraries: Adafruit_BME280 library and Adafruit unified sensor library
Asynchronous Web Server Libraries
To build the asynchronous web server, you also need to install the following libraries:
- ESPAsyncWebServer library (download ESPAsyncWebServer library)
- Async TCP library (download AsyncTCP library)
These libraries are not available to install through the Library Manager. So, you need to unzip the libraries and move them to the Arduino IDE installation libraries folder.
Alternatively, you can go to Sketch > Include Library > Add .ZIP library… and select the libraries you’ve just downloaded.
NTPClient Library
Everytime the LoRa receiver picks up a new a LoRa message, it will request the date and time from an NTP server so that we know when the last packet was received.
For that we’ll be using the NTPClient library forked by Taranais. Follow the next steps to install this library in your Arduino IDE:
IMPORTANT: we’re not using the default NTPClient library. To follow this tutorial you need to install the library we recommend using the following steps.
- Click here to download the NTP Client library. You should have a .zip folder in your Downloads
- In your Arduino IDE, go to Sketch > Include Library > Add . ZIP library…
- Select the .ZIP file of the library you just downloaded.
- The library will be installed after a few seconds.
LoRa Sender
The LoRa Sender is connected to a BME280 sensor and sends temperature, humidity, and pressure readings every 10 seconds. You can change this period of time later in the code.
Recommended reading: ESP32 with BME280 Sensor using Arduino IDE (Pressure, Temperature, Humidity)
LoRa Sender Circuit
The BME280 we’re using communicates with the ESP32 using I2C communication protocol. Wire the sensor as shown in the next schematic diagram:
BME280 | ESP32 |
VIN | 3.3 V |
GND | GND |
SCL | GPIO 13 |
SDA | GPIO 21 |
LoRa Sender Code
The following code reads temperature, humidity and pressure from the BME280 sensor and sends the readings via LoRa radio.
Copy the following code to your Arduino IDE.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-lora-sensor-web-server/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//Libraries for BME280
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 866E6
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
//BME280 definition
#define SDA 21
#define SCL 13
TwoWire I2Cone = TwoWire(1);
Adafruit_BME280 bme;
//packet counter
int readingID = 0;
int counter = 0;
String LoRaMessage = "";
float temperature = 0;
float humidity = 0;
float pressure = 0;
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
//Initialize OLED display
void startOLED(){
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("LORA SENDER");
}
//Initialize LoRa module
void startLoRA(){
//SPI LoRa pins
SPI.begin(SCK, MISO, MOSI, SS);
//setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);
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!");
display.setCursor(0,10);
display.clearDisplay();
display.print("LoRa Initializing OK!");
display.display();
delay(2000);
}
void startBME(){
I2Cone.begin(SDA, SCL, 100000);
bool status1 = bme.begin(0x76, &I2Cone);
if (!status1) {
Serial.println("Could not find a valid BME280_1 sensor, check wiring!");
while (1);
}
}
void getReadings(){
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100.0F;
}
void sendReadings() {
LoRaMessage = String(readingID) + "/" + String(temperature) + "&" + String(humidity) + "#" + String(pressure);
//Send LoRa packet to receiver
LoRa.beginPacket();
LoRa.print(LoRaMessage);
LoRa.endPacket();
display.clearDisplay();
display.setCursor(0,0);
display.setTextSize(1);
display.print("LoRa packet sent!");
display.setCursor(0,20);
display.print("Temperature:");
display.setCursor(72,20);
display.print(temperature);
display.setCursor(0,30);
display.print("Humidity:");
display.setCursor(54,30);
display.print(humidity);
display.setCursor(0,40);
display.print("Pressure:");
display.setCursor(54,40);
display.print(pressure);
display.setCursor(0,50);
display.print("Reading ID:");
display.setCursor(66,50);
display.print(readingID);
display.display();
Serial.print("Sending packet: ");
Serial.println(readingID);
readingID++;
}
void setup() {
//initialize Serial Monitor
Serial.begin(115200);
startOLED();
startBME();
startLoRA();
}
void loop() {
getReadings();
sendReadings();
delay(10000);
}
How the Code Works
Start by including the necessary libraries for LoRa, OLED display and BME280 sensor.
//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
//Libraries for BME280
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
Define the pins used by the LoRa transceiver module. We’re using the TTGO LoRa32 SX1276 OLED board V1.0 and these are the pins used by the LoRa chip:
//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
Note: if you’re using another LoRa board, check the pins used by the LoRa transceiver chip.
Select the LoRa frequency:
#define BAND 866E6
Define the OLED pins.
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
Define the OLED size.
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Define the pins used by the BME280 sensor.
//BME280 definition
#define SDA 21
#define SCL 13
Create an I2C instance for the BME280 sensor and a bme object.
TwoWire I2Cone = TwoWire(1);
Adafruit_BME280 bme;
Create some variables to hold the LoRa message, temperature, humidity, pressure and reading ID.
int readingID = 0;
int counter = 0;
String LoRaMessage = "";
float temperature = 0;
float humidity = 0;
float pressure = 0;
Create a display object for the OLED display.
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
setup()
In the setup(), we call several functions that were created previously in the code to initialize the OLED display, the BME280 and the LoRa transceiver module.
void setup() {
Serial.begin(115200);
startOLED();
startBME();
startLoRA();
}
loop()
In the loop(), we call the getReadings() and sendReadings() functions that were also previously created. These functions are responsible for getting readings from the BME280 sensor, and to send those readings via LoRa, respectively.
void loop() {
getReadings();
sendReadings();
delay(10000);
}
getReadings()
Getting sensor readings is as simple as using the readTemperature(), readHumidity(), and readPressure() methods on the bme object:
void getReadings(){
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100.0F;
}
sendReadings()
To send the readings via LoRa, we concatenate all the readings on a single variable, LoRaMessage:
void sendReadings() {
LoRaMessage = String(readingID) + "/" + String(temperature) + "&" + String(humidity) + "#" + String(pressure);
Note that each reading is separated with a special character, so the receiver can easily identify each value.
Then, send the packet using the following:
LoRa.beginPacket();
LoRa.print(LoRaMessage);
LoRa.endPacket();
Each time we send a LoRa packet, we increase the readingID variable so that we have an idea on how many packets were sent. You can delete this variable if you want.
readingID++;
The loop() is repeated every 10000 milliseconds (10 seconds). So, new sensor readings are sent every 10 seconds. You can change this delay time if you want.
delay(10000);
Testing the LoRa Sender
Upload the code to your ESP32 LoRa Sender Board.
Go to Tools > Port and select the COM port it is connected to. Then, go to Tools > Board and select the board you’re using. In our case, it’s the TTGO LoRa32-OLED V1.
Finally, press the upload button.
Open the Serial Monitor at a baud rate of 115200. You should get something as shown below.
The OLED of your board should be displaying the latest sensor readings.
Your LoRa Sender is ready. Now, let’s move on to the LoRa Receiver.
LoRa Receiver
The LoRa Receiver gets incoming LoRa packets and displays the received readings on an asynchronous web server. Besides the sensor readings, we also display the last time those readings were received and the RSSI (received signal strength indicator).
The following figure shows the web server we’ll build.
As you can see, it contains a background image and styles to make the web page more appealing. There are several ways to display images on an ESP32 web server. We’ll store the image on the ESP32 filesystem (LittleFS). We’ll also store the HTML file on LittleFS.
Organizing your Files
To build the web server you need three different files: the Arduino sketch, the HTML file and the image. The HTML file and the image should be saved inside a folder called data inside the Arduino sketch folder, as shown below.
Creating the HTML File
Create an index.html file with the following content or download all the project files here:
<!DOCTYPE HTML><html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" href="data:,">
<title>ESP32 (LoRa + Server)</title>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.7.2/css/all.css" integrity="sha384-fnmOCqbTlWIlj8LyTjo7mOUStjsKC4pOpQbqyi7RrhN7udi9RwhKkMHpvLbHG9Sr" crossorigin="anonymous">
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
header {
margin: 0;
padding-top: 5vh;
padding-bottom: 5vh;
overflow: hidden;
background-image: url(winter);
background-size: cover;
color: white;
}
h2 {
font-size: 2.0rem;
}
p { font-size: 1.2rem; }
.units { font-size: 1.2rem; }
.readings { font-size: 2.0rem; }
</style>
</head>
<body>
<header>
<h2>ESP32 (LoRa + Server)</h2>
<p><strong>Last received packet:<br/><span id="timestamp">%TIMESTAMP%</span></strong></p>
<p>LoRa RSSI: <span id="rssi">%RSSI%</span></p>
</header>
<main>
<p>
<i class="fas fa-thermometer-half" style="color:#059e8a;"></i> Temperature: <span id="temperature" class="readings">%TEMPERATURE%</span>
<sup>°C</sup>
</p>
<p>
<i class="fas fa-tint" style="color:#00add6;"></i> Humidity: <span id="humidity" class="readings">%HUMIDITY%</span>
<sup>%</sup>
</p>
<p>
<i class="fas fa-angle-double-down" style="color:#e8c14d;"></i> Pressure: <span id="pressure" class="readings">%PRESSURE%</span>
<sup>hpa</sup>
</p>
</main>
<script>
setInterval(updateValues, 10000, "temperature");
setInterval(updateValues, 10000, "humidity");
setInterval(updateValues, 10000, "pressure");
setInterval(updateValues, 10000, "rssi");
setInterval(updateValues, 10000, "timestamp");
function updateValues(value) {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById(value).innerHTML = this.responseText;
}
};
xhttp.open("GET", "/" + value, true);
xhttp.send();
}
</script>
</body>
</html>
We’ve also included the CSS styles on the HTML file as well as some JavaScript that is responsible for updating the sensor readings automatically.
Something important to notice are the placeholders. The placeholders go between % signs: %TIMESTAMP%, %TEMPERATURE%, %HUMIDITY%, %PRESSURE% and %RSSI%.
These placeholders will then be replaced with the actual values by the Arduino code.
The styles are added between the <style> and </style> tags.
<style>
body {
margin: 0;
font-family: Arial, Helvetica, sans-serif;
text-align: center;
}
header {
margin: 0;
padding-top: 10vh;
padding-bottom: 5vh;
overflow: hidden;
width: 100%;
background-image: url(winter.jpg);
background-size: cover;
color: white;
}
h2 {
font-size: 2.0rem;
}
p { font-size: 1.2rem; }
.units { font-size: 1.2rem; }
.readings { font-size: 2.0rem; }
</style>
If you want a different image for your background, you just need to modify the following line to include your image’s name. In our case, it is called winter.jpg.
background-image: url(winter.jpg);
The JavaScript goes between the <scritpt> and </script> tags.
<script>
setInterval(updateValues("temperature"), 5000);
setInterval(updateValues("humidity"), 5000);
setInterval(updateValues("pressure"), 5000);
setInterval(updateValues("rssi"), 5000);
setInterval(updateValues("timeAndDate"), 5000);
function updateValues(value) {
console.log(value);
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
document.getElementById(value).innerHTML = this.responseText;
}
};
xhttp.open("GET", "/" + value, true);
xhttp.send();
}
</script>
We won’t explain in detail how the HTML and CSS works, but a good place to learn is the W3Schools website.
LoRa Receiver Arduino Sketch
Copy the following code to your Arduino IDE or download all the project files here. Then, you need to type your network credentials (SSID and password) to make it work.
/*********
Rui Santos & Sara Santos - Random Nerd Tutorials
Complete project details at https://RandomNerdTutorials.com/esp32-lora-sensor-web-server/
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files.
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
*********/
// Import Wi-Fi library
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
#include <LittleFS.h>
//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Libraries to get time from NTP Server
#include <NTPClient.h>
#include <WiFiUdp.h>
//define the pins used by the LoRa transceiver module
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 866E6
//OLED pins
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
// Replace with your network credentials
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
// Define NTP Client to get time
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
// Variables to save date and time
String formattedDate;
String day;
String hour;
String timestamp;
// Initialize variables to get and save LoRa data
int rssi;
String loRaMessage;
String temperature;
String humidity;
String pressure;
String readingID;
// Create AsyncWebServer object on port 80
AsyncWebServer server(80);
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
// 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 == "PRESSURE"){
return pressure;
}
else if(var == "TIMESTAMP"){
return timestamp;
}
else if (var == "RRSI"){
return String(rssi);
}
return String();
}
//Initialize OLED display
void startOLED(){
//reset OLED display via software
pinMode(OLED_RST, OUTPUT);
digitalWrite(OLED_RST, LOW);
delay(20);
digitalWrite(OLED_RST, HIGH);
//initialize OLED
Wire.begin(OLED_SDA, OLED_SCL);
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3c, false, false)) { // Address 0x3C for 128x32
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
display.clearDisplay();
display.setTextColor(WHITE);
display.setTextSize(1);
display.setCursor(0,0);
display.print("LORA SENDER");
}
//Initialize LoRa module
void startLoRA(){
int counter;
//SPI LoRa pins
SPI.begin(SCK, MISO, MOSI, SS);
//setup LoRa transceiver module
LoRa.setPins(SS, RST, DIO0);
while (!LoRa.begin(BAND) && counter < 10) {
Serial.print(".");
counter++;
delay(500);
}
if (counter == 10) {
// Increment readingID on every new reading
Serial.println("Starting LoRa failed!");
}
Serial.println("LoRa Initialization OK!");
display.setCursor(0,10);
display.clearDisplay();
display.print("LoRa Initializing OK!");
display.display();
delay(2000);
}
void connectWiFi(){
// 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(500);
Serial.print(".");
}
// Print local IP address and start web server
Serial.println("");
Serial.println("WiFi connected.");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
display.setCursor(0,20);
display.print("Access web server at: ");
display.setCursor(0,30);
display.print(WiFi.localIP());
display.display();
}
// Read LoRa packet and get the sensor readings
void getLoRaData() {
Serial.print("Lora packet received: ");
// Read packet
while (LoRa.available()) {
String LoRaData = LoRa.readString();
// LoRaData format: readingID/temperature&soilMoisture#batterylevel
// String example: 1/27.43&654#95.34
Serial.print(LoRaData);
// Get readingID, temperature and soil moisture
int pos1 = LoRaData.indexOf('/');
int pos2 = LoRaData.indexOf('&');
int pos3 = LoRaData.indexOf('#');
readingID = LoRaData.substring(0, pos1);
temperature = LoRaData.substring(pos1 +1, pos2);
humidity = LoRaData.substring(pos2+1, pos3);
pressure = LoRaData.substring(pos3+1, LoRaData.length());
}
// Get RSSI
rssi = LoRa.packetRssi();
Serial.print(" with RSSI ");
Serial.println(rssi);
}
// Function to get date and time from NTPClient
void getTimeStamp() {
while(!timeClient.update()) {
timeClient.forceUpdate();
}
// The formattedDate comes with the following format:
// 2018-05-28T16:00:13Z
// We need to extract date and time
formattedDate = timeClient.getFormattedDate();
Serial.println(formattedDate);
// Extract date
int splitT = formattedDate.indexOf("T");
day = formattedDate.substring(0, splitT);
Serial.println(day);
// Extract time
hour = formattedDate.substring(splitT+1, formattedDate.length()-1);
Serial.println(hour);
timestamp = day + " " + hour;
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
startOLED();
startLoRA();
connectWiFi();
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting LittleFS");
return;
}
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html", String(), false, processor);
});
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", temperature.c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", humidity.c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", pressure.c_str());
});
server.on("/timestamp", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", timestamp.c_str());
});
server.on("/rssi", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(rssi).c_str());
});
server.on("/winter", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/winter.jpg", "image/jpg");
});
// Start server
server.begin();
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(0);
}
void loop() {
// Check if there are LoRa packets available
int packetSize = LoRa.parsePacket();
if (packetSize) {
getLoRaData();
getTimeStamp();
}
}
How the Code Works
You start by including the necessary libraries. You need libraries to:
- build the asynchronous web server;
- access the ESP32 filesystem (LittleFS);
- communicate with the LoRa chip;
- control the OLED display;
- get date and time from an NTP server.
// Import Wi-Fi library
#include <WiFi.h>
#include "ESPAsyncWebServer.h"
#include <LittleFS.h>
//Libraries for LoRa
#include <SPI.h>
#include <LoRa.h>
//Libraries for OLED Display
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// Libraries to get time from NTP Server
#include <NTPClient.h>
#include <WiFiUdp.h>
Define the pins used by the LoRa transceiver module.
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
Note: if you’re using another LoRa board, check the pins used by the LoRa transceiver chip.
Define the LoRa frequency:
//433E6 for Asia
//866E6 for Europe
//915E6 for North America
#define BAND 866E6
Set up the OLED pins:
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
Enter your network credentials in the following variables so that the ESP32 can connect to your local network.
const char* ssid = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";
Define an NTP Client to get date and time:
WiFiUDP ntpUDP;
NTPClient timeClient(ntpUDP);
Create variables to save date and time:
String formattedDate;
String day;
String hour;
String timestamp;
More variables to store the sensor readings received via LoRa radio.
int rssi;
String loRaMessage;
String temperature;
String humidity;
String pressure;
String readingID;
Create an AsyncWebServer object called server on port 80.
AsyncWebServer server(80);
Create an object called display for the OLED display:
AsyncWebServer server(80);
processor()
The processor() function is what will attribute values to the placeholders we’ve created on the HTML file.
It accepts as argument the placeholder and should return a String that will replace that placeholder.
For example, if it finds the TEMPERATURE placeholder, it will return the temperature String variable.
// 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 == "PRESSURE"){
return pressure;
}
else if(var == "TIMESTAMP"){
return timestamp;
}
else if (var == "RRSI"){
return String(rssi);
}
return String();
}
setup()
In the setup(), you initialize the OLED display, the LoRa communication, and connect to Wi-Fi.
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
startOLED();
startLoRA();
connectWiFi();
You also initialize LittleFS:
if(!LittleFS.begin()){
Serial.println("An Error has occurred while mounting LittleFS");
return;
}
Async Web Server
The ESPAsyncWebServer library allows us to configure the routes where the server will be listening for incoming HTTP requests.
For example, when a request is received on the route URL, we send the index.html file that is saved in the ESP32 LittleFS:
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/index.html", String(), false, processor);
});
As mentioned previously, we added a bit of Javascript to the HTML file that is responsible for updating the web page every 10 seconds. When that happens, it makes a request on the /temperature, /humidity, /pressure, /timestamp, /rssi URLs.
So, we need to handle what happens when we receive those requests. We simply need to send the temperature, humidity, pressure, timestamp and rssi variables. The variables should be sent in char format, that’s why we use the .c_str() method.
server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", temperature.c_str());
});
server.on("/humidity", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", humidity.c_str());
});
server.on("/pressure", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", pressure.c_str());
});
server.on("/timestamp", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", timestamp.c_str());
});
server.on("/rssi", HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, "text/plain", String(rssi).c_str());
});
Because we included an image in the web page, we’ll get a request “asking” for the image. So, we need to send the image that is saved on the ESP32 LittleFS.
server.on("/winter", HTTP_GET, [](AsyncWebServerRequest *request){
request->send(LittleFS, "/winter.jpg", "image/jpg");
});
Finally, start the web server.
server.begin();
NTPClient
Still in the setup(), create an NTP client to get the time from the internet.
timeClient.begin();
The time is returned in GMT format, so if you need to adjust for your timezone, you can use the following:
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(0);
loop()
In the loop(), we listen for incoming LoRa packets:
int packetSize = LoRa.parsePacket();
If a new LoRa packet is available, we call the getLoRaData() and getTimeStamp() functions.
if (packetSize) {
getLoRaData();
getTimeStamp();
}
The getLoRaData() function receives the LoRa message and splits it to get the different readings.
The getTimeStamp() function gets the time and date from the internet at the moment we receive the packet.
Uploading Code and Files
After inserting your network credentials, save your sketch. Then, in your Arduino IDE go to Sketch > Show Sketch Folder, and create a folder called data.
Inside that folder, you should have the HTML file and the image file.
After making sure you have all the needed files in the right directories, you need to upload the files to the ESP32 LittleFS filesystem.
Press [Ctrl] + [Shift] + [P] on Windows or [⌘] + [Shift] + [P] on MacOS to open the command palette. Search for the Upload LittleFS to Pico/ESP8266/ESP32 command and click on it.
If you don’t have this option it’s because you didn’t install the filesystem uploader plugin. Check this tutorial.
Important: make sure the Serial Monitor is closed before uploading to the filesystem. Otherwise, the upload will fail.
After a few seconds, the files should be successfully uploaded to LittleFS.
Now, upload the sketch to your board.
Open the Serial Monitor at a baud rate of 115200.
You should get the ESP32 IP address, and you should start receiving LoRa packets from the sender.
You should also get the IP address displayed on the OLED.
Demonstration
Open a browser and type your ESP32 IP address. You should see the web server with the latest sensor readings.
With these boards we were able to get a stable LoRa communication up to 180 meters (590 ft) in open field. These means that we can have the sender and receiver 180 meters apart and we’re still able to get and check the readings on the web server.
Getting a stable communication at a distance of 180 meters with such low cost boards and without any further customization is really impressive.
However, in a previous project using an RFM95 SX1276 LoRa transceiver chip with an home made antenna, we got better results: more than 250 meters with many obstacles in between.
The communication range will really depend on your environment, the LoRa board you’re using and many other variables.
Wrapping Up
You can take this project further and build an off-the-grid monitoring system by adding solar panels and deep sleep to your LoRa sender. The following articles might help you do that:
- ESP32 Deep Sleep with Arduino IDE and Wake Up Sources
- Power ESP32 with Solar Panels
- ESP32 with Built-in SX1276 LoRa and SSD1306 OLED Display (Review)
You may also want to access your sensor readings from anywhere or plot them on a chart:
- Visualize Your Sensor Readings from Anywhere in the World (ESP32 + MySQL + PHP)
- ESP32 Plot Sensor Readings in Real Time Charts – Web Server
We hope you’ve found this project interesting. If you’d like to see more projects using LoRa radio, let us know in the comments’ section.
Thanks for reading.
Could this be powered by one or more 6 volt solar panels, similar to the article “Power ESP32/ESP8266 with Solar Panels” but using the on-board battery regulator ?
Nice! Smartly-adapted thinking at work and well instructed!
Thanks 😀
Rui,
Nice Tutorial, but I think you should emphasize some LoRa facts:
Choice of Frequency has to be relevant to both the country/region you are in and the board you purchase. The TTGO seems to ship with a the same antenna, whatever band you choose (is it 433Mhz?). I have been unable to do a frequency test on the ones I have but they are not very good at 915Mhz.
Since the frequency bands are a shared resource, most countries have limitations on how often you can transmit your information. Every 10 seconds is good for testing, but Temperature/Humidity/Air Pressure readings would be just as relevant if sent every 30 or 60 seconds.
If someone is considering other data they should consider how often they need to update the information.
Dave
Hi Dave.
Thank you for your comment.
Yes, you are right, you need to choose a LoRa board with a frequency suitable for your country.
And I agree with you that 10 seconds is a very short interval. In a real world application, I suggest using deep sleep and send readings every hour or every 30 minutes.
Regards,
Sara
I think if it’s loraWan then there is a limit but using just the LoRa node to node you can TX as much as you like.
Great project!
I need to send dust sensor data (sensor=SDS 011) via LoRa. I will try out your tutorial and hope it will word with this I2C sensor, too.
Could you do a tutorial about sending LoRa packets to a TTN gateway?
Hi Joerg.
Thank you for your comment.
We plan to write a tutorial about sending LoRa packets to a TTN gateway. However, we still don’t know when we’ll start doing it.
Regards,
Sara
First of all, great job RandomNerd tutos!! I’m a Big fan!
For the LoRa node sending packets to a TTN gateway, I have just finished a working prototype:
https://marcoroda.com/2020/04/12/TTGO-LORA-TTN.html
Hope you find it useful.
Cheers,
Marco Roda
Hi Marco.
Thank you so much for sharing.
I’ll take a look at it when I have some free time.
Thanks 😀
Regards,
Sara
Very nice tutorial and much appreciated. Well done Rui.
The distance achieved should be much better. The following two youtube videos will provide more insight.
https://www.youtube.com/watch?v=BOc3N3Yl38o
https://www.youtube.com/watch?v=cjVwTf8iDFY
Josias
Hi Josias.
Thank you for sharing those videos.
Andreas Spiess’s videos are great!
Regards,
Sara
This is really useful. The Sender code worked without any difficulties.
The received code produced –
‘class NTPClient’ has no member named ‘getformattedDate’
Any ideas how to fix?
Hi.
You’ve probably installed the wrong NTPClient library.
You need to install the NTP Client library forked by Taranais that includes that method.
Here’s the link: https://github.com/taranais/NTPClient
Regards,
Sara
Yes thanks – problem solved when I installed the correct library.
Great!
Very nice tutorial and much appreciated.I have already put into practice your many tutorials and all work perfectly. wonderful tutorials
do you know a way to monitor battery voltage on this model board
Yves
Hi Yves.
Thank you for your comment.
There are boards that come with a pin called “bat” in which you can read the voltage level. I haven’t find a pin like that in this board.
So, I guess you need to create your own voltage level monitoring circuit.
Regards,
Sara
have you any idea how i can make voltage level monitoring circuit.??
pick up phisically the positive lead of battery and wire it to gpio ?
many thank’s
Yes.
But pay attention that you can’t read more than 3.3V on the ESP32 GPIOs. So, if your battery has a higher voltage, you may need to add a voltage divider circuit.
See the example in this project: https://randomnerdtutorials.com/power-esp32-esp8266-solar-panels-battery-level-monitoring/
Search for the “Battery Voltage Level Monitoring Circuit” in that article.
Regards,
Sara
Hi Sara, Bonjour Yves,
I use a LiFe battery delivering 3.2 V
LiitoKala – LiFePO4 battery, 3.2V, 32700, 6500mAh, high power, with DIY Nickel foils connectors, continuous discharge 35a, Maximum 55a
Operates very well ! The quality is also correct
Excuse me I forgot to ask you if it is possible to have several transmitters (for example 10,20 or 30) and a single receiver?
thanks again for your tutorials and for your answer
Yves
Hi Yves.
In theory, that’s possible. But you have to experiment and see if it is feasible.
Regards,
Sara
thank you very much for your answer, i experiment that and tell you if it’s working (iI already tried with three sender and it’s work fine)
regards
Yves
Do you have a copy of your code that you could share? I am looking at transmitting both analog values and digital (on/off) values from a few nodes to a master.
Excellent article!
What distances did you get between the LoRa devices during your testing?
Hi Jaco.
180 meters.
Regards,
Sara
Worth information.
Thanks for your gratitude.
do you know how to know the loss of connection with the receiver, I made a system of monitoring the proper operation of pumps levies, but I can not solve this problem ????
https://www.instructables.com/id/Operating-Sensors-for-Individual-Sampling-Pumps/
What type of connection do you have with the receiver?
connect with lora.
many thank’s for your answer
best regards
Nice tutorial again,
I bought this one: Labeled the same as yours but the drawing you show is backwards to this one:
https://www.ebay.com/itm/LILYGO-TTGO-LORA32-868Mhz-SX1276-ESP32-Oled-Display-bluetooth-WIFI-Lora-Developm/113836869637?ssPageName=STRK%3AMEBIDX%3AIT&_trksid=p2057872.m2749.l2649
Also looks like pin 13 is not scl on this one, but 22. Can’t seem to get this one to work and the OLED is all white with garbage in it.
Apologies, the pinout on the ebay page is wrong and I blew a bme280. Now works just as you described.
hello,
I have this error with the receiver.
Advice ?
Thanks,
C:\2.DATA\DEV\libraries\AsyncTCP\src\AsyncTCP.cpp: In function ‘bool _start_async_task()’:
C:\2.DATA\DEV\libraries\AsyncTCP\src\AsyncTCP.cpp:221:141: error: ‘xTaskCreateUniversal’ was not declared in this scope
xTaskCreateUniversal(_async_service_task, “async_tcp”, 8192 * 2, NULL, 3, &_async_service_task_handle, CONFIG_ASYNC_TCP_RUNNING_CORE);
^
exit status 1
Error compiling for board TTGO LoRa32-OLED V1.
I bought 2 of these from LilyGO and neither one is recognized by my computer. Do I need a 10uF cap between EN and GND? But, that would have anything to do with the USB port recognized. Any guesses?
Hi.
You don’t need to do that.
Have you ever gotten an ESP32 recognized by your computer?
I just needed to connect via USB cable and it worked straight away.
Regards,
Sara
Hi Sara,
Yes I use the ESP32-CAM (although I wish I could figure out how to make it auto refresh on my phone and computer) and the ESP32 for controlling relays.
Hi Sara
The project is running fine, thank you.
But I’ve some questions about the receiver part.
From time to time (1h to 6-7h but never longer), the sketch stops.
And this with Edge or Chrome.
I suppose it stops reading datas but the serial monitor does not show activities neither the www.
I’ve already exchanged the ESP w/o success.
Searching on internet shows “delay” topics.
You mention in “https://rntlab.com/question/solved-esp32-web-server-drops-connection-crashes/” some identical prblm adding also “delay” but only with Chrome.
I can’t find any solution.
What do you suggest?
Thanks
Hi Jean-Luc,
I have the same problem, need to further investigate with serial debugging where it hangs. Were you able to find a solution already?
Fixed it by little research on the web. Just put delay(1) at the begin of the loop and continues to run 😉
I don’t understand the choice of board for this project.
If the sensor is a distance away, in a field or somewhere inaccessible, why have an OLED on it? It just wastes power…
Similarly, if the ‘receiver=base station’ has a web server that shows data on a phone, why bother with an OLED?
It’s a tutoria Duncan. It’s for learning and the screens help.
When you learn everything possible then you can for sure code your own weather station with any board you like to save power.
Hi Sara and Rui,
First of all, thank you for your so interesting tutorials, they are always very well done and very instructive. Thank you so much!
I was just surprised of the range of 180 m according to your tests. This is much smaller than the range of 250 m you tested with the simple WIFI connection of ESP-NOW in another of your tutorials, and significantly lower than the long range normally expected for LoRa devices (a few 100 m or even a few km). Do you have any idea why? Is it due to the buidling quality of that specific TTGO board? Or does it need further tweaking to increase the range? If so, I would be grateful if you could make some tutorial about this aspect, or point to relevant information sources.
Thank you very much in advance for your help!
Best regards,
Sam
Hi Sam.
Thanks for your comment.
Yes, you are right. We were also disappointed about the communication range with LoRa. I think it may be due to the environment where we were testing and to the LoRa settings set by default.
One of our readers reported a communication range of a few km with some changes on the LoRa settings.
Here are the links for the changes:
https://pastebin.com/5feAAf4A
https://pastebin.com/qVqJbQYt
It may be worth taking a look at this article: https://www.ncbi.nlm.nih.gov/pmc/articles/PMC5038744/
I hope this helps.
Regards,
Sara
Thank you very much for your answer!
Best regards,
Sam
I’m getting up to about 500 meters through trees and a few houses in my neighborhood and across the highway. Better than I expected for sure without any optimization of parameters. 915Mhz band. This is just snd and receive sketch so nothing fancy on data transfer. Am going to add GPS to do distance calculations when I get a chance.
Hello,
Very interesting project.
Do you have any experience using it (this TTGO ESP32 and LoRA) for Radio Control of a model sailboat?
Do you how many times per second I can be able to send the Potentiometer value (from a Joystick) to the receiver?
I have a different board (also from TTGO but the one with Oled, GPS, Bluetooth and WiFi and LoRA, of course. Do you know if the same sketch could work? Or is your sketch speficic for the TTGO used in the project?
One thing I have tried but it did not compile was to use this project with a Heltec Esp32 with LoRA. It can not find the LoRa class…
Hi.
This code should be compatible with any board that has an OLED and a LoRa module. To make it compatible you need to make sure that you have the right pin definition for your LoRa board.
What I mean by this, is that you need to know which pins your board uses to connect to the LoRa module and to the OLED display. Then, insert the right pins on the following lines:
For the LoRa module:
#define SCK 5
#define MISO 19
#define MOSI 27
#define SS 18
#define RST 14
#define DIO0 26
And for the OLED
#define OLED_SDA 4
#define OLED_SCL 15
#define OLED_RST 16
If you have an error that it can’t find the LoRa class, that probably means that you don’t have the library installed.
I hope this helps.
Regards,
Sara
Hi,
Your tutorials are very explicit and easy to learn.
After trying this project and other from your tutorials, i´m having problems to connect to my wifi. It can´t connect to wifi. It hold in while() cycle printing dots and doesn´t end cycle.
Using other examples from other examples, i draw a code to try wifi connection and can connect after few seconds. Even when i use same lines from my code in this project and it still can´t connected.
Per example, i defined Wifi.mode(WiFi_STA) and WiFi.disconnect() before WiFi.Begin() like i did in my program and still can´t connect.
Can you help me with some solution?
Regards,
Hugo Morais
Hi Hugo.
Are you using the exact code we’re using in this tutorial?
Were you able to connect the same board but using a different code?
REgards,
sara
Hi,
My boards are TTGO T1.
I tried the exact code. With your code the while() loop doesn´t finish and isn’t connected.
Using other code i made it to connect my wifi.
Regards, Hugo
What code do you use to connect to Wi-Fi?
Isn’t that the same we use in the code?
Have you inserted the right network credentials?
Regards,
Sara
#include “WiFi.h”
void setup()
{
Serial.begin(115200);
// Set WiFi to station mode and disconnect from an AP if it was previously connected
WiFi.mode(WIFI_STA);
WiFi.disconnect();
delay(100);
Serial.println(“Setup done”);
}
void prtStatus(){
Serial.print (“Wifi.status: “);
Serial.print(WiFi.status());
Serial.print(” -> “);
switch (WiFi.status()) {
case WL_CONNECTED: Serial.println(“Connected”); break;
case WL_NO_SHIELD: Serial.println(“Wifi not available”); break;
case WL_IDLE_STATUS: Serial.println(“Waiting for .begin to end”); break;
case WL_NO_SSID_AVAIL: Serial.println(“No networks available”); break;
case WL_SCAN_COMPLETED: Serial.println(“Scanning is complete”); break;
case WL_CONNECT_FAILED: Serial.println(“Connection failed”); break;
case WL_CONNECTION_LOST: Serial.println(“Connection lost”); break;
case WL_DISCONNECTED: Serial.println(“Disconnected”); break;
}
}
// new SSID and new Pass
bool chkWifi(char *nSSID, char *nPass){
bool isConn=WiFi.status() == WL_CONNECTED; //if connected then goes true
int i=0;
prtStatus();
if (!isConn) {
Serial.print(“Scanning for “);
Serial.println(nSSID);
// WiFi.scanNetworks will return the number of networks found
int n = WiFi.scanNetworks();
prtStatus();
if (n == 0) {
Serial.println("No networks found");
} else {
Serial.print(n);
Serial.println(" networks found");
while (i<n && !isConn ) {
// Print SSID and RSSI for each network found
Serial.print(i + 1);
Serial.print(": ");
Serial.print(WiFi.SSID(i));
prtStatus();
if (WiFi.SSID(i)==nSSID) {
WiFi.begin(nSSID,nPass);
isConn=WiFi.status() == WL_CONNECTED;
prtStatus();
}
Serial.print(" (");
Serial.print(WiFi.RSSI(i));
Serial.print(")");
Serial.println((WiFi.encryptionType(i) == WIFI_AUTH_OPEN) ? " " : "*");
delay(10);
i++;
}
}
Serial.println("");
}
if (isConn && String(nSSID)!=WiFi.SSID(i)) {
Serial.print(“Already connected to “);
Serial.println(nSSID);
Serial.print(“Signal: “);
Serial.println(WiFi.RSSI());
Serial.print(“IP: “);
Serial.println(WiFi.localIP());
}
else {isConn=false;}
return isConn;
}
void loop()
{
if (!chkWifi(“WIFI1″,”pass1”)) {
Serial.println(“–> Not connect <–“);
if (!chkWifi(“Wifi2″,”pass2”)) {
Serial.println(“–> Not connect <–“);
}
}
delay(2000);
}
It’s some config of wifi or something. Went to my office with different router and it connects well and now i can see webserver and all.
My router at home is HS8247W from Vodafone.
But my sketch works at home also….
Ty for help
I have the same problem.
My router is also the HS8247W from Vodafone.
Have you found a solution?
I was asking for support from Vodafone, they were responding to me in 48 hours…
Hi, Viorino.
It takes longer but it will connect. Probably Vodafone don´t have a answer for you If they do can you share it?
Regards,
Hi, Rui and Sara.
Just a simple question, may i work with the BMP180 with this code?
If can work, and how i can change the code?
Thanks for good work!
Regards.
Yes.
You can use BMP180.
You can learn how to interface with the BMP180 here: https://randomnerdtutorials.com/esp32-with-bmp180-barometric-sensor/
Then, replace the lines that use the BME280 with the appropriate functions to use BMP180.
Take into account that BMP180 does read humdity.
Regards,
Sara
Hi, Sara.
I was already did it, but i got the problem with the I2C, because library of the BMP085 not included
“TwoWire I2Cone = TwoWire(1);”
so at the sensor funtion didn´t work theses 2 lines:
#I2Cone.begin(SDA, SCL, 100000);
#bool status1 = bme.begin(0x76, &I2Cone);
some solution for this problem?
Thanks so much for help!
Hallo,
ich hab dieses schöne Projekt nachgebaut. Mein Sender ist ein arduino mini pro mit RF95 Modul und den BME280E als Sensor.
Der Empfänger ist ein Heltec WIFI LoRa 32 V2 SX1276 868MHz mit OLED und einer selbstgebauten Antenne (Doppelquad Antenne) für 868MHz.
Für WLAN hab ich eine kleine externe Antenne angeschlossen.
In der Software hab ich nur meine Pins zum LoRa Modul geändert.
Der Sender ist im Garten 1km entfernt. Der Empfänger ist auf den Dachboden installiert.
Mein Computer und der Router ist in der Wohnung 25m vom Empfänger entfernt.
Es geht alles wunderbar. Der Empänger verbindet sich mit den Router und aller 5 Minuten kommen neue Daten vom Sender.
Das geht aber nur solange wie ich die Webseite in kurzen Abständen aufrufe.
Bei langen Pausen verliert sich die WLAN Verbindung zum Router. Ich kann dann die Seite nicht mehr abrufen.
Wenn ich den Empänger kurz abschalte oder beim Reset des Empfängers geht wieder alles normal.
Wer kann mir helfen? Ist es möglich das der Empfänger den Router regelmäßig kontaktiert um die Verbindung nicht zu verlieren.
Welche Möglichkeit gibt es um die WLAN Verbindung ständig zu halten ?
Für Hilfe wäre ich sehr dankbar.
Eric
Hi,
I have recreated this beautiful project. My transmitter is an arduino mini pro with an RF95 module and the BME280E as a sensor.
The receiver is a Heltec WIFI LoRa 32 V2 SX1276 868MHz with OLED and a self-made antenna (double quad antenna) for 868MHz.
For WLAN I have connected a small external antenna.
In the software I only changed my pins for the LoRa module.
The transmitter is 1km away in the garden. The receiver is installed in the attic.
My computer and the router are 25m away from the receiver in the apartment.
Everything is going well. The receiver connects to the router and new data comes from the transmitter every 5 minutes.
But this only works as long as I visit the website at short intervals.
With long breaks, the WLAN connection to the router is lost. I can then no longer access the page.
If I switch off the receiver briefly or when the receiver is reset, everything will go back to normal.
Who can help me? Is it possible for the receiver to contact the router regularly in order not to lose the connection.
What possibility is there to keep the WiFi connection constantly?
I would be very thankful for help.
Eric
Hi Eric.
See the suggestion in this discussion to check if the wifi connection is still alive every x number of seconds.
https://rntlab.com/question/esp32-wifi-not-connecting-after-2-hours/
Regards,
Sara
Hi Sara
Thank you for the quick information.
At the weekend I only come to test. I will contact you again.
many Greetings
Eric
Hi Sara,
I think everything seems to be ok now. An attempt is made to re-establish the WLAN connection every 30 seconds if the connection was not ok.
Many thanks for your help.
https://www.reddit.com/r/esp32/comments/7trl0f/reconnect_to_wifi/
I ran into a similar problem this weekend where running my code overnight would result in a loss of wifi connection that never reconnected automatically. I solved it within my main loop (in my case I’m re-checking every 30 seconds). Below is the code but I think the main function you are looking for is WiFi.disconnect();
unsigned long check_wifi = 30000;
void loop() {
// if wifi is down, try reconnecting every 30 seconds
if ((WiFi.status() != WL_CONNECTED) && (millis() > check_wifi)) {
Serial.println(“Reconnecting to WiFi…”);
WiFi.disconnect();
WiFi.begin(SSID, PASS);
check_wifi = millis() + 30000;
}
}
I added that in the loop
greeting
Eric
hi sara
i wanna ask u something. btw im a newbie. the question is how about using esp32 + chip lora sx1278 without oled? could this work base on ur project?
Hi.
Yes, it will also work.
You will need to remove the lines of code that use OLED.
Additionally, you probably need to change the pins assigned to your LoRa module.
Usually, different LoRa boards use different pin assignments.
Regards,
Sara
Sara and Rui,
I have the Lora working when both sender and receiver are in the same room about 20 feet apart and even in the next building 50 feet away. I now have them set up about 200 feet away and I get gibberish like this
AF��,�٩ȳ���[�;��\;ȍ�s̘ᵸ����_�xٲi��|�iQ����'(�G{8Lz�’z�f��W��B�,-��G�zRѶ�1������;3 – – RSSI -120
RSSI when close is around -92.
The receiver uploads data to Adafruit IO, works fine when closer.
is this weak signal, if so can I increase it? I have antennas on both units, correct length.
Also I have the sender in Deep Sleep on solar and battery. the most I have been able to sleep the sender is 30 minutes like your code, but it stops working if more that 1800 sec. Is that the max? I would like to sleep for 2 hours between transmissions. Using ESP32 as your tutorial.
Thanks
How to send ESP32 CAM LORA RF pictures?
Hi.
I don’t think it is possible to use LoRa to send pictures.
Regards,
Sara
Great project!
Please add also a soil moisture sensor to this project.
It will be great for iot in agricultural fields.
Regards
U don’t know how much I love this website :)) lol
Hello Sara,
I am confused about RFM95 and RFM95W . Which one to use for Europe?
Thanks and regards
Said Zakaria
Nice project. I´m a beginner and I like to try this.
But I have one question:
I like to use a accu to power up the sender. How can I save power of the accu? Is it possible to send the ESP to sleep after sending data to the receiver? And after 30 sec I like to wake up the ESP for next data reading and sending. What can I do with the Oled to save power?
Can you help me with the code? What must I change in your code?
Thanks.
Hi.
I recommend taking a look at our deep sleep tutorial: https://randomnerdtutorials.com/esp32-timer-wake-up-deep-sleep/
If you want save power, remove the commands that control the OLED.
Regards,
Sara
Thanks for answer.
Can I use this board with accu as sender? What changes are necessary?
https://www.amazon.de/Stemedu-Funkknoten-Arduino-ATmega328P-Antenne/dp/B07SMZPNR7
Still waiting!!
Be nice. When we are asking for resources (like time, knowledge, etc) we need to respect that our question could take some time to be aswered
Hi.
I’m sorry but I’m not familiar with that board.
They provide some resources here that can be helpful: https://github.com/IOT-MCU
After understanding how to send readings with this board, it can be easily added to this project.
Regards,
Sara
Hi, Would it be possible to display values on IPS display instead of Web Server?
Many thanks!
Martin
Hi.
Yes. However, at the moment we don’t have any tutorial about that subject.
Regards,
Sara
Hey there!
Finally I managed to merge a lot of your very useful tutorials into one single „solar powered ESP32 weatherstation sending 15 values via LoRa to a LoRa-reciever and then to a mySQL database – Project“.
Last year I didn‘t even have a single idea how to program with arduino ide or calculate voltage dividers for example.
Thanks to your tutorials I‘m getting better and better and I still learn a lot every single day.
But now I am facing a problem for which I could not find any solution since now.
My Lora-reciever recieves some traffic from another source – I guess (RSSI for some packets is less than -110dBm).
These packets seem not to contain any variables like the readings my weatherstation is sending – like you suggested in one of your tutorials.
Like this:
void sendReadings() {
LoRaMessage = String(readingID) + “/” + String(temperature) + “&” + String(humidity) + “#” + String(pressure);
So my reciever recieves some unknown traffic and creates a httpPost with no values.
As a result I get a blank entry in my database and an „empty gap“ in the visualization (like you described in your tutorials about visualize sensor readings in MySQL and PHP).
Is there any solution to filter this unknown traffic or assign my station a „Special sender-reciever ID“?
Or just a way to tell in PHP to ignore „empty“ MySQL da ta?
Thanks in advance for your help!
Cheers,
Nico
Hi Nico.
I think the easiest solution is to set a syncword.
The receiver will only get packages from the boards with the same syncword.
This tutorial uses a syncword: https://randomnerdtutorials.com/esp32-lora-rfm95-transceiver-arduino-ide/
And this is the “official” example with syncword:https://github.com/sandeepmistry/arduino-LoRa/blob/master/examples/LoRaSetSyncWord/LoRaSetSyncWord.ino
I hope this helps.
Regards,
Sara
Hi Sara.
Thank you for the quick response!
That’s exactly what I was looking for, and such an easy solution as well.
How come I didn’t find that on my own?!
Next time I need to read ALL of your tutorials more attentive and search for the right keywords.
Thank you very much!
Don’t worry. We’re here to help.
You’re welcome!
Regards,
Sara
Hi Sara,
I have problems with SyncWord function.
I tested it with one sender (Heltic ESP32 LORA) and two receiver (heltic). One receiver has the same syncword as the sender. This works great. Only the receiver with the same syncword get the Packages from the sender.
Next test: the two receiver (Heltec) with different syncwords and a sender ATmega328P board with the syncword of one receiver. This receiver get the packages and show it on the OLED. But the other reveiver (Heltec) with different syncword shows the packages too. But wrong formatting.
Is the syntax of syncword on ATmega328P different from Heltic ESP32 Lora?
Hi.
I think the syntax is the same.
Maybe the other board receives the packages, but can’t “decode” the message??
I’m not sure what happens in that situation.
Maybe you can try to open an issue about that on the GitHub Library Issues page?
Here is the link: https://github.com/sandeepmistry/arduino-LoRa/issues
I hope this helps.
Regards,
Sara
Hi
bealtiful schematic diagram, wich tool you used? I tried Fritzing but do not have ESP32 TTGO.
Thaks!
Hi.
Fritzing doesn’t have this board.
I designed it myself.
Regards,
Sara
Hallo,
ein sehr schönes Projekt, das ich gerne nachbauen möchte.
Ich verwende als Sender ein Stemedu ATmega328 LoRa Board mit Akku. Dieses sendet die Daten des BME280. Hier ein Beispiel Daten-String: 21.7&41#1011
(Temperatur, Humidity, Pressure).
Das funktioniert so sehr gut.
Probleme habe ich auf der Seite des Receivers.
Hier verwende ich einen Heltec ESP32 LoRa. Leider wird die Uhrzeit immer um eine Stunde frtüher angezeigt, obwohl ich timeClient.setTimeOffset(+2); geändert habe.
Auch der empfangene Daten-String ist meistens ganz merkwürdig.
Z.B.
Lora packet received: 21.7&41#1011 with RSSI -89
2021-02-18T16:48:12Z
2021-02-18
16:48:12
Lora packet received: g⸮r1⸮⸮⸮#1011 with RSSI -90
2021-02-18T16:48:46Z
2021-02-18
16:48:46
Die Datenanzeige auf der Webside ist dann ebenso falsch.
Ich verwende hier euren Sketch ohne readingID.
Gerne kann ich euch auch meine beiden sketche schicken.
Viele Grüße
Ulrich Engel
Das updaten der Librarys hat den Anzeigenfehler der Wetterdaten behoben.
Was aber bleibt ist die falsche Zeitanzeige. Die Stundenanzeige ist um eine Stunde geringer. Dieses habe ich eigentlich mit timeClient.setTimeOffset(+1); ausgleichen wollen. Geht aber nicht.
Hi,
I now try a second Heltec ESP32 LORA as Sender. I use your sketch LORA_Sender_BME280 .
I get a compilation error line: bool status1 = bme.begin(0x76, &I2Cone);
Error message: no matching function for call to ‘Adafruit_BME280::begin(int, TwoWire*)’
Can you help me?
Thanks Ulrich Engel
Hi,
I solved this problem with updating my libraries.
Great!
I’m glad you solved the problem.
Regards,
Sara
Hi, after solving my first problems with old librarys, two problems are left:
First: I cannot fix the timestamp problem. The time is one hour behind. I tried to use timeClient.setTimeOffset(+1); But the time does not change +1 hour.
Second: I test the project over 6 hours. The transmission stopped after about 5 hours. I have to make a reboot to start transmission again. This is not good for my project “Weather-Data-Recording”.
What can I do to fix this two problems?
Thanks .
Hallo Ulrich.
Zu deinem Problem mit dem Timestamp – hast du denn die entsprechenden Zeilen auch auskommentiert? Ändert sich denn überhaupt was wenn du +/- „n“ eingibst?
Das Problem, dass die Übertragung nach x-Stunden abbricht lässt sich durch einen regelmäßigen Wifi-Check lösen.
Hatte ich auch.
Meine Station läuft seit zwei Wochen ununterbrochen mit einer Li-Ion 18650.
Ich habe leider nur weiterhin Dropouts trotz SyncWord.
Danke für die Infos. Kannst du mir die Sketch-Zeilen für den Check schicken?
Gruß Ulli
Ich hatte bei der Zeile unter den GMT-Kommentaren
timeClient.setTimeOffset(+1);
in die Klammern statt der 0 nun +1 eingetragen. Es bleibt aber weiterhin die Uhr eine Stunde zurück. Also 11:00 statt 12:00 Uhr.
Hallo Ulrich,
ich fürchte du hast da etwas übersehen.
Du müsstest das Offset in Sekunden angeben.
Dann müsste es funktionieren.
Siehe hier:
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(0);
}
Hallo Ulrich,
Du findest alle nötigen Informationen hier:
https://randomnerdtutorials.com/solved-reconnect-esp32-to-wifi/
Was mir auch geholfen hat war ein delay(1); direkt nach dem void loop().
Hier meine Sketch-Zeilen für den Wifi-Check. Der ESP32 rebootet zusätzlich automatisch immer nach einem Tag. Falls unerwünscht einfach löschen.
Erst wtimer definieren.
long wtimer; // Wifi Check Timer
Dann im void loop() {
//Timer Check WiFi nach x Sekunden (360 = 6 Min.)
if (millis() / 1000 > wtimer + 360) {
wtimer = millis() / 1000;
check_wifi();
}
//Automatischer Timer Reboot ESP nach x Sekunden (86400 = 1 Tag)
if (millis() / 1000 > 86400) {
ESP.restart();
}
}
void check_wifi() {
int wifi_retry;
while (WiFi.status() != WL_CONNECTED && wifi_retry < 5 ) {
wifi_retry++;
Serial.println(“WiFi not connected. Try to reconnect”);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
delay(5000);
}
if (wifi_retry >= 5) {
Serial.println(“Reboot”);
ESP.restart();
}
}
Siehe hier:
https://randomnerdtutorials.com/solved-reconnect-esp32-to-wifi/
Definiere zuerst den wtimer:
long wtimer; //Check Wifi
Im void loop dann:
// Timer check wifi every 6 minutes
if (millis() / 1000 > wtimer + 360) {
wtimer = millis() / 1000;
check_wifi();
}
// Timer reboot ESP every day
if (millis() / 1000 > 86400) {
ESP.restart();
}
}
void check_wifi() {
int wifi_retry;
while (WiFi.status() != WL_CONNECTED && wifi_retry < 5 ) {
wifi_retry++;
Serial.println(“WiFi not connected. Try to reconnect”);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
delay(5000);
}
if (wifi_retry >= 5) {
Serial.println(“Reboot”);
ESP.restart();
}
}
Hallo Nico,
ich habe jetzt deine Zeilen eingefügt:
……………
// Function to test ESP WiFi connection
void check_wifi() {
int wifi_retry;
while (WiFi.status() != WL_CONNECTED && wifi_retry < 5 ) {
wifi_retry++;
Serial.println(“WiFi not connected. Try to reconnect”);
WiFi.disconnect();
WiFi.mode(WIFI_OFF);
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
delay(5000);
}
if (wifi_retry >= 5) {
Serial.println(“Reboot”);
ESP.restart();
}
}
void setup() {
// Initialize Serial Monitor
Serial.begin(115200);
startOLED();
startLoRA();
connectWiFi();
if(!SPIFFS.begin()){
Serial.println(“An Error has occurred while mounting SPIFFS”);
return;
}
// Route for root / web page
server.on(“/”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/index.html”, String(), false, processor);
});
server.on(“/temperature”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, temperature.c_str());
});
server.on(“/humidity”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, humidity.c_str());
});
server.on(“/pressure”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, pressure.c_str());
});
server.on(“/timestamp”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, timestamp.c_str());
});
server.on(“/rssi”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send_P(200, “text/plain”, String(rssi).c_str());
});
server.on(“/winter”, HTTP_GET, [](AsyncWebServerRequest *request){
request->send(SPIFFS, “/winter.jpg”, “image/jpg”);
});
// Start server
server.begin();
// Initialize a NTPClient to get time
timeClient.begin();
// Set offset time in seconds to adjust for your timezone, for example:
// GMT +1 = 3600
// GMT +8 = 28800
// GMT -1 = -3600
// GMT 0 = 0
timeClient.setTimeOffset(3600);
}
void loop() {
// Timer check wifi every 6 minutes
if (millis() / 1000 > wtimer + 360) {
wtimer = millis() / 1000;
check_wifi();
}
// Timer reboot ESP every day
if (millis() / 1000 > 86400) {
ESP.restart();
}
// Check if there are LoRa packets available
int packetSize = LoRa.parsePacket();
if (packetSize) {
getLoRaData();
getTimeStamp();
}
}
Leider nach ca. 4 Stunden “hängt” das Receiver-Board. Im serial monitor kommen auch keine Ausgaben/Fehlermeldungen. Nach meinem Hard-Reset (USB-Stecker ziehen) läuft er dann weiter.
Hat also noch nicht geholfen.
Viele Grüße Ulli
Hallo Nico, vielen Dank für deine Informationen. Diese Aussetzer beim ESP scheinen ja den Profis bekannt zu sein. Mir als Anfänger waren sie neu. Ich habe mich nur gewundert über diese Abbrüche und Fehler bei mir gesucht. Typisch Anfänger.
Ich habe zu Lora auch viel auf YouTube gesehen. U.a. den Kanal aeq-web.com von Alex Egger. Aber leider wird dort auf Kommentare nur sehr schleppend geantwortet. Für Anfänger nicht so unterstützend. Aber er ist wohl sehr komepetent.
Noch eine Frage zu deinem Code:
Ist hier nicht eine } Klamme zu viel (die letzte) ?
// Timer reboot ESP every day
if (millis() / 1000 > 86400) {
ESP.restart();
}
}
Das Problem mit dem timestamp ist nun gelöst. Da habe ich wohl falsch herum gedacht.
Viele Grüße Ulli
Hallo Ulrich,
ich habe den Code bei mir komplett am Stück ganz unten als allerletztes im void loop().
Damit funktioniert es einwandfrei.
Du hast den Code zerhackstückelt, vermutlich liegt darin das Problem.
Schau mal ein paar Posts weiter oben vom 17. Juni 2020.
Sara verlinkte die Lösung.
Eric hatte das selbe Problem und liefert am 18. Juni seine funktionierende Lösung.
Hi Ulrich,
take a look at some posts from June 17th 2020. Eric had the same problem.
Sara posted a link to the solution that works perfectly fine.
Cheers.
Hallo Nice,
könntest du mir deinen Sketch mal Mailen? arduino123(at)gmx.net
Oder soll ich die meinen aktuellen Sketch mal schicken?
Hi, I have one question:
Is it possible to use two SENDER –> RECEIVER Connections at the same time nearby?
I solved this with SynWord. I use your tutorial to SyncWord.
Is it possible to send the data from the receiver to ThingSpeak?
How can I change the LoRa Package from string to float?
Hi.
Yes, you can do that.
You can use the toFloat() method:https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/tofloat/
Regards,
Sara
Thank you very much. I thing this will help me. I try it.
After this my next step is to use a PMS5003 dust sensor with my weatherstation. Do you have some information for me, how to use the PMS5003 with an Heltec Lora32 board sender reading 1.0 , 2.5 and 10 ppm particle and send the data package with lora to the receiver?
Thanks Ulli
Hi.
At the moment, we don’t have any tutorials about that subject.
Regards,
Sara
Hi Sara,
a very nice project that I recreated. I only used another board as a sensor: Stemedu LoRa Radio Node V1.0 868MHz RFM95 SX1276. With a strong battery.
Everything works very well and the data is displayed on the phone and on the receiver Display.
But now I would also like to display the data in my ThingSpeak account. So send the data to the URL server api.thingspeak.com.
Can you tell me how I can add this second client to my receiver sketch?
If I only install the ThingSpeak part instead of the mobile phone display webserver, it works great and the data is displayed.
It just doesn’t work if I use both at the same time.
Many Thanks
Ulli
Hi.
I never tried combining those two things.
Maybe there is some incompatibility with the two sketches or the libraries you’re using; or there is something wrong with the code preventing it from doing both tasks.
Without further information, it is very difficult to find out what might be wrong.
Regards,
Sara
I have now expanded my small weather station so that I can visualize the data in ThindSpeak.
Works fine so far. If you want, I can send you the sketches. How can I send you files?
Many greetings Ulli
Hi.
Send an email to support saying you want to share your project with me: https://randomnerdtutorials.com/support/
Rui will answer you and tell you what to do.
Regards,
Sara
Hi, I’m interesting. You can share me that? [email protected]
How to fix ? Please help
exit status 1
Error compiling for board TTGO LoRa32-OLED V1.
Hi.
Can you provide more details about the error?
Regards,
Sara
Bonjour,
Pour transmettre une information grâce aux ondes, j’utilise deux cartes Lora.
La première carte Lora qui envoie l’information est :
Fengyuanhong TTGO T-Beam ESP32 WiFi sans Fil Bluetooth Module ESP 32 GPS NEO-M8N IPEX Lora 32 Titulaire de la Batterie, 868MHz: Amazon.fr: Cuisine & Maison
Et la deuxième carte Lora qui reçoit l’information est :
ILS – TTGO 2 pièces/lot ESP32 SX1276 Lora 868/915 MHz Bluetooth WI-FI Lora Conseil de développement: Amazon.fr: High-tech
Mes codes sont bons, mais durant le téléversement de la première carte Lora qui m’affiche cette erreur:
esptool.py v2.6
Serial port COM4
Connecting…….._____….._____….._____….._____….._____….._____….._____
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
A fatal error occurred: Failed to connect to ESP32: Timed out waiting for packet header
Pouvez-vous m’aider ?
Merci beaucoup!!!
Hi.
Take a look at this article:
https://randomnerdtutorials.com/solved-failed-to-connect-to-esp32-timed-out-waiting-for-packet-header/
Regards,
Sara
Hi Sara,
can i use this sketch to made an acces point (without connecting to the local network) and how to ?
Thank’s
Hi.
Yes. You can follow this tutorial to learn how to set an access point: https://randomnerdtutorials.com/esp32-access-point-ap-web-server/
Then, you need to use an external RTC to get the date and time (because you need access to the local network to get date and time).
We have this tutorial about RTC (it is for Arduino, but should be similar for the ESP32): https://randomnerdtutorials.com/guide-for-real-time-clock-rtc-module-with-arduino-ds1307-and-ds3231/
Regards,
Sara
Hi Sara,
thank’s for your quick answer but
without WiFi.softAP(ssid, password);
Le croquis utilise 1062638 octets (81%) de l’espace de stockage de programmes. Le maximum est de 1310720 octets.
Les variables globales utilisent 36508 octets (12%) de mémoire dynamique, ce qui laisse 258404 octets pour les variables locales. Le maximum est de 294912 octets.
and with
Le croquis utilise 1337014 octets (102%) de l’espace de stockage de programmes. Le maximum est de 1310720 octets.
Les variables globales utilisent 52396 octets (17%) de mémoire dynamique, ce qui laisse 242516 octets pour les variables locales. Le maximum est de 294912 octets.
Croquis trop gros ; vois http://www.arduino.cc/en/Guide/Troubleshooting#size pour des conseils de réduction.
Erreur de compilation pour la carte TTGO LoRa32-OLED V1
i want to send temperature data that received from lora receiver, how i can do it possible ?
you make connect lora receiver to web browser use Wifi.
I want to interface lora Esp32 with sht30 humidity sensor, this also operates on I2C. Do u have an example?
Hi.
Unfortunately, we don’t have any examples for the SHT30 sensor.
Regards,
Sara
Is the furthest distance that can be reached only 180m, if we test at a longer distance, what do you think?
Hi.
The distance depends on the environment.
You may be able to get a longer distance.
Regards,
Sara
does the RSSI value on the web server represent transmit strength or signal strength?
hi…
i wanna ask some question for your project. I wanna know value of bandwith, spread factor and data rate for your lora using.
Thanks
Hi Sara,
I am always impressed by the originality and the quality of your sketches, as well as by the desire to remain very didactic.
Thank you . I have learn a lot reading your site.
I tested a sender composed by ESP32, RFM95, BME280 and OLED display, adapting GPIOs’ accordingly.
Sender operates very well, but freeze in LoRa.endPacket() after one or two succesfully sent readings .
ESP32 feeded by USB serial cable to my computer.
Any ideas how I can solve this problem ?
Hi Sara,
My problem of freezing by Lora.endpacket() is solved !
I discover that the Ground connection of RFM95 was doubtfull. I secure this and now all operates very well.
I have red that this issue (freezing) seems to occur by others also. Perhaps interesting to push them to control feeding quality of their Lora chips !?
Thank you very much for your splendid work !
I’m glad you found the solution to your issue.
Thanks for sharing that.
Regards,
Sara
Good Day Sir Rui. I’m Victor, your student. Please my ESP32 LoRa transmitter interfaced with BME280 is working very well.
The LoRa receiver is also working well. But the issue now is that the LoRa receiver wasn’t connecting to the web of the same network. Arduino IDE serial monitor brought the full details when I pressed the RESET button such as IP address, sensor readings and RSSI.
But it couldn’t display these values on the web of any browser. I need assistance please
Hi Victor.
Can you provide more details about the issue? When you say you couldn’t display the values on the web browser, what happens?
If you are one of our students, please post your issue on the RNTLab forum: https://rntlab.com/forum/
You’ll get better guidance.
Regards,
Sara
Hello everyone, unfortunately I have the problem that I get wrong data. E.g. I am always shown 182.5 degrees and 100% humidity.
I load the example sketch from adafruit onto the esp and then I get normal values. maybe someone has an idea what the proeb is.
Hi, I have a SHT31 temp/humidity sensor and want to connect it thru IIC to Lora TTGO ESP32, I followed the instructions for bme thinking its just a replacement but somehow the ESP32 does not detect the SHT31. I guess its about the IIC already used by the OLED but in your example you use different sda/scl pins. Any leads or examples where SHT31 Lora ESP32 are used or any hint?
Hi.
The SHT31 is a different sensor from the BME280. So, the code is not the same.
At the moment, we don’t have any tutorials for the SHT31 sensor.
Regards,
Sara
Hi Sara and Rui,
I am trying to run this experiment on LoRa TTGO V1 with bme280. Sender working without problem. With receiver I have problems. It’s not connecting to internet. When compile receivers code error came up:
C:\Program Files (x86)\Arduino\libraries\WiFi\src/WiFi.h:79:9: note: initializing argument 1 of ‘int WiFiClass::begin(char*, const char)’
int begin(char ssid, const char passphrase);
^
exit status 1
invalid conversion from ‘const char‘ to ‘char*’ [-fpermissive]
Then I changed code lines:
from
// Replace with your network credentials
const char* ssid = “wifissid”;
const char* password = “mypassword”;
to
// Replace with your network credentials
char* ssid = “wifissid”;
char* password = “mypassword”;
Compiled and uploaded code. Now on Lora TTGO v1 board I see message: LoRa Initialization OK!
Serial monitor:
14:48:33.814 -> …………….ets Jul 29 2019 12:21:46
14:48:41.901 ->
14:48:41.901 -> rst:0x1 (POWERON_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
14:48:41.901 -> configsip: 0, SPIWP:0xee
14:48:41.901 -> clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
14:48:41.901 -> mode:DIO, clock div:1
14:48:41.901 -> load:0x3fff0018,len:4
14:48:41.901 -> load:0x3fff001c,len:1044
14:48:41.901 -> load:0x40078000,len:10124
14:48:41.901 -> load:0x40080400,len:5856
14:48:41.901 -> entry 0x400806a8
14:48:42.101 -> LoRa Initialization OK!
14:48:44.141 -> Connecting to wifissid
14:48:44.811 -> …………………………………………………………………………
and it never connects to my wifi.
Tried with several Lora TTGO v1 boards and everything exactly same.
Can you help me solve this problem.
Thank you,
Bjørn
Hi,
Thank you for nice project. I done this project on two Lora devices and it works.
Have only one really annoying problem. Receiver wifi connection on stop working after one hour. To start work again I need to restart receiver.
My programing skills are really low. Can someone help me how to implement restart function on receiver. I would like to restart receiver once per hour.
Thank you!
Jeff
Hi Sara,
I have a project that I will use the website to send signals from the Receiver module to the Sender module.
Do you have any idea to do that?
Thank you,
Lac Nguyen
I use the website to send signal like control led but I don’t know how to do it
Lac Nguyen
Hi Sara
Looks like a great project.
But I can’ t get past the transmitter build with
Arduino: 1.8.20 Hourly Build 2021/12/20 07:25 (Linux), Board: “Heltec WiFi LoRa 32(V2), Disabled, 240MHz (WiFi/BT), 921600, None, REGION_US915, Freq”
/home/jim/Arduino/Lora32-Temperature-Transmit/Lora32-Temperature-Transmit.ino: In function ‘void startBME()’:
Lora32-Temperature-Transmit:111:32: error: call of overloaded ‘begin(int, int, int)’ is ambiguous
I2Cone.begin(SDA, SCL, 100000);
^
In file included from /home/jim/Arduino/Lora32-Temperature-Transmit/Lora32-Temperature-Transmit.ino:17:
/home/jim/.arduino15/packages/esp32/hardware/esp32/2.0.2/libraries/Wire/src/Wire.h:79:10: note: candidate: ‘bool TwoWire::begin(int, int, uint32_t)’
bool begin(int sda=-1, int scl=-1, uint32_t frequency=0); // returns true, if successful init of i2c bus
^~~~~
/home/jim/.arduino15/packages/esp32/hardware/esp32/2.0.2/libraries/Wire/src/Wire.h:80:10: note: candidate: ‘bool TwoWire::begin(uint8_t, int, int, uint32_t)’
bool begin(uint8_t slaveAddr, int sda=-1, int scl=-1, uint32_t frequency=0);
^~~~~
/home/jim/Arduino/Lora32-Temperature-Transmit/Lora32-Temperature-Transmit.ino: At global scope:
Lora32-Temperature-Transmit:169:2: error: expected unqualified-id before numeric constant
}2
^
Multiple libraries were found for “Adafruit_GFX.h”
Used: /home/jim/Arduino/libraries/Adafruit_GFX_Library
Not used: /home/jim/Arduino/libraries/Adafruit-GFX-Library-master
Multiple libraries were found for “Adafruit_SSD1306.h”
Used: /home/jim/Arduino/libraries/Adafruit_SSD1306
Not used: /home/jim/Arduino/libraries/Adafruit_SSD1306-master
Multiple libraries were found for “Adafruit_Sensor.h”
Used: /home/jim/Arduino/libraries/Adafruit_Sensor-master
Not used: /home/jim/Arduino/libraries/Adafruit_Unified_Sensor
exit status 1
call of overloaded ‘begin(int, int, int)’ is ambiguous
Do you have any suggestions?
Thanks
Jim
Hi.
The code compiles just fine for me.
Tools > Boards > Boards Manager search for ESP32 and check the version you have installed.
I have 1.0.6 and everything is compiling fine.
Regardsm
Sara
Thanks Sara
I was on I believe v2.01
I rolled it back to 1.06 and indeed, it did build.
The problem with the newer versions seems related to this information (linked) but I have no idea how to go about implementing the suggested solution.
I’ll stick with your suggestion.
https://techoverflow.net/2021/12/17/how-to-fix-arduino-i2c-wire-error-call-of-overloaded-beginconst-int-const-int-int-is-ambiguous/
Cheers
Jim
Hi.
I think you need to define the frequency as an uint32_t variable.
For example:
uint32_t frequency = 400000
Then, call:
Wire.begin(Pin_I2C_SDA, Pin_I2C_SCL, frequency);
I didn’t try it, but that should be it.
Regards,
Sara
Thank you for this tutorial. Is it possible to build server with websocket in this tutorial? How would it be?
Hi.
It is possible.
You’ll have to implement a websocket server.
We have this example that you’ll have to adapt to your needs: https://randomnerdtutorials.com/esp32-websocket-server-arduino/
Regards,
Sara
Thank you very much Sara.
Buenos días Sara!. Tengo una duda acerca de la cantidad de nodos que se podrían ‘enlazar’ con el Receptor Lora configurado como (receptor + webserver) . Sabes si hay algún número máximo de dispositivos (emisores Lora) que se puedan enlazar al receptor Lora?
Muchas gracias!. Un proyecto fantástico!
Hi.
I don’t know. I guess you can have a huge number of nodes as long as they don’t send the messages at the same time.
Regards
Sara
Thank you so much for posting this tutorial, very well executed.
I am getting a new error that I can’t seem to track down. This is the error:
ERR_CONNECTION_REFUSED every time I try to access the page.
I do not believe it is my browser because it happens across several different browsers. I checked the router settings and it appears to be functioning properly. I pinged the IP address issued to the ESP32 device by the router and it returns the ping in 62ms on average.
Accessing the actual page seems to be the issue. Any advice?
Thank you for the tutorial,
Gary W
Hi
Project in pipe for having a Lora based tracker ?
What’s the range reachable by the Lora sender ?
Currently only GPS/cellular techno are used to do geolocalisation .
So could be very usefull to track vehicule for exemple.
Thanks.
Hola, excelente tutorial. Felicitaciones. Quisiera consultar si es posible realizar un enlace multipunto con 2 transmisores y 1 receptor y si ese receptor ya seria considerado un Gateway
Hi
you did a great job. Thank you so much! I did it and it works well for me. – You have another great tutorial – ‘ESP32/ESP8266: Send BME280 Sensor Readings to InfluxDB’. And now i wonder if there is a way to send the LoRaData from the receiver to a database (e.g. InfluxDB) instead to a async. webserver? I tried it by myself with code of both tutorials but without success. Do you have any ideas? I would be greatful.
Regards
Norbert
Hi.
It should work.
Probably there is something wrong with the implementation of your code.
Can you be more specific about the issue?
Regards,
Sara
Hi Sara
Congratulations on your toutorials on ESP32 they are all very interesting.
Regarding the Lora board of this toutorial ,I would like to ask you a question, How many pins of digital I/O do I have available to drive external devices without having internal conflict problems?
Hi.
I recommend taking a look at the board pinout: https://makeradvisor.com/esp32-sx1276-lora-ssd1306-oled/
If you’re using LoRa features and the OLED, I recommend not using the pins highlighted with an arrow for other peripherals: https://makeradvisor.com/wp-content/uploads/2019/10/TTGO-LoRa32-OLED-Board-Pinout.jpg
Regards,
Sara
Hi. I am with problems. The dates send don’t update. The monitor stopped in this step and don’t update more.
LoRa Initialization OK!
Connecting to xxxxxxxxx
…
WiFi connected.
IP address:
xxxxxxxxxx
Lora packet received: 109/26.46&37.18#947.86 with RSSI -32
Regards
Paulo
I am using a Heltec ESP32 Lora like receiver. The hour, data don’t appear.
This structure appear don’t work:
// Function to get date and time from NTPClient
void getTimeStamp() {
while(!timeClient.update()) {
timeClient.forceUpdate();
}
// The formattedDate comes with the following format:
// 2018-05-28T16:00:13Z
// We need to extract date and time
formattedDate = timeClient.getFormattedDate();
Serial.println(formattedDate);
I upload the library.
Thank you very much.
Hi Sara,
thank you for all your projects.
It’s the first time I have a problem with your tutorial. I use a TTGO LORA V2 1.6, I changed the LORA RTS pin to 23, OLED SDA to 21 and OLED SCL to 22 (obviously also the BME280 pin from 21 to 34.
I select TTGO OLED and TTGO OLED V2(1.16) (but also other boards…)
Unfortunately the display remains black and on the serial port I have these continuous messages.
rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
ets Jun 8 2016 00:22:57
rst:0x8 (TG1WDT_SYS_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 188777542, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0030,len:1184
load:0x40078000,len:13132
load:0x40080400,len:3036
entry 0x400805e4
ets Jun 8 2016 00:22:57
Sorry Sara for my stupid comment. Work FINE with dr quark’s suggestion
LORA RST 23
OLED SDA 21
OLED SCL 22
OLED RST -1 !!!
Thanks for your tutorials
Luca
Hi Sara. I don’t understand why no SyncWord has been set
cheers
Peter
I used this lesson in 2021 and it worked great. I now need to update it with another sensor and I’d get the message that it wouldn’t compile for ESP32.
I tracked it down and the problem is with” #include “ESPAsyncWebServer.h”. A change must have been made to the library and now this library needs to be used also. #include “AsyncTCP.h”
My sketch now uses:
#include “AsyncTCP.h”
#include “ESPAsyncWebServer.h”
and all works fine.
Thanks for all the great content!!
There are some bugs in the sender code.
In the startOLED() function there is no display.display(); at the end and therefore when I run the program it just displays garbage.
Also, my sensor (which turned out to be a BMP280 not a BME280) runs fine using the test code( replacing Adafruit_BME280 with Adafruit_BMP280 and removing the humidity references)
but it this sketch never finds it. If I run a I2C scan after startOLED(); then only the 0x3c address can be detected.
I think there is something not right with this line:
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RST);
I did it and it works perfect. Thanks. Is it possible to integrate web server page to Home Assistant?