LoRa driver for Raspberry Pi with Python wrapper

Here you will find my recent contribution to LoRa drivers. This post describes the LoRa driver for a Raspberry Pi SBC (Single Board Computer). Additionally, a wrapper written in Python is available making it very easy to use and prototype. Raspberry Pi gets more and more attention. Adding LoRa communication enables it to communicate with IoT devices such as remote thermometers, soil moisture sensors and many more others. You can find HAT boards thatoffer a LoRa module. Here, I describe how to connect and how to use a low-cost LoRa RFM95W module. This particular module comes with different frequency options. However, this post describes the one which uses 868 MHz frequency.

Let’s start with a bit different piece of information. Some time ago I have published a driver for STM32 for a SX1278 LoRa module. This works fine and you can read more about it in a post tiled STM32 HAL driver for LoRa SX1278 wireless module.

Why then write a driver for Raspberry Pi? The reason is quite obvious. Raspberry Pi is a great platform which allows for fast prototyping. Adding a feature to communicate over long distance sounds like a good idea. Moreover, the driver supports Python through C bindings to this script language. Transmitting a data package can be done in only 3 lines: importing LoRa module, initializing device and sending data over the air.

Connect module to RPI

You need to connect power, SPI lines and two additional pins to Raspberry Pi. Below you can find the pinout of LoRa module.

source: https://www.hoperf.com/modules/lora/RFM95.html

Below a pinout of Raspberry Pi is available.

source: https://www.raspberrypi.org/documentation/usage/gpio/

Using the RFM95W pinout and Raspberry Pi pinout you can connect the module to the mini computer. The connections were gathered in a shape of a table which was attached below.

RFM95W pinRaspberry Pi pinDescription
3.3V3V3, pin 13V3 power supply
GNDGND, pin 6power ground
MISOGPIO 9 (MISO), pin 21SPI Master Input Slave Output
MOSIGPIO 10 (MOSI), pin 19SPI Master Output Slave Input
SCKGPIO 11 (SCLK), pin 23SPI clock
NSSGPIO 25, pin 22SPI chip select
RESETGPIO 17, pin 11LoRa module reset
DIO0GPIO 4 (GPCLK0), pin 7LoRa status line
Connection between RFM95W LoRa module and Raspberry Pi

Update Raspberry Pi

Before diving into wireless communication an additional step is needed. Operating system has to be updated and equipped with Python 3 package. Updating OS on RPi is pretty straightforward. Then let’s go ahead and type following

sudo apt update
sudo apt dist-upgrade -y
sudo apt install -y python3

The LoRa RPi driver makes use of wiringPi library. This should come as default if not you have to install it.

sudo apt install wiringpi

Additionally, you have to enable SPI interface. For this use raspi-tool. This will open a console application, navigate through the menu and enable SPI interface. After that save changes and exit the application. Restart your Raspberry Pi to apply changes.

Compile the driver

Before compiling you have to verify the Python 3 version. Keep in mind that Python 3 is used instead of Python 2. This is important in terms of used bindings. The version number can be checked with

python3 --version

Example output is

Python 3.7.1

After identifying the exact Python 3 version make appropriate changes to the Makefile. Proper version has to be set as a constant in Makefile. Thus, if the version is 3.7.1 you only have to put 3.7. This is required to make proper bindings to Python libraries. After the changes following line should be present in the Makefile.

PYTHONVER=python3.7

Compile the code. If you only need the library, not the application which acts as sender/receiver, you can invoke following command

make lib

If the compilation succeed a loralib.so file should have been created. This is a library which acts as a Python module, therefore it can be imported with import command in Python script. Using it is straightforward, below work example was given.

Test the driver

To test the driver you can do following

import loralib

Above will import loralib module. If you see an error this is probably due to lacking the loralib library in current working directory. When you start Python interpreter make sure that the library is placed in the same directory from where you are invoking Python. The module is equipped with some function. There are only three so the first one initializes the module, one sends the data and the last but not least receives data.

For more detailed information on what is available got to my GitHub rpeository. the link to the GitHub can be found at the bottom of this post.

Receive data

To receive some data transmitted by an another LoRa module you have to initialize the driver with init() and then invoke the recv().

loralib.init(1, 868000000, 7)
data = loralib.recv()
print(data[0])

init() takes 3 parameters. The first sets the module to receiver mode (0) or transmitter mode (1). The second parameter sets the demanded frequency expressed in Hertz. The third argument is the spread factor. Other parameters like bandwidth and coding ratio were hardcoded and set to 125kHz and 4/5 accordingly.

Please keep in mind that using different frequencies then the radio was designed for can cause very poor reception/transition due to the fact of band pass filters presence in the module. Also, wireless transmission is under government regulation so first check what kind of power, modulation, frequency you can use.

recv() returns a tuplet containing six elements:

  • buffer — the actual data
  • buffer length
  • PRRSI — last packet RSSI (received signal strength indicator) [dBm]
  • RRSI — current RSSI [dBm]
  • SNR — signal noise ratio
  • error — if 0 then no error occurred, if other then 0 then CRC error occurred

If there was a correct reception registered then following should be fulfilled:

data[1] > 0 and data[5] == 0

It translates to two things. The first one checks if there was some data received and the second one checks integrity of received package.

Transmitting data

The data can be transmitted with following

loralib.init(0, 868000000, 7)                                           
loralib.send(b'hello')

This initializes the LoRa module in sender (transmitter) mode and sends data with send() method. This method accepts a byte array. So before sending a string it has to be encoded.

Source code

The full source code and more detailed documentation is available under LoRa-RaspberryPi repository.

3 thoughts on “LoRa driver for Raspberry Pi with Python wrapper

  1. uli

    hello Wojciech Domski,
    I just use your loralib.so for Python, (Python 3.9) it seems to work but I get this:
    DeprecationWarning: PY_SSIZE_T_CLEAN will be required for ‘#’ formats
    data=loralib.recv()
    do you know, how to fix that?

    Reply
    1. uli

      hi,
      to answer myself, I ignore the warning with:
      ————
      import warnings
      warnings.filterwarnings(“ignore”, category=DeprecationWarning)
      ———–
      Thank you for the wrapper, because Python is much better for a programming amateur like me!

    2. Wojciech Domski Post author

      Hi! I am glad that you have solved your problem. However, the issue is related to the hastag when parsing data from python to C. I have been using this wrapper for python 3.7. Apparently, for Python 3.9 some things have changed. The fix would be to slightly modify the wrapper’s code. Filtering warnings only suppresses it but does not solve this issue.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.