How to get started with LoRa LPWAN using TTGO LoRa32

This tutorial covers how to get started with LoRa LPWAN using TTGO LoRa32 SX1276. TTGO Lora32 is an ESP32 device with a LoRa module and an SSD1306 LCD display.

Using a pair of these devices, we will explore how to send and receive packets using a LoRa network. This is a point-to-point communication where one TTGO Lora32 acts as a sender and the other one is the receiver. Using the LCD display we will visualize the packets transmitted. In this project, we will use PlatformIO to build this project, even if you can choose the IDE you like.

What is LoRa LPWAN?

Before using TTGO LoRa32 with SX1276 chipset, it is useful to describe briefly what is LoRa. LoRa stands for Long Range and is a low-power wide-area network (LPWAN). It uses a wide range of radio frequencies that are:

  • 868MHz in Europe
  • 915MHz in Australia and North America
  • 923MHz in Asia

These are free frequencies. LoRa is very efficient network that can transmit data packets in a long-range (more than 10Km in rural areas). If you want to have more information you can refer to Semtech website.

TTGO LoRa32 SX1276 pins

TTGO LoRa32 is an ESP32 device with an SX1276 chipset that handles the LoRa network and an SSD1306 LCD display. It is useful to list the pins we will use. You can buy these devices at DigitSpace.com.

SSD1306 Pins

The SSD1306 is connected to the ESP32 using I2C protocol. The pins used are:

NameESP32 Pins
SDA4
SCL15
RST16

SX1276 Pins – LoRa module

The LoRa module SX1276 is connected to the ESP32 using the SPI protocol. The pins used are:

NameESP32 Pins
MISO19
CS17
MOSI27
SCK5
RST14
IRQ26

Installing the LoRa library and the SSD1306 library using PlatformIO

Before jumping into the project, it is necessary to select the right libraries to use. This tutorial uses PlatformIO to develop this project. Anyway, you can build it with Arduino IDE. We assume you are familiar with PlatformIO so it is necessary to create a project and select the TTGO LoRa32 device as shown below:

How to use TTGO LoRa32

Next, open the platformio.ini file. Here we will configure the library used in this project. Add the following lines:

lib_deps = sandeepmistry/LoRa @ ^0.7.2 adafruit/Adafruit SSD1306 @ ^2.4.0 adafruit/Adafruit GFX Library @ ^1.10.1 adafruit/Adafruit BusIO @ ^1.5.0

LoRa sender code

Now we can develop the LoRa sender. Below the code to use:

#include <Arduino.h> // LoRa include #include <SPI.h> #include <LoRa.h> // display include #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> // Define OLED PIN #define OLED_SDA 4 #define OLED_SCL 15 #define OLED_RST 16 // LoRa pins #define LORA_MISO 19 #define LORA_CS 18 #define LORA_MOSI 27 #define LORA_SCK 5 #define LORA_RST 14 #define LORA_IRQ 26 // LoRa Band (change it if you are outside Europe according to your country) #define LORA_BAND 866E6 // Simple counter int counter = 0; Adafruit_SSD1306 display(128, 32, &Wire, OLED_RST); void resetDisplay() { digitalWrite(OLED_RST, LOW); delay(25); digitalWrite(OLED_RST, HIGH); } void initializeDisplay() { Serial.println("Initializing display..."); Wire.begin(OLED_SDA, OLED_SCL); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { Serial.println("Failed to initialize the dispaly"); for (;;); } Serial.println("Display initialized"); display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(1); display.setCursor(0,0); display.println("Welcome to LORA"); display.setTextSize(1); display.println("Lora sender"); display.display(); } void initLoRa() { Serial.println("Initializing LoRa...."); SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ); // Start LoRa using the frequency int result = LoRa.begin(LORA_BAND); if (result != 1) { display.setCursor(0,10); display.println("Failed to start LoRa network!"); for (;;); } Serial.println("LoRa initialized"); display.setCursor(0,15); display.println("LoRa network OK!"); display.display(); delay(2000); } void setup() { Serial.begin(9600); Serial.println("Setup LoRa Sender...."); resetDisplay(); initializeDisplay(); initLoRa(); } void loop() { // As example, we will send a simple packet LoRa.beginPacket(); LoRa.print("Hi LoRa receiver. This is number:"); LoRa.print(counter); LoRa.endPacket(); display.clearDisplay(); display.setCursor(0,2); display.print("Packet: "); display.print(counter); display.display(); counter++; delay(2000); }

