Introduction

Interfacing Arduino with NRF24L01

Having two or more MCU boards be able to communicate with each other wirelessly over a distance opens lots of possibilities like remotely monitoring sensor data, controlling robots, home automation and the list goes on. And when it comes down to having inexpensive yet reliable 2-way RF solutions, no one does a better job than nRF24L01+ transceiver module from Nordic Semiconductor.nRF24L01+ (plus) transceiver module can often be obtained online for less than two dollars, making it one of the most inexpensive data communication options that you can get. And best of all, these modules are super tiny, allowing you to incorporate a wireless interface into almost any project. I will also post some tutorial links where I have interfaced NRF24L01 with other microcontrollers. If you have any queries about it, ask in the comments and I will resolve it.

Hardware Introduction

Arduino UNO R3

Arduino Uno is a microcontroller board based on the ATmega328P (datasheet). It has 14 digital input/output pins (of which 6 can be used as PWM outputs), 6 analog inputs, a 16 MHz ceramic resonator (CSTCE16M0V53-R0), a USB connection, a power jack, an ICSP header and a reset button. It contains everything needed to support the microcontroller; simply connect it to a computer with a USB cable or power it with a AC-to-DC adapter or battery to get started. You can tinker with your Uno without worrying too much about doing something wrong, worst case scenario you can replace the chip for a few dollars and start over again.

“Uno” means one in Italian and was chosen to mark the release of Arduino Software (IDE) 1.0. The Uno board and version 1.0 of Arduino Software (IDE) were the reference versions of Arduino, now evolved to newer releases. The Uno board is the first in a series of USB Arduino boards, and the reference model for the Arduino platform; for an extensive list of current, past or outdated boards see the Arduino index of boards.

Picture 1. Arduino UNO R3 pin out

Arduino Uno Features

Processor: ATMega328P Processor

Memory

  • + AVR CPU at up to 16 MHz
  • + 32KB Flash
  • + 2KB SRAM
  • + 1KB EEPROM

Security

  • + Power On Reset (POR)
  • + Brown Out Detection (BOD)

Peripherals

+ 2x 8-bit Timer/Counter with a dedicated period register and compare channels

+ 1x 16-bit Timer/Counter with a dedicated period register, input capture and compare channels

+ 1x USART with fractional baud rate generator and start-of-frame detection

+ 1x controller/peripheral Serial Peripheral Interface (SPI)

+ 1x Dual mode controller/peripheral I2C

+ 1x Analog Comparator (AC) with a scalable reference input

+ Watchdog Timer with separate on-chip oscillator

+ Six PWM channels

+ Interrupt and wake-up on pin change

Power

+ 2.7-5.5 volts

Arduino Analog Pin Description

Arduino Digital Pin Description

NRF24l01  

NRF24L01 Pinout Diagram

NRF24L01 is a single chip radio transceiver for the world wide 2.4 – 2.5 GHz ISM band. The transceiver consists of a fully integrated frequency synthesizer, a power amplifier, a crystal oscillator, a demodulator, modulator and Enhanced ShockBurst™ protocol engine. Output power, frequency channels, and protocol setup are easily programmable through a SPI interface. Current consumption is very low, only 9.0mA at an output power of -6dBm and 12.3mA in RX mode. Built-in Power Down and Standby modes makes power saving easily realizable. 

NRF24L01 specification:

Features of the nRF24L01 include: 

  • Radio X Worldwide 2.4GHz ISM band operation
  • 126 RF channels 
  • Common RX and TX pins 
  • GFSK modulation 
  • 1 and 2Mbps air data rate 
  • 1MHz non-overlapping channel spacing at 1Mbps 
  • 2MHz non-overlapping channel spacing at 2Mbps

Transmitter 

  • Programmable output power: 0, -6, -12 or -18dBm 
  • 11.3mA at 0dBm output power

Receiver 

  • Integrated channel filters 
  • 12.3mA at 2Mbps 
  •  -82dBm sensitivity at 2Mbps
  • -85dBm sensitivity at 1Mbps 
  • Programmable LNA gain 

