Skip to content

Commit 1d4c764

Browse files
authored
Merge pull request #24 from jerryneedell/jerryn_ack
Implement "reliable datagram"
2 parents f1b0001 + a7b0446 commit 1d4c764

File tree

9 files changed

+717
-126
lines changed

9 files changed

+717
-126
lines changed

README.rst

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ Introduction
1717
CircuitPython RFM69 packet radio module. This supports basic RadioHead-compatible sending and
1818
receiving of packets with RFM69 series radios (433/915Mhz).
1919

20-
.. note:: This does NOT support advanced RadioHead features like guaranteed delivery--only 'raw' packets are currently supported.
21-
2220
.. warning:: This is NOT for LoRa radios!
2321

2422
.. note:: This is a 'best effort' at receiving data using pure Python code--there is not interrupt

adafruit_rfm69.py

Lines changed: 215 additions & 124 deletions
Large diffs are not rendered by default.

examples/rfm69_header.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Example to display raw packets including header
2+
# Author: Jerry Needell
3+
#
4+
import board
5+
import busio
6+
import digitalio
7+
import adafruit_rfm69
8+
9+
# set the time interval (seconds) for sending packets
10+
transmit_interval = 10
11+
12+
# Define radio parameters.
13+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
14+
# module! Can be a value like 915.0, 433.0, etc.
15+
16+
# Define pins connected to the chip.
17+
CS = digitalio.DigitalInOut(board.CE1)
18+
RESET = digitalio.DigitalInOut(board.D25)
19+
20+
# Initialize SPI bus.
21+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
22+
23+
# Initialze RFM radio
24+
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)
25+
26+
# Optionally set an encryption key (16 byte AES key). MUST match both
27+
# on the transmitter and receiver (or be set to None to disable/the default).
28+
rfm69.encryption_key = (
29+
b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
30+
)
31+
32+
# Wait to receive packets.
33+
print("Waiting for packets...")
34+
# initialize flag and timer
35+
while True:
36+
# Look for a new packet: only accept if addresses to my_node
37+
packet = rfm69.receive(with_header=True)
38+
# If no packet was received during the timeout then None is returned.
39+
if packet is not None:
40+
# Received a packet!
41+
# Print out the raw bytes of the packet:
42+
print("Received (raw header):", [hex(x) for x in packet[0:4]])
43+
print("Received (raw payload): {0}".format(packet[4:]))
44+
print("RSSI: {0}".format(rfm69.last_rssi))
45+
# send reading after any packet received

examples/rfm69_node1.py

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Example to send a packet periodically between addressed nodes
2+
# Author: Jerry Needell
3+
#
4+
import time
5+
import board
6+
import busio
7+
import digitalio
8+
import adafruit_rfm69
9+
10+
11+
# set the time interval (seconds) for sending packets
12+
transmit_interval = 10
13+
14+
# Define radio parameters.
15+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
16+
# module! Can be a value like 915.0, 433.0, etc.
17+
18+
# Define pins connected to the chip.
19+
CS = digitalio.DigitalInOut(board.CE1)
20+
RESET = digitalio.DigitalInOut(board.D25)
21+
22+
# Initialize SPI bus.
23+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
24+
# Initialze RFM radio
25+
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)
26+
27+
# Optionally set an encryption key (16 byte AES key). MUST match both
28+
# on the transmitter and receiver (or be set to None to disable/the default).
29+
rfm69.encryption_key = (
30+
b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
31+
)
32+
33+
# set node addresses
34+
rfm69.node = 1
35+
rfm69.destination = 2
36+
# initialize counter
37+
counter = 0
38+
# send a broadcast message from my_node with ID = counter
39+
rfm69.send(
40+
bytes("Startup message {} from node {}".format(counter, rfm69.node), "UTF-8")
41+
)
42+
43+
# Wait to receive packets.
44+
print("Waiting for packets...")
45+
now = time.monotonic()
46+
while True:
47+
# Look for a new packet: only accept if addresses to my_node
48+
packet = rfm69.receive(with_header=True)
49+
# If no packet was received during the timeout then None is returned.
50+
if packet is not None:
51+
# Received a packet!
52+
# Print out the raw bytes of the packet:
53+
print("Received (raw header):", [hex(x) for x in packet[0:4]])
54+
print("Received (raw payload): {0}".format(packet[4:]))
55+
print("Received RSSI: {0}".format(rfm69.last_rssi))
56+
if time.monotonic() - now > transmit_interval:
57+
now = time.monotonic()
58+
counter = counter + 1
59+
# send a mesage to destination_node from my_node
60+
rfm69.send(
61+
bytes(
62+
"message number {} from node {}".format(counter, rfm69.node), "UTF-8"
63+
),
64+
keep_listening=True,
65+
)
66+
button_pressed = None

