RF24Ethernet - For DIY Internet of Things and Home Sensor Networks
Adding internet connectivity to RF24Networks using nrf24l01+ modules as ethernet cards

RF24Ethernet, What is it and how does it work?

For anybody not familiar with my blog, I have done a lot of recent work in improving the radio driver and related network library for NRF24L01+ radio modules, using Arduino and Raspberry Pi or using two or more Arduinos. These very inexpensive and feature-rich devices can be used to create your own home sensor network, with very little cost when compared to most available solutions.

RF24Ethernet will allow you to use a Raspberry Pi or Arduino as the 'gateway' machine to your network, and lets you connect to your sensors directly, using any device that has a web-browser, whether it is an iPod, PC, etc. or your sensors can connect out to the internet for information.

Current Libraries:
RF24 - OSI Layer 2 radio driver for nrf24l01+ modules
RF24Network - OSI Layer 3 network driver for RF24
RF24Ethernet - OSI Layer 4 Protocol (TCP/IP) driver for RF24Network
RF24Mesh - Mesh networking layer for RF24Network (Dynamic config and topology)

How it works: (Updated)

The RF24Ethernet library is currently in the testing phase, and uses the UIP TCP/IP stack.
The library has been modelled after the Arduino Ethernet library, allowing users to create web enabled, wireless devices, without having to learn the RF24 or RF24Network APIs. The addition of a real protocol (TCP) on top of RF24Network provides a level of simplicity, consistency and reliability beyond what was previously possible.

The IP address of each node needs to be statically assigned. Translation between RF24/RF24Network (MAC) addresses and IP addresses is handled in one of two ways, depending on the configuration. The default configuration uses ARP requests to find the correct node when TCP data is incoming, and users can optionally utilize RF24Mesh to provide MAC/IP translation and/or dynamic address assignment at the network layer.

Configuration/Testing: (Updated)

Configuration is now integrated directly into RF24Ethernet, with the RF24Network address specified as the MAC address, and this can be further automated by utilizing the RF24Mesh layer along with RF24Ethernet. Users have the option of creating a static network, or utilizing RF24Mesh to create a dynamic network with nodes capable of moving around physically or utilizing fail-over nodes. The RF24toTUN application running on a Raspberry Pi automatically performs discovery and routing for incoming TCP/IP data, so users only have to configure static IP addresses, and a unique identifier for each node when used with RF24Mesh.

Setup (Arduino & RPi):
  Install RF24, RF24Network, RF24Mesh & RF24toTUN libraries
  Note: RF24toTUN requires the boost libraries. Run sudo apt-get install libboost1.50-all 
  a: wget
  b: chmod +x
  c: ./  (Note: This should be run without sudo or all your base files will belong to root)
 a:  Install RF24 lib
  c: Install RF24Ethernet library
  d: If using with a RPi, run any of the Getting_Started examples. You should be able to ping and connect to the remote Arduino.
  e: If using with a SLIP interface (non-RPi) :
      1. Run the  SLIP_Gateway.ino example on the Arduino connected to the PC/MAC etc
      2. Run the SLIP_InteractiveServer.ino example on another Arduino.
      3. Once the SLIP interface is configured as per the examples, you should be able to ping and connect to the remote Arduino.

 RF24Ethernet - Setup, config and demo
The initial proof of concept interface borrowed directly from the SerialIP library, using the uIP TCP/IP stack and uIP proto-sockets/proto-threads. Since testing was very succesful, the library has been developed to provide a simpler user interface, very similar to the Arduino Ethernet library. In its current form, a node running RF24Ethernet can act as a standard TCP server, and can function as a telnet or web server, by modifying the included example.

How can this be used?

