From fc9b0e9cb018d2b941256737d8e888f35d8f6a81 Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 8 Mar 2019 14:02:39 -0600 Subject: [PATCH 01/12] Fixed broken CoC link, tweaked spacing. --- README.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 1e274b3..bd9eb78 100644 --- a/README.rst +++ b/README.rst @@ -40,7 +40,7 @@ To set it to 1000000 use : .. code-block:: python # Initialze RFM radio - rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ,baudrate=1000000) + rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=1000000) @@ -48,7 +48,7 @@ Contributing ============ Contributions are welcome! Please read our `Code of Conduct -`_ +`_ before contributing to help this project stay welcoming. Building locally From 7205d164b6e47a7121ed621e59f5e8d4f97edc69 Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 8 Mar 2019 14:03:25 -0600 Subject: [PATCH 02/12] Added Python 3.7 to compatible versions per local testing. --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 236f5f4..ed7f39d 100644 --- a/setup.py +++ b/setup.py @@ -49,6 +49,7 @@ 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.7', ], # What does your project relate to? From 3f33b9a4034d200441023fd5122b6c1adbafda0a Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 8 Mar 2019 15:04:13 -0600 Subject: [PATCH 03/12] Expose controls for spreading factor, coding rate, signal bandwidth. --- README.rst | 35 +++++++++++++++++++++++++++++++++-- adafruit_rfm9x.py | 38 ++++++++++++++++++++++++++++++++++---- 2 files changed, 67 insertions(+), 6 deletions(-) diff --git a/README.rst b/README.rst index bd9eb78..b8f54c0 100644 --- a/README.rst +++ b/README.rst @@ -29,7 +29,26 @@ This is easily achieved by downloading Usage Example ============= -See examples/rfm9x_simpletest.py for a demo of the usage. +Initialization of the RFM radio requires specifying a frequency appropriate to +your radio hardware (i.e. 868-915 or 433 MHz) and specifying the pins used in your +wiring from the controller board to the radio module. + +This example code matches the wiring used in the +`LoRa and LoRaWAN Radio for Raspberry Pi `_ +project: + +.. code-block:: python + import digitalio + import board + import busio + import adafruit_rfm9x + + RADIO_FREQ_MHZ = 915.0 + CS = digitalio.DigitalInOut(board.CE1) + RESET = digitalio.DigitalInOut(board.D25) + spi = busio.SPI(board.SCK, MOSI=board.MOSI, MISO=board.MISO) + rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ) + Note: the default baudrate for the SPI is 50000000 (5MHz). The maximum setting is 10Mhz but transmission errors have been observed expecially when using breakout boards. For breakout boards or other configurations where the boards are separated, it may be necessary to reduce @@ -39,9 +58,21 @@ To set it to 1000000 use : .. code-block:: python - # Initialze RFM radio + # Initialze RFM radio with a more conservative baudrate rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=1000000) +Optional controls exist to alter the signal bandwidth, coding rate, and spreading factor +settings used by the radio to achieve better performance in different environments. +By default, settings compatible with RadioHead Bw125Cr45Sf128 mode are used, matching +the following example: + +.. code-block:: python + + # Initialze RFM radio with conservative baudrate and default modem config + rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=1000000, + signal_bandwidth=125000, coding_rate=5, spreading_factor=7) + +See examples/rfm9x_simpletest.py for an expanded demo of the usage. Contributing diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index 2289e6e..3e4a93d 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -192,6 +192,8 @@ _RH_RF95_LOW_DATA_RATE_OPTIMIZE = const(0x01) # RH_RF95_REG_1E_MODEM_CONFIG2 0x1e +_RH_RF95_DETECTION_OPTIMIZE = const(0x31) +_RH_RF95_DETECTION_THRESHOLD = const(0x37) _RH_RF95_SPREADING_FACTOR = const(0xf0) _RH_RF95_SPREADING_FACTOR_64CPS = const(0x60) _RH_RF95_SPREADING_FACTOR_128CPS = const(0x70) @@ -334,7 +336,8 @@ def __set__(self, obj, val): rx_done = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=6, bits=1) def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, - high_power=True, baudrate=5000000): + high_power=True, baudrate=5000000, signal_bandwidth=125000, + coding_rate=5, spreading_factor=7): self.high_power = high_power # Device support SPI mode 0 (polarity & phase = 0) up to a max of 10mhz. # Set Default Baudrate to 5MHz to avoid problems @@ -367,10 +370,37 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, self._write_u8(_RH_RF95_REG_0F_FIFO_RX_BASE_ADDR, 0x00) # Set mode idle self.idle() - # Set modem config to RadioHead compatible Bw125Cr45Sf128 mode. + # Defaults set modem config to RadioHead compatible Bw125Cr45Sf128 mode. + # Set signal bandwidth (set to 125000 to match RadioHead Bw125). + bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) + for bw, cutoff in enumerate(bins): + if bandwidth <= cutoff: + break + else: + bw = 9 + self._write_u8( + _RH_RF95_REG_1D_MODEM_CONFIG1, + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0f) | (bw << 4) + ) + # Set coding rate (set to 5 to match RadioHead Cr45). + denominator = min(max(coding_rate, 5), 8) + cr = denominator - 4 + self._write_u8( + _RH_RF95_REG_1D_MODEM_CONFIG1, + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf1) | (cr << 1) + ) + # Set spreading factor (set to 7 to match RadioHead Sf128). + sf = min(max(spreading_factor, 6), 12) + self._write_u8(_RH_RF95_DETECTION_OPTIMIZE, 0xc5 if sf == 6 else 0xc3) + self._write_u8(_RH_RF95_DETECTION_THRESHOLD, 0x0c if sf == 6 else 0x0a) + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + ( + (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x0f) | + ((sf << 4) & 0xf0) + ) + ) # Note no sync word is set for LoRa mode either! - self._write_u8(_RH_RF95_REG_1D_MODEM_CONFIG1, 0x72) # Fei msb? - self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, 0x74) # Fei lsb? self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb? # Set preamble length (default 8 bytes to match radiohead). self.preamble_length = preamble_length From b2d6f15b7a7d3dff12e75364cd0a8a2799e8c7df Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 8 Mar 2019 15:08:59 -0600 Subject: [PATCH 04/12] Tweak appearance of docs. --- README.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/README.rst b/README.rst index b8f54c0..1261280 100644 --- a/README.rst +++ b/README.rst @@ -38,6 +38,7 @@ This example code matches the wiring used in the project: .. code-block:: python + import digitalio import board import busio From ff73d37107bc4a0714849ce8f81ba1aa6c1e3dbd Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 8 Mar 2019 15:40:25 -0600 Subject: [PATCH 05/12] Fix typo. --- adafruit_rfm9x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index 3e4a93d..306d060 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -374,7 +374,7 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, # Set signal bandwidth (set to 125000 to match RadioHead Bw125). bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) for bw, cutoff in enumerate(bins): - if bandwidth <= cutoff: + if signal_bandwidth <= cutoff: break else: bw = 9 From 8eb678ae67b96829401da70742cd083b6519682b Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Thu, 14 Mar 2019 22:17:57 -0500 Subject: [PATCH 06/12] Exposed control of CRC checking on inbound. --- README.rst | 3 ++- adafruit_rfm9x.py | 6 +++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/README.rst b/README.rst index 1261280..c1cf0b4 100644 --- a/README.rst +++ b/README.rst @@ -71,7 +71,8 @@ the following example: # Initialze RFM radio with conservative baudrate and default modem config rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=1000000, - signal_bandwidth=125000, coding_rate=5, spreading_factor=7) + signal_bandwidth=125000, coding_rate=5, spreading_factor=7, + enable_crc=False) See examples/rfm9x_simpletest.py for an expanded demo of the usage. diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index 306d060..57b17a1 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -337,7 +337,7 @@ def __set__(self, obj, val): def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, high_power=True, baudrate=5000000, signal_bandwidth=125000, - coding_rate=5, spreading_factor=7): + coding_rate=5, spreading_factor=7, enable_crc=False): self.high_power = high_power # Device support SPI mode 0 (polarity & phase = 0) up to a max of 10mhz. # Set Default Baudrate to 5MHz to avoid problems @@ -400,6 +400,10 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, ((sf << 4) & 0xf0) ) ) + # Optionally enable CRC checking on incoming packets. + if enable_crc: + config = self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 + self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, config) # Note no sync word is set for LoRa mode either! self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb? # Set preamble length (default 8 bytes to match radiohead). From 315f4cfc2c8d4ae72190f2b3314a96b19dfc025c Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 14:26:47 -0500 Subject: [PATCH 07/12] Implement bad CRC triggers warning and skip packet if desired. --- adafruit_rfm9x.py | 50 ++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index 57b17a1..e0f141a 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -33,6 +33,12 @@ import digitalio from micropython import const +try: + from warnings import warn +except ImportError: + def warn(msg, cat=None, stacklevel=1): + print("%s: %s" % ("Warning" if cat is None else cat.__name__, msg)) + import adafruit_bus_device.spi_device as spidev @@ -335,6 +341,8 @@ def __set__(self, obj, val): rx_done = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=6, bits=1) + crc_error = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=5, bits=1) + def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, high_power=True, baudrate=5000000, signal_bandwidth=125000, coding_rate=5, spreading_factor=7, enable_crc=False): @@ -403,7 +411,10 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, # Optionally enable CRC checking on incoming packets. if enable_crc: config = self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 - self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, config) + else: + config = self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb + self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, config) + self.enable_crc = enable_crc # Note no sync word is set for LoRa mode either! self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb? # Set preamble length (default 8 bytes to match radiohead). @@ -651,25 +662,28 @@ def receive(self, timeout=0.5, keep_listening=True, with_header=False, # Payload ready is set, a packet is in the FIFO. packet = None if not timed_out: - # Grab the length of the received packet and check it has at least 5 - # bytes to indicate the 4 byte header and at least 1 byte of user data. - length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES) - if length < 5: - packet = None + if self.enable_crc and self.crc_error: + warn("CRC error, packet ignored") else: - # Have a good packet, grab it from the FIFO. - # Reset the fifo read ptr to the beginning of the packet. - current_addr = self._read_u8(_RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR) - self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr) - packet = bytearray(length) - # Read the packet. - self._read_into(_RH_RF95_REG_00_FIFO, packet) - if (rx_filter != _RH_BROADCAST_ADDRESS and packet[0] != _RH_BROADCAST_ADDRESS - and packet[0] != rx_filter): + # Grab the length of the received packet and check it has at least 5 + # bytes to indicate the 4 byte header and at least 1 byte of user data. + length = self._read_u8(_RH_RF95_REG_13_RX_NB_BYTES) + if length < 5: packet = None - elif not with_header: # skip the header if not wanted - packet = packet[4:] - # Listen again if necessary and return the result packet. + else: + # Have a good packet, grab it from the FIFO. + # Reset the fifo read ptr to the beginning of the packet. + current_addr = self._read_u8(_RH_RF95_REG_10_FIFO_RX_CURRENT_ADDR) + self._write_u8(_RH_RF95_REG_0D_FIFO_ADDR_PTR, current_addr) + packet = bytearray(length) + # Read the packet. + self._read_into(_RH_RF95_REG_00_FIFO, packet) + if (rx_filter != _RH_BROADCAST_ADDRESS and packet[0] != _RH_BROADCAST_ADDRESS + and packet[0] != rx_filter): + packet = None + elif not with_header: # skip the header if not wanted + packet = packet[4:] + # Listen again if necessary and return the result packet. if keep_listening: self.listen() else: From be5723b51445e8e60a2a6adeebfe1cfdf5b06321 Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 15:40:54 -0500 Subject: [PATCH 08/12] Address pylint complaints. --- adafruit_rfm9x.py | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index e0f141a..d7abe6f 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -36,8 +36,9 @@ try: from warnings import warn except ImportError: - def warn(msg, cat=None, stacklevel=1): - print("%s: %s" % ("Warning" if cat is None else cat.__name__, msg)) + def warn(msg, **kwargs): + # Issue a warning to stdout. + print("%s: %s" % ("Warning" if kwargs.get("cat") is None else kwargs["cat"].__name__, msg)) import adafruit_bus_device.spi_device as spidev @@ -343,6 +344,8 @@ def __set__(self, obj, val): crc_error = _RegisterBits(_RH_RF95_REG_12_IRQ_FLAGS, offset=5, bits=1) + bw_bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) + def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, high_power=True, baudrate=5000000, signal_bandwidth=125000, coding_rate=5, spreading_factor=7, enable_crc=False): @@ -380,32 +383,36 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, self.idle() # Defaults set modem config to RadioHead compatible Bw125Cr45Sf128 mode. # Set signal bandwidth (set to 125000 to match RadioHead Bw125). - bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) - for bw, cutoff in enumerate(bins): + for bwid, cutoff in enumerate(self.bw_bins): if signal_bandwidth <= cutoff: break else: - bw = 9 + bwid = 9 self._write_u8( _RH_RF95_REG_1D_MODEM_CONFIG1, - (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0f) | (bw << 4) + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0f) | (bwid << 4) ) # Set coding rate (set to 5 to match RadioHead Cr45). - denominator = min(max(coding_rate, 5), 8) - cr = denominator - 4 self._write_u8( _RH_RF95_REG_1D_MODEM_CONFIG1, - (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf1) | (cr << 1) + ( + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf1) | + ((min(max(coding_rate, 5), 8) - 4) << 1) + ) ) # Set spreading factor (set to 7 to match RadioHead Sf128). - sf = min(max(spreading_factor, 6), 12) - self._write_u8(_RH_RF95_DETECTION_OPTIMIZE, 0xc5 if sf == 6 else 0xc3) - self._write_u8(_RH_RF95_DETECTION_THRESHOLD, 0x0c if sf == 6 else 0x0a) + spreading_factor = min(max(spreading_factor, 6), 12) + self._write_u8( + _RH_RF95_DETECTION_OPTIMIZE, 0xc5 if spreading_factor == 6 else 0xc3 + ) + self._write_u8( + _RH_RF95_DETECTION_THRESHOLD, 0x0c if spreading_factor == 6 else 0x0a + ) self._write_u8( _RH_RF95_REG_1E_MODEM_CONFIG2, ( - (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x0f) | - ((sf << 4) & 0xf0) + (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x0f) | + ((spreading_factor << 4) & 0xf0) ) ) # Optionally enable CRC checking on incoming packets. From 11470279c82a50224cecea05b6d8f090919f5914 Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 15:46:55 -0500 Subject: [PATCH 09/12] Address one more pylint complaint. --- adafruit_rfm9x.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index d7abe6f..b6c8152 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -37,7 +37,7 @@ from warnings import warn except ImportError: def warn(msg, **kwargs): - # Issue a warning to stdout. + "Issue a warning to stdout." print("%s: %s" % ("Warning" if kwargs.get("cat") is None else kwargs["cat"].__name__, msg)) import adafruit_bus_device.spi_device as spidev From ce0a8f0581fb6a29070efb6e49781ea187bd2f67 Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 15:54:50 -0500 Subject: [PATCH 10/12] Eliminate one more local variable because pylint likes the number 15. --- adafruit_rfm9x.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index b6c8152..13d6e52 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -417,10 +417,15 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, ) # Optionally enable CRC checking on incoming packets. if enable_crc: - config = self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 + ) else: - config = self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb - self._write_u8(_RH_RF95_REG_1E_MODEM_CONFIG2, config) + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb + ) self.enable_crc = enable_crc # Note no sync word is set for LoRa mode either! self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb? From 4d25d7625ed6c7de647fe8b8bdc0104c8b7f151d Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 17:59:12 -0500 Subject: [PATCH 11/12] Refactor RFM9x __init__ parameters into properties. --- README.rst | 13 +++-- adafruit_rfm9x.py | 146 +++++++++++++++++++++++++++++++--------------- 2 files changed, 106 insertions(+), 53 deletions(-) diff --git a/README.rst b/README.rst index c1cf0b4..328ee91 100644 --- a/README.rst +++ b/README.rst @@ -64,15 +64,16 @@ To set it to 1000000 use : Optional controls exist to alter the signal bandwidth, coding rate, and spreading factor settings used by the radio to achieve better performance in different environments. -By default, settings compatible with RadioHead Bw125Cr45Sf128 mode are used, matching -the following example: +By default, settings compatible with RadioHead Bw125Cr45Sf128 mode are used, which can +be altered in the following manner (continued from the above example): .. code-block:: python - # Initialze RFM radio with conservative baudrate and default modem config - rfm9x = adafruit_rfm9x.RFM9x(spi, CS, RESET, RADIO_FREQ_MHZ, baudrate=1000000, - signal_bandwidth=125000, coding_rate=5, spreading_factor=7, - enable_crc=False) + # Apply new modem config settings to the radio to improve its effective range + rfm9x.signal_bandwidth = 62500 + rfm9x.coding_rate = 6 + rfm9x.spreading_factor = 8 + rfm9x.enable_crc = True See examples/rfm9x_simpletest.py for an expanded demo of the usage. diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index 13d6e52..f6c1261 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -347,8 +347,7 @@ def __set__(self, obj, val): bw_bins = (7800, 10400, 15600, 20800, 31250, 41700, 62500, 125000, 250000) def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, - high_power=True, baudrate=5000000, signal_bandwidth=125000, - coding_rate=5, spreading_factor=7, enable_crc=False): + high_power=True, baudrate=5000000): self.high_power = high_power # Device support SPI mode 0 (polarity & phase = 0) up to a max of 10mhz. # Set Default Baudrate to 5MHz to avoid problems @@ -382,51 +381,11 @@ def __init__(self, spi, cs, reset, frequency, *, preamble_length=8, # Set mode idle self.idle() # Defaults set modem config to RadioHead compatible Bw125Cr45Sf128 mode. - # Set signal bandwidth (set to 125000 to match RadioHead Bw125). - for bwid, cutoff in enumerate(self.bw_bins): - if signal_bandwidth <= cutoff: - break - else: - bwid = 9 - self._write_u8( - _RH_RF95_REG_1D_MODEM_CONFIG1, - (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0f) | (bwid << 4) - ) - # Set coding rate (set to 5 to match RadioHead Cr45). - self._write_u8( - _RH_RF95_REG_1D_MODEM_CONFIG1, - ( - (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf1) | - ((min(max(coding_rate, 5), 8) - 4) << 1) - ) - ) - # Set spreading factor (set to 7 to match RadioHead Sf128). - spreading_factor = min(max(spreading_factor, 6), 12) - self._write_u8( - _RH_RF95_DETECTION_OPTIMIZE, 0xc5 if spreading_factor == 6 else 0xc3 - ) - self._write_u8( - _RH_RF95_DETECTION_THRESHOLD, 0x0c if spreading_factor == 6 else 0x0a - ) - self._write_u8( - _RH_RF95_REG_1E_MODEM_CONFIG2, - ( - (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x0f) | - ((spreading_factor << 4) & 0xf0) - ) - ) - # Optionally enable CRC checking on incoming packets. - if enable_crc: - self._write_u8( - _RH_RF95_REG_1E_MODEM_CONFIG2, - self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 - ) - else: - self._write_u8( - _RH_RF95_REG_1E_MODEM_CONFIG2, - self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb - ) - self.enable_crc = enable_crc + self.signal_bandwidth = 125000 + self.coding_rate = 5 + self.spreading_factor = 7 + # Default to disable CRC checking on incoming packets. + self.enable_crc = False # Note no sync word is set for LoRa mode either! self._write_u8(_RH_RF95_REG_26_MODEM_CONFIG3, 0x00) # Preamble lsb? # Set preamble length (default 8 bytes to match radiohead). @@ -590,6 +549,99 @@ def rssi(self): # Remember in LoRa mode the payload register changes function to RSSI! return self._read_u8(_RH_RF95_REG_1A_PKT_RSSI_VALUE) - 137 + @property + def signal_bandwidth(self): + """The signal bandwidth used by the radio (try setting to a higher + value to increase throughput or to a lower value to increase the + likelihood of successfully received payloads). Valid values are + listed in RFM9x.bw_bins.""" + bw_id = (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf0) >> 4 + if bw_id >= len(self.bw_bins): + return 500000 + else: + return self.bw_bins[bw_id] + + @signal_bandwidth.setter + def signal_bandwidth(self, val): + # Set signal bandwidth (set to 125000 to match RadioHead Bw125). + for bw_id, cutoff in enumerate(self.bw_bins): + if val <= cutoff: + break + else: + bw_id = 9 + self._write_u8( + _RH_RF95_REG_1D_MODEM_CONFIG1, + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0f) | (bw_id << 4) + ) + + @property + def coding_rate(self): + """The coding rate used by the radio to control forward error + correction (try setting to a higher value to increase tolerance of + short bursts of interference or to a lower value to increase bit + rate). Valid values are limited to 5, 6, 7, or 8.""" + cr_id = (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0x0e) >> 1 + denominator = cr_id + 4 + return denominator + + @coding_rate.setter + def coding_rate(self, val): + # Set coding rate (set to 5 to match RadioHead Cr45). + denominator = min(max(val, 5), 8) + cr_id = denominator - 4 + self._write_u8( + _RH_RF95_REG_1D_MODEM_CONFIG1, + (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf1) | (cr_id << 1) + ) + + @property + def spreading_factor(self): + """The spreading factor used by the radio (try setting to a higher + value to increase the receiver's ability to distinguish signal from + noise or to a lower value to increase the data transmission rate). + Valid values are limited to 6, 7, 8, 9, 10, 11, or 12.""" + sf_id = (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xf0) >> 4 + return sf_id + + @spreading_factor.setter + def spreading_factor(self, val): + # Set spreading factor (set to 7 to match RadioHead Sf128). + val = min(max(val, 6), 12) + self._write_u8( + _RH_RF95_DETECTION_OPTIMIZE, 0xc5 if val == 6 else 0xc3 + ) + self._write_u8( + _RH_RF95_DETECTION_THRESHOLD, 0x0c if val == 6 else 0x0a + ) + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + ( + (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x0f) | + ((val << 4) & 0xf0) + ) + ) + + @property + def enable_crc(self): + """Set to True to enable hardware CRC checking of incoming packets. + Incoming packets that fail the CRC check are not processed. Set to + False to disable CRC checking and process all incoming packets.""" + return (self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0x04) == 0x04 + + @enable_crc.setter + def enable_crc(self, val): + # Optionally enable CRC checking on incoming packets. + if val: + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) | 0x04 + ) + else: + self._write_u8( + _RH_RF95_REG_1E_MODEM_CONFIG2, + self._read_u8(_RH_RF95_REG_1E_MODEM_CONFIG2) & 0xfb + ) + def send(self, data, timeout=2., tx_header=(_RH_BROADCAST_ADDRESS, _RH_BROADCAST_ADDRESS, 0, 0)): """Send a string of data using the transmitter. From 9e44a93e2cebf5b73430cbc5ab54e5095d84823a Mon Sep 17 00:00:00 2001 From: Davin Potts Date: Fri, 15 Mar 2019 18:05:29 -0500 Subject: [PATCH 12/12] Because pylint does not like multiple returns. --- adafruit_rfm9x.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/adafruit_rfm9x.py b/adafruit_rfm9x.py index f6c1261..8d84a66 100644 --- a/adafruit_rfm9x.py +++ b/adafruit_rfm9x.py @@ -557,9 +557,10 @@ def signal_bandwidth(self): listed in RFM9x.bw_bins.""" bw_id = (self._read_u8(_RH_RF95_REG_1D_MODEM_CONFIG1) & 0xf0) >> 4 if bw_id >= len(self.bw_bins): - return 500000 + current_bandwidth = 500000 else: - return self.bw_bins[bw_id] + current_bandwidth = self.bw_bins[bw_id] + return current_bandwidth @signal_bandwidth.setter def signal_bandwidth(self, val):