examples/rfm69_node1_ack.py

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# Example to send a packet periodically between addressed nodes with ACK
2+
# Author: Jerry Needell
3+
#
4+
import time
5+
import board
6+
import busio
7+
import digitalio
8+
import adafruit_rfm69
9+
10+
# set the time interval (seconds) for sending packets
11+
transmit_interval = 10
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.
18+
# set GPIO pins as necessary -- this example is for Raspberry Pi
19+
CS = digitalio.DigitalInOut(board.CE1)
20+
RESET = digitalio.DigitalInOut(board.D25)
21+
22+
# Initialize SPI bus.
23+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
24+
# Initialze RFM radio
25+
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)
26+
27+
# Optionally set an encryption key (16 byte AES key). MUST match both
28+
# on the transmitter and receiver (or be set to None to disable/the default).
29+
rfm69.encryption_key = (
30+
b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
31+
)
32+
33+
# set delay before sending ACK
34+
rfm69.ack_delay = 0.1
35+
# set node addresses
36+
rfm69.node = 1
37+
rfm69.destination = 2
38+
# initialize counter
39+
counter = 0
40+
ack_failed_counter = 0
41+
# send startup message from my_node
42+
rfm69.send_with_ack(bytes("startup message from node {}".format(rfm69.node), "UTF-8"))
43+
44+
# Wait to receive packets.
45+
print("Waiting for packets...")
46+
# initialize flag and timer
47+
time_now = time.monotonic()
48+
while True:
49+
# Look for a new packet: only accept if addresses to my_node
50+
packet = rfm69.receive(with_ack=True, with_header=True)
51+
# If no packet was received during the timeout then None is returned.
52+
if packet is not None:
53+
# Received a packet!
54+
# Print out the raw bytes of the packet:
55+
print("Received (raw header):", [hex(x) for x in packet[0:4]])
56+
print("Received (raw payload): {0}".format(packet[4:]))
57+
print("RSSI: {0}".format(rfm69.last_rssi))
58+
# send reading after any packet received
59+
if time.monotonic() - time_now > transmit_interval:
60+
# reset timeer
61+
time_now = time.monotonic()
62+
counter += 1
63+
# send a mesage to destination_node from my_node
64+
if not rfm69.send_with_ack(
65+
bytes("message from node node {} {}".format(rfm69.node, counter), "UTF-8")
66+
):
67+
ack_failed_counter += 1
68+
print(" No Ack: ", counter, ack_failed_counter)

