LoRa point to point on Raspberry PLCs
Connections
Raspberry PLC Family
The Raspberry PI PLC uses the following pins to communicate with the RN2483 LoRa module:
- RESET PIN: 0x4008
- SLAVE SELECT: 17
In addition to the reset pin, the module communicates with the Raspberry PI 4B board through an UART Expansor, which utilizes the SPI from the Raspberry PI board.
Touchberry Screen Family
The Touchberry Screens use the following pin to communicate with the RN2483 LoRa module:
- RESET PIN: 0x2003
In addition to the reset pin, the module communicates with the Raspberry PI 4B board through an UART Expansor, which utilizes I2C from the Raspberry PI board. The address for the I2C slave expansion port is 0x78.
Module operation
Module initialization
Before configuring the LoRa module, make the following checks to make sure the Raspberry PLC is ready to work with the module:
- Make sure to have the librpiplc library.
- Ensure that the /boot/config.txt file ends with this lines (Otherwise, replace the previous [all] configuration with this one):
- Set the LoRa reset pin to HIGH (Replace Version and Model with your own, follow this section for more information):
- Configure the port to 57600 baud:
[all] dtparam=spi=on gpio=8=pd dtoverlay=spi0-1cs,cs0_pin=7 dtoverlay=w5500,cs=0,int_pin=6 dtparam=i2c_arm=on dtoverlay=i2c-rtc,ds3231 dtoverlay=sc16is752-spi1-rpiplc-v4,xtal=14745600 enable_uart=1
sudo ~/test/[RPIPLC_Version]/[RPIPLC_Model]/set-digital-output EXP1_RST 1
stty 57600 -F /dev/ttySC0
Interacting with the module
To send data to the RN2483 module, use this command:
echo -e "[COMMAND]\r" > /dev/ttySC0
The available commands are the ones that appear in this User Manual from the RN2483 module.
The basic ones to send "Hello" through LoRa are:
echo -e "mac pause\r" > /dev/ttySC0
echo -e "radio set freq 868000000\r" > /dev/ttySC0
echo -e "radio tx 48656c6c6f\r" > /dev/ttySC0
To receive a message:
echo -e "mac pause\r" > /dev/ttySC0
echo -e "radio set freq 868000000\r" > /dev/ttySC0
echo -e "radio rx 0\r" > /dev/ttySC0
For a total of 15 seconds, the module will be in reception mode until a message is received or the time has expired. This timeout can be modified or removed with "radio set wdt [time]\r". Change [time] for a number of milliseconds (set to 0 to remove the timeout).
Every command is sent to the module, it responds depending on the result of the operation. To read the responses, open a terminal and type:
cat /dev/ttySC0
For example, after performing the "radio rx 0" command, the module will respond whether the command was successful, and after that, it will respond again with the data it received.
Python approach
In addition to interacting through terminal commands with the LoRa module, you can use a Python script to send and receive messages with another LoRa module. Take a look at the following sketch:
#!/usr/bin/env python3 from lora import LoRa debug = False # print debug information of current command in REPL timeout_s = None # timeout of serial and lora reception timeout_l = 0 lora_mode = input("Type mode (tx | rx): ") lora = LoRa("/dev/ttySC0", timeout_s, timeout_l, debug) if lora_mode == "tx": while True: # transmit data i = input("Write message to send! ").encode() lora.send_str(i) elif lora_mode == "rx": while True: rx_str = lora.recv_str() print("Received: " + rx_str) else: print("Wrong mode! tx or rx") exit
#!/usr/bin/env python3 from lora import LoRa debug = False # print debug information of current command in REPL timeout_s = None # timeout of serial and lora reception timeout_l = 0 lora_mode = input("Type mode (tx | rx): ") lora = LoRa("/dev/ttySC0", timeout_s, timeout_l, debug) if lora_mode == "tx": while True: # transmit data i = input("Write message to send! ").encode() lora.send_str(i) elif lora_mode == "rx": while True: rx_str = lora.recv_str() print("Received: " + rx_str) else: print("Wrong mode! tx or rx") exit
As it can be seen, this script can be used for both send or receive, depending on the first input "tx" or "rx". Be aware that in RX mode the program will not end until data is received. To change this, set a "timeout_l" bigger than 0 to stop the receive mode after "timeout_l" seconds.
To be able to execute the code you will also need the lora.py file, which you can download here:
lora.py
Before configuring the module, first make sure the Raspberry PLC is properly set:
- Make sure the librpiplc is installed.
- Ensure that the /boot/config.txt file ends with the following lines (Otherwise, add this settings and restart the PLC):
- Set the LoRa reset pin to HIGH. Make sure that the test folder exists in your home directory. If not, you can get it from this link. Simply call this URL with wget and extract the contents.
- Configure the port at 57600 baudrate with:
[all] dtparam=spi=on gpio=8=pd dtoverlay=spi0-1cs,cs0_pin=7 dtoverlay=w5500,cs=0,int_pin=6 dtparam=i2c_arm=on dtoverlay=i2c-rtc,ds3231 dtoverlay=sc16is752-spi1-rpiplc-v4,xtal=14745600 enable_uart=1
sudo ~/test/[RPIPLC_Version]/[RPIPLC_Model]/set-digital-output EXP1_RST 1
stty 57600 -F /dev/ttySC0
Module initialization
To work with the LoRa module, the GPIO 0x2003 has to be in HIGH state, but this can be easily done within the code.
Interacting with the module
The easiest way to interact with the RN2483 module is using Python. A simple snippet code would be:
#!/usr/bin/python # -*- coding:utf-8 -*- import smbus import time address = 0x78 gpio_address = 0x20 busNumber = 1 bus = smbus.SMBus(busNumber) macPause = [0x6D, 0x61, 0x63, 0x20, 0x70, 0x61, 0x75, 0x73, 0x65, 0x0D, 0x0A] str = "" class expBoard: def __init__(self, addr, port): self.addr = addr self.bus = smbus.SMBus(port) def write_block_data(self, byte, array): self.bus.write_i2c_block_data(self.addr, byte, array) def write_data(self, value): self.bus.write_byte(self.addr, value) def write_byte_data(self, add, value): self.bus.write_byte_data(self.addr, add, value) def read_data(self): self.bus.read_byte(self.addr) def read_nbytes_data(self, data, n): return self.bus.read_i2c_block_data(self.addr, data, n) i2c_bus = expBoard(address, busNumber) i2c_bus_2 = expBoard(gpio_address, busNumber) i2c_bus_2.write_byte_data(0x01, 0x08) i2c_bus.write_data(123) time.sleep(0.7) i2c_bus.write_data(17) time.sleep(0.1) while True: print("---> {}".format(str.join(chr(n) for n in macPause))) i2c_bus.write_block_data(0x00, macPause) time.sleep(0.7) rx = i2c_bus.read_nbytes_data(0x00, len("4294967245")+2) list = [chr(n) for n in rx] print(str.join(list))
#!/usr/bin/python # -*- coding:utf-8 -*- import smbus import time address = 0x78 gpio_address = 0x20 busNumber = 1 bus = smbus.SMBus(busNumber) macPause = [0x6D, 0x61, 0x63, 0x20, 0x70, 0x61, 0x75, 0x73, 0x65, 0x0D, 0x0A] str = "" class expBoard: def __init__(self, addr, port): self.addr = addr self.bus = smbus.SMBus(port) def write_block_data(self, byte, array): self.bus.write_i2c_block_data(self.addr, byte, array) def write_data(self, value): self.bus.write_byte(self.addr, value) def write_byte_data(self, add, value): self.bus.write_byte_data(self.addr, add, value) def read_data(self): self.bus.read_byte(self.addr) def read_nbytes_data(self, data, n): return self.bus.read_i2c_block_data(self.addr, data, n) i2c_bus = expBoard(address, busNumber) i2c_bus_2 = expBoard(gpio_address, busNumber) i2c_bus_2.write_byte_data(0x01, 0x08) i2c_bus.write_data(123) time.sleep(0.7) i2c_bus.write_data(17) time.sleep(0.1) while True: print("---> {}".format(str.join(chr(n) for n in macPause))) i2c_bus.write_block_data(0x00, macPause) time.sleep(0.7) rx = i2c_bus.read_nbytes_data(0x00, len("4294967245")+2) list = [chr(n) for n in rx] print(str.join(list))
Let's take a look:
- The I2C address for the serial communication is 0x78. The 0x20 address is used to interact with the Expansion Module I/Os.
- We first enable the module by setting the reset pin (0x2003) to HIGH. Then, we reset the module by writing 123 and set the baudrate to 57600 with 17.
- In the loop function, we send the "macPause" command over and over, while reading the module's response. We expect the string "4294967245\r\n", so we read exactly the desired bytes (12).
This is a basic example on how to use the LoRa module. For a more complex design, replace the commands with the desired ones.
There are no comments for now.