How nRF24L01+ Wireless Module Works & Interface with Arduino

Being able to have two or more Arduinos communicate with each other wirelessly, opens up many possibilities such as remotely monitoring sensor data, controlling robots, home automation, etc.

And when it comes to an affordable but reliable 2-way RF solution, none does a better job than the nRF24L01+ transceiver module from Nordic Semiconductor.

The nRF24L01+ module can often be obtained online for less than two dollars, making it one of the most affordable data communication options you can find.

And the best part is that these modules are very small, allowing you to incorporate a wireless interface into almost any project.

Hardware Overview

Radio Frequency

The nRF24L01+ module is designed to operate in 2.4 GHz worldwide ISM frequency band and uses GFSK modulation for data transmission. The data transfer rate is configurable and can be one of 250kbps, 1Mbps and 2Mbps.

The 2.4 GHz band is one of the Industrial, Scientific, and Medical (ISM) bands internationally reserved for unlicensed low power devices. Devices such as cordless phones, Bluetooth devices, Near Field Communication (NFC) devices, and wireless computer networks (WiFi) all use ISM frequencies.

Power

The module’s operating voltage ranges from 1.9 to 3.6V, but the good news is that the logic pins are 5-volt tolerant, so you can use it with your favorite 3.3V or 5V microcontroller without worry.

The module supports programmable output power i.e. 0 dBm, -6 dBm, -12 dBm or -18 dBm. At 0 dBm the module consumes only 12 mA during transmission which is less than the consumption of a single LED.

And the best part is that it consumes 26 µA in standby mode and 900 nA in power down mode. That’s why it’s a go-to wireless device for low-power applications.

SPI Interface

The nRF24L01+ communicates over a 4-pin SPI (Serial Peripheral Interface) with a maximum data rate of 10Mbps.

All parameters such as frequency channel (125 selectable channels), output power (0 dBm, -6 dBm, -12 dBm or -18 dBm), and data rate (250kbps, 1Mbps, or 2Mbps) can be configured through the SPI interface.

The SPI bus uses the concept of a master and a slave. In most of our projects the Arduino is the master and the nRF24L01+ module is the slave.

Unlike the I2C bus, the SPI bus has a limited number of slaves. That’s why you can use up to two SPI slaves i.e. two nRF24L01+ modules on one Arduino.

Technical Specifications

Here are complete specifications:

Frequency Range2.4 GHz ISM Band
Maximum Air Data Rate2 Mb/s
Modulation FormatGFSK
Max. Output Power0 dBm
Operating Supply Voltage1.9 V to 3.6 V
Max. Operating Current13.5mA
Min. Current(Standby Mode)26µA
Logic Inputs5V Tolerant
Communication Range800+ m (line of sight)

For more details, please refer below datasheet.

nRF24L01+ module -vs- nRF24L01+ PA/LNA module

There are different types of modules available based on the nRF24L01+ chip. Below are the two most popular versions.

nRF24L01+ Wireless Transceiver Module
nRF24L01+ Wireless Module

The first version uses an on-board antenna allowing a more compact version of the breakout. However a smaller antenna also means a shorter transmission range.

With this version you will be able to communicate over a distance of 100 meters. Of course that is outdoors in an open space. Its range becomes a bit weak inside the house especially due to the walls.

nRF24L01+ PA LNA External Antenna Wireless Transceiver Module
nRF24L01+ PA LNA Wireless Transceiver Module with External Antenna

The second version comes with an SMA connector and a duck-antenna but that’s not the only difference. It comes with a special RFX2401C range extender chip that integrates PA, LNA and transmit-receive switching circuitry. This chip helps the module to achieve a much larger transmission range of up to 1000 meters.

Both modules are drop-in compatible except for this difference. Meaning, if you build your project with one you can simply unplug it and use the other without making any changes to the system.

What is PA and LNA?

PA stands for Power Amplifier. It only amplifies the signal strength being transmitted from the nRF24L01+ chip. Whereas LNA stands for Low-Noise Amplifier whose function is to take an extremely weak signal from the antenna (usually below microvolts or -100 dBm) and amplify it to a more useful level (usually around 0.5 to 1 V).

nRF24L01+ RF PA LNA Power Amplifier Low Noise Amplifier Block Diagram
nRF24L01+ PA/LNA Block Diagram

The low-noise amplifier (LNA) of the receive path and the power amplifier (PA) of the transmit path connect to the antenna through a duplexer, which isolates the two signals and prevents the relatively powerful PA output from overloading the sensitive LNA input. For more information read this article on digikey.com

How nRF24L01+ module works?

RF Channel Frequency