You can find the sender source code at Github.

How the sender code works

The code is easy. At the beginning we define the libraries to include. First, the libraries needed to handle LoRa protocol:

// LoRa include #include <SPI.h> #include <LoRa.h>

and next the libraries to handle the SSD1306 LCD:

// display include #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h>

Initializing the SSD1306

Now, the ESP32 sketch initializes the LCD display. First, the sketch defines the PINS to use to interact with the SSD1306 using the PINS shown above:

// Define OLED PIN #define OLED_SDA 4 #define OLED_SCL 15 #define OLED_RST 16

Next, we initialize the LCD display, creating an Adafruit_SSD1306 object as shown below:

Adafruit_SSD1306 display(128, 32, &Wire, OLED_RST);

Now, we define two functions: one to reset the display:

void resetDisplay() { digitalWrite(OLED_RST, LOW); delay(25); digitalWrite(OLED_RST, HIGH); }

In the code above, the sketch send an LOW signal to the reset pin and then an HIGH value to reset it.

Finally, we can initialize the SSD1306 using the code below:

void initializeDisplay() { Serial.println("Initializing display..."); Wire.begin(OLED_SDA, OLED_SCL); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { Serial.println("Failed to initialize the dispaly"); for (;;); } Serial.println("Display initialized"); display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(1); display.setCursor(0,0); display.println("Welcome to LORA"); display.setTextSize(1); display.println("Lora sender"); display.display(); }

In the line 4, we start an I2C communication using the SDA PIN (data pin) and the CLK PIN (the clock).

In the line 5, the code initializes the LCD screen using 0x3C address. If everything works as expected, it is possible to interact with the OLED display using the Adafruit library functions.

Initializing the SX1276 Module

Next, we initialize the LoRa module SX1276. As said before, the module uses the SPI protocol, therefore we have to define the following PINS as described previously:

// LoRa pins #define LORA_MISO 19 #define LORA_CS 18 #define LORA_MOSI 27 #define LORA_SCK 5 #define LORA_RST 14 #define LORA_IRQ 26

It is necessary to define the LoRa band:

// LoRa Band (change it if you are outside Europe according to your country) #define LORA_BAND 866E6

If you are outside Europe, you have to change it using the following values:

//433E6 for Asia //915E6 for North America

Then, we can initialize the LoRa module SX1276 setting the SPI pins:

SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS);

and then the LoRa pins:

LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ);

The last step is initializing the LoRa protocol setting the right frequency:

int result = LoRa.begin(LORA_BAND); if (result != 1) { display.setCursor(0,10); display.println("Failed to start LoRa network!"); for (;;); }

Sending the LoRa packet

To make things simple, we can suppose to send a simple packet every 2 seconds. This packet is a simple string with a counter that is incremented everytime we send a new packet. In the loop() to send a packet, it is necessary to define a new packet using:

LoRa.beginPacket();

Next, we fill the packet with the string we want to send and with the counter:

LoRa.print("Hi LoRa receiver. This is number:"); LoRa.print(counter);

Finally, when we have finished our packet we call:

LoRa.endPacket();

LoRa receiver source code

Now, we will develop the LoRa receiver that will receive the packets send from the LoRa sender. In this case, you have to care a new project using PlatfromIO. The receiver sketch is very simple and it is similar to the sender:

