Arduino: Using the full potential of NRF24L01 radio modules
A New, Optimized Fork of the RF24 Radio Library: High speed data transfers and more!
Includes updates and new features for the RF24Network Library

Updated Jan 2015
  NRF24L01+ radio modules are very inexpensive, and provide a robust interface for transferring data wirelessly between devices with minimal resource and power consumption. I've been working with them more and more as time goes on, but have always struggled with some of the inner workings and limitations of the current libraries available.

After initially studying the operation of the radio modules and reviewing the details in the data sheet, I was convinced that the modules could perform much faster. Further research into the additional library forks, blog posts, and countless hours of testing revealed that the modules can be very sensitive to the timing of things. I also discovered a number of bugs and/or issues that would hinder performance and/or reliability. 

Initial testing proved very fruitful, with speeds maxing out the configured data-rate of the chip, and reliability was improved over previous iterations of the library. Over the course of the following year, the library has been further optimized and extended, with many new features, bug-fixes, and improved reliability and performance.

(See bottom of page for download links and documentation)

Taking Advantage of the Improvements:

From a user perspective, very little is changed from previous forks/libraries beyond the usage of the available() function. This is the main compatibility difference between this and the previous libraries. The available() function will always return 1 if data is available, to align the library with standard Arduino functions. From a technical perspective, the improvements are dramatic.

 Users will benefit from the improvements just by using the new library with old code, and some things not previously possible, can now be achieved. The included .ino examples have been configured to demonstrate 'standard' usage, but advanced users can still drive the chip outside the 'manufacturer recommended operation'

Additional functions have been added to aid in streaming or rapid-transmission situations, where 2 or more payloads are sent in rapid succession, or streamed at a high transfer rate. These include writeFast, writeBlocking, and txStandby. Use of these functions allow users to maximize throughput without overrunning the FIFO buffers. See the documentation for more info on usage. 

The addressing format has been extended to allow the use of 24,32 or 40-bit addresses, as well as defining and handling of addresses via byte arrays or integers.

For example, the following addresses are the same, and either format can be used:

uint64_t myAddress = 0x68524d5431LL;   ( Old Format   )
uint64_t myAddresses[] = { 0x68524d5431LL, 0x68524d5432LL};

byte myAddress[] = "1TMRh";                    ( New Format )
byte myAddress[] = {'1','T','M','R','h'};
byte myAddresses[][6] = {"1TMRh","2TMRh"};

Technical Info:
One of the primary factors in increasing efficiency was eliminating power ups and power downs from the general operation of the radio, which many of the existing forks already had identified. A power up takes 1.5ms or 1500us, where a transition from standby-I or standby-ii takes only 130us. In addition, leaving the CE pin high while data is written allows the possibility to have 0 delay if the TX FIFO buffer is kept busy, which this library makes use of via the writeFast() and writeBlocking() features.

This changes the operation of the radio a little bit, in that the radio needs to be powered up or powered down manually, instead of being powered down after every write.

The radio modules have shown to be very sensitive to the timing and order of operations, and many hours of testing and review have determined the optimal settings and order of operations to achieve the highest speed and reliability. Delays have been removed where possible, added where required, and minimized in every case.

As mentioned, the the available() and isAckPayloadAvailable() functions now simply check the FIFO buffer to see if a payload is available. This allowed simplification of the write() function, and should help to ensure that no packets are missed. Previous iterations used the interrupt flag, which can result in a number of issues.

The overall change in response is apparent when running example sketches like the GettingStarted_CallResponse sketch included with the library or the Transfer examples.

At this point, there are so many changes, bugfixes and details, it is best to see GitHub for all of the changes and technical info.

RF24Network: The standard RF24Network library has been updated to support the new changes, and a DEV version has implemented many new features like fragmentation/reassembly and multicast. This library is recommended if connecting any number of nodes, and provides addressing, routing, etc to help manage data in a network configuration. RF24Mesh is an overlay for RF24Network that provides automatic addrressing, and a dynamic topology for nodes running RF24Network and/or RF24Ethernet.

