Skip to content

enable interrupt handling for received packets #19

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Dec 18, 2019
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ ignored-classes=optparse.Values,thread._local,_thread._local
# (useful for modules/projects where namespaces are manipulated during runtime
# and thus existing member attributes cannot be deduced by static analysis. It
# supports qualified module names, as well as Unix pattern matching.
ignored-modules=board
ignored-modules=board,RPi.GPIO

# Show a hint with possible names when a member name was not found. The aspect
# of finding the hint is based on edit distance.
Expand Down
34 changes: 20 additions & 14 deletions adafruit_rfm69.py
Original file line number Diff line number Diff line change
Expand Up @@ -674,7 +674,7 @@ def frequency_deviation(self, val):
self._write_u8(_REG_FDEV_MSB, fdev >> 8)
self._write_u8(_REG_FDEV_LSB, fdev & 0xFF)

def send(self, data, timeout=2.,
def send(self, data, timeout=2., keep_listening=False,
tx_header=(_RH_BROADCAST_ADDRESS, _RH_BROADCAST_ADDRESS, 0, 0)):
"""Send a string of data using the transmitter.
You can only send 60 bytes at a time
Expand Down Expand Up @@ -717,8 +717,12 @@ def send(self, data, timeout=2.,
while not timed_out and not self.packet_sent:
if (time.monotonic() - start) >= timeout:
timed_out = True
# Go back to idle mode after transmit.
self.idle()
# Listen again if necessary and return the result packet.
if keep_listening:
self.listen()
else:
# Enter idle mode to stop receiving other packets.
self.idle()
if timed_out:
raise RuntimeError('Timeout during packet send')

Expand All @@ -727,7 +731,7 @@ def receive(self, timeout=0.5, keep_listening=True, with_header=False,
"""Wait to receive a packet from the receiver. Will wait for up to timeout_s amount of
seconds for a packet to be received and decoded. If a packet is found the payload bytes
are returned, otherwise None is returned (which indicates the timeout elapsed with no
reception).
reception). If timeout is None then it is not used ( for use with interrupts)
If keep_listening is True (the default) the chip will immediately enter listening mode
after reception of a packet, otherwise it will fall back to idle mode and ignore any
future reception.
Expand All @@ -744,17 +748,19 @@ def receive(self, timeout=0.5, keep_listening=True, with_header=False,
If rx_filter is not 0xff and packet[0] does not match rx_filter then
the packet is ignored and None is returned.
"""
# Make sure we are listening for packets.
self.listen()
# Wait for the payload_ready interrupt. This is not ideal and will
# surely miss or overflow the FIFO when packets aren't read fast
# enough, however it's the best that can be done from Python without
# interrupt supports.
start = time.monotonic()
timed_out = False
while not timed_out and not self.payload_ready:
if (time.monotonic() - start) >= timeout:
timed_out = True
if timeout is not None:
# Make sure we are listening for packets.
self.listen()
# Wait for the payload_ready interrupt. This is not ideal and will
# surely miss or overflow the FIFO when packets aren't read fast
# enough, however it's the best that can be done from Python without
# interrupt supports.
start = time.monotonic()
timed_out = False
while not timed_out and not self.payload_ready:
if (time.monotonic() - start) >= timeout:
timed_out = True
# Payload ready is set, a packet is in the FIFO.
packet = None
# Enter idle mode to stop receiving other packets.
Expand Down
83 changes: 83 additions & 0 deletions examples/rfm69_rpi_interrupt.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
# Example using Interrupts to send a message and then wait indefinitely for messages
# to be received. Interrupts are used only for receive. sending is done with polling.
# This example is for systems that support interrupts like the Raspberry Pi with "blinka"
# CircuitPython does not support interrupts so it will not work on Circutpython boards
import time
import board
import busio
import digitalio
import RPi.GPIO as io
import adafruit_rfm69

# setup interrupt callback function
def rfm69_callback(rfm69_irq):
global packet_received #pylint: disable=global-statement
print("IRQ detected on pin {0} payload_ready {1} ".format(rfm69_irq, rfm69.payload_ready))
# see if this was a payload_ready interrupt ignore if not
if rfm69.payload_ready:
packet = rfm69.receive(timeout = None)
if packet is not None:
# Received a packet!
packet_received = True
# Print out the raw bytes of the packet:
print('Received (raw bytes): {0}'.format(packet))
print([hex(x) for x in packet])
print('RSSI: {0}'.format(rfm69.rssi))


# Define radio parameters.
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
# module! Can be a value like 915.0, 433.0, etc.

# Define pins connected to the chip, use these if wiring up the breakout according to the guide:
CS = digitalio.DigitalInOut(board.CE1)
RESET = digitalio.DigitalInOut(board.D25)

# Initialize SPI bus.
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# Initialze RFM radio
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)

# Optionally set an encryption key (16 byte AES key). MUST match both
# on the transmitter and receiver (or be set to None to disable/the default).
rfm69.encryption_key = b'\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08'

# Print out some chip state:
print('Temperature: {0}C'.format(rfm69.temperature))
print('Frequency: {0}mhz'.format(rfm69.frequency_mhz))
print('Bit rate: {0}kbit/s'.format(rfm69.bitrate/1000))
print('Frequency deviation: {0}hz'.format(rfm69.frequency_deviation))

# configure the interrupt pin and event handling.
RFM69_G0 = 22
io.setmode(io.BCM)
io.setup(RFM69_G0, io.IN,pull_up_down=io.PUD_DOWN) # activate input
io.add_event_detect(RFM69_G0,io.RISING)
io.add_event_callback(RFM69_G0,rfm69_callback)
packet_received = False

# Send a packet. Note you can only send a packet up to 60 bytes in length.
# This is a limitation of the radio packet size, so if you need to send larger
# amounts of data you will need to break it into smaller send calls. Each send
# call will wait for the previous one to finish before continuing.
rfm69.send(bytes('Hello world!\r\n',"utf-8"), keep_listening = True)
print('Sent hello world message!')
# If you don't wawnt to send a message to start you can just start lintening
# rmf69.listen()

# Wait to receive packets. Note that this library can't receive data at a fast
# rate, in fact it can only receive and process one 60 byte packet at a time.
# This means you should only use this for low bandwidth scenarios, like sending
# and receiving a single message at a time.
print('Waiting for packets...')

# the loop is where you can do any desire processing
# the global variable packet_received can be used to determine if a packet was received.
while True:
# the sleep time is arbitrary since any incomming packe will trigger an interrupt
# and be received.
time.sleep(.1)
if packet_received:
print('received message!')
packet_received = False
55 changes: 55 additions & 0 deletions examples/rfm69_transmit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Example to send a packet periodically
# Author: Jerry Needell
#
import time
import board
import busio
import digitalio
import adafruit_rfm69

transmit_interval=10

# Define radio parameters.
RADIO_FREQ_MHZ = 915.0 # Frequency of the radio in Mhz. Must match your
# module! Can be a value like 915.0, 433.0, etc.

# Define pins connected to the chip.
CS = digitalio.DigitalInOut(board.CE1)
RESET = digitalio.DigitalInOut(board.D25)

# Initialize SPI bus.
spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO)

# Initialze RFM radio
rfm69 = adafruit_rfm69.RFM69(spi, CS, RESET, RADIO_FREQ_MHZ)

# Optionally set an encryption key (16 byte AES key). MUST match both
# on the transmitter and receiver (or be set to None to disable/the default).
rfm69.encryption_key = b'\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08'

# initialize counter
counter = 0
#send a broadcast mesage
rfm69.send(bytes("message number {}".format(counter),"UTF-8"))

# Wait to receive packets.
print('Waiting for packets...')
#initialize flag and timer
send_reading=False
time_now=time.monotonic()
while True:
# Look for a new packet - wait up to 5 seconds:
packet = rfm69.receive(timeout=5.0)
# If no packet was received during the timeout then None is returned.
if packet is not None:
# Received a packet!
# Print out the raw bytes of the packet:
print('Received (raw bytes): {0}'.format(packet))
# send reading after any packet received
if time.monotonic()-time_now>transmit_interval:
#reset timeer
time_now=time.monotonic()
#clear flag to send data
send_reading=False
counter = counter + 1
rfm69.send(bytes("message number {}".format(counter),"UTF-8"))