Skip to content

Commit 8f0b80e

Browse files
authored
Merge pull request #10 from jerryneedell/jerryn_spreadf
Fix configuration for Spreading Factor = 6
2 parents 8a55e34 + 073912e commit 8f0b80e

File tree

3 files changed

+227
-0
lines changed

3 files changed

+227
-0
lines changed

adafruit_rfm/rfm9x.py

+24
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ class RFM9x(RFMSPI):
169169

170170
auto_agc = RFMSPI.RegisterBits(_RF95_REG_26_MODEM_CONFIG3, offset=2, bits=1)
171171

172+
header_mode = RFMSPI.RegisterBits(_RF95_REG_1D_MODEM_CONFIG1, offset=0, bits=1)
173+
172174
low_datarate_optimize = RFMSPI.RegisterBits(_RF95_REG_26_MODEM_CONFIG3, offset=3, bits=1)
173175

174176
lna_boost_hf = RFMSPI.RegisterBits(_RF95_REG_0C_LNA, offset=0, bits=2)
@@ -424,6 +426,11 @@ def signal_bandwidth(self, val: int) -> None:
424426
else:
425427
self.write_u8(0x2F, 0x44)
426428
self.write_u8(0x30, 0)
429+
# set low_datarate_optimize for signal duration > 16 ms
430+
if 1000 / (self.signal_bandwidth / (1 << self.spreading_factor)) > 16:
431+
self.low_datarate_optimize = 1
432+
else:
433+
self.low_datarate_optimize = 0
427434

428435
@property
429436
def coding_rate(self) -> Literal[5, 6, 7, 8]:
@@ -461,14 +468,21 @@ def spreading_factor(self, val: Literal[6, 7, 8, 9, 10, 11, 12]) -> None:
461468

462469
if val == 6:
463470
self.detection_optimize = 0x5
471+
self.header_mode = 1 # enable implicit header mode
464472
else:
465473
self.detection_optimize = 0x3
474+
self.header_mode = 0 # enable exlicit header mode
466475

467476
self.write_u8(_RF95_DETECTION_THRESHOLD, 0x0C if val == 6 else 0x0A)
468477
self.write_u8(
469478
_RF95_REG_1E_MODEM_CONFIG2,
470479
((self.read_u8(_RF95_REG_1E_MODEM_CONFIG2) & 0x0F) | ((val << 4) & 0xF0)),
471480
)
481+
# set low_datarate_optimize for signal duration > 16 ms
482+
if 1000 / (self.signal_bandwidth / (1 << self.spreading_factor)) > 16:
483+
self.low_datarate_optimize = 1
484+
else:
485+
self.low_datarate_optimize = 0
472486

473487
@property
474488
def enable_crc(self) -> bool:
@@ -491,6 +505,16 @@ def enable_crc(self, val: bool) -> None:
491505
self.read_u8(_RF95_REG_1E_MODEM_CONFIG2) & 0xFB,
492506
)
493507

508+
@property
509+
def payload_length(self) -> int:
510+
"""Must be set when using Implicit Header Mode - required for SF = 6"""
511+
return self.read_u8(_RF95_REG_22_PAYLOAD_LENGTH)
512+
513+
@payload_length.setter
514+
def payload_length(self, val: int) -> None:
515+
# Set payload length
516+
self.write_u8(_RF95_REG_22_PAYLOAD_LENGTH, val)
517+
494518
@property
495519
def crc_error(self) -> bool:
496520
"""crc status"""

examples/rfm_lora_sf_base.py

+98
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import time
5+
6+
import board
7+
import busio
8+
import digitalio
9+
10+
# Define radio parameters.
11+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
12+
# module! Can be a value like 915.0, 433.0, etc.
13+
14+
# Define pins connected to the chip, use these if wiring up the breakout according to the guide:
15+
CS = digitalio.DigitalInOut(board.CE1)
16+
RESET = digitalio.DigitalInOut(board.D25)
17+
18+
# Initialize SPI bus.
19+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
20+
21+
# Initialze RFM radio
22+
# uncommnet the desired import and rfm initialization depending on the radio boards being used
23+
24+
# Use rfm9x for two RFM9x radios using LoRa
25+
26+
from adafruit_rfm import rfm9x
27+
28+
rfm = rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
29+
30+
rfm.radiohead = False # don't appent RadioHead heade
31+
# set spreading factor
32+
rfm.spreading_factor = 7
33+
print("spreading factor set to :", rfm.spreading_factor)
34+
print("low_datarate_optimize set to: ", rfm.low_datarate_optimize)
35+
# rfm.signal_bandwidth = 500000
36+
print("signal_bandwidth set to :", rfm.signal_bandwidth)
37+
print("low_datarate_optimize set to: ", rfm.low_datarate_optimize)
38+
if rfm.spreading_factor == 12:
39+
rfm.xmit_timeout = 5
40+
print("xmit_timeout set to: ", rfm.xmit_timeout)
41+
if rfm.spreading_factor == 12:
42+
rfm.receive_timeout = 5
43+
elif rfm.spreading_factor > 7:
44+
rfm.receive_timeout = 2
45+
print("receive_timeout set to: ", rfm.receive_timeout)
46+
rfm.enable_crc = True
47+
# send startup message
48+
message = bytes(f"startup message from base", "UTF-8")
49+
if rfm.spreading_factor == 6:
50+
payload = bytearray(40)
51+
rfm.payload_length = len(payload)
52+
payload[0 : len(message)] = message
53+
rfm.send(
54+
payload,
55+
keep_listening=True,
56+
)
57+
else:
58+
rfm.send(
59+
message,
60+
keep_listening=True,
61+
)
62+
# Wait to receive packets.
63+
print("Waiting for packets...")
64+
# initialize flag and timer
65+
# set a delay before sending the echo packet
66+
# avoide multibples of .5 second to minimize chances of node missing
67+
# the packet between receive attempts
68+
transmit_delay = 0.75
69+
last_transmit_time = 0
70+
packet_received = False
71+
while True:
72+
if rfm.payload_ready():
73+
packet_received = False
74+
packet = rfm.receive(timeout=None)
75+
if packet is not None:
76+
# Received a packet!
77+
# Print out the raw bytes of the packet:
78+
print(f"Received (raw payload): {packet}")
79+
print([hex(x) for x in packet])
80+
print(f"RSSI: {rfm.last_rssi}")
81+
packet_received = True
82+
last_transmit_time = time.monotonic()
83+
if packet_received and ((time.monotonic() - last_transmit_time) > transmit_delay):
84+
# send back the received packet
85+
if rfm.spreading_factor == 6:
86+
payload = bytearray(40)
87+
rfm.payload_length = len(payload)
88+
payload[0 : len(packet)] = packet
89+
rfm.send(
90+
payload,
91+
keep_listening=True,
92+
)
93+
else:
94+
rfm.send(
95+
packet,
96+
keep_listening=True,
97+
)
98+
packet_received = False