Power Management 

  • Integrated voltage regulator 
  • 1.9 to 3.6V supply range 
  • Idle modes with fast start-up times for advanced power management 
  • 22uA Standby-I mode, 900nA power down mode 
  • Max 1.5ms start-up from power down mode 
  • Max 130us start-up from standby-I mode 

RF Synthesizer 

  • Fully integrated synthesizer 
  • No external loop filter, VCO varactor diode or resonator 
  •  Accepts low cost ±60ppm 16MHz crystal

• Enhanced ShockBurst™ 

  • 1 to 32 bytes dynamic payload length 
  • Automatic packet handling 
  • Auto packet transaction handling 
  • 6 data pipe MultiCeiver™ for 1:6 star networks

Enhanced ShockBurst™ uses ShockBurst™ for automatic packet handling and timing. During transmit, ShockBurst™ assembles the packet and clocks the bits in the data packet into the transmitter for transmission. During receive, ShockBurst™ constantly searches for a valid address in the demodulated signal.

When ShockBurst™ finds a valid address, it processes the rest of the packet and validates it by CRC. If the packet is valid the payload is moved into the RX FIFO. The high speed bit handling and timing is controlled by ShockBurst™.

Enhanced ShockBurst™ features automatic packet transaction handling that enables the implementation of a reliable bi-directional data link. An Enhanced ShockBurst™ packet transaction is a packet exchange between two transceivers, where one transceiver is the Primary Receiver (PRX) and the other is the Primary Transmitter (PTX). An Enhanced ShockBurst™ packet transaction is always initiated by a packet transmission from the PTX, the transaction is complete when the PTX has received an acknowledgment packet(ACK packet) from the PRX.

GND is the Ground Pin. It is usually marked by encasing the pin in a square so it can be used as a reference for identifying the other pins.

VCC supplies power for the module. This can be anywhere from 1.9 to 3.9 volts. You can connect it to 3.3V output from your Arduino. Remember connecting it to a 5V pin will likely destroy your nRF24L01+ module!

CE (Chip Enable) is an active-HIGH pin. When selected the nRF24L01 will either transmit or receive, depending upon 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 begins 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 SPI input to the nRF24L01.

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

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

Power consumption.

Packet TX operation

You activate PTX mode by setting the CE pin high. If there is a packet present in the TX FIFO the nRF24L01 enters TX mode and transmits the packet. If Auto Retransmit is enabled, the state machine checks if the NO_ACK flag is set. If it is not set, the nRF24L01 enters RX mode to receive an ACK packet. If the received ACK packet is empty, only the TX_DS IRQ is asserted. If the ACK packet contains a payload, both TX_DS IRQ and RX_DR IRQ are asserted simultaneously before nRF24L01 returns to standby-I mode.

If the ACK packet is not received before timeout occurs, the nRF24L01 returns to standby-I mode. It stays in standby-I mode until the ARD has elapsed. If the number of retransmits has not reached the ARC, the nRF24L01 enters TX mode and transmits the last packet once more.

While executing the Auto Retransmit feature, the number of retransmits can reach the maximum number defined in ARC. If this happens, the nRF24L01 asserts the MAX_RT IRQ and returns to standby-I mode.

If the CE is high and the TX FIFO is empty, the nRF24L01 enters Standby-II mode.

Packet RX Operation:

You activate PRX mode by setting the CE pin high. The nRF24L01 enters RX mode and starts searching for packets. If a packet is received and Auto Acknowledgement is enabled the nRF24L01 decides if this is a new packet or a copy of a previously received packet. If the packet is new the payload is made available in the RX FIFO and the RX_DR IRQ is asserted. If the last received packet from the transmitter is acknowledged with an ACK packet with payload, the TX_DS IRQ indicates that the PTX received the ACK packet.with payload. If the No_ACK flag is not set in the received packet, the PRX enters TX mode. If there is a pending payload in the TX FIFO it is attached to the ACK packet. After the ACK packet is transmitted, the nRF24L01 returns to RX mode.

A copy of a previously received packet might be received if the ACK packet is lost. In this case, the PRX discards the received packet and transmits an ACK packet before it returns to RX mode.

Function:

Multiceiver:

Multiceiver is a feature used in RX mode that contains a set of 6 parallel data pipes with unique addresses. A data pipe is a logical channel in the physical RF channel. Each data pipe has its own physical address decoding in the nRF24L01.

nRF24L01 configured as PRX (primary receiver) can receive data addressed to six different data pipes in one frequency channel.Each data pipe has its own unique address and can be configured for individual behavior.Up to six nRF24L01s configured as PTX can communicate with one nRF24L01 configured as PRX. All data pipe addresses are searched for simultaneously. Only one data pipe can receive a packet at a time. All data pipes can perform Enhanced ShockBurst™ functionality

Auto Acknowledgement

Auto acknowledgment is a function that automatically transmits an ACK packet to the PTX after it has received and validated a packet. The auto acknowledgement function reduces the load of the system MCU and can remove the need for dedicated SPI hardware. This also reduces cost and average current consumption. The Auto Acknowledgement feature is enabled by setting the EN_AA register.

Auto Retransmission (ART)

The auto retransmission is a function that retransmits a packet if an ACK packet is not received. It is used at the PTX side in an auto acknowledgement system. You can set up the number of times a packet is allowed to be retransmitted if a packet is not acknowledged with the ARC bits in the SETUP_RETR register.

PTX enters RX mode and waits a time period for an ACK packet each time a packet is transmitted.

NRF24L01+

NRF24L01 comes in an advanced version. It is  2.4GHz NRF24L01+PA+LNA SMA Wireless Transceiver Antenna.This board features a reverse polarized SMA connector for maximum RF range. And there is PA and LNA circuit on board, with the external antenna it can reach a longer distance than the one without these parts.This module comes with the 2.4G antenna (2DB), with a 250Kbps transmission rate on open-air it can reach the 800-1K meters communication distance.

NRF24L01+ Features:

  • Voltage: 3-3.6V (recommended 3.3V) V.
  • Maximum output power: +20dBm.
  • Power-down mode current: 4.2uA.
  • Operating Range: 1Km
  • Antenna Gain (peak): 2Dbi.
  • 2MB rate (Open area): 520m.
  • 1MB rate (Open area): 750m.
  • 250Kb rate (Open area): 1100m.
  • It uses 2.4GHz global open ISM band, with license free.
  • Facilitate the development for customers, without development RF part.
  • Low cost: integrated with high-speed signal processing parts associated with RF protocol, such as: automatically resend lost packets and generate acknowledge signal;

Package Includes :

  • 1 x 2.4GHz NRF24L01 Transceiver module.
  • 1 x SMA Antenna

Specification:

Schematic Diagram

Pin Connection Table

Arduino UNO R3NRF24L01
GNDGND
3V3Vcc
12MISO
11MOSI
13SCK
9CE
10CSN

Source Code

FOR TRANSMITTER

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN        
const byte address[6] = "00001";    
int button_pin = 2;
boolean button_state = 0;
void setup() 
{
pinMode(button_pin, INPUT);
radio.begin();                  
radio.openWritingPipe(address); 
radio.setPALevel(RF24_PA_MIN);  
radio.stopListening();          
}
void loop()
{
button_state = digitalRead(button_pin);
if(button_state == HIGH)
{
const char text[] = "Your Button State is HIGH";
radio.write(&text, sizeof(text));                  
}
else
{
const char text[] = "Your Button State is LOW";
radio.write(&text, sizeof(text));                 
}
radio.write(&button_state, sizeof(button_state));  
delay(1000);
}

Code Explanation

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN        
const byte address[6] = "00001";    
int button_pin = 2;
boolean button_state = 0;

Include the libraries SPI.h, nRF24L01.h and RF24.h

As we have connected NRF24L01 CS and CSN pins to the 9 and 10 pin connection of Arduino we are declaring the same in the code. An RF module (short for radio-frequency module) is a (usually) small electronic device used to transmit and/or receive radio signals between two devices. In an embedded system it is often desirable to communicate with another device wirelessly. This wireless communication may be accomplished through optical communication or through radio-frequency (RF) communication. 

Next we are declaring a byte array representing the address. This is the address where we will send the data. This should be the same on the receiving side.

We are initializing int button_pin  and boolean button_state.