#include <Arduino.h> // LoRa include #include <SPI.h> #include <LoRa.h> // display include #include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> // Define OLED PIN #define OLED_SDA 4 #define OLED_SCL 15 #define OLED_RST 16 // LoRa pins #define LORA_MISO 19 #define LORA_CS 18 #define LORA_MOSI 27 #define LORA_SCK 5 #define LORA_RST 14 #define LORA_IRQ 26 // LoRa Band (change it if you are outside Europe according to your country) #define LORA_BAND 866E6 // Simple counter int counter = 0; String data; Adafruit_SSD1306 display(128, 32, &Wire, OLED_RST); void resetDisplay() { digitalWrite(OLED_RST, LOW); delay(25); digitalWrite(OLED_RST, HIGH); } void initializeDisplay() { Serial.println("Initializing display..."); Wire.begin(OLED_SDA, OLED_SCL); if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3c)) { Serial.println("Failed to initialize the dispaly"); for (;;); } Serial.println("Display initialized"); display.clearDisplay(); display.setTextColor(WHITE); display.setTextSize(1); display.setCursor(0,0); display.println("Welcome to LORA"); display.setTextSize(1); display.println("Lora receiver"); display.display(); } void onReceive(int packetSize) { Serial.println("Packet received"); if (packetSize) { while (LoRa.available()) { data = LoRa.readString(); Serial.println("Data:" + data); } } display.setCursor(0,20); display.println(data); display.display(); } void initLoRa() { Serial.println("Initializing LoRa...."); SPI.begin(LORA_SCK, LORA_MISO, LORA_MOSI, LORA_CS); LoRa.setPins(LORA_CS, LORA_RST, LORA_IRQ); // Start LoRa using the frequency int result = LoRa.begin(LORA_BAND); if (result != 1) { display.setCursor(0,10); display.println("Failed to start LoRa network!"); for (;;); } // LoRa.onReceive(onReceive); // LoRa.receive(); Serial.println("LoRa initialized"); display.setCursor(0,15); display.println("LoRa network OK!"); display.display(); delay(2000); } void setup() { Serial.begin(9600); Serial.println("Setup LoRa Sender...."); resetDisplay(); initializeDisplay(); initLoRa(); } void loop() { //try to parse packet int packetSize = LoRa.parsePacket(); if (packetSize) { //received a packet Serial.print("Received packet "); //read packet while (LoRa.available()) { data = LoRa.readString(); Serial.print(data); } display.clearDisplay(); display.setCursor(0,2); display.println(data); display.display(); } }

The code is very simple to the code used for the sender. Let us analyze how to receive packets in LoRa.

The receiver source code is available a Github.

How to receive packets in LoRa32 SX1276

There are two different methods to receive packets:

  • Using a callback function
  • Handling the incoming packets in the loop() method

Implementing a callback function to receive packets

If we want to use a callback function, the first step is implementing it:

void onReceive(int packetSize) { Serial.println("Packet received"); if (packetSize) { while (LoRa.available()) { data = LoRa.readString(); Serial.println("Data:" + data); } } }

In this piece of code, the sketch simply checks if the packetSize is greater than zero. If this condition is satisfied, we can read the data packets, using:

LoRa.readString();

Next, it is necessary to register this callback function:

LoRa.onReceive(onReceive);

Finally, the sketch calls:

LoRa.receive();

to start receiving packets.

Reading LoRa packets in the loop() method

The alternative method is reading LoRa packets in the loop() method. First, we have to check if a new packet is available:

int packetSize = LoRa.parsePacket();

Next, if the a new packet is ready we can read it:

if (packetSize) { //received a packet Serial.print("Received packet "); //read packet while (LoRa.available()) { data = LoRa.readString(); Serial.print(data); } ... }

That’s all!

You may like other tutorials about ESP32:

Testing the LoRa receiver and the LoRa sender

You can now upload the code to the LoRa receiver through the PlatformIO. Below some images of the LoRa receiver at work:

LoRa sender. Send LoRa packets usign TTGO LoRa32

Below the LoRa receiver:

LoRa receiver using TTGO LoRa32

Finally, the sender and receiver while exchange packets:

LoRa network to exchange packets

Wrapping up

In this article, we have covered how to get started with LoRa network and you have learned how to use TTGO LoRa32 SX1276 to build a simple LoRa network where the sender and the receiver exchanges packets.

We have developed a LoRa sender and a LoRa receiver using PlatformIO, you can improve this project using LoRa to send and receive sensor readings.

    1. Dave312 October 13, 2020
    2. Cliffex October 16, 2020
    3. RV October 20, 2020
      • Francesco Azzola October 21, 2020

    Add Your Comment