Skip to content
zaneshreve edited this page Mar 16, 2017 · 13 revisions

nRF24L01+

About the Chip

RF24

The nRF24L01+ is a fairly inexpensive chip (~$1 for a breakout module) that possesses the capabilities to communicate as both a radio frequency receiver and transmitter. As a breakout module, the RF24 operates at a working voltage of 3.3 V (very important!) and uses SPI protocol to interface with microcontroller registers in a synchronous way. The module also offers an enable pin to set the mode (RX/TX) and an interrupt pin (not used in this project). To see how the module is connected in this project, see the wiring diagrams here.

Addressable Pipes

The RF24 features 6 unique communication channels called "pipes". Each pipe has a unique 3-5 byte address, and these addresses must be explicitly stated and identical in the code for both the receiver and transmitter. Because there are 6 pipes, a total network can be created with up to 7 modules.

Packet Communication

The RF24 communicates between modules using a form of packet communication. The RF24 is different than other radio frequency communicators because it allows for its payloads to have a dynamic size. The packet communication is organized as follows:

1 Preamble byte (synchronizes the receiver)
Address bytes (3-5 bytes)
Payload length (6 bits)
Packet ID (2 bits)
No-Ack flag (1 bit)
Payload bytes (0-32 bytes)
Redundancy check (1 or 2 bytes)

The packet ID, no-ack flag, and redundancy check work together as automatic error detection between the receiver and transmitter modules, and the modules will auto-resend payloads that are not properly acknowledged.

Packet communication allows for simple, dynamic communication between a transmitter and receiver. The standards specified by the transmit module let the receiver know what sort of (and how much) data to expect, and allow it to know whether or not that data has been correctly delivered.

Library Used

In order to interface this module with the Arduino, I made use of the extensive RF24 Library, originally created by Github user maniacbug, but optimized by Github user TMRh20. TMRh20's changes to the library include the addition of an isAvailable() method that determines whether or not a receiver module has "heard" any data, and changes to the way users can define addresses, as well as general speed and power consumption improvements.

The core of the library is focused on sending and receiving data, and the methods associated with this, but another key aspect is the ability to "set up" the modules in the Arduino environment's setup() method. Modules must be assigned pipe addresses for all pipes to be used in the code (up to 6), and with TMRh20's fork of the library, these addresses can be any primitive data type. A feature of huge importance, though, is specifying the same address(es) on the receiving and transmitting side of the code. Along with specifying addresses, the modules are set up by specifying a communication channel within a chosen frequency range (both optional - a channel at 2.4 GHz is default), and calling the begin() function to "turn on" the module. Once the module is active, and before communication can begin, a pipe must be opened for writing (openWritingPipe()) on the transmit side or for reading (openReadingPipe()) on the receive side. Both of these functions accept the address of the pipe to open as an argument.

Communication is simplified with this library, as it hides all SPI communication and register adjustments behind simple methods. The methods write(), read(), and isAvailable() are all that are required once a module has been properly set up, and these are the only three methods used in the loop() function of my Arduino code. The isAvailable() function, as stated above, was added by TMRh20 and acts as a flag to determine if a receiver module has received any data. The write() and read() methods act similarly to one another, and have the same arguments. Each of these functions accept a reference to a data variable and an integer to specify that data's size. Inside of the write() and read() functions, the RF24 library uses this information to construct a communication packet based on the size of the data and the data itself as in the write() case, or prepare the module (by setting registers and alerting the receiver of what to expect) in the case of the read() function. The Arduino code passes this information along to the RF24 module via SPI communication, which is a synchronous communication protocol and is simplified by Arduino's SPI library (which is used by the RF24 library).