RF24Mesh: Automates addressing etc. for RF24Network and provides a seamless, self-healing network on top of all the layer 3 network features. 

RF24Ethernet adds a surprising level of reliability, consistency, and ease of use to nodes running RF24Network, by using standard TCP/IP networking. It uses a PC-connected Arduino or a Rasberry Pi as a network gateway, to allow RF24Network nodes to connect directly to web services or act as a web-server etc. Allows users to control nrf24l01 sensors or systems easily, reliably, and simply using any device with a web-browser. The API is very similar to the standard Arduino Ethernet library.  

Class documentation now available here

Testing & Results:
Testing is now fully automated, with the introduction of TCP/IP support, with standard networking tools being used to test transfer speeds and reliability. Users can easily make use of the full data-rate in no-ack mode, or half-rate if using Enhanced ShockBurst (ESB). This has allowed many improvements to related libraries like RF24Network as well as the low level RF24 radio driver.

Since the initial release, many users including previous RF24 contributors have adopted the new library and provided feedback towards further improvements.See here for a demo of the initial transfer rate testing.
The wireless audio sketch/library that inspired these improvements is now linked below. The audio library itself is limited to around 16-20khz sample rate, which produces very reasonable sound quality for voice transmission. The limitation is due to the use of interrupts for virtually every part of the library, however, this makes it very simple to configure and use. See here for the development sketch, which was used to design the library, and is capable of higher quality audio. The wireless audio portion of the TMRpcm library has been updated to allow audio streaming and multicasting directly from SD card over RF24 modules as well.

See the new store for reliable RF24 hardware and kits.

Reference Material/Libraries:

Raspberry Pi Simple Library Installer:

RF24 - Low Level Radio Driver (Generally used for device-to-device communication)
TMRh20 RF24 Fork on GitHub  - Download
RF24 Documentation 

RF24Network (Provides addressing, routing and many other features for use with multiple devices)
TMRh20 RF24Network Fork on GitHub - Download 

RF24Mesh (Dynamic 'mesh' layer for RF24Network)
RF24Mesh on GitHub - Download

RF24Ethernet (Modelled after Arduino Ethernet API - TCP/IP over RF24Network)
RF24Ethernet on Github - Download

RF24Audio (Digital Audio over RF24 radio modules)
RF24Audio Library

MySensors.org - Create user friendly sensor networks using RF24 radio modules

Alternative: RadioHead NRF24 Library - (Supports multiple radio devices)

NRF24L01 Data sheet
Original/Old RF24 Library by ManiacBug


BernhardF said...

Many thanks for your good work! Although your library is already several years old, I found it now and experimented with it with good success.

Only one problem I have: I must access the OBSERVE_TX register for some test purposes.

In forums, some people are gussing around how the function print_observe_tx should be used. But it looks like the needed value cannot reached, because the read_register function is private.

So I suggest the addition of a new function:

In RF24.h - before 'private:' :
* Get the count of lost packets since the last channel selection
* and the count of retries at the last transmission
* Both counts are packed into one byte:
* @code
* uint8_t b = getObserve_tx();
* uint8_t lost = b >> 4;
* uint8_t retr = b & 0xF;
* @endcode
* @return (count of lost packets) << 4 | (count of retries)
uint8_t getObserve_tx(void);

and in RF24.cpp:
uint8_t RF24::getObserve_tx(void)
return read_register(OBSERVE_TX);

Unknown said...

Wie kann man verhindern das eine node über eine andere geleitet wird?
Wenn ich die einzelnen Nodes schlafen lege (strom sparen) kann sie natürlich keine andere weiter leiten.Viele Grüsse Peter .
Übersetzt mit Google:
How con one prevent a node being directed over another?
If i sleep the individual nodes lake of course ,you can not forward any another.
Many greetings Peter

Encrypted Audio Comms with XIAO 52840 Sense

Encrypted Audio Comms with XIAO 52840 Sense The beginnings of wireless audio comms I've been playing around with the NRF52840 boards I h...