Arduino Wireless Communication – NRF24L01 Tutorial

In this Arduino tutorial we will learn how to make a wireless communication between two Arduino boards using the NRF24L01 transceiver module. You can watch the following video or read the written tutorial below.

Overview


For explaining the wireless communication we will make two examples, the first one will be sending a simple “Hello World” message from one Arduino to another, and in the second example we will have a bi-directional communication between the Arduino boards, where using the Joystick at the first Arduino we will control the servo motor at the second Arduino, and vice versa, using the push button at the second Arduino we will control the LED at the first Arduino.

Arduino and NRF24L01 Tutorial Example 2

NRF24L01 Transceiver Module


Let’s take a closer look at the NRF24L01 transceiver module. It uses the 2.4 GHz band and it can operate with baud rates from 250 kbps up to 2 Mbps. If used in open space and with lower baud rate its range can reach up to 100 meters.

NRF24L01 Transceiver Module

The module can use 125 different channels which gives a possibility to have a network of 125 independently working modems in one place. Each channel can have up to 6 addresses, or each unit can communicate with up to 6 other units at the same time.

NRF24L01 Working Principles of Channels and Addresses

The power consumption of this module is just around 12mA during transmission, which is even lower than a single LED. The operating voltage of the module is from 1.9 to 3.6V, but the good thing is that the other pins tolerate 5V logic, so we can easily connect it to an Arduino without using any logic level converters.

NRF24L01 Transceiver Module Pinouts Connections

Three of these pins are for the SPI communication and they need to be connected to the SPI pins of the Arduino, but note that each Arduino board have different SPI pins. The pins CSN and CE can be connected to any digital pin of the Arduino board and they are used for setting the module in standby or active mode, as well as for switching between transmit or command mode. The last pin is an interrupt pin which doesn’t have to be used.

So once we connect the NRF24L01 modules to the Arduino boards we are ready to make the codes for both the transmitter and the receiver.

NRF24L01 and Arduino Tutorial Circuit Schematic

You can get the components needed for this Arduino Tutorial from the links below:

  • NRF24L01 Transceiver Module…………. Amazon
  • Arduino Board ………………………………… Amazon

*Please note: These are affiliate links. I may make a commission if you buy the components through these links.
I would appreciate your support in this way!

Arduino Codes


First we need to download and install the RF24 library which makes the programming less difficult.

Here are the two codes for the wireless communication and below is the description of them.

Transmitter Code

/*
* Arduino Wireless Communication Tutorial
*     Example 1 - Transmitter Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CNS, CE

const byte address[6] = "00001";

void setup() {
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MIN);
  radio.stopListening();
}

void loop() {
  const char text[] = "Hello World";
  radio.write(&text, sizeof(text));
  delay(1000);
}

Receiver Code

/*
* Arduino Wireless Communication Tutorial
*       Example 1 - Receiver Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(7, 8); // CNS, CE

const byte address[6] = "00001";

void setup() {
  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));
    Serial.println(text);
  }
}

Description:

So we need to include the basic SPI and the newly installed RF24 libraries and create an RF24 object. The two arguments here are the CSN and CE pins.

RF24 radio(7, 8); // CE, CSN

Next we need to create a byte array which will represent the address, or the so called pipe through which the two modules will communicate.

const byte address[6] = "00001";

We can change the value of this address to any 5 letter string and this enables to choose to which receiver we will talk, so in our case we will have the same address at both the receiver and the transmitter.

In the setup section we need to initialize the radio object and using the radio.openWritingPipe() function we set the address of the receiver to which we will send data, the 5 letter string we previously set.

radio.openWritingPipe(address);

On the other side, at the receiver, using the radio.setReadingPipe() function we set the same address and in that way we enable the communication between the two modules.

radio.openReadingPipe(0, address);

Then using the radio.setPALevel() function we set the Power Amplifier level, in our case I will set it to minimum as my modules are very close to each other.

radio.setPALevel(RF24_PA_MIN);

Note that if using a higher level it is recommended to use a bypass capacitors across GND and 3.3V of the modules so that they have more stable voltage while operating.

Next we have the radio.stopListening() function which sets module as transmitter, and on the other side, we have the radio.startListening() function which sets the module as receiver.

// at the Transmitter
radio.stopListening();
// at the Receiver
radio.startListening();

In the loop section, at the transmitter, we create an array of characters to which we assign the message “Hello World”. Using the radio.write() function we will send that message to the receiver. The first argument here is the variable that we want to be sent.

void loop() {
 const char text[] = "Hello World";
 radio.write(&text, sizeof(text));
 delay(1000);
}

By using the “&” before the variable name we actually set an indicating of the variable that stores the data that we want to be sent and using the second argument we set the number of bytes that we want to take from that variable. In this case the sizeof() function gets all bytes of the strings “text”. At the end of the program we will add 1 second delay.

On the other side, at the receiver, in the loop section using the radio.available() function we check whether there is data to be received. If that’s true, first we create an array of 32 elements, called “text”, in which we will save the incoming data.

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

Using the radion.read() function we read and store the data into the “text” variable. At the end we just print text on the serial monitor. So once we upload both programs, we can run the serial monitor at the receiver and we will notice the message “Hello World” gets printed each second.

Arduino Wireless Bi-directional Communication


Let’s see the second example, a bi-directional wireless communication between two Arduino boards. Here’s the circuit schematics:

Arduino Wireless Communication NRF24L01 Circuit Schematic Tutorial

You can get the components needed for this example from the links below:

  • NRF24L01 Transceiver Module…………. Amazon
  • Joystick Module ………………………………. Amazon
  • Arduino Board ………………………………… Amazon
  • Servo Motor ……………………………………. Amazon
  • Pushbutton …………………………………….. Amazon
  • LED ………………………………………………… Amazon

*Please note: These are affiliate links. I may make a commission if you buy the components through these links.
I would appreciate your support in this way!

Source Codes


Here are the two codes and below is the description of them.

Transmitter Code

/*
* Arduino Wireless Communication Tutorial
*     Example 2 - Transmitter Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#define led 12

RF24 radio(7, 8); // CNS, CE
const byte addresses[][6] = {"00001", "00002"};
boolean buttonState = 0;

void setup() {
  pinMode(12, OUTPUT);
  radio.begin();
  radio.openWritingPipe(addresses[1]); // 00001
  radio.openReadingPipe(1, addresses[0]); // 00002
  radio.setPALevel(RF24_PA_MIN);
}

void loop() {
  delay(5);

  radio.stopListening();
  int potValue = analogRead(A0);
  int angleValue = map(potValue, 0, 1023, 0, 180);
  radio.write(&angleValue, sizeof(angleValue));

  delay(5);
  radio.startListening();
  while (!radio.available());
  radio.read(&buttonState, sizeof(buttonState));
  if (buttonState == HIGH) {
    digitalWrite(led, HIGH);
  }
  else {
    digitalWrite(led, LOW);
  }
}

Receiver Code

/*
* Arduino Wireless Communication Tutorial
*     Example 2 - Receiver Code
*                
* by Dejan Nedelkovski, www.HowToMechatronics.com
* 
* Library: TMRh20/RF24, https://github.com/tmrh20/RF24/
*/

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <Servo.h>

#define button 4

RF24 radio(7, 8); // CNS, CE
const byte addresses[][6] = {"00001", "00002"};
Servo myServo;
boolean buttonState = 0;

void setup() {
  pinMode(button, INPUT);
  myServo.attach(5);
  radio.begin();
  radio.openWritingPipe(addresses[0]); // 00002
  radio.openReadingPipe(1, addresses[1]); // 00001
  radio.setPALevel(RF24_PA_MIN);
}

void loop() {
  delay(5);
  radio.startListening();
  if ( radio.available()) {
    while (radio.available()) {
      int angleV = 0;
      radio.read(&angleV, sizeof(angleV));
      myServo.write(angleV);
    }
    delay(5);
    radio.stopListening();
    buttonState = digitalRead(button);
    radio.write(&buttonState, sizeof(buttonState));
  }
}

What’s different here from the previous example is that we need to create two pipes or addresses for the bi-directional communication.

const byte addresses[][6] = {"00001", "00002"};

In the setup section we need to define both pipes, and note that the writing address at the first Arduino needs to be the reading address at the second Arduino, and vice versa, the reading address at the first Arduino needs to be the writing address at the second Arduino.

// at the Transmitter
radio.openWritingPipe(addresses[1]); // 00001
radio.openReadingPipe(1, addresses[0]); // 00002
// at the Receiver
radio.openWritingPipe(addresses[0]); // 00002
radio.openReadingPipe(1, addresses[1]); // 00001

In the loop section using the radio.stopListening() function we set the first Arduino as transmitter, read and map the value of Joystick from 0 to 180, and using the radio.write() function send the data to the receiver.

radio.stopListening();
int potValue = analogRead(A0);
int angleValue = map(potValue, 0, 1023, 0, 180);
radio.write(&angleValue, sizeof(angleValue));

On the other side, using the radio.startListening() function we set the second Arduino as receiver and we check whether there is available data. While there is data available we will read it, save it to the “angleV” variable and then use that value to rotate the servo motor.

radio.startListening();
  if ( radio.available()) {
    while (radio.available()) {
      int angleV = 0;
      radio.read(&angleV, sizeof(angleV));
      myServo.write(angleV);
    }

Next, at the transmitter, we set the first Arduino as receiver and with an empty “while” loop we wait for the second Arduino the send data, and that’s the data for the state of the push button whether is pressed or not. If the button is pressed the LED will light up. So these process constantly repeats and both Arduino boards are constantly sending and receiving data.

That’s all, I hope you enjoyed this tutorial and feel free to ask any question in the comments section below.

Related Posts

26 Responses

  1. Azhar

    Thank you for sharing this very useful tutorial. Can you help me with the code to control More than one servo (I need to control 6 servo) using 6 potentiometer in one direction?

    Reply
    • Dejan Nedelkovski

      Well this shouldn’t be a problem, you just have to send those potentiometer values to the other Arduino and apply them to the servo motors. The same method would be used.

      Reply
  2. Peyman

    Hi,how can send data for specific pipe and get answer from it.
    Master have one address and if send data all slave get,s it?
    I wont have one master that get data from 2 slave.

    Reply
  3. Terry Chen

    Hi, do you know any possible reason why my serial output is “yyyyyy yyyyyy yyyyy”???

    Reply
  4. Jim

    Can I extend the range to 200 meters by using a repeater. Master to repeater (slave/master) to other slaves and back?

    Reply
  5. Azhar

    Hello, is your circuit diagram is wrong? The SCK of nrf2401 is not going to Pin 13 of arduino nano.

    Reply
  6. Sufi Shah Hamid Jalali

    Your tutorials are just wonderful. I very much like the way you present them. Very clear and very helpful. Keep up, man!!

    Reply
  7. Vitaly

    Hi. Wonderfull explanation. Q? Will system stand duplex if continuously move the joystick? In this case the program will be inside the while() function all time.

    Reply
    • Dejan Nedelkovski

      Thanks. It depends on the situation but it could work. You can notice in the introduction that I’m able to light up the LED while moving the joystick.

      Reply
  8. anil

    Hi dejan
    I have successfully trans communicated with mega 2560 to uno. … But my problem is the connection is not lasting for long time ..its just working for few seconds and stopping… Resetting on both boards Is also not working … When I disconnect two boards and connect them to power supply again its working for few seconds… But working time is different in each case….. Can you help me with this

    Reply
    • Dejan Nedelkovski

      The problem might be the power. Try to use more stable external power. These wireless module can be power hungry when transmitting data, so you might be losing the connection. Also try yo use decoupling capacitors.

      Reply
  9. kubajz 22

    Well, I solved it by changing while (!radio.available()); to if (!radio.available());
    works fine, good tut

    Reply
  10. Marek

    Excellent Tutorial, Thank you.
    What resistor are you using in the second example though?
    Thanks

    Reply
  11. Eldon Tenorio

    Hi there!

    I was able to make this project work. However, I am faced with an issue. Whenever I move the two Arduino boards (each with the NRF24L01 module attached in them), the signal gets lost. It was as if the modules can only work less than one meter in range? Unless I have missed something from the tutorial.

    Thanks in advance for the reply.

    Reply
  12. Leo

    Thanks for the tutorial.

    Do you have any ideas on how to establish a connection and receive data with a laptop computer rather than a second arduino?

    Thanks

    Reply

Leave a Reply

Your email address will not be published.