examples/rfm_lora_sf_node.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
# Example to send a packet periodically between addressed nodes with ACK
5+
# Author: Jerry Needell
6+
#
7+
import time
8+
9+
import board
10+
import busio
11+
import digitalio
12+
13+
# Define radio parameters.
14+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
15+
# module! Can be a value like 915.0, 433.0, etc.
16+
17+
# Define pins connected to the chip, use these if wiring up the breakout according to the guide:
18+
CS = digitalio.DigitalInOut(board.CE1)
19+
RESET = digitalio.DigitalInOut(board.D25)
20+
21+
# Initialize SPI bus.
22+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
23+
24+
# Initialze RFM radio
25+
# uncommnet the desired import and rfm initialization depending on the radio boards being used
26+
27+
# Use rfm9x for two RFM9x radios using LoRa
28+
29+
from adafruit_rfm import rfm9x
30+
31+
rfm = rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
32+
33+
rfm.radiohead = False # Do not use RadioHead Header
34+
# set spreading factor
35+
rfm.spreading_factor = 7
36+
print("spreading factor set to :", rfm.spreading_factor)
37+
print("low_datarate_optimize set to: ", rfm.low_datarate_optimize)
38+
# rfm.signal_bandwidth = 500000
39+
print("signal_bandwidth set to :", rfm.signal_bandwidth)
40+
print("low_datarate_optimize set to: ", rfm.low_datarate_optimize)
41+
if rfm.spreading_factor == 12:
42+
rfm.xmit_timeout = 5
43+
print("xmit_timeout set to: ", rfm.xmit_timeout)
44+
if rfm.spreading_factor == 12:
45+
rfm.receive_timeout = 5
46+
elif rfm.spreading_factor > 7:
47+
rfm.receive_timeout = 2
48+
print("receive_timeout set to: ", rfm.receive_timeout)
49+
rfm.enable_crc = True
50+
# set the time interval (seconds) for sending packets
51+
transmit_interval = 10
52+
53+
# initialize counter
54+
counter = 0
55+
# send startup message from my_node
56+
message = bytes(f"startup message from node", "UTF-8")
57+
if rfm.spreading_factor == 6:
58+
payload = bytearray(40)
59+
rfm.payload_length = len(payload)
60+
payload[0 : len(message)] = message
61+
rfm.send(
62+
payload,
63+
keep_listening=True,
64+
)
65+
else:
66+
rfm.send(
67+
message,
68+
keep_listening=True,
69+
)
70+
71+
# Wait to receive packets.
72+
print("Waiting for packets...")
73+
# initialize flag and timer
74+
last_transmit_time = time.monotonic()
75+
while True:
76+
# Look for a new packet: only accept if addresses to my_node
77+
packet = rfm.receive()
78+
# If no packet was received during the timeout then None is returned.
79+
if packet is not None:
80+
# Received a packet!
81+
# Print out the raw bytes of the packet:
82+
print(f"Received (raw payload): {packet}")
83+
print([hex(x) for x in packet])
84+
print(f"RSSI: {rfm.last_rssi}")
85+
# send reading after any packet received
86+
if time.monotonic() - last_transmit_time > transmit_interval:
87+
# reset timeer
88+
last_transmit_time = time.monotonic()
89+
# send a mesage to destination_node from my_node
90+
message = bytes(f"message from node {counter}", "UTF-8")
91+
if rfm.spreading_factor == 6:
92+
payload = bytearray(40)
93+
rfm.payload_length = len(payload)
94+
payload[0 : len(message)] = message
95+
rfm.send(
96+
payload,
97+
keep_listening=True,
98+
)
99+
else:
100+
rfm.send(
101+
message,
102+
keep_listening=True,
103+
)
104+
105+
counter += 1

0 commit comments

Comments
 (0)