examples/rfm69_node1_bonnet.py

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Example to send a packet periodically between addressed nodes
2+
# Author: Jerry Needell
3+
#
4+
import board
5+
import busio
6+
import digitalio
7+
8+
# Import the SSD1306 module.
9+
import adafruit_ssd1306
10+
import adafruit_rfm69
11+
12+
# Button A
13+
btnA = digitalio.DigitalInOut(board.D5)
14+
btnA.direction = digitalio.Direction.INPUT
15+
btnA.pull = digitalio.Pull.UP
16+
17+
# Button B
18+
btnB = digitalio.DigitalInOut(board.D6)
19+
btnB.direction = digitalio.Direction.INPUT
20+
btnB.pull = digitalio.Pull.UP
21+
22+
# Button C
23+
btnC = digitalio.DigitalInOut(board.D12)
24+
btnC.direction = digitalio.Direction.INPUT
25+
btnC.pull = digitalio.Pull.UP
26+
27+
# Create the I2C interface.
28+
i2c = busio.I2C(board.SCL, board.SDA)
29+
30+
# 128x32 OLED Display
31+
reset_pin = digitalio.DigitalInOut(board.D4)
32+
display = adafruit_ssd1306.SSD1306_I2C(128, 32, i2c, reset=reset_pin)
33+
# Clear the display.
34+
display.fill(0)
35+
display.show()
36+
width = display.width
37+
height = display.height
38+
39+
40+
# set the time interval (seconds) for sending packets
41+
transmit_interval = 10
42+
43+
# Define radio parameters.
44+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
45+
# module! Can be a value like 915.0, 433.0, etc.
46+
47+
# Define pins connected to the chip.
48+
CS = digitalio.DigitalInOut(board.CE1)
49+
RESET = digitalio.DigitalInOut(board.D25)
50+
51+
# Initialize SPI bus.
52+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
53+
54+
# Initialze RFM radio
55+
56+
# Attempt to set up the RFM69 Module
57+
try:
58+
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)
59+
display.text("RFM69: Detected", 0, 0, 1)
60+
except RuntimeError:
61+
# Thrown on version mismatch
62+
display.text("RFM69: ERROR", 0, 0, 1)
63+
64+
display.show()
65+
66+
67+
# Optionally set an encryption key (16 byte AES key). MUST match both
68+
# on the transmitter and receiver (or be set to None to disable/the default).
69+
rfm69.encryption_key = (
70+
b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
71+
)
72+
73+
# set node addresses
74+
rfm69.node = 1
75+
rfm69.destination = 2
76+
# initialize counter
77+
counter = 0
78+
# send a broadcast message from my_node with ID = counter
79+
rfm69.send(
80+
bytes("Startup message {} from node {}".format(counter, rfm69.node), "UTF-8")
81+
)
82+
83+
# Wait to receive packets.
84+
print("Waiting for packets...")
85+
button_pressed = None
86+
while True:
87+
# Look for a new packet: only accept if addresses to my_node
88+
packet = rfm69.receive(with_header=True)
89+
# If no packet was received during the timeout then None is returned.
90+
if packet is not None:
91+
# Received a packet!
92+
# Print out the raw bytes of the packet:
93+
print("Received (raw header):", [hex(x) for x in packet[0:4]])
94+
print("Received (raw payload): {0}".format(packet[4:]))
95+
print("Received RSSI: {0}".format(rfm69.last_rssi))
96+
# Check buttons
97+
if not btnA.value:
98+
button_pressed = "A"
99+
# Button A Pressed
100+
display.fill(0)
101+
display.text("AAA", width - 85, height - 7, 1)
102+
display.show()
103+
if not btnB.value:
104+
button_pressed = "B"
105+
# Button B Pressed
106+
display.fill(0)
107+
display.text("BBB", width - 75, height - 7, 1)
108+
display.show()
109+
if not btnC.value:
110+
button_pressed = "C"
111+
# Button C Pressed
112+
display.fill(0)
113+
display.text("CCC", width - 65, height - 7, 1)
114+
display.show()
115+
# send reading after any button pressed
116+
if button_pressed is not None:
117+
counter = counter + 1
118+
# send a mesage to destination_node from my_node
119+
rfm69.send(
120+
bytes(
121+
"message number {} from node {} button {}".format(
122+
counter, rfm69.node, button_pressed
123+
),
124+
"UTF-8",
125+
),
126+
keep_listening=True,
127+
)
128+
button_pressed = None

examples/rfm69_node2.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# Example to send a packet periodically between addressed nodes
2+
# Author: Jerry Needell
3+
#
4+
import time
5+
import board
6+
import busio
7+
import digitalio
8+
import adafruit_rfm69
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.
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+
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)
23+
24+
# Optionally set an encryption key (16 byte AES key). MUST match both
25+
# on the transmitter and receiver (or be set to None to disable/the default).
26+
rfm69.encryption_key = (
27+
b"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08"
28+
)
29+
30+
# set node addresses
31+
rfm69.node = 2
32+
rfm69.destination = 1
33+
# initialize counter
34+
counter = 0
35+
# send a broadcast message from my_node with ID = counter
36+
rfm69.send(bytes("startup message from node {} ".format(rfm69.node), "UTF-8"))
37+
38+
# Wait to receive packets.
39+
print("Waiting for packets...")
40+
# initialize flag and timer
41+
time_now = time.monotonic()
42+
while True:
43+
# Look for a new packet: only accept if addresses to my_node
44+
packet = rfm69.receive(with_header=True)
45+
# If no packet was received during the timeout then None is returned.
46+
if packet is not None:
47+
# Received a packet!
48+
# Print out the raw bytes of the packet:
49+
print("Received (raw header):", [hex(x) for x in packet[0:4]])
50+
print("Received (raw payload): {0}".format(packet[4:]))
51+
print("Received RSSI: {0}".format(rfm69.last_rssi))
52+
# send reading after any packet received
53+
counter = counter + 1
54+
# after 10 messages send a response to destination_node from my_node with ID = counter&0xff
55+
if counter % 10 == 0:
56+
time.sleep(0.5) # brief delay before responding
57+
rfm69.identifier = counter & 0xFF
58+
rfm69.send(
59+
bytes(
60+
"message number {} from node {} ".format(counter, rfm69.node),
61+
"UTF-8",
62+
),
63+
keep_listening=True,
64+
)

0 commit comments

Comments
 (0)