The possibilities from here are virtually endless, with very inexpensive sensor networks being provided with direct TCP/IP connectivity. One of the more obvious applications involves simple retrieval of information from network or internet sources, such as the time or the current weather. Controlling a connected LED or other attached device can be as simple as opening a bookmark in your browser.
To take things a whole lot further, this could even allow RF24Network to be utilized as a bridge betwen LANs, using sensor networks for emergency commuinications etc, when main connections are down. Testing shows that speeds  across the network are slightly better than or equivalent to a dial-up connection, so it seems to provide a practical solution for low-speed data transfers like sensor data, text-based email or chat.

Results of Testing:

The above picture presents an idea of the latency, etc when sending ping requests of varying sizes from the RPi master node to a connected sensor node.

Documentation/Further Development?
See for available documentation.

Update Nov24:
Working with UIP TCP/IP stack has been a bit of a challenge to say the least, but things seem to be coming along nicely. The RF24toTUN library has been updated to route payloads according to the radio MAC address, so integration with RF24Network is coming along nicely. Support for the RPi to send fragmented multicast payloads has been added, so ARP requests are working nicely within RF24Network. This will allow full integration with RF24Mesh, to create a dynamic TCP/IP mesh sensor network if desired, with very little to no configuration needed by the user. I've commited the current code to a new branch (master_dev) to hold the new code until it is cleaned up and more functionality is added. Currently, it only supports incoming data connections as a simple server, and ICMP packets.

Update Nov30:
The Server and Client API to match the official Ethernet library is now in place and working for the most part. DHCP, DNS lookups and UDP in generall is not developed yet. There are still some bugs and oddities to work out, but overall, the TCP server and client seem to perform fairly well given the circumstances. Web client and server examples have been included.

Update Dec 7:
The library seems to be working very well now, and the API is about 95% complete. Most bugs have been addressed, with only a few minor issues left, generally surrounding timeouts during very large data transfers. The existing examples have been updated, and some new examples have been added, demonstrating a simple web server and interaction with a sensor node via a web browser. Some documentation has also been created and is linked below.

Update Dec9:
RF24Mesh has been integrated with RF24toTUN, to provide automated addressing and mesh support for RF24Ethernet. When building RF24toTUN, use 'sudo make install MESH=1' to compile with RF24Mesh support. If using with RF24Ethernet, see the new SimpleServer_Mesh.ino example for usage. An install script has also been created for RPi, to simplify installation of the various libraries.

Update Dec 14:
Updated RF24Ethernet to support SLIP or TUN devices as well. This requires RF24Mesh to perform MAC/IP translation. Two new examples have been added, SLIP_Gateway.ino demonstrates how an Arduino can act as a simple USB interface to any device that supports SLIP. SLIP_InteractiveServer demonstrates how to use RF24Ethernet and RF24Mesh with a SLIP or TUN interface.

Update Dec 28:
Modified the MAC address format due to issues with standards when using it on RPi/Linux. Modified the timing of uip restarts. Updated RF24toTUN to provide cmd line configuration for all major options including node addressing. Fixes and updates to RF24Network and RF24toTUN seem to have addressed some buggy behaviour.

Update Dec 30:
Todays latest updates should be applied along with the latest updates to RF24toTUN and RF24Network. The main change fixes corrupt client requests, which would have been noticed when establishing outgoing connections. The remaining changes revolve around reliability, the order of operations, and the timing of things, and seem to really bring RF24Ethernet closer to a stable, reliable library. 
Update Jan 2, 2015
This round of updates comes after a very long round of testing and coding. The RF24 library has been updated to provide even better timing, reliability and throughput. Changes to RF24Network improve fragmentation/reassembly. RF24toTUN has been updated to fully support all 3 datarates, and throughput has been improved for all speeds. RF24Ethernet has been updated to provide a timeout for connections, part of better handling for TCP window reopening and failures, and allows users to configure the periodic timer via uip-conf.h to provide faster transfers. These changes bring RF24Ethernet a lot closer to a stable release. Testing shows that these updates provide easily noticeable increases in reliability and speed at all levels, and updating all the mentioned libraries is recommended.

Update Jan 4, 2015
Added connection timeouts to recover from hangs during failed client donwloads, which adds improved reliability to the library. Added better TCP window management to prevent those hangs during client downloads, along with configuration options. Documentation updated to include new features and options.

Update Jan 16, 2015
Updated to v1.2b - Adds UDP and DNS support along with a pile of fixes and updates. Users should update RF24Network and RF24toTUN along with RF24Ethernet. This will be the final update to this blog post. See the documenation below or check back here at for additional posts.

See for all related code/library downloads, and for available documentation.


RF24Network Arduino/RPi Library - A New Development

What is RF24Network?

It is a library built upon the core RF24 driver for nrf24l01 radio modules that attempts to provide a simple interface for connecting anywhere from a few, to hundreds of wireless radio modules, connected to Arduino or Raspberry Pi devices. Uses don't need to know every detail of the radio modules in order to setup and operate a network of them. The library handles configuration, addressing, interconnections, and routing, so users can focus on creating household or long distance radio sensor networks, with data being routed automatically through the network to its intended destination.

Whats New?

I've been doing quite a bit of work on the core RF24 radio driver, including a wide range of changes and updates, and wanted to test out some of the more interesting features of the modules on a large scale. The existing network layer (originally by ManiacBug) provided a great foundation to begin, as it contained all of the required features of an RF24 radio network, and used a system of routing and addressing that is well suited to small devices like Arduino or ATTiny.
Some of the new features may seem unnecessary or overkill, and some will probably be, but others will support scenarios just not possible in the previous configuration. I've created a development repository and associated documentation that will be kept up roughly in accordance with development, since it will all take time to test fully, but it seems to work well and some of the features are pretty interesting. 

Updated 12/14:
RF24Network now supports fragmentation for all devices, including via multicasting and is enabled for all devices except ATTiny by default. The library is fairly stable at this point, and testing is ongoing with RF24Ethernet and RF24Mesh.

Updated 10/14:
Fragmentation support was recently added for the RPi and Arduino Due. Standard AVR devices (Arduino Uno etc) are able to send large, fragmented payloads, but cannot yet reassemble them. See below to enable. Usage is exactly the same, but any very long payload lengths will be accepted.

 Routing changes have been partially reverted to use a limited number of retries (auto-ack) where possible, and function similarly to the master branch, although network ACKs are still utilized.

Some defaults have been changed:
  • Multicasting is enabled by default. This limits the number of normal child nodes/parent to 4.
  • Fragmentation is totally disabled by default on AVR devices
  • Uncomment defines in RF24Network_config.h to disable/enable these options


Fragmentation and reassembly support is enabled by default, with a maximum payload size of 120 bytes. Users can configure the memory buffers, or disable fragmentation by editing the config.h file. See here for the documenation. When enabled, data is sent as usual, and the network layer manages fragmenting and reassembling the data automatically.

Addressing Formats:

The development version currently uses a different addressing format, using specific addressing chosen for use in radio transmission. See the datasheet and this blog post for more information. Users simply specify an octal address (01-05) as before for example, and the radio addresses will be configured accordingly.

Routing and Acknowledgement

Previously, payloads that were routed over one or more nodes were not acknowledged, so the transmitting radio had no way of knowing if payloads were delivered. *New: In the development version, users have the ability to specify whether or not the network will respond with an ACK, simply by choosing from a range of message types. Typical user message types of  65 through 127 will be acknowledged, and message types 1 through 64 will not be acknowledged. There are a few benefits to this arrangement, since network acks can automatically help to prevent nodes from flooding the network with traffic, and no-acks can be used when a response is desired from the recipient etc.

Direct Routing and Failovers

Network frames can now be logically addressed to one node, and sent to any other node for routing. This allows some dynamic topology, and can also be used to reduce routed traffic on a network. See the documentation links below for specifics and limitations.


A multicasting feature has also been added that allows, for example, the master node to send out a single network payload, and have it delivered to hundreds of network nodes very rapidly. Multicast relay nodes can be used to disperse messages throughout all or partial areas of the network. Multicasting is enabled by un-commenting #define RF24NetworkMulticast in the RF24Network_config.h file, since it requires additional program space and memory.

Improved Performance

Performance on the network will be similar, but users will see a much higher error rate using the development version, as it gives a real indication of success or failure of payloads. Data throughput should be increased in most cases, due to reduced retry periods, and the new routing protocol.

Additional Technical Details and Information:

Documentation for the development version can be found here, and should be kept pretty consistent with changes. It contains information specific to the new routing and delivery protocols, as well as updated class documentation for usage. 
The development repo is found here, and it can be downloaded here. Features and functions found to be stable and beneficial are likely to be merged into the master branch eventually. The development branch should be relatively stable at any given time, but is in no way guaranteed to be.

The RF24 communication stack and documentation can be found here:


Arduino AVR Timers and Waveform Generation

I've had a number of questions regarding Arduino timers and the generation of signals and waveforms, so here is (hopefully) a simple tutorial on using Arduino timers.

This tutorial requires a basic understanding of the difference between bits and bytes, along what it means to read or write bits and bytes to AVR registers.

Timers can be seen as additional components used to offload work from the processor. A timer running on its own can create a signal or waveform without any interaction from the CPU, allowing the CPU to do things like interact with the timer to modify the waveform or handle other tasks.

The most basic function of a timer is to count from 0 to a specified number, lets say 255, and then start all over again and count from 0 to 255 again. Using a standard Arduino board running at 16 million cycles/second, the timer will count from 0 to 255 at a set frequency, which can be determined using a simple calculation:

CPU Freq / TIMER TOP  =   Timer Frequency (cycles/second)
16mHz     /         255          =   62,745 cycles/second  ( 62.75kHz )

The UNO has both 8-bit timers (TIMER0, TIMER2) and a 16-bit timer (TIMER1) which can all be used to perform various functions. This means that timer0 and timer2 can handle or count in increments ranging from 0 to 255, and TIMER1 will handle values from 0 to 65,535.

Timer Parameters & How to generate a signal:

Timer TOP:
Basic timer functionality is simple, we set a TOP value, and the timer will count from 0 to TOP, then start counting at 0 again.

Timers can also be set to toggle an output or trigger an interrupt when the timer value reaches a set value. Lets say the TOP value has been set to 255, the compare value is 127, and an LED is connected to pin 9 on an Arduino UNO. The following will take place:

a: The timer will increment its value by 1 every 16-millionth of a second, starting at 0
b: The LED stays lit until the counter value reaches 127, then is turned off.
c: The LED turns back on once the counter value is reset to 0 (after reaching its defined TOP value)
d: GoTo b:

Result: This produces an approximately 50% duty cycle PWM signal at 62.75kHz

Example Code:

void setup(){

   //This sets the timer1 mode, prescaler and enables timer PWM output on Uno pin 9 (not covered in this tutorial)
    TCCR1A = _BV(WGM11) | _BV(COM1A1);
    TCCR1B = _BV(WGM13) | _BV(WGM12) | _BV(CS10);

    //This sets the TOP value, or the value that the timer will count up to before resetting to 0
    ICR1 = 255;
   // This sets the OUTPUT COMPARE value A ( Compare A for pin 9, Compare B is linked to pin 10)
   OCR1A = 127;


Changing the Duty Cycle (how long the pin output is HIGH vs LOW):

Changing the duty cycle is as simple as changing the value of the OCR1A register. Since these examples use timer1, 16-bit (0-65535) values could be used, but since the TOP value is set at 255, only those values can be used for this demonstration.

Example Code (Uses the above setup() code) :

void loop(){
    OCR1A = OCR1A + 1;
    if(OCR1A == 255){
         OCR1A = 0;

Result: The example above will increment the duty cycle by 1/255 (0.4%) every 15 milliseconds until it has reached 100%, then it will reset to 0 and continue to increment. A connected LED will be seen to get brighter and brighter until the timer compare register reaches the TOP value, and the duty cycle (OCR1A) will be reset to 0.

Changing the Frequency:

To change the frequency, simply adjust the timer TOP value in the above example code:
ICR1 = 30000;

Calculation:  16,000,000 / 30000 = 533.33... HZ (cycles/second)

Note: The compare register (OCR1A) can be set to any value between 0 and 30,000 in this example.


The frequency can be made lower by adjusting the prescaler. The system clock signal will be divided by the prescaler before being made available to the timer. This is not required to be understood for this tutorial.

Calculation: CPU Freq. / Pre-Scaler / TIMER TOP = frequency

Basic Theory of Creating Audio:

One of the simplest and most common forms of uncompressed audio is the WAV or PCM format. PCM stands for Pulse-Code-Modulation, which can be replicated using the Arduino timers, and the information provided above.

In the case of recording 8-bit audio, the voltage of an audio signal is converted to a number ranging from 0 to 255. The higher the voltage, the higher the number. This is done at a set frequency, say 16kHz or 16,000 times a second.

Recreating an audio signal can get fairly complicated and in-depth, but basically just needs to meet the following requirements:

1. Frequency of the timer generally should equal the frequency that the audio was sampled at (sample rate)
2. Sample values need to be fed into the timer every cycle

To create audio of 16khz sample rate, the timer needs to run at 16,000 cycles/second, and a new sample value needs to be fed into the timer every time it reaches its TOP value (every 62.5 microseconds) This generally requires the use of interrupts, which is out of the scope of this tutorial.

The above example code can be used to create simple audio tones by varying the frequency from 0 to about 10,000 hz max, and volume controlled by adjusting the duty cycle.


This overview is intended to cover very basic timer usage in Fast PWM mode via TIMER1. Additional timers, modes, details, usage, etc can be determined by referencing the datasheet, which is really the best reference for any kind of advanced timer usage. All of the timers are accessed in very similar ways, but some settings like prescaling are different between timers.

RF24Audio Library Released:
 Wireless Digital Audio Streaming and more with Arduino and NRF24L01 modules

  Its been a little while in the making, but I am finally releasing my RF24Audio library. The library offers a number of features, mainly the ability to wirelessly stream realtime data or audio captured from an analog input to one or more other devices. 'Other devices' can include Arduinos, PCs, or any other device capable of reading the data stream.
  Since the library utilizes the core RF24 radio library, advanced usage and customization can be configured, and allows interaction with audio devices in a number of different ways. The TMRpcm audio library (WAV audio from SD card) has been updated to support the RF24Audio library as well, being capable of multicasting audio to a number of devices. A demonstration of this interaction is shown in the following video:

  The library is designed to be very easy to setup and configure, just connect a radio module, microphone and speaker. External buttons are optional, and are managed internally by the library. This can be disabled to allow further customization via keypads, etc. Users can also utilize the core RF24 library to interact with the audio devices in a number of ways, including capturing audio streams and feeding the data to a PC.

  • User friendly setup and configuration: For beginners too: Just connect a radio module, microphone, and speaker. The library handles the rest.
  • Recording and broadcasting of audio to multiple devices using only Arduino, RF24 modules and input/output devices (speaker,microphone)
  • Multicast: Enables broadcasting to all nodes, single nodes, or partial groups of nodes
  • External controls: Use external buttons or code to control audio streaming
  • Volume control: Use external buttons or code to control audio volume on receiving devices.
  • Remote control: Start recording remotely via radio commands (Currently cannot stop remote recording)
  • LED Indicator/Visualization: Indicates audio playback and amplitude.
  • Customization: Using the underlying RF24 core library allows custom interaction with audio devices running this library. Receive audio data and stream it to a PC over USB, create and broadcast computer generated audio in realtime, and more! See the USB_Audio example for more info.
  • Create additional node groups: Allows nodes to join private broadcast groups, and multicast only within their group as desired

Pin Assignments:
  • Speakers: Arduino Uno,Nano,etc: pins 9,10 Arduino Mega: 11,12 (Timer pins cannot be changed, but can use 1 pin and ground)
  • pin A0: Microphone/Input pin
  • pin A1: Transmission/Recording Start pin
  • pin A2: Volume Up
  • pin A3: Volume Down
  • pin A4: Trigger remote recording (Only working with dual devices)
  • Cannot be changed: LED Pin: Uno,Nano,etc: pin 6 Mega 2560: pin 13 (main LED pin)

Library Documentation

Source Code:
RF24Audio Library
RF24 Radio Library
TMRpcm Audio Library


Testing New RF24 Arduino Library Fork for NRF24L01 Radio Modules: Comparative Testing - Transfer Rates


Per my previous blog posts, I have been working on some improvements to the RF24 radio library, and the main benefits of the changes have been realized. The following video compares the difference against the fork found at I did not compare against the main library since the gcopeland fork outperforms it quite a bit already.

The new library, source code and documentation can be found at Info in previous blog posts.

More to come...


Arduino Radio/Intercom/Wireless Audio:
Streaming Audio in Real Time using Arduino and NRF24L01

  In my last blog post, I talked about using inexpensive radio modules to transmit audio at reasonable rates using only the radio modules, a microphone or input device, and an Arduino. This started out as what I thought would be a simple project, and ended up being a WAY bigger project than I thought, since it required improving the speed of the extremely well written RF24 library for the radio modules. Although there wasn't a lot of room for improvement, from my (biased) testing, some cases show performance increases up to 25% in some situations over the fastest fork I could identify.

  I think this streaming audio code would be good in library form, but for now, the sketches I am using to develop the library are posted on GitHub Here the whole sketch folder is required. The audio is only 8-bit right now, but even that is not bad. Judging by the transfer speeds, I should be able to do 10-bit audio, but the code in 8bit was just simpler to start with. To put the quality in perspective, telephone quality could be about 8khz, 12bit, 96bps data rate, while CD quality could be said to be 44.1khz, 16bit,706k Data rate. This sketch currently does 8 to 44khz+ at 8-bit, with the possibility to go to 10-bit. Depending on the sample rate and bit rate, the user can adjust the quality according to the application.

  The sketch is simple to configure for testing, just edit the user variables defined at the top of the sketch and upload. It can then be controlled by sending 'r' to start recording/sending and 's' to stop, and '=','-' to raise or lower the volume when receiving. External buttons can also be defined in the user config section to allow users to create things like intercoms or even a portable radio or wireless headset. The audio at 10-bit will not be super high quality, but should be very reasonable for voice transmission.

Recording is simply done from an analog pin, and should work with microphones etc designed for Arduino. It currently uses the 5v voltage reference for recording.

  This sketch could be easily converted to use any transmission medium that can support the streaming data at a consistent sample rate, and the library could support multiple radio devices and more advanced hardware, but that would definitely take some time. If it does end up as a library, it will of course be published on GitHub for anyone to use or modify.

The library may work ok with the standard RF24 library or current forks, but my fork has been designed specifically for these purposes, so don't forget to install it if using the data rate/sample rate combinations shown in the example. Download Lib


10-bit Audio: I comtemplated a few different ways to include the extra two bits in the transmission, and ended up putting the main 8bits of each sample in the first 25 bytes of the payload. The remaining bit-pairs are then placed into bytes 26 to 31. This seemed like the easiest way to 'encode' and thus 'decode' the data, but it does put a bit of an extra load on the MCU. The max sample rate for 10-bit audio is about 24khz, but with 32khz it will just be 9-bit.

Multicasting: The only changes required to include multicasting involved setting all the radios to listen on the same pipe by default, and setting all radios to transmit on the same pipe when transmitting. Since only one radio should be transmitting at a time, it is pretty straightforward. This also removes the need to configure radios differently. If using the same Arduino board, all the radios can be configured exactly the same unless using remote commands, which would require some code changes.

Update 2:
See for more info. The library can be installed using the Arduino library manager.


 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 - 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

Arduino Audio: WAV Playback from SD Card  
*TMRpcm Library update*

Due to popular demand, the PCM audio library now supports 32khz sample rate audio for improved sound quality, and better performance at lower rates. Some of the notable improvements in this round of updates are documented below. See the Wiki on GitHub for usage information.

Multi Track Playback
Dual tracks can be played at once on separate pins. Limited to about 16-20kHz sample rate, see wiki page for updated usage and info.

SdFat Library Support
The library now optionally supports direct use of the SdFat library for lower program and memory usage and increased performance.

Metadata (ID3v2.3 and Info/List) Tag Support
The library now has a configurable option ( pcmConfig.h ) to handle and bypass metadata when reading audio files. It also provides limited support for retrieving song, artist and album information from audio files. Standard info (LIST) tags are supported as well as ID3 tags.

Easy WAV file generation and playback
One command to generate a standard WAV file and header, another to finalize it once data is written. Raw data from analog inputs or other sensors or information sources can be written to the file to generate digital audio that can be played on any device that supports WAV files, or easily converted to other standard formats.

Commands have been added to enable recording of WAV files to SD card. Performance is very much dependant on the write speed of SD card as well as the amount of SRAM used. Results seem to be ok with a class4 SD card.

Audio Formats and Options
The library is now capable of Stereo or pseudo 16-bit playback with a resistor ladder to a limited degree.
An option to operate using TIMER2 for compatility was added.
A function to start playback at a given number of seconds was added

Buffered SD Reads
After a bit of messing around with the standard SD library, I realized there was a buffered read that would improve the response quite a bit. It doesn't seem to be documented in the library reference, but the usage is as follows:

Normal Read:
byte buffer[32];
for(int i=0; i<32; i++){
   buffer[i] =;

Buffered Read:
byte buffer[32];
int bytesRead =*)buffer,32);

*Update*PWM 'Pop' sounds on timer start/stop
*Edit* - There seems to be differences in how the timers are engaged on different boards. The library now autoselects between the ramping methods. See pcmConfig.h to manually select.
I suspected that the typical pwm 'popping' sound could be removed by creating an appropriate ramp, and was able to remove it via the following process on the Arduino Mega.

On Startup:
1. OCR1A and OCR1B are set for opposing PWM. If both are set at 0, one will be high and one will be low.
2. Before enabling the timer, OCR1A is set to 0, OCR1B set to maximum (Timer TOP value) so that there is no power flow on startup.
3. OCR1B is then ramped down to 0, and power is applied gradually
4. OCR1A and OCR1B can now be fed with the same value, without a popping noise

Between Tracks:
1. The OCR1A register always contains the value of the last sample from the previous track, unless disabled.
2. Read OCR1A, and read the first value of the next track.
3. Ramp the value of OCR1A from its current value, to the value of the next track 

On Disable:
1. Get the current value of OCR1A/OCR1B
2. Ramp OCR1B up to maximum (Timer TOP value) from the current value
3. Ramp OCR1A down to minimum (0) from the current value

On a Nano or Duemilanove board, the process is a bit different:

On Startup:
No ramp needed, handled by track transition ramp. There will be a pop the first time PWM is enabled, and no popping thereafter if disabled or enabled.

Between Tracks: 
Same as with Mega 

On Disable:
1. Get the current value of OCR1A/OCR1B
2. Ramp both OCR1A/OCR1B down to 0 from the current value

I applied a few more tweaks to bring the performance up a bit more, mainly converting 16bit variables to 8bit where possible, and improving on details of the playback process. The quality/oversampling option now defaults to 0. The update is available on GitHub:

NRF52840 and Arduino: Encrypted and Authenticated Radio Mesh Networks

 NRF52840 and Arduino:  Encrypted and Authenticated Radio Mesh Networks In a recent post, I mentioned using the on-board encryption module o...