The nRF24L01+ module transmits and receives data on a certain frequency called a channel. For two or more modules to communicate with each other, they must be on the same channel. This channel can be any frequency in the 2.4 GHz ISM band, or to be more precise, it can be between 2.400 to 2.525 GHz (2400 to 2525 MHz).

Each channel takes up a bandwidth of less than 1MHz. This gives us 125 possible channels with 1MHz spacing.

This means the nRF24L01+ can use 125 different channels, allowing you to create a network of 125 independently working modems in one place.

nRF24L01+ Wireless Transceiver 2.4GHz 125 RF Channels 1MHz Spacing

The channel takes up a bandwidth of less than 1MHz at 250kbps and 1Mbps air data rate. However at a 2 Mbps air data rate, 2MHz of bandwidth is required (greater than the resolution of the RF channel frequency setting). So in 2 Mbps mode you should keep a gap of 2MHz between the two channels to ensure non-overlapping channels and reduce cross-talk.

The RF channel frequency of your selected channel is determined according to the following formula:

Freq(Selected) = 2400 + CH(Selected)

For example if you select 108 as your channel for data transmission, the RF channel frequency of your channel will be 2508 MHz (2400 + 108).

nRF24L01+ Multiceiver Network

The nRF24L01+ has a feature called Multiceiver. It is an abbreviation for Multiple Transmitter Single Receiver.

In a multiceiver network each RF channel is logically divided into 6 parallel data channels called data pipes. In other words, the data pipe is one of six logical channels in a single physical RF channel. Each data pipe has its own unique address called a data pipe address. Only one data pipe can receive a packet at a time.

A multiceiver network can be depicted as below.

nRF24L01+ Wireless Multiceiver Network Multiple Transmitters Single Receiver
nRF24L01+ Multiceiver Network – Multiple Transmitters Single Receiver

To understand multiserver network imagine that the primary receiver is acting as a hub receiver that collects information from 6 different transmitter nodes simultaneously. The hub receiver can stop listening at any time and act as a transmitter.

Enhanced ShockBurst Protocol

The nRF24L01+ uses a packet structure known as Enhanced ShockBurst. This simple packet structure is divided into 5 different fields as you can see below.

nRF24L01+ Wireless Transceiver Enhanced ShockBurst Packet Structure
nRF24L01+ Enhanced ShockBurst Packet Structure

The original shockburst structure only included Preamble, Address, Payload and the Cyclic Redundancy Check (CRC) fields. Enhanced Shockburst brought more functionality for more advanced communications using the newly introduced Packet Control Field (PCF).

This new structure is great for several reasons.

  • Firstly, it allows variable length payloads with a payload length specifier, meaning that payloads can vary from 1 to 32 bytes.
  • Secondly, it assigns a packet ID to each sent packet, which allows the receiving device to determine whether a message is new or has been retransmitted.
  • Lastly, and most importantly, each message can request the receiver to send an acknowledgment after receiving the message.

nRF24L01+ Automatic Packet Handling

Let us discuss three scenarios to get a better understanding of how the two nRF24L01+ modules interact with each other.

  • Transaction with an acknowledgment:

    This is an example of a positive scenario. Here the transmitter initiates the communication by sending a data packet to the receiver. Once the packet is transmitted, it waits approximately 130 µs to receive the acknowledgment packet (ACK packet). When the receiver receives the packet it sends the ACK packet to the transmitter. The transaction ends when the transmitter receives the ACK packet.

    nRF24L01+ Transceiver Working Packet Transmission
  • Transaction with a lost data packet:

    This is a negative scenario where retransmission is required due to the loss of the transmitted packet. After the packet is transmitted, the transmitter waits to receive the ACK packet.

    If the transmitter does not receive it within the auto-retransmit-delay (ARD) time it retransmits the packet. When the receiver receives the retransmitted packet, it transmits the ACK packet thereby terminating the transaction.

    nRF24L01+ Transceiver Working Packet Transmission Data Lost
  • Transaction with a lost acknowledgment:

    This is again a negative scenario where retransmission is required due to loss of ACK packets. Here even though the receiver has received the packet in the first attempt itself, due to the loss of the ACK packet, the transmitter thinks that the receiver has not received the packet.

    So after the Auto-Retransmit-Delay timeout, the transmitter retransmits the packet. Now when the receiver receives the packet with the same ID as before, it discards it and sends the ACK packet again. The transaction ends when the transmitter receives the ACK packet.

    nRF24L01+ Transceiver Working Packet Transmission Acknowledgement Lost

This entire packet handling is done automatically by the nRF24L01+ chip without the involvement of the microcontroller.

nRF24L01+ Module Pinout

