ESP32 LoRa Communication using Arduino IDE

ESP32 LoRa Communication using Arduino IDE

The IoT industries introduced lots of technologies, but none of them was ideal for IoT devices, as they needed to transmit information to a long distance without using much power until the LoRa technology was introduced. LoRa Technology can perform very-long range transmission with low power consumption. According to Industry analyst IHS Market by 2023, 43% of all LPWAN connections will be based on LoRa. LoRa Technology is flexible for smart cities, smart homes, smart agriculture, smart metering, and smart supply chain & logistics applications. 

 

Previously we learned about LoRa technology and interfaced SX1278 Lora Module with Arduino. Now we will replace the Arduino, and use ESP32 with the SX1278 LoRa module. Here two LoRa modules will be interfaced with two ESP32 Boards to send and receive data packets from one board to another. ESP32 is a very popular Wi-Fi transceiver and microcontroller, learn more about ESP32 and its working by going through various IoT applications built on it.

 

Components Required

  • ESP32 (2)
  • LoRa -02 SX1278 Module (2)
  • 16*2 LCD Module (2)

 

SX1278 LoRa Module

 

Circuit Diagram

Circuit diagrams for the LoRa ESP32 based transmitter and receiver are given below. In this project, we are going to exchange data between two ESP32 modules using the LoRa SX1278 module. Transmitting side LoRa module will send a ‘Hello’ to the receiver side LoRa with a counter. This message can be easily replaced with any sensor data.

 

Interfacing LoRa with ESP32- Transmitting Side

On the transmitting side, ESP32 is connected with the LoRa module and 16*2 LCD Display. Here an I2C module is used to interface the LCD with ESP32. The interfacing of the ESP32 with LoRa and 16x2 LCD module is shown below. A push-button is also interfaced with ESP32 to start sending the data to the receiver.

ESP32 LoRa Communication Sender Circuit Diagram

ESP32 LoRa Communication Sender

Complete connections are given in the below table.

LoRa SX1278 Module

ESP32

3.3V

3.3V

GND

GND

NSS

D5

DIO0

D2

SCK

D18

MISO

D19

MOSI

D23

RST

D14

LCD With I2C

Arduino Uno

VCC

5V

GND

GND

SCL

D22

SDA

D21

 

Interfacing LoRa SX1278 with ESP32- Receiving Side

For the Receiving side, we are using an ESP32 with the LoRa transceiver module and 16×2 LCD module. Here the LCD is connected with ESP32 without I2C. The interfacing of the ESP32 with LoRa and LCD module is shown below

ESP32 LoRa Communication Receiver Circuit Diagram

ESP32 LoRa Communication Receiver

The connections are the same except the LCD module connected with ESP32 without using the I2C module. Complete connections are given in the below table.

LoRa SX1278 Module

ESP32

3.3V

3.3V

GND

GND

NSS

D5

DIO0

D2

SCK

D18

MISO

D19

MOSI

D23

RST

D14

LCD

ESP32

 

VSS

GND

VDD

5V

VO

Potentiometer

RS

D22

RW

GND

E

D4

D4

D15

D5

D13

D6

D26

D7

D21

A

5V

K

GND

 

ESP32 LoRa Transmitter Code

Complete code for the LoRa transmitter and receiver side is given at the end of the document. Here we are explaining some important snippets of code.

There are many libraries for LoRa communication. In this project, we are using the LoRa library by Sandeep Mistry.

 

First, include all the required libraries. SPI.h is used for SPI communication between ESP32 and LoRa and LiquidCrystal_I2C.h is used for I2C communication between ESP32 and LCD I2C module. Wire.h Library allows communication between I2C devices.

#include <SPI.h>

#include <LoRa.h>

#include <Wire.h>

#include <LiquidCrystal_I2C.h>

 

After that, define the pins where you have connected the LoRa module.

#define ss 5

#define rst 14

#define dio0 2

 

Then, define the pin for the push button.

const int buttonPin = 15;

 

Now initialize a counter to count the sent packages;

int counter = 0;

 

Change the LoRa.begin() function’s frequency. Change the frequency according to your model.

My LoRa module works on 433MHz frequency.

while (!LoRa.begin(433E6)) {

    Serial.println(".");

    delay(500);

 

Now set the sync word. Both the receiver and the sender should use the same sync word.

LoRa.setSyncWord(0xF3);

 

Now inside the void loop(), read the button state, and if the button state is high, then call the sendpacket() function.

void loop() {

   reading = digitalRead(buttonPin);

  if (reading == HIGH) {         // check if the input is HIGH (button released)

    sendpacket();

 

In sendpacket loop, initialize a packet with the beginPacket() method. LoRa.print function is used to write the data into the packet.

LoRa.beginPacket();

LoRa.print("hello ");

 

ESP32 LoRa Receiver Code

LoRa receiver code is similar to the transmitter code. The only difference is instead of sending, we are receiving the packets.

Inside the void loop function, it searches for a new packet using the LoRa.parsePacket() function. If it founds a new packet, it will read its content using the LoRa.readString() function, and then it will print it on the serial monitor.

int packetSize = LoRa.parsePacket();

    if (packetSize) {

    Serial.print("Received packet '");

    while (LoRa.available()) {

    String LoRaData = LoRa.readString();

    Serial.print(LoRaData);

    lcd.print(LoRaData);

 

Testing the LoRa Sender and Receiver

Once the hardware and program are ready, upload the sender and receiver codes in the respective ESP32 modules and power them using an adapter or USB cable. Both transmitter and receiver sections have 16x2 LCDs. LCD connected to the Sender side will show the values that are being sent while the receiver side LCD will display the received values with RSSI Values. The term RSSI stands for Received Signal Strength Indicator. The value will always be negative; in our case, it is around -68. The closer this value is to zero the stronger your signal strength is.

ESP32 LoRa Communication using Arduino IDE Working

The complete working video is given below. If you have any problem regarding this project, leave your questions in the comment section.

Code

ESP32 LoRa Transmitter Code

#include <SPI.h>
#include <LoRa.h>
#include <Wire.h> 
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2);
//define the pins used by the transceiver module
#define ss 5
#define rst 14
#define dio0 2
const int buttonPin = 15; 
int buttonState;             // the current reading from the input pin
int lastButtonState = LOW;   // the previous reading from the input pin
long lastDebounceTime = 0;  // the last time the output pin was toggled
long debounceDelay = 50;    // the debounce time; increase if the output flickers
int counter = 0;
void setup() {
  //initialize Serial Monitor
  Serial.begin(115200);
  pinMode(buttonPin, INPUT);
  lcd.begin();
  lcd.home();
  lcd.backlight();
  lcd.clear();
  while (!Serial);
  Serial.println("LoRa Sender");
  //lcd.clear();
  lcd.println("LoRa Sender     ");
  //setup LoRa transceiver module
  LoRa.setPins(ss, rst, dio0);
  //replace the LoRa.begin(---E-) argument with your location's frequency 
  //433E6 for Asia
  //866E6 for Europe
  //915E6 for North America
  while (!LoRa.begin(433E6)) {
    Serial.println(".");
    delay(500);
  }
   // Change sync word (0xF3) to match the receiver
  // The sync word assures you don't get LoRa messages from other LoRa transceivers
  // ranges from 0-0xFF
  LoRa.setSyncWord(0xF3);
  Serial.println("LoRa Initializing OK!");
}
void loop() {
   int reading = digitalRead(buttonPin);
   //Serial.print("Button State: ");
   //Serial.print(reading);
   //delay(2000);
    //if (reading == HIGH) {         // check if the input is HIGH (button released)
    //sendpacket();
//}
  if (reading != lastButtonState) {
    lastDebounceTime = millis();
  }
  if ((millis() - lastDebounceTime) > debounceDelay) 
  {
    // if the button state has changed:
    if (reading != buttonState) 
    {
      Serial.print("Button now ");
      Serial.println(LOW == reading ? "HIGH" : "LOW");
      buttonState = reading;
// When the button is in the LOW state (pulled high) the button has been pressed so send the event.
      if (buttonState == HIGH) {
        Serial.print("button pressed");
        sendpacket();
      }
}
  //Serial.print("sdfgh");
}
 lastButtonState = reading;
 //delay(2000);
}
void sendpacket()
{
  //lcd.clear();
  Serial.print("Sending packet: ");
  lcd.setCursor(0, 1);
  //lcd.print("Sending packet:");
  Serial.println(counter);
  //lcd.println(counter);
  //Send LoRa packet to receiver
  LoRa.beginPacket();
  LoRa.print("hello ");
  lcd.print("hello ");
  LoRa.print(counter);
  lcd.print(counter);
  LoRa.endPacket();
  counter++;
  delay(5000);
}

 

ESP32 LoRa Receiver Code

#include <SPI.h>
#include <LoRa.h>
#include <LiquidCrystal.h>
//define the pins used by the transceiver module
#define ss 5
#define rst 14
#define dio0 2
const int rs = 22, en = 4, d4 = 15, d5 = 13, d6 = 26, d7 = 21;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);
void setup() {
  //initialize Serial Monitor
  Serial.begin(115200);
  lcd.begin(16, 2);
  lcd.clear();
  while (!Serial);
  Serial.println("LoRa Receiver");
  lcd.print("LoRa Receiver");
  //setup LoRa transceiver module
  LoRa.setPins(ss, rst, dio0);
  //replace the LoRa.begin(---E-) argument with your location's frequency 
  //433E6 for Asia
  //866E6 for Europe
  //915E6 for North America
  while (!LoRa.begin(433E6)) {
    Serial.println(".");
    delay(500);
  }
   // Change sync word (0xF3) to match the receiver
  // The sync word assures you don't get LoRa messages from other LoRa transceivers
  // ranges from 0-0xFF
  LoRa.setSyncWord(0xF3);
  Serial.println("LoRa Initializing OK!");
}
void loop() {
  // try to parse packet
  int packetSize = LoRa.parsePacket();
  lcd.setCursor(0, 1);
  if (packetSize) {
    // received a packet
    Serial.print("Received packet '");
    // read packet
    while (LoRa.available()) {
      String LoRaData = LoRa.readString();
      Serial.print(LoRaData);
      lcd.print(LoRaData); 
    }
    // print RSSI of packet
    Serial.print("' with RSSI ");
    lcd.print("' RSSI");
    Serial.println(LoRa.packetRssi());
    lcd.println(LoRa.packetRssi());
  }
}

Video