Interrupt driven LoRa RFM9x library for Raspberry Pi inspired by RadioHead
Project description
pyLoraRFM9x
This project is a fork of raspi-lora project.
pyLoraRFM9x is a interrupt based Python library for using HopeRF RFM95/96/97/98 LoRa radios with a Raspberry Pi. The design was inspired by the RadioHead project that is popular on Arduino-based platforms. Several handy features offered by RadioHead are present here, including encryption, addressing, optional acknowledgments and retransmission. The motivation of this project is to allow Raspberry Pis to communicate with devices using the RadioHead RF95 driver.
This fork fixes bugs in the interrupt handling, and supports both acknowledged and unacknowledged transfers with the use of flags in the packet header.
Usage
Installation
Requires Python >= 3.5. lgpio and spidev will be installed as requirements
pip install --upgrade pyLoraRFM9x
Wiring
Example wiring for the HopeRF RFM95W and the Raspberry Pi:
RFM module pin | Raspberry Pi GPIO pin |
---|---|
MISO | MISO |
MOSI | MOSI |
NSS/CS | CE1 |
CLK | SCK |
RESET | GPIO 25 |
DIO0 | GPIO 5 |
3.3V | 3.3V |
GND | GND |
Remember to connect an antenna or a quarter wavelength wire to the RFM modules ANT pin.
Getting Started
First ensure that SPI is enabled on your Raspberry Pi:
sudo raspi-config
Go to 5 Interfacing Options, select P4 SPI and select Yes to enable.
Reboot and verify that you see two devices when writing
ls -l /dev/spidev*
in the terminal.
Next, here is a quick example that sets things up and sends a message:
from pyLoraRFM9x import LoRa, ModemConfig
# This is our callback function that runs when a message is received
def on_recv(payload):
print("From:", payload.header_from)
print("Received:", payload.message)
print("RSSI: {}; SNR: {}".format(payload.rssi, payload.snr))
# Lora object will use spi port 0 and use chip select 1. GPIO pin 5 will be used for interrupts and set reset pin to 25
# The address of this device will be set to 2
lora = LoRa(0, 1, 5, 2, reset_pin = 25, modem_config=ModemConfig.Bw125Cr45Sf128, tx_power=14, acks=True)
lora.on_recv = on_recv
# Send a message to a recipient device with address 10
# Retry sending the message twice if we don't get an acknowledgment from the recipient
message = "Hello there!"
status = lora.send_to_wait(message, 10, retries=2)
if status is True:
print("Message sent!")
else:
print("No acknowledgment from recipient")
Encryption
If you'd like to send and receive encrypted packets, you'll need to install the PyCrypto package. If you're working with devices running RadioHead with RHEncryptedDriver, I recommend using the AES cipher.
pip install pycrypto
and in your code:
from Crypto.Cipher import AES
crypto = AES.new("my-secret-encryption-key")
then pass in crypto
when instantiating the LoRa
object:
lora = LoRa(0, 17, 2, crypto=crypto)
Configuration
Initialization
LoRa(spi_channel, interrupt_pin, my_address, spi_port = 0, reset_pin=reset_pin, freq=915, tx_power=14,
modem_config=ModemConfig.Bw125Cr45Sf128, acks=False, crypto=None)
spi_channel
SPI channel to use (either 0 or 1, if your LoRa radio if connected to CE0 or CE1, respectively)
interrupt_pin
GPIO pin (BCM-style numbering) to use for the interrupt
my_address
The address number (0-254) your device will use when sending and receiving packets
**spi_port
** SPI port connected to module, 0 or 1
reset_pin
The pin that resets the module. Defaults to None
freq
Frequency used by your LoRa radio. Defaults to 915Mhz
tx_power
Transmission power level from 5 to 23. Keep this as low as possible. Defaults to 14
model_config
Modem configuration. See RadioHead docs. Default to Bw125Cr45Sf128.
acks
If True
, send an acknowledgment packet when a message is received and wait for an acknowledgment when transmitting a message. This is equivalent to using RadioHead's RHReliableDatagram
crypto
An instance of PyCrypto Cipher.AES (see above example)
Other options:
A LoRa
instance also has the following attributes that can be changed:
- cad_timeout Timeout for channel activity detection. Default is 1 second
- retry_timeout Time to wait for an acknowledgment before attempting a retry. Defaults to 0.5 seconds
- wait_packet_sent_timeout Timeout for waiting for a packet to transmit. Default is 0.5 seconds
Methods
send_to_wait(data, header_to, header_flags=0)
Send a message and block until an acknowledgment is received or a timeout occurs. Returns True
if successful
data
Your message. Can be a string or byte stringheader_to
Address of recipient (0-255). If address is 255, the message will be broadcast to all devices andsend_to_wait
will returnTrue
without waiting for acknowledgmentsheader_flags
Bitmask that can contain flags specific to your application
send(data, header_to, header_id=0, header_flags=0)
Similar to send_to_wait
but does not block or wait for acknowledgments and will always return True
data
Your message. Can be a string or byte stringheader_id
Unique ID of message (0-255)header_to
Address of recipient (0-255). If address is 255, the message will be broadcast to all devicesheader_flags
Bitmask that can contain flags specific to your application
set_mode_rx()
Set radio to RX continuous mode
set_mode_tx()
Set radio to TX mode
set_mode_idle()
Set radio to idle (disabling receiving or transmitting)
sleep()
Set radio to low-power sleep mode
wait_packet_sent()
Blocks until a packet has finished transmitting. Returns False
if a timeout occurs
close()
Cleans up GPIO pins and closes the SPI connection. This should be called when your program exits.
Callbacks
on_recv(payload)
Callback function that runs when a message is received
payload
has the following attributes:
header_from
, header_to
, header_id
, header_flags
, message
, rssi
, snr
Verify pin usage
Use gpioinfo
command in the shell
Resources
RadioHead - The RadioHead project. Very useful source of information on working with LoRa radios.
Forked version of RadioHead for Raspberry Pi - A fork of the original RadioHead project that better accommodates the Raspberry Pi. Currently is a few years out of date.
pySX127x - Another Python LoRa library that allows for a bit more configuration.
Adafruit CircuitPython module for the RFM95/6/7/8 - LoRa library for CircuitPython
Changelog
1.0.2
Typo fixed in error handling call
1.0.1
Added option to select SPI module
1.0.0
Removed RPi.GPIO dependency and ported to lgpio due to the removal of the sysfs GPIO interface in newer kernels
0.9.4
Fixed a timing issue that could cause the modem to hang when transmitting.
0.9.3
Removed unecessary numpy import
0.9.2
Merged martynwheeler's fix for handling ACKS, and straend's naming
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pylorarfm9x-1.0.2.tar.gz
.
File metadata
- Download URL: pylorarfm9x-1.0.2.tar.gz
- Upload date:
- Size: 12.8 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 9e7866aa3c837e0e7f689be3a510775ceba17b83044cd6b3584c94fc6625f5c4 |
|
MD5 | 3a8beef7c7a02a260a1404e346150634 |
|
BLAKE2b-256 | 269ecbafe1202a69bd1cf5397481064061295a9ab5da3f7ed2c3a03f8f064d51 |
File details
Details for the file pyLoraRFM9x-1.0.2-py3-none-any.whl
.
File metadata
- Download URL: pyLoraRFM9x-1.0.2-py3-none-any.whl
- Upload date:
- Size: 11.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.0.0 CPython/3.11.8
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 04dfd58467c28da5a8f1afd17fdccd50df201d4b744b85535b35b61cffea9ca3 |
|
MD5 | fc080d73bec9f3ca50f1b034af13daeb |
|
BLAKE2b-256 | b7bd400ba699c44e16a71ebff045abcbc224bab504139fc8203fc6ae997dd99d |