Circuitpython-nrf24l01

Latest version: v2.1.3

Safety actively analyzes 634631 Python packages for vulnerabilities to keep your Python projects secure.

Scan your dependencies

Page 2 of 3

2.0.0

Breaking backward compatibility changes
- **NEW** `available()` function provided as a convenience instead of using `nrf.update() and nrf.pipe is not None` (a technique introduced in the last release). To expose this new `available()` function in the `FakeBLE` API, I had to rename the current `available()` function to `len_available()`.
- **RENAMED** `recv()` is now `read()`. The descriptive name `read()` makes more sense because this function isn't actually doing the receiving, rather it is simply reading payload data that was already received and stored in the radio's RX FIFO.
- **RENAMED** `what_happened()` to `print_details()`. The name "what_happened" came from my misunderstanding of the TMRh20 library's `RF24::whatHappened()` (& partly I just liked the name). Now, using "print_details" makes more sense because it is an apt description of what the function actually does.
- **REMOVED** `FakeBLE.to_android` attribute because it was marked for deprecation.
- **REMOVED** `RF24.read_ack()` function because it was marked for deprecation.
- All examples now use `time.monotonic_ns()` to measure transmission times. This change requires Python v3.7 in Linux, thus *setup.py* stipulates this requirement via `python_requires` option. Recommend using latest release of the Raspberry Pi OS which ships with Python v3.7.2 (as of this writing).
- `auto_ack` returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.
- `dynamic_payloads` returns an integer (instead of a boolean) where each bit represent the feature's setting about a pipe.
- `payload_length` returns the current setting of pipe 0 instead of a list for all pipes. This actually fixes a bug that allowed a flood of other subsequent bugs.
- In v1.2.0 - v1.2.3, if a user called `payload_length[0] = 0`, there was nothing in the code to prevent this mis-configuration (payload length cannot be 0). Furthermore this mis-configuration was not written to the corresponding nRF24L01 registers which would cause errors in every other function that handled payloads and/or payload lengths (namely `any()`, `send()`, `write()`, `recv()`, & `what_happened(True)`)

Code Changes Include
- **TRANSMISSIONS THAT PREVIOUSLY TOOK 32 MILLISECONDS NOW TAKE ABOUT 2 OR 3 MILLISECONDS!!!** (~10x Speed-up!) I've achieved this huge speed-up by removing the `time.sleep(0.005)` calls in the SPI access functions. To compensate for the inherent CSN pin bouncing instability, I've implemented the `extra_clocks=8` parameter to Circuitpython's `SPIDevice` c'tor. Essentially this means that after the CSN pin is set inactive HIGH, the `SPIDevice` object writes another dummy byte to let the CSN pin settle. This technique is faster than trying to do a time-based delay using `time.sleep()` (& also turns the disadvantage of Python's slow execution time into more of a strength). I'm aware that this technique is meant for SD cards and is dependent on the SPI bus' frequency, but if we encounter problems... I'll cross that bridge if we come to it.
- Removed any other `time.sleep()` call that waited for less than 100 microseconds. Also, I took an idea from TMRh20's `RF24::write()` and moved the `ce_pin.value = 0` call to after the resulting status flags are asserted.
- **REMOVED** the `CSN_DELAY` constant since altering its value had no real-time affect on the SPI access functions. Additionally, it isn't needed anymore due to the first point about implementing the huge speed-up.
- `listen` no longer flushes RX FIFO when entering RX mode.
- `listen` now flushes TX FIFO when entering TX mode and `ack` payloads are enabled.
- `listen` closes pipe 0 if it hasn't been designated for RX when entering RX mode.
- `open_tx_pipe()` does not actually open pipe 0 when `auto_ack` is enabled. Rather, `listen` now opens pipe 0 when entering TX mode and `auto_ack` is enabled for pipe 0.
- `send()` & `resend()` doesn't clear the Status flags when finished anymore. This change will likely have little impact on applications since the status flags are still cleared when entering `write()` and `resend()`. This was done to speed up execution.
- `auto_ack` now force-enables the automatic acknowledgement feature for pipe 0 when any other RX pipe has `auto_ack` enabled.
- **NEW** `set_*()` & `get_*()` publicly exposed functions for `auto_ack`, `dynamic_payloads`, `payload_length`, & `ard`/`arc` attributes. These should allow faster, easier, & less error-prone interaction when setting or getting the configuration for said attributes on any individual pipe or all pipes at once. I haven't deprecated the attribute's older setter-decorated functions for backward compatibility (the new `set_*()` functions still utilize the attribute's setter-decorated functions as helpers).
- `ard`, `arc`, & `crc` attributes now clamp invalid input values instead throwing a `ValueError` exception.
- **NEW** `allow_ask_no_ack` attribute for unofficial support of the Si24R1 (a flaw from cloning a typo in the nRF24L01 datasheet)
- **NEW** `last_tx_arc` attribute for getting the number of retry attempts made in previous transmission. This data was previously only available in `what_happened()`, I found it useful when helping people troubleshhoot TMRh20's RF24 library.
- `FakeBLE` now inherits from `RF24`. Some attributes/functions are overridden to raise a `NotImplementedError` exception, so some vital ingredients to the BLE operation isn't compromised via the `FakeBLE` API.
- `close_rx_pipe()` now properly prevents the `listen` attribute from overriding the pipe 0 reading address
- `print_details()` now prints a more accurate representation of the addresses used on the pipes. Like the TMRh20 RF24 library's `printDetails()`, the address now prints a "hexlified" string in big endian form.
- **NEW** `address_repr()` function (belonging to the rf24.py module not the RF24 class) is the helper function that returns the address specified as a "hexlified" string in big endian form.

Revised examples + new *nrf24l01_manual_ack_test.py* & *nrf24l01_scanner_test.py*
- **NEW** *scanner_test* example that prints a vertical graph of potential RF interference for all applicable frequencies (vertically labeled by channel number).
- In making a similar contribution to TMRh20's RF24 library, TMRh20 kindly emphasized the importance of demonstrating "proper addressing" related to pipe usage. To show my appreciation for the discussion (& lessons learned), the examples have all (except the multiceiver example) been revised to use pipe 0 for TX & pipe 1 for RX. This revision adds a preliminary prompt that asks "Which radio is this?" Whereby:
- entering 0 uses `b"1Node"` on pipe 0 and `b"2Node"` on pipe 1
- entering 1 uses `b"2Node"` on pipe 0 and `b"1Node"` on pipe 1
- some examples' payloads have also been altered. This has been done to match the new examples I've submitted to TMRh20's RF24 library.
- *simple_test* uses a incrementing float that persists between calling `master()` & `slave()`
- *ack_payload_test* shows data structure usage and C-string's NULL terminating char with a counter that increments on successful transmissions and persists between calling `master()` & `slave()`
- **NEW** *manual_ack_test* mimics the *ack_payload_test*, but it doesn't use ACK payloads. Rather it uses manually switch between RX/TX modes.
- *multiceiver_test* uses an 8 byte payload that is properly packed using Python's `struct` library (instead of directly encoding the UTF-8 data into the bytearray)
- **REMOVED** *nrf24l01_2arduino_handling_data.py* in favor of the **NEW** *nrf24l01_manual_ack_test.py* example (they're practically identical).
- Compatibility with TMRh20's library now only requires;
1. `dynamic_payloads` has to be disabled
2. `payload_length` has to be set accordingly to match TMRh20's RF24 new examples' configuration


I've left these 2 lines commented out for easy modification (instead of typing it in the python REPL). Because *most* examples are compatible with TMRh20's new examples, the docs now have a table and hints about making this library compatible with TMRh20's RF24 library (instead of using 1 dedicated example).
- *multiceiver_test* doesn't use ACK payloads for `node(1)` anymore. This demonstration was a bit over zealous anyway, and removing it better matches the *multiceiverDemo.ino* example I submitted to TMRh20's RF24 library.
- all examples can be executed from CLI. This change is really helpful in that it requires less typing and less prone to typos (using terminal's auto-complete mechanism). This really only applies to the Linux platform, and there is no support for CLI args because CircuitPython firmware doesn't use them.

Other changes
- Behold the new project Logo for usage on rtfd.io and social media links
![image](https://user-images.githubusercontent.com/14963867/103445442-010e0c00-4c29-11eb-84e5-9f7cfbfec048.png)
Also changed the favicon to a miniature version of this logo. This should fall under the repo's MIT license, and I'm pretty sure its not as original as I think it is.
- changed docs theme to use [sphinx-material theme](https://github.com/bashtage/sphinx-material) (better display on mobile screens)
- Of course, there are corresponding doc changes to suit all code changes.
- Docs now contain retroactive changes related to different versions of the library using Sphinx's admonitions `.. versionadded::` and `.. versionchanged::`.
- I've added a feature to the Github action *build.yml* workflow: Archiving built assets (namely the mpy files for Circuitpython firmware) as workflow artifacts that can be downloaded (for up to a maximum of 90 days).
- The PyPi upload process now uses an API key because my PyPi account has 2FA enabled.

1.3.0

This release is a retrofitting of non-breaking backward compatible features introduced in v2.0.0. However, this also fixes 1 bug that allowed a flood of subsequent errors:
- `payload_length` returns the setting for only pipe 0. This attribute can still be used to set individual pipes ([see docs](https://circuitpython-nrf24l01.readthedocs.io/en/1.x/configure_api.html#payload-length)), but in v1.2.0-v1.2.3 it returned an internal list that prevented properly setting payload lengths for individual pipes. This error would also cause malfunctions in `any()`, `send()`, `resend()`, `recv()`, and `write()`. Use the new `get_payload_length()` function to retrieve the current setting for any pipe.

New features
- Huge Speed-up (~10x faster transmissions)!
- Examples retrofitted to be forward compatible not backward compatible. Additionally, all examples (except _nrf24l01_context_test.py_ and _nrf24l01_fake_ble_test.py_) are compatible with the new examples in TMRh20's RF24 library (I wrote those examples also 😉 ). Conversely, the examples still use `time.monotonic()` to preserve compatibility with CPython v3.4 where v2.0.0 now requires CPython v3.7+ on Linux (because that's when `time.monotonic_ns()` was introduced).
- Examples can now also be executed from Linux CLI (no need to keep `from example_name import *` anymore - but you still can).
- New scanner example (warning: it runs a bit slower on older RPi). Also replaced _nrf24l01_2arduino_handling_data.py_ with _nrf24l01_manual_ack_test.py_.
- New `available()` function provided as a convenience instead of using `nrf.update() and nrf.pipe is not None` (a technique introduced in v1.2.3). Because `FakeBLE` class now inherits from `RF24` class, this new function is overridden in the `FakeBLE` class with the existing `available()` function to prevent breaking backward compatibility. The difference in functionality will really only affect those trying to implement receiving BLE advertisements (officially unsupported at this time) using the `FakeBLE` API.
- New `set_*()` and `get_*()` methods for `auto_ack`, `dynamic_payloads` `payload_length`, and `ard`/`arc` attributes. `ard`/`arc` attributes are consolidated into `*et_auto_retries()` methods (because they live in the same register on the nRF24L01).
- Much more underlying optimizations listed in [v2.0.0 release description](https://github.com/2bndy5/CircuitPython_nRF24L01/releases/tag/2.0.0) under "Code Changes Include" section... However, `auto_ack` and `dynamic_payloads` attributes still return boolean (not integers like in v2.0.0).

Final Release
This will likely be the last release for v1.x. I just couldn't leave users constricted to using v1.x without the huge speed-up implementation and a known bug.

1.2.3

Library changes (rf24.py and rf24_lite.py)
- `update()` now always returns True
- this allows for calling the `update()` function in a conditional statement.
e.g. `if nrf.update() and nrf.pipe is not None:` (which is a bit faster than using `if nrf.any():` as some of the examples used prior to this change)
- `write()` returns a boolean describing if the payload was written to the TX FIFO
- new `master_fifo()` function in the stream example to compare with original `master()` function.
- `master_fifo()` uses the `write()` function to utilize all 3 levels of the TX FIFO. This function can provide some additional incite as to how many failed transmissions get retried when using `send(buf, force_retry=2)` in the original `master()` function.
- `master()` still uses the `send()` function, but only manages 1 level of the TX FIFO (as it always has).
- I got tired of changing the addresses in the `2arduino_handling_data.py` example, so I mirrored the use of the `radioNumber` boolean variable from the TMRh20 library's `GettingStarted_HandlingData.ino` example. I also adjusted some function calls in this example script to show how this library behaves a little differently internally (as compared to the TMRh20 library); these adjustments now closely match the behavior of the TMRh20 library's behavior.
- As always, I found more errors in the docs; this time it was about what `fifo()` returned when the `check_empty` parameter isn't specified. There were some insignificant typos too.

This release's revised stream test seems to have most significant performance differences on the Raspberry Pi. The following is my test result on the RPi2:
python
>>> from nrf24l01_stream_test import *
nRF24L01 Stream test
Run slave() on receiver
Run master() on transmitter to use 1 level of the TX FIFO
Run master_fifo() on transmitter to use all 3 levels of the TX FIFO.
>>> master()
Transmission took 1630.3276280164719 ms
successfully sent 100.0% (32/32)
>>> master_fifo()
Transmission took 1002.7778159976006 ms with 20 failures detected.

HINT: Try playing with the 'ard' and 'arc' attributes to reduce the number of
failures detected. Tests were better with these attributes at higher values, but
notice the transmission time differences.
>>> max out the auto-retransmit feature's attributes
>>> nrf.arc = 15
>>> nrf.ard = 4000
>>> master_fifo()
Transmission took 990.8866219520569 ms with 0 failures detected. You Win!
>>> master()
Transmission took 1595.034959077835 ms
successfully sent 100.0% (32/32)

1.2.2

Thanks to [generous testing done by jerryneedell](https://github.com/floe/BTLE/issues/3#issuecomment-706079635), This release clears up some confusion/misconception I had about what PDU type to use in the BLE advertisements.

original misconception
PDU type `0x40` only worked for iPhone, and PDU type `0x42` only worked for Android. Thus the `FakeBLE.to_iphone` attribute would act in accordance with this misconception.

correct implementation
PDU type `0x40` does _not_ work for Android, but it does work for iPhone. PDU type `0x42` works for both iPhone and Android smartphones.

Changes
- The `FakeBLE.to_iphone` attribute is now `FakeBLE.to_android`.
- The default value for the `FakeBLE.to_android` attribute is `True`. This means BLE advertisements use PDU type `0x42` by default which targets both iPhone & Android smartphones.
- removed any use of the old `FakeBLE.to_iphone` attribute from the `nrf24l01_fake_ble_test.py` example.
- Updated the docs accordingly
- Marked the new `FakeBLE.to_android` attribute for deprecation (on next major release) as it is no longer necessary to specify which BLE advertising PDU type to use.

1.2.1

This release is mostly a documentation revision since Nordic's Multiceiver<sup>TM</sup> was always unofficially supported anyway. Now its official.
- added example of Multiceiver<sup>TM</sup> (up to 6 nRF24L01 TX-ing to 1 RX nRF2401)
- uses ACK payloads for any nRF24L01 acting as `node(1)`
- ACK packets have no ACK payload for any other nRF24L01 that isn't acting as `node(1)`
- examples are getting numerous. They are now organized into 3 categories (in the Table of Contents):
- nRF24L01 features
- Library Features
- OTA compatibility
- any exception thrown about specifying an invalid data pipe number is now an `IndexError` (was previously a mix of `IndexError` and `ValueError` exceptions)

1.2.0

Import statements have changed with the addition of a couple new modules
See the examples for the proper expected usage. WARNING: examples from older versions are NOT compatible with this version because of this fundamental change (`__init__.py` file is blank now).

New Modules
- A lite version (`rf24_lite.py`) has been introduced for boards with limited available memory (e.g. ATSAMD21 core M0 based boards). Although, using TMRh20's Arduino/PlatformIO library is still highly recommended (especially for complex applications) as CircuitPython leaves little room for user-space code in this scenario. This lite version may not remain in the next release, so consider it experimental. Info about what was stripped away can be found in the docs (main difference is no context manager compatibility in the lite version). 10
- A new module named `fake_ble.py` has been added to implement using the nRF24L01+ as a fake BLE advertising beacon. Docs have been updated to include an example and describe the [additional API](https://circuitpython-nrf24l01.readthedocs.io/en/latest/ble_api.html#) including battery level, URL, and temperature measurement service data helper classes. `FakeBLE` class allows advertising a device `name`, the nRF24L01's `pa_level` as "TX power level", custom `mac` address, & a `to_iphone` flag to aim advertisements at different smartphones. This new `fake_ble.py` module is NOT compatible with the `rf24_lite.py` module.

Optimizations:
- Constructor now only takes required parameters (spi, csn, & ce objects). This saves storage space and de-clutters the docs a bit. Notice there are setters for all attributes that were affected by all previously available kwargs to constructor. Per 15 the constructor also takes an optional kwarg `spi_frequency` to customize the frequency used for SPI transactions. However the SPI frequency cannot be changed after instantiating the RF24 or FakeBLE objects.
- `send()` has been re-written. It now employs recursion when passing a list/tuple of payloads. Payload format checking now relies on internal `write()` call. `send()` no longer calculates a timeout, rather it blocks until a status flag is asserted by the ESB protocol from the nRF24L01 (application will only hang if there is a SPI bus malfunction). `send()` now only returns `False` or `True`; it can still return an ACK payload, but empty ACK payloads will show as `True` (not `None`). NEW `send_only` parameter to disable automatic fetching of ACK payloads when calling `send()` or `resend()` (this parameter defaults to `False` for backward compatibility).
- Docs have been more adequately indexed in the sidebar navigation.
- Fixed an issue where `any()` may have been returning incorrect data in some cases. This seemed to affect `recv()` also because it calls `any()` to get the RX'd payload length.
- `recv()` now takes an optional parameter, `length`, that can manually specify how many bytes to read from the RX FIFO. Notice every attempt to read from the RX FIFO starts with the first byte (if available) in the top level of the RX FIFO. A payload is only removed when it is completely read from the RX FIFO.
- If `length` is greater than payload in top level, then data from next available payload(s) is returned.
- If `length` is greater than last available payload in RX FIFO, then the returned buffer is padded with the last byte in payload and payload is removed from FIFO. Also, the last byte read from RX FIFO is repeatedly returned when reading from an empty RX FIFO.
- If `length` is less than payload in top level, the payload will remain in RX FIFO.
- Doc strings split. Source code now only contains a brief description of functions/attributes (for quick usage of python's builtin `help()`). Detailed info on function parameters and attributes now live in online documentation. This reduced the size of source code stored on CIRCUITPY drive by more than 50% (84 kB -> 30 kB when using rf24.py -- rf24.mpy compiles to less than 20 kB).
- Switched to Github actions instead of using travisCI.
- Tested compatible with STM32F405 Feather (requires CircuitPython v6.x). Thank you water5
- Removed `address_length` check on `open_rx_pipe()` & `open_tx_pipe()`. The nRF24L01 will only save up to 5 bytes for addresses assigned to pipes 0 & 1 (1 byte max for the rest of the data pipes). Furthermore, the nRF24L01 will only use the first X number of bytes (where X is specified using `address_length` attribute) when reading addresses from the respective pipe address registers during automatic packet assembly.
- `write()` now has an optional parameter called `write_only`. Use this parameter as `True` to fill the nRF24L01's TX FIFO before beginning transmissions.

Changes
- import statements now require the form `from circuitpython_nrf24l01.<module> import <object(s)>` (see examples as they have been updated accordingly).
- `read_ack()` marked for deprecation. It is currently still available until the next major release for backward compatibility with previous versions of this library. I highly recommend using `recv()` instead as it is synonymous with `read_ack()`
- IRQ attributes' names are now pythonic. `irq_DS` is now `irq_ds`, `irq_DF` is now `irq_df`, `irq_DR` is now `irq_dr`.
- Context manager now powers down the nRF24L01 when exiting a with statement block. Context manager also now persists pipe addresses (both RX & TX).
- `pipe()` is now a read-only attribute with same name (`RF24.pipe`)
- RX & TX addresses can be fetched using the new `address()` function (read-only; see docs for more info).
- Expanded info about data pipes in `what_happened(True)` to show expected `payload_length` setting for static payloads (when `dynamic_payloads` are disabled) only on open pipes.
- Fixed typo in examples and readme about what MCU pin to connect to the nRF24L01's IRQ pin. Thank you jerryneedell
- Removed the `reset` parameter from `close_rx_pipe()`. It doesn't matter what the address for a data pipe is if that data pipe is closed. Error in v1.1.2 docs: addresses for data pipes _do_ reset to factory defaults on nRF24L01 boot (when VCC goes from 0V to 3.3V).
- NEW `rpd` attribute (read-only) for advanced usage. This can be used to detect interference or a carrier wave on a specific channel. Docs contain link to datasheet for more detail.
- NEW `start_carrier_wave()` and `stop_carrier_wave()` functions to verify the nRF24L01 TX output is functioning. This a hardware test only. The carrier wave can be detected with another nRF24l01 `listen`ing for a `rpd` flag (example code in API docs).
- `pa_level` now accepts list or tuple in addition to original functionality to compensate for the peculiar LNA_HUCRR bit used by nRF24L01 (non-plus variant) and the Si24R1 (cheap nRF24L01 clone).
- NEW `is_plus_variant` attribute to determine if the nRF24L01 is a plus variant module or an older non-plus variant module. This attribute is also used internally to accommodate the difference in expected behaviors among the 2 variants.
- `dynamic_payloads`, `auto_ack`, & `payload_length` all now take an optional tuple or list of parameters to control the respective features on a per pipe basis. A `payload_length` of 0 means that pipe remains unaffected. Setting a pipe's `auto_ack` or `dynamic_payload` feature to a negative number means that pipe will remain unaffected.
- The interrupt pin example has been re-written to show how to use the `write()` function properly in conjunction with the nRF24L01's IRQ pin (while also using the nRF24L01's `ack` payloads feature). Notice that this example runs extremely quick as there are no unnecessary `time.sleep()` calls.

Page 2 of 3

© 2024 Safety CLI Cybersecurity Inc. All Rights Reserved.