Let’s take a look at the pinouts of both versions of the nRF24L01+ module.

Pinout nRF24L01+ Wireless Transceiver Module
Pinout nRF24L01+ PA LNA External Antenna Wireless Transceiver Module

GND is the ground pin. It is marked with a square to identify it from the other pins.

VCC supplies power to the module. It can be anywhere from 1.9 to 3.9 volts. You can connect it to the 3.3V output from your Arduino. Remember that connecting this to the 5V pin will probably destroy your nRF24L01+ module!

CE (Chip Enable) is an active-high pin. When selected, the nRF24L01 will either transmit or receive, depending on which mode it is currently in.

CSN (Chip Select Not) is an active-low pin and is normally kept HIGH. When this pin goes low, the nRF24L01 starts listening on its SPI port for data and processes it accordingly.

SCK (Serial Clock) accepts clock pulses provided by the SPI bus master.

MOSI (Master Out Slave In) is the SPI input to the nRF24L01.

MISO (Master In Slave Out) is the SPI output from the nRF24L01.

IRQ is an interrupt pin that can alert the master when new data is available to process.

Wiring a nRF24L01+ module to an Arduino

Now that we have a complete understanding of how the nRF24L01+ module works we can start connecting it to our Arduino!

To start, connect the VCC pin on the module to 3.3V and the GND pin to ground on the Arduino. Pins CSN and CE can be connected to any digital pin on the Arduino. In our case, these are connected to digital pins #8 and #9 respectively. Now we are left with the pins that are used for SPI communication.

Since the nRF24L01+ module requires a lot of data transfer, it will give the best performance when connected to the hardware SPI pins on the microcontroller.

Note that each Arduino board has different SPI pins that must be connected accordingly. Check the table below for quick understanding.

MOSIMISOSCK
Arduino Uno111213
Arduino Nano111213
Arduino Mega515052

If you are using a different Arduino than the boards mentioned above, please check the Arduino’s official documentation before proceeding.

Arduino Wiring Fritzing Connections with nRF24L01+ Wireless Transceiver Module
Wiring nRF24L01+ Wireless Transceiver Module to Arduino UNO
Arduino Wiring Fritzing Connections with nRF24L01+ PA LNA External Antenna Wireless Module
Wiring nRF24L01+ PA LNA Wireless Module to Arduino UNO

Remember you need to make two such circuits. One will act as transmitter and the other as receiver. Both have the same wiring.

Once you have connected everything you are ready to go!

Library Installation

Interfacing a nRF24L01+ module is a lot of work but luckily there are many libraries available to us. One of the popular libraries is RF24. This library has been around for many years. It’s easy to use for beginners, but still offers a lot for advanced users. This is the library we will use in our examples.

This library is not included in the Arduino IDE, so you will need to install it first.

To install the library navigate to Sketch > Include Libraries > Manage Libraries… Wait for Library Manager to download the library index and update the list of installed libraries.

manage libraries

Filter your search by typing ‘rf24‘. Look for the library by TmRh20. Click on that entry, and then select Install.

rf24 library installation

Arduino Example Code – For Transmitter

Here is the code we will be using for our transmitter. It will simply send a traditional ‘Hello World‘ message to the receiver.

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
  radio.begin();
  
  //set the address
  radio.openWritingPipe(address);
  
  //Set module as transmitter
  radio.stopListening();
}
void loop()
{
  //Send message to receiver
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  
  delay(1000);
}

Code Explanation

The sketch starts by including the required libraries. The SPI.h library handles the SPI communication while the nRF24L01.h and RF24.h control the module.

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

Next we create an RF24 object. The constructor of this object accepts two pin numbers as arguments to which the CE and CSN signals are connected.

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

Next we create a byte array that will represent the pipe address through which the two nRF24L01+ modules will communicate.

//address through which two modules communicate.
const byte address[6] = "00001";

The pipe address does not have to be “00001”, it can be any 5-character string such as “node1” as long as the transmitter and receiver both use the same address.

If you have few modules in your network, you can select a particular module and communicate with it with the help of pipe address.

In the setup section we first call the begin() function to initialize the radio object and then the openWritingPipe() function to set the transmitter address.

radio.begin();

//set the address
radio.openWritingPipe(address);

Finally we set the module as transmitter using stopListening() function.

//Set module as transmitter
radio.stopListening();

In the loop section, first we create an array of characters and assign the message “Hello World” to it.

We send that message to the receiver by using write() function. This function accepts two arguments, first the message you want to send and second the number of bytes it contains.

const char text[] = "Hello World";
radio.write(&text, sizeof(text));

Note that you can send messages up to 32 bytes at a time, as this is the maximum size of a packet that the nRF24L01+ can handle.

If you need confirmation that the receiver has received the data, the method write() returns a bool value. It returns TRUE when the data reaches the receiver or it returns FALSE if the data is lost.

Note that the write() function blocks the program until it receives the acknowledgment or runs out of all attempts of retransmission.

Arduino Example Code – For Receiver

Here is the sketch we will be using for our receiver.

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

//create an RF24 object
RF24 radio(9, 8);  // CE, CSN

//address through which two modules communicate.
const byte address[6] = "00001";

void setup()
{
  while (!Serial);
    Serial.begin(9600);
  
  radio.begin();
  
  //set the address
  radio.openReadingPipe(0, address);
  
  //Set module as receiver
  radio.startListening();
}

void loop()
{
  //Read the data if available in buffer
  if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

Code Explanation

This code is very similar to the transmitter’s code except for a few changes.

At the beginning of the setup function we initiate the serial communication. After that using openReadingPipe() function we set the same address as transmitter. In this way we enable communication between transmitter and receiver.

  //set the address
  radio.openReadingPipe(0, address);

The first argument to the openReadingPipe() function is the number of the stream. We only created the address for stream #0, however you can create up to six streams responding to different addresses. The second argument is the address to which the stream will react to collect data.

The next step is to set up the module as a receiver and start receiving data. To do this we use the startListening() function. From this moment the modem starts waiting for data sent to the specified address.

//Set module as receiver
  radio.startListening();

The code in the loop section checks whether any data has been reached at the address using the available() method. This method returns TRUE when there is data available in the buffer.

if (radio.available())
  {
    char text[32] = {0};
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }

When data is available, an array of 32 characters filled with zeros is created. Then we use the read(& text, sizeof (text)) method to read the data from the buffer and store it in our character array.

Finally we print the received message on the serial monitor. If everything is fine you should see something like this in your serial monitor.

nRF24L01+ Transceiver RF24 Library Sketch Output on Serial Monitor
nRF24L01+ Transceiver Output on Serial Monitor

Ways to Improve the Range of the nRF24L01+ Module

A key parameter for a wireless communication system is the communication range. In many cases this is the deciding factor for choosing an RF solution. So let’s discuss what we can do to get a better range for our module.

Reduce Power Supply Noise

An RF circuit that generates a radio frequency (RF) signal is very sensitive to power supply noise. If not controlled, power supply noise can significantly reduce the range you can achieve.

Unless the power source is a stand-alone battery, there is a good chance that there is noise associated with the power output. To prevent this noise from entering the system, it is advisable to place a 10 µf filter capacitor across the power supply line as physically close to the nRF24L01+ module as possible.

The easiest way to get rid of it is to use a very inexpensive adapter for the nRF24L01+ module.

nRF24L01+ 5V Power Adapter
nRF24L01+ Adapter

This adapter has an 8-pin female connector that allows you to plug your nRF24L01+ module in. It can accommodate both versions of the nRF24L01+ module we discussed earlier – one with an integrated antenna and the other with an external antenna (PA/LNA).

It also has a 6-pin male connector for SPI and interrupt connections, and a 2-pin connector for power input.

The adapter has its own 3.3V voltage regulator and filter capacitors, so you can power it with a 5V power supply without worry.

Change Channel Frequency

Another potential source of noise for RF circuits is the external environment, especially if you have neighboring networks set on the same channel.

Since WiFi mostly uses the lower frequency channels, it is recommended to use the highest 25 channels of your nRF24L01+ to prevent these signals from causing problems.

Use a Lower Data Rate

nRF24L01+ offers highest receiver sensitivity at 250Kbps speed which is -94dBm. At a 2MBps data rate, however, receiver sensitivity drops to -82dBm. Meaning at 250kbps the receiver is about 10 times more sensitive than at 2Mbps. In other words at 250kbps the receiver can decode 10 times weaker signal.

So reducing the data rate can significantly improve the range you can achieve. Plus a speed of 250kbps is more than enough for most of our projects.

What does Receiver (Rx) sensitivity mean?

Receiver sensitivity is the minimum power level at which the receiver can detect an RF signal. The larger the absolute value of a negative number, the better the sensitivity of the receiver. For example a receiver sensitivity of −94dBm is better than a receiver sensitivity of −82dBm by 12dB.

Use of Higher Output Power

Setting the maximum output power can also improve the communication range. The nRF24L01+ lets you choose from different output power options such as 0dBm, -6dBm, -12dBm or -18dBm. Selecting 0dBm output power sends stronger signals into the air at the cost of higher power consumption.