pinMode(button_pin, INPUT);
radio.begin();                  
radio.openWritingPipe(address); 
radio.setPALevel(RF24_PA_MIN);  
radio.stopListening();  

After this we are starting wireless communication and Setting the address where we will send the data.

{
button_state = digitalRead(button_pin);
if(button_state == HIGH)
{
const char text[] = "Your Button State is HIGH";
radio.write(&text, sizeof(text));                  
}
else
{
const char text[] = "Your Button State is LOW";
radio.write(&text, sizeof(text));                 
}
radio.write(&button_state, sizeof(button_state));  
delay(1000);
}

You can set it as minimum or maximum value of the power amplifier  depending on the distance between the transmitter and receiver.

so for powerLevels we have RF24_PA_MIN = 0 to -18dBm, RF24_PA_LOW = -12dBm to 7.5dBm, RF24_PA_HIGH = -6dBm to 9.0dBm, RF24_PA_MAX = 0dBm to 11.3dBm.

After this, consider a loop which equates button_state as reading the button pin value which is set initially as 2. If button_state value is high then we have to display a message saying that the button state is high. Then we are sending the message to the receiver. Else if  button_state value is low we are displaying that the button state is low and again sending the message to the receiver. At last providing a delay of 1000. 

FOR RECEIVER 

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN
const byte address[6] = "00001";
boolean button_state = 0;
int led_pin = 3;
void setup() {
pinMode(6, OUTPUT);
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);   
radio.setPALevel(RF24_PA_MIN);       
radio.startListening();              
}
void loop()
{
if (radio.available())              
{
char text[32] = "";                
radio.read(&text, sizeof(text));    
radio.read(&button_state, sizeof(button_state));    
if(button_state == HIGH)
{
digitalWrite(6, HIGH);
Serial.println(text);
}
else
{
digitalWrite(6, LOW);
Serial.println(text);
}
}
delay(5);
}

Code explanation for receiver

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
RF24 radio(9, 10); // CE, CSN
const byte address[6] = "00001";
boolean button_state = 0;
int led_pin = 3;

Include the libraries SPI.h, nRF24L01.h and RF24.h

As we have connected NRF24L01 CS and CSN pins to the 9 and 10 pin connection of Arduino we are declaring the same in the code. An RF module (short for radio-frequency module) is a (usually) small electronic device used to transmit and/or receive radio signals between two devices. In an embedded system it is often desirable to communicate with another device wirelessly. This wireless communication may be accomplished through optical communication or through radio-frequency (RF) communication. 

pinMode(6, OUTPUT);
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);   
radio.setPALevel(RF24_PA_MIN);       
radio.startListening();  

Next we are declaring a byte array representing the address. This is the address where we will send the data. This should be the same on the receiving side.

We are initializing int led_pin  and boolean button_state.

Setting the baud rate to 9600.

After this we are starting wireless communication and Setting the address where we will receive the data.

You can set it as the minimum or maximum value of the power amplifier depending on the distance between the transmitter and receiver. So for powerLevels we have RF24_PA_MIN = 0 to -18dBm, RF24_PA_LOW = -12dBm to 7.5dBm, RF24_PA_HIGH = -6dBm to 9.0dBm, RF24_PA_MAX = 0dBm to 11.3dBm

radio.startListening(); this code sets the module as receiver
{
if (radio.available())              
{
char text[32] = "";                
radio.read(&text, sizeof(text));    
radio.read(&button_state, sizeof(button_state));    
if(button_state == HIGH)
{
digitalWrite(6, HIGH);
Serial.println(text);
}
else
{
digitalWrite(6, LOW);
Serial.println(text);
}
}
delay(5);
}

Then it looks for the data and saves the incoming data.

radio.read(&text, sizeof(text)) code read the data.

Then checking whether button_state is high, and if high we are printing the text else printing it as low.

Providing a delay of 5.

Github link:

https://github.com/iottrends/iottrends/tree/main/NRF24L01

5 2 votes
Article Rating
Previous articleHow to Interface Raspberry Pi Pico with AdaFruit LoRa
Next articleHow to Interface ESP8266 with AdaFruit LoRa RFM69HCW
Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments