Skip to content

Commit 1560223

Browse files
committed
enable interrupt handling for received packets - add transmit example
1 parent 8b70dc1 commit 1560223

File tree

4 files changed

+153
-16
lines changed

4 files changed

+153
-16
lines changed

.pylintrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local
156156
# (useful for modules/projects where namespaces are manipulated during runtime
157157
# and thus existing member attributes cannot be deduced by static analysis. It
158158
# supports qualified module names, as well as Unix pattern matching.
159-
ignored-modules=board
159+
ignored-modules=board,RPi.GPIO
160160

161161
# Show a hint with possible names when a member name was not found. The aspect
162162
# of finding the hint is based on edit distance.

adafruit_rfm9x.py

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,7 @@ def enable_crc(self, val):
646646
self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb
647647
)
648648

649-
def send(self, data, timeout=2.,
649+
def send(self, data, timeout=2., keep_listening=False,
650650
tx_header=(_RH_BROADCAST_ADDRESS, _RH_BROADCAST_ADDRESS, 0, 0)):
651651
"""Send a string of data using the transmitter.
652652
You can only send 252 bytes at a time
@@ -685,9 +685,13 @@ def send(self, data, timeout=2.,
685685
while not timed_out and not self.tx_done:
686686
if (time.monotonic() - start) >= timeout:
687687
timed_out = True
688-
# Go back to idle mode after transmit.
689-
self.idle()
690-
# Clear interrupts.
688+
# Listen again if necessary and return the result packet.
689+
if keep_listening:
690+
self.listen()
691+
else:
692+
# Enter idle mode to stop receiving other packets.
693+
self.idle()
694+
# Clear interrupt.
691695
self._write_u8(_RH_RF95_REG_12_IRQ_FLAGS, 0xFF)
692696
if timed_out:
693697
raise RuntimeError('Timeout during packet send')
@@ -699,7 +703,7 @@ def receive(self, timeout=0.5, keep_listening=True, with_header=False,
699703
"""Wait to receive a packet from the receiver. Will wait for up to timeout_s amount of
700704
seconds for a packet to be received and decoded. If a packet is found the payload bytes
701705
are returned, otherwise None is returned (which indicates the timeout elapsed with no
702-
reception).
706+
reception). If timeout is None it isnot used ( for use with interrupts)
703707
If keep_listening is True (the default) the chip will immediately enter listening mode
704708
after reception of a packet, otherwise it will fall back to idle mode and ignore any
705709
future reception.
@@ -716,17 +720,18 @@ def receive(self, timeout=0.5, keep_listening=True, with_header=False,
716720
If rx_filter is not 0xff and packet[0] does not match rx_filter then
717721
the packet is ignored and None is returned.
718722
"""
719-
# Make sure we are listening for packets.
720-
self.listen()
721-
# Wait for the rx done interrupt. This is not ideal and will
722-
# surely miss or overflow the FIFO when packets aren't read fast
723-
# enough, however it's the best that can be done from Python without
724-
# interrupt supports.
725-
start = time.monotonic()
726723
timed_out = False
727-
while not timed_out and not self.rx_done:
728-
if (time.monotonic() - start) >= timeout:
729-
timed_out = True
724+
if timeout is not None:
725+
# Make sure we are listening for packets.
726+
self.listen()
727+
# Wait for the rx done interrupt. This is not ideal and will
728+
# surely miss or overflow the FIFO when packets aren't read fast
729+
# enough, however it's the best that can be done from Python without
730+
# interrupt supports.
731+
start = time.monotonic()
732+
while not timed_out and not self.rx_done:
733+
if (time.monotonic() - start) >= timeout:
734+
timed_out = True
730735
# Payload ready is set, a packet is in the FIFO.
731736
packet = None
732737
if not timed_out:

examples/rfm9x_rpi_interrupt.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Simple demo of sending and recieving data with the RFM95 LoRa radio.
2+
# Author: Tony DiCola
3+
import time
4+
import board
5+
import busio
6+
import digitalio
7+
import RPi.GPIO as io
8+
import adafruit_rfm9x
9+
10+
11+
# setup interrupt callback function
12+
def rfm9x_callback(rfm9x_irq):
13+
global packet_received #pylint: disable=global-statement
14+
print("IRQ detected ",rfm9x_irq, rfm9x.rx_done)
15+
# check to see if this was a rx interrupt - ignore tx
16+
if rfm9x.rx_done:
17+
packet = rfm9x.receive(timeout = None)
18+
if packet is not None:
19+
packet_received = True
20+
# Received a packet!
21+
# Print out the raw bytes of the packet:
22+
print('Received (raw bytes): {0}'.format(packet))
23+
print([hex(x) for x in packet])
24+
print('RSSI: {0}'.format(rfm9x.rssi))
25+
26+
27+
# Define radio parameters.
28+
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
29+
# module! Can be a value like 915.0, 433.0, etc.
30+
31+
# Define pins connected to the chip, use these if wiring up the breakout according to the guide:
32+
CS = digitalio.DigitalInOut(board.CE1)
33+
RESET = digitalio.DigitalInOut(board.D25)
34+
35+
# Initialize SPI bus.
36+
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)
37+
38+
# Initialze RFM radio
39+
rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
40+
41+
# Note that the radio is configured in LoRa mode so you can't control sync
42+
# word, encryption, frequency deviation, or other settings!
43+
44+
# You can however adjust the transmit power (in dB). The default is 13 dB but
45+
# high power radios like the RFM95 can go up to 23 dB:
46+
rfm9x.tx_power = 23
47+
48+
# configure the interrupt pin and event handling.
49+
RFM9X_G0 = 22
50+
io.setmode(io.BCM)
51+
io.setup(RFM9X_G0, io.IN,pull_up_down=io.PUD_DOWN) # activate input
52+
io.add_event_detect(RFM9X_G0,io.RISING)
53+
io.add_event_callback(RFM9X_G0,rfm9x_callback)
54+
55+
packet_received = False
56+
# Send a packet. Note you can only send a packet up to 252 bytes in length.
57+
# This is a limitation of the radio packet size, so if you need to send larger
58+
# amounts of data you will need to break it into smaller send calls. Each send
59+
# call will wait for the previous one to finish before continuing.
60+
rfm9x.send(bytes("Hello world!\r\n","utf-8"), keep_listening = True)
61+
print('Sent Hello World message!')
62+
63+
# Wait to receive packets. Note that this library can't receive data at a fast
64+
# rate, in fact it can only receive and process one 252 byte packet at a time.
65+
# This means you should only use this for low bandwidth scenarios, like sending
66+
# and receiving a single message at a time.
67+
print('Waiting for packets...')
68+
while True:
69+
time.sleep(.1)
70+
if packet_received:
71+
rfm9x.send(bytes("back at you\r\n","utf-8"), keep_listening = True)
72+
print('received message!')
73+
packet_received = False

examples/rfm9x_transmit.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Example to send a packet periodically
2+
# Author: Jerry Needell
3+
#
4+
import time
5+
import board
6+
import busio
7+
import digitalio
8+
import adafruit_rfm9x
9+
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+
rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ)
25+
26+
# Note that the radio is configured in LoRa mode so you can't control sync
27+
# word, encryption, frequency deviation, or other settings!
28+
29+
# You can however adjust the transmit power (in dB). The default is 13 dB but
30+
# high power radios like the RFM95 can go up to 23 dB:
31+
rfm9x.tx_power = 23
32+
33+
34+
# initialize counter
35+
counter = 0
36+
#send a broadcast mesage
37+
rfm9x.send(bytes("message number {}".format(counter),"UTF-8"))
38+
39+
# Wait to receive packets.
40+
print('Waiting for packets...')
41+
#initialize flag and timer
42+
send_reading=False
43+
time_now=time.monotonic()
44+
while True:
45+
# Look for a new packet - wait up to 5 seconds:
46+
packet = rfm9x.receive(timeout=5.0)
47+
# If no packet was received during the timeout then None is returned.
48+
if packet is not None:
49+
# Received a packet!
50+
# Print out the raw bytes of the packet:
51+
print('Received (raw bytes): {0}'.format(packet))
52+
# send reading after any packet received
53+
if time.monotonic()-time_now>transmit_interval:
54+
#reset timeer
55+
time_now=time.monotonic()
56+
#clear flag to send data
57+
send_reading=False
58+
counter = counter + 1
59+
rfm9x.send(bytes("message number {}".format(counter),"UTF-8"))

0 commit comments

Comments
 (0)