Getting to know the nRF24L01 RF Module

The nRF24L01 modules are transceiver modules, meaning each module can both send and receive data but since they are half-duplex they can either send or receive data at a time. The module has the generic nRF24L01 IC from Nordic semi-conductors which is responsible for transmission and reception of data. The IC communicates using the SPI protocol and hence can be easily interfaced with any microcontrollers. It gets a lot easier with Arduino since the libraries are readily available. The pinouts of a standard nRF24L01 module is shown below





The module has on operating voltage from 1.9V to 3.6V (typically 3.3V) and consumes very less current of only 12mAduring normal operation which makes it battery efficient and hence can even run on coin cells. Even though the operating voltage is 3.3V most of the pins are 5V tolerant and hence can be directly interfaced with 5V microcontrollers like Arduino. Another advantage of using these modules is that, each module has 6 Pipelines. Meaning, each module can communicate with 6 other modules to transmit or receive data. This makes the module suitable for creating star or mesh networks in IoT applications. Also they have a wide address range of 125 unique ID’s, hence in a closed area we can use 125 of these modules without interfering with each other.


Interfacing nRF24L01 with Arduino

In this tutorial we will learn how to interface the nRF24L01 with Arduino by controlling the servo motor connected with one Arduino by varying the potentiometer on the other Arduino. For the sake of simplicity we have used one nRF24L01 module as transmitter and the other is receiver, but each module can be programmed to send and receive data individually.

The circuit diagram to connect the nRF24L01 module with Arduino is shown below. For varity, I have used the UNO for the receiver side and Nano for the transmitter side. But the logic for connection remains the same for other Arduino boards like mini, mega as well.

Receiver side: Arduino Uno nRF24L01 module connections









As said earlier the nRF24L01 communicates with the help of SPI protocol. On Arduino Nano and UNO the pins 11, 12 and 13 are used for SPI communication. Hence we connect the MOSI, MISO and SCK pins from nRF to the pins 11, 12 and 13 respectively. The pins CE and CS are user configurable, I have used pin 7 and 8 here, but you can use any pin by altering the program. The nRF module is powered by the 3.3V pin on Arduino, which in most cases will work. If not, a separate power supply can be tried. Apart from interfacing the nRF I have also connected a servo motor to pin 7 and powered it through the 5V pin on Arduino. Similarly the transmitter circuit is shown below.


Transmitter side: Arduino Nano nRF24L01 module Connections










The connections for the transmitter is also the same, additionally I have used a potentiometer connected across the 5V ad Ground pin of Arduino. The output analog voltage which will vary from 0-5V is connected to the A7 pin of the Nano. Both the boards are powered through the USB port.


Working with nRF24L01+ Wireless Transceiver Module


However in order to make our nRF24L01 to work free from noise we might want to consider the following things. I have been working on this nRF24L01+ for a long time and learnt the following points which can help you from getting hit on a wall. You can try these when the modules did not work the normal way.

1. Most of the nRF24L01+ modules in the market are fake. The cheap ones that we can find on Ebay and Amazon are the worst (Don’t worry, with few tweaks we can make them work)

2. The main problem is the power supply, not your code. Most of the codes online will work properly, I myself have a working code which I personally tested, Let me know if you need them.

3. Pay attention because the modules which are printed as NRF24L01+ are actually Si24Ri (Yes a Chinese product).

4. The clone and fake modules will consume more power, hence do not develop your power circuit based on nRF24L01+ datasheet, because Si24Ri will have high current consumption about 250mA.

5. Beware of Voltage ripples and current surges, these modules are very sensitive and might easily burn up. (;-( fried up 2 modules so far)

6. Adding a couple capacitors (10uF and 0.1uF) across Vcc and Gnd of the module helps in making your supply pure and this works for most of the modules.

Programming nRF24L01 for Arduino

It is very easy to use these modules with Arduino, due to the readily available library created by maniacbug on GitHub. Click on the link to download the library as ZIP folder and add it to your Arduino IDE by using the Sketch -> Include Library -> Add .ZIP library option. After adding the program We have to write two programs, one is the transmitter side and the other for receiver side. However as I said before each module can work both as a transmitter and receiver. Both the programs were given at the end of this page, in the transmitter code the receiver option will be commented out and in the receiver program the transmitter code will be commented. You can use it if you are trying a project in which the module has to work both as well. The work of the program is explained below.

Like all programs Since the nRF uses SPI protocol we have included the SPI header and also the library that we just downloaded. The servo motor used to control

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


The library is about the CE and CS pins. In our circuit diagram we have connected CE to pin 7 and CS to pin 8 so we set the line as

RF24 myRadio (7, 8);



All the variables that are associated with the RF library should be declared as a composite variable structure. In this program the variable message is used to send and receive data from the RF module.


struct package
{
int msg;
};
typedef struct package Package;
Package data;



Each RF module has a unique address using which user can use the respective device. Since we are having only one pair here, we set the address to zero in both transmitter and receiver but if you have multiple module you can set the ID to any unique 6 digit string.

byte addresses [] [6] = {"0"};

Next in the void setup function we initialize the RF module and set to work with 115 band which is free from noise and also set the module to work in minimum power consumption mode with minimum speed of 250Kbps.

void setup ()
{
Serial.begin (9600);
myRadio.begin ();
myRadio.setChannel (115); // 115 band above WIFI signals
myRadio.setPALevel (RF24_PA_MIN); // MIN power low rage
myRadio.setDataRate (RF24_250KBPS); // Minimum speed
myservo.attach (6);
Serial.print ("Setup Initialized");
delay (500);
}

void WriteData () function writes the data passed to it. As told before the nRF has 6 different pipes to which we can read or write data, here we have used 0xF0F0F0F066 as address to write data. On the receiver side we have used the same address on ReadData () function to get the data that was written.

void WriteData ()
{
myRadio.stopListening (); // Stop Receiving and start transminitng
myRadio.openWritingPipe (0xF0F0F066); // Sends data on this 40-bit address
myRadio.write (& data, sizeof (data));
delay (300);
}


void WriteData () function reads the data and puts it in a variable. Again out of 6 different pipes using which we read or write data here we used 0xF0F0F0F0AA as address to read data This means the transmitter of the other module has written something on this address and hence we are reading it from the same.


void ReadData ()
{
myRadio.openReadingPipe (1, 0xF0F0F0F0AA); // Which pipe to read, 40 bit address
myRadio.startListening (); // Stop Transminting and start Reveicing
if (myRadio.available ())
{
while (myRadio.available ())
{
myRadio.read (& data, sizeof (data));
}
Serial.println (data.text);
}
}



Controlling Servo Motor using nRF24L01 wirelessly





Once you are ready with the program upload the transmitter and receiver code (given below) on respective Arduino boards and power them up with USB port. You can also launch the serial monitor of both the boards to check what value is being transmitted and what is being received. If everything is working as expected when you turn the POT knob on transmitter side the servo on the other side should also turn accordingly.

Code

Code for Transmitter Part:


/ * Transmit POT value through NRF24L01 using Arduino
*
* Pin Conections
* CE - 7
MISO-12
MOSI-11
SCK-13
CS-8
POT-A7
* /
#include <SPI.h>
#include "RF24.h"
RF24 myRadio (7, 8);

struct package
{
int msg = 0;
};
byte addresses [] [6] = {"0"};
typedef struct package Package;
Package data;
void setup ()
{
Serial.begin (9600);
myRadio.begin ();
myRadio.setChannel (115); // 115 band above WIFI signals
myRadio.setPALevel (RF24_PA_MIN); // MIN power low rage
myRadio.setDataRate (RF24_250KBPS); // Minimum speed
delay (500);
Serial.print ("Setup Initialized");
}
void loop ()
{
int Read_ADC = analogRead (A7);
char servo_value = map (Read_ADC, 0, 1024, 0,180);
if (servo_value> 1)
data.msg = servo_value;
WriteData ();
delay (50);
// ReadData ();
// delay (200);
}
void WriteData ()
{
myRadio.stopListening (); // Stop Receiving and start transminitng
myRadio.openWritingPipe (0xF0F0F0F0AA); // Sends data on this 40-bit address
myRadio.write (& data, sizeof (data));
Serial.print ("\ nSent:");
Serial.println (data.msg);
delay (300);
}
void ReadData ()
{
myRadio.openReadingPipe (1, 0xF0F0F0F066); // Which pipe to read, 40 bit address
myRadio.startListening (); // Stop Transminting and start Reveicing
if (myRadio.available ())
{
while (myRadio.available ())
{
myRadio.read (& data, sizeof (data));
}
Serial.print ("\ nReceived:");
Serial.println (data.msg);
}
}

Code for Receiver Part:
/ * CE - 7
MISO-12
MOSI-11
SCK-13
CS-8
Recently tested with nano
* /
#include <SPI.h>
#include "RF24.h"
#include <Servo.h>
Servo myservo;
RF24 myRadio (7, 8);
struct package
{
int msg;
};
typedef struct package Package;
Package data;
byte addresses [] [6] = {"0"};
void setup ()
{
Serial.begin (9600);
myRadio.begin ();
myRadio.setChannel (115); // 115 band above WIFI signals
myRadio.setPALevel (RF24_PA_MIN); // MIN power low rage
myRadio.setDataRate (RF24_250KBPS); // Minimum speed
myservo.attach (6);
Serial.print ("Setup Initialized");
delay (500);
}
int servo_value;
int Pev_servo_value;
void loop ()
{
ReadData ();
delay (50);

Pev_servo_value = Servo_value;
Servo_value = data.msg;
while (Pev_servo_value <Servo_value)
{
myservo.write (Pev_servo_value);
Pev_servo_value ++;
delay (2);
}
while (Pev_servo_value> Servo_value)
{
myservo.write (Pev_servo_value);
Pev_servo_value--;
delay (2);
}
//data.msg = "nothing to send";
// WriteData ();
// delay (50);
}
void ReadData ()
{
myRadio.openReadingPipe (1, 0xF0F0F0F0AA); // Which pipe to read, 40 bit address
myRadio.startListening (); // Stop Transminting and start Reveicing
if (myRadio.available ())
{
while (myRadio.available ())
{
myRadio.read (& data, sizeof (data));
}
Serial.print ("\ nReceived:");
Serial.println (data.msg);
}
}
void WriteData ()
{
myRadio.stopListening (); // Stop Receiving and start transminitng
myRadio.openWritingPipe (0xF0F0F066); // Sends data on this 40-bit address
myRadio.write (& data, sizeof (data));
Serial.print ("\ nSent:");
Serial.println (data.msg);
delay (300);
}



No comments

Theme images by Dizzo. Powered by Blogger.