LoRa port for TARPN node: Difference between revisions

From TARPN Wiki
No edit summary
No edit summary
Line 12: Line 12:


=== Get LoRa bonnet working ===
=== Get LoRa bonnet working ===
You can read more about these steps on [https://learn.adafruit.com/adafruit-radio-bonnets/rfm9x-raspberry-pi-setup this Adafruit page].


# sudo apt install python3-pip
# sudo apt install python3-pip
# sudo pip3 install --upgrade setuptools
# sudo pip3 install --upgrade setuptools
# sudo pip3 install --upgrade adafruit-python-shell
# sudo pip3 install --upgrade adafruit-python-shell
# wget https://github.com/adafruit/Adafruit_CircuitPython_framebuf/raw/main/examples/font5x8.bin
# wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
# wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
# sudo python3 raspi-blinka.py (this will require reboot)
# sudo python3 raspi-blinka.py '''(this will require reboot at the end)'''
# sudo pip3 install adafruit-circuitpython-ssd1306
# sudo pip3 install adafruit-circuitpython-ssd1306
# sudo pip3 install adafruit-circuitpython-framebuf
# sudo pip3 install adafruit-circuitpython-framebuf
# sudo pip3 install adafruit-circuitpython-rfm9x
# sudo pip3 install adafruit-circuitpython-rfm9x
# create this test script rfm9x_check.py, which you should run ("python3 rfm9x_check.py") to prove your bonnet is properly connected and working:
<nowiki>
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
Wiring Check, Pi Radio w/RFM9x
Learn Guide: https://learn.adafruit.com/lora-and-lorawan-for-raspberry-pi
Author: Brent Rubell for Adafruit Industries
"""
import time
import busio
from digitalio import DigitalInOut, Direction, Pull
import board
# Import the SSD1306 module.
import adafruit_ssd1306
# Import the RFM9x radio module.
import adafruit_rfm9x
# Button A
btnA = DigitalInOut(board.D5)
btnA.direction = Direction.INPUT
btnA.pull = Pull.UP
# Button B
btnB = DigitalInOut(board.D6)
btnB.direction = Direction.INPUT
btnB.pull = Pull.UP
# Button C
btnC = DigitalInOut(board.D12)
btnC.direction = Direction.INPUT
btnC.pull = Pull.UP
# Create the I2C interface.
i2c = busio.I2C(board.SCL, board.SDA)
# 128x32 OLED Display
reset_pin = DigitalInOut(board.D4)
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin)
# Clear the display.
display.fill(0)
display.show()
width = display.width
height = display.height
# Configure RFM9x LoRa Radio
CS = DigitalInOut(board.CE1)
RESET = DigitalInOut(board.D25)
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
while True:
    # Clear the image
    display.fill(0)
    # Attempt to set up the RFM9x Module
    try:
        rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, 915.0)
        display.text('RFM9x: Detected', 0, 0, 1)
    except RuntimeError as error:
        # Thrown on version mismatch
        display.text('RFM9x: ERROR', 0, 0, 1)
        print('RFM9x Error: ', error)
    # Check buttons
    if not btnA.value:
        # Button A Pressed
        display.text('Ada', width-85, height-7, 1)
        display.show()
        time.sleep(0.1)
    if not btnB.value:
        # Button B Pressed
        display.text('Fruit', width-75, height-7, 1)
        display.show()
        time.sleep(0.1)
    if not btnC.value:
        # Button C Pressed
        display.text('Radio', width-65, height-7, 1)
        display.show()
        time.sleep(0.1)
    display.show()
    time.sleep(0.1)</nowiki>
=== Turn it into a TCP KISS TNC ===
See [https://github.com/IZ7BOJ/RPi-LoRa-KISS-TNC-2ndgen/blob/main/INSTALL.md the github project] for more info.
# sudo apt install git aprx python3-rpi.gpio python3-spidev python3-pil python3-smbus
# git clone https://github.com/IZ7BOJ/RPi-LoRa-KISS-TNC-2ndgen.git
# cd RPi-LoRa-KISS-TNC-2ndgen
# git clone https://github.com/mayeranalytics/pySX127x.git
# sudo mv board_config.py pySX127x/SX127x/board_config.py
# sudo mv LoRa.py pySX127x/SX127x//LoRa.py
# Replace config.py with these contents. You can/should customize the frequency to anything in the 33cm band (but at least 500kHz from the band edge) and '''if you have poor link conditions you can increase "spreadingfactor" above 7''', which is the fastest this bonnet can handle:
<nowiki>
## Config file for RPi-LoRa-KISS-TNC 2nd generation
## Lora Module selection
sx127x = True #if True, enables sx127x family, else sx126x
## Display enable and font
disp_en = False
font_size = 8
## Log enable and path
log_enable = True
logpath='/var/log/lora/lora.log' #log filename. Give r/w permission!
## KISS Settings
# Where to listen?
# TCP_HOST can be "localhost", "0.0.0.0" or a specific interface address
# TCP_PORT as configured in aprx.conf <interface> section
TCP_HOST = "0.0.0.0"
TCP_PORT = 10001
## Hardware Settings
# See datasheets for detailed pinout.
# The default pin assignment refers to PCB designed by I8FUC.
# The user can wire the module by his own and change pin assignment.
# assign "-1" if the pin is not used
# Settings valid for both SX126x and SX127x
busId = 0 #SPI Bus ID. Must be enabled on raspberry (sudo raspi-config). Default is 0
csId = 1 #SPI Chip Select pin. Valid values are 0 or 1
irqPin = 22 #DIO0 of sx127x and DIO1 of sx126x, used for IRQ in rx
# Settings valid only for SX126x. Default pin assignment refers to the PCB schematic /doc/LoRa_RPi_Companion_2022.pdf
resetPin = 6
busyPin = 4
# If txen and rxen are disabled (=-1), then DIO2 will be set as RF Switch control
txenPin = 0 #In Ebyte modules, it's used for switching on the tx pa.
rxenPin = 1 #In Ebyte modules, it's used for switching on the rx lna
# If Lora module has a TCXO, the following parameter must be True
# If True, the DIO3 line will be set as control voltage of the TCXO
tcxo=False
## LoRa Settings valid for both SX127x and SX126x modules
frequency = 910300000 #frequency in Hz
preamble = 32 #valid preable lenght is 8/16/24/32
spreadingFactor = 7 #valid spreading factor is between 5 and 12
bandwidth = 500000 #possible BW values: 7800, 10400,15600, 20800, 31250, 41700, 62500, 125000, 250000, 500000
codingrate = 5 #valid code rate denominator is between 5 and 8
appendSignalReport = False #append signal report when packets are forwarded to aprs server
outputPower = 17 #maximum TX power is 22(22dBm) for SX126x, and 17 (17dBm) for SX127x . Higher values will be forced to max allowed!
TX_OE_Style = False #if True, tx RF packets are in OE Style, otherwise in standard AX25
#sync_word = 0x1424 #sync word is x4y4. Es: 0x12 of 1st gen LoRa chip --> 0x1424 of 2nd gen LoRa chip
sync_word = 0x12
crc = True #defines if CRC is calculated and transmitted in the header. Note that modem works in explicit mode
#LoRa Settings valid only for SX126x
RX_GAIN_POWER_SAVING = False #If false, receiver is set in boosted gain mode (needs more power)</nowiki>
This github project needs more modification to work with TARPN, since it was originally written only for APRS packets and will break with any other kind. It also assumed ~400MHz, whereas the Adafruit bonnet is 33cm (902-928MHz). Here is how to update it (TODO these should be in a forked github project to remove these steps):
# nano pySX127x/SX127x/board_config.py '''(Change low_band = True, to False for 33cm support)'''
# nano pySX127x/SX127x/LoRa.py '''(Search for “43” and change multiple occurences to 915MHz)'''
# nano LoraAprsKissTnc_sx127x.py '''(Ditto, there's only 1 occurence in this one)'''
# sudo mkdir /var/log/lora
# sudo touch /var/log/lora/lora.log
Start/test your TCP-based KISS TNC with this command (you should see it print out the config values and say it's listening for connections, with no errors listed):
* sudo python3 Start_lora-tnc.py
When you run the TNC for long-term use, you'll want to run it with "nohup sudo python3 Start_lora-tnc.py &" which will disassociate it with your linux account and run it in the background until manually terminated. In the future, we should wrap this in a systemd service.

Revision as of 23:10, 14 August 2023

KV4P has been experimenting with adding LoRa ports to his TARPN node. LoRa is very desirable for TARPN because LoRa transceivers are very inexpensive yet have good range, are very small and low-power, and reduce the overall setup cost of a new link.

Materials:

  • Raspberry Pi Zero 2 W (~$15 when in stock), WITH gpio header. You can use any Rapsberry Pi model for this, but this is what I used.
  • Adafruit LoRa Radio Bonnet with OLED - RFM95W @ 915MHz - RadioFruit ($32.50)
  • 78mm of magnet wire (33cm band 1/4 wave), soldered to the radio bonnet antenna center conductor via (right next to the connector we won't use)

This assumes you already have a TARPN node. With this experimental guide, you'll be buiding a LoRa radio that shows up on your network as a TCP-based KISS TNC, which port 11 or port 12 of your TARPN node will connect to via the network.

I'm going to assume you already have the Raspberry Pi configured with Raspberry Pi OS, and connected to your local network (the same network as your TARPN node). You'll want to assign a static IP to it (rather than DHCP), so you can ensure your TARPN node will be able to find it on the network after restarts.

Get LoRa bonnet working

You can read more about these steps on this Adafruit page.

  1. sudo apt install python3-pip
  2. sudo pip3 install --upgrade setuptools
  3. sudo pip3 install --upgrade adafruit-python-shell
  4. wget https://github.com/adafruit/Adafruit_CircuitPython_framebuf/raw/main/examples/font5x8.bin
  5. wget https://raw.githubusercontent.com/adafruit/Raspberry-Pi-Installer-Scripts/master/raspi-blinka.py
  6. sudo python3 raspi-blinka.py (this will require reboot at the end)
  7. sudo pip3 install adafruit-circuitpython-ssd1306
  8. sudo pip3 install adafruit-circuitpython-framebuf
  9. sudo pip3 install adafruit-circuitpython-rfm9x
  10. create this test script rfm9x_check.py, which you should run ("python3 rfm9x_check.py") to prove your bonnet is properly connected and working:
# SPDX-FileCopyrightText: 2018 Brent Rubell for Adafruit Industries
#
# SPDX-License-Identifier: MIT

"""
Wiring Check, Pi Radio w/RFM9x

Learn Guide: https://learn.adafruit.com/lora-and-lorawan-for-raspberry-pi
Author: Brent Rubell for Adafruit Industries
"""
import time
import busio
from digitalio import DigitalInOut, Direction, Pull
import board
# Import the SSD1306 module.
import adafruit_ssd1306
# Import the RFM9x radio module.
import adafruit_rfm9x

# Button A
btnA = DigitalInOut(board.D5)
btnA.direction = Direction.INPUT
btnA.pull = Pull.UP

# Button B
btnB = DigitalInOut(board.D6)
btnB.direction = Direction.INPUT
btnB.pull = Pull.UP

# Button C
btnC = DigitalInOut(board.D12)
btnC.direction = Direction.INPUT
btnC.pull = Pull.UP

# Create the I2C interface.
i2c = busio.I2C(board.SCL, board.SDA)

# 128x32 OLED Display
reset_pin = DigitalInOut(board.D4)
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin)
# Clear the display.
display.fill(0)
display.show()
width = display.width
height = display.height

# Configure RFM9x LoRa Radio
CS = DigitalInOut(board.CE1)
RESET = DigitalInOut(board.D25)
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

while True:
    # Clear the image
    display.fill(0)

    # Attempt to set up the RFM9x Module
    try:
        rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, 915.0)
        display.text('RFM9x: Detected', 0, 0, 1)
    except RuntimeError as error:
        # Thrown on version mismatch
        display.text('RFM9x: ERROR', 0, 0, 1)
        print('RFM9x Error: ', error)

    # Check buttons
    if not btnA.value:
        # Button A Pressed
        display.text('Ada', width-85, height-7, 1)
        display.show()
        time.sleep(0.1)
    if not btnB.value:
        # Button B Pressed
        display.text('Fruit', width-75, height-7, 1)
        display.show()
        time.sleep(0.1)
    if not btnC.value:
        # Button C Pressed
        display.text('Radio', width-65, height-7, 1)
        display.show()
        time.sleep(0.1)

    display.show()
    time.sleep(0.1)

Turn it into a TCP KISS TNC

See the github project for more info.

  1. sudo apt install git aprx python3-rpi.gpio python3-spidev python3-pil python3-smbus
  2. git clone https://github.com/IZ7BOJ/RPi-LoRa-KISS-TNC-2ndgen.git
  3. cd RPi-LoRa-KISS-TNC-2ndgen
  4. git clone https://github.com/mayeranalytics/pySX127x.git
  5. sudo mv board_config.py pySX127x/SX127x/board_config.py
  6. sudo mv LoRa.py pySX127x/SX127x//LoRa.py
  7. Replace config.py with these contents. You can/should customize the frequency to anything in the 33cm band (but at least 500kHz from the band edge) and if you have poor link conditions you can increase "spreadingfactor" above 7, which is the fastest this bonnet can handle:
## Config file for RPi-LoRa-KISS-TNC 2nd generation

## Lora Module selection
sx127x = True #if True, enables sx127x family, else sx126x

## Display enable and font
disp_en = False
font_size = 8

## Log enable and path
log_enable = True
logpath='/var/log/lora/lora.log' #log filename. Give r/w permission!

## KISS Settings
# Where to listen?
# TCP_HOST can be "localhost", "0.0.0.0" or a specific interface address
# TCP_PORT as configured in aprx.conf <interface> section
TCP_HOST = "0.0.0.0"
TCP_PORT = 10001

## Hardware Settings
# See datasheets for detailed pinout.
# The default pin assignment refers to PCB designed by I8FUC.
# The user can wire the module by his own and change pin assignment.
# assign "-1" if the pin is not used

# Settings valid for both SX126x and SX127x
busId = 0 #SPI Bus ID. Must be enabled on raspberry (sudo raspi-config). Default is 0
csId = 1 #SPI Chip Select pin. Valid values are 0 or 1
irqPin = 22 #DIO0 of sx127x and DIO1 of sx126x, used for IRQ in rx

# Settings valid only for SX126x. Default pin assignment refers to the PCB schematic /doc/LoRa_RPi_Companion_2022.pdf
resetPin = 6
busyPin = 4
# If txen and rxen are disabled (=-1), then DIO2 will be set as RF Switch control
txenPin = 0 #In Ebyte modules, it's used for switching on the tx pa.
rxenPin = 1 #In Ebyte modules, it's used for switching on the rx lna

# If Lora module has a TCXO, the following parameter must be True
# If True, the DIO3 line will be set as control voltage of the TCXO
tcxo=False

## LoRa Settings valid for both SX127x and SX126x modules
frequency = 910300000 #frequency in Hz
preamble = 32 #valid preable lenght is 8/16/24/32
spreadingFactor = 7 #valid spreading factor is between 5 and 12
bandwidth = 500000 #possible BW values: 7800, 10400,15600, 20800, 31250, 41700, 62500, 125000, 250000, 500000
codingrate = 5 #valid code rate denominator is between 5 and 8
appendSignalReport = False #append signal report when packets are forwarded to aprs server
outputPower = 17 #maximum TX power is 22(22dBm) for SX126x, and 17 (17dBm) for SX127x . Higher values will be forced to max allowed!
TX_OE_Style = False #if True, tx RF packets are in OE Style, otherwise in standard AX25
#sync_word = 0x1424 #sync word is x4y4. Es: 0x12 of 1st gen LoRa chip --> 0x1424 of 2nd gen LoRa chip
sync_word = 0x12
crc = True #defines if CRC is calculated and transmitted in the header. Note that modem works in explicit mode

#LoRa Settings valid only for SX126x
RX_GAIN_POWER_SAVING = False #If false, receiver is set in boosted gain mode (needs more power)

This github project needs more modification to work with TARPN, since it was originally written only for APRS packets and will break with any other kind. It also assumed ~400MHz, whereas the Adafruit bonnet is 33cm (902-928MHz). Here is how to update it (TODO these should be in a forked github project to remove these steps):

  1. nano pySX127x/SX127x/board_config.py (Change low_band = True, to False for 33cm support)
  2. nano pySX127x/SX127x/LoRa.py (Search for “43” and change multiple occurences to 915MHz)
  3. nano LoraAprsKissTnc_sx127x.py (Ditto, there's only 1 occurence in this one)
  4. sudo mkdir /var/log/lora
  5. sudo touch /var/log/lora/lora.log

Start/test your TCP-based KISS TNC with this command (you should see it print out the config values and say it's listening for connections, with no errors listed):

  • sudo python3 Start_lora-tnc.py

When you run the TNC for long-term use, you'll want to run it with "nohup sudo python3 Start_lora-tnc.py &" which will disassociate it with your linux account and run it in the background until manually terminated. In the future, we should wrap this in a systemd service.