•Remote sensors for temperature, pressure, alarms, much more
•Robot control and monitoring from 50 feet to 2000 feet distances
•Remote control and monitoring of nearby or neighborhood buildings
•Autonomous vehicles of all kinds
|Fig 2. nRF24L01+ Module|
|Fig 4. Bottom View Pinout of nRF24L01 Module and corresponding Pin mapping with Rpi2 and Rpi Model B|
To configure the nRF24L01+, we have to refer the Product Specification document, "nRF24L01P_Product_Specification_1_0.pdf", Chapter 6, Pg. no. 21, talks about Radio Control, which is required to be understood, in order to control the Radio. You can configure the nRF24L01+ in power down, standby, RX or TX mode. When the VDD reaches 1.9V or higher nRF24L01+ enters the Power on reset state where it remains in reset until entering the Power Down mode. The below state diagram(Pg. no. 22) illustrates, the relationship between the states, with changes in control Signals, like CE, and PRIM_RX, which are required to control the Radio Transfer operations.
Power Down Mode
However, if the automatic protocol features (Enhanced ShockBurst™) in the baseband protocol engine are enabled, the nRF24L01+ can enter other modes in order to execute the protocol.
In RX mode a Received Power Detector (RPD) signal is available. The RPD is a signal that is set high when a RF signal higher than -64 dBm is detected inside the receiving frequency channel. The internal RPD signal is filtered before presented to the RPD register. The RF signal must be present for at least 40µs before the RPD is set high.
data. It can be 250kbps, 1Mbps or 2Mbps. Using lower air data rate gives better receiver sensitivity than higher air data rate. But, high air data rate gives lower average current consumption and reduced probability of on-air collisions.
The air data rate is set by the RF_DR bit in the RF_SETUP register. A transmitter and a receiver must be programmed with the same air data rate to communicate with each other. nRF24L01+ is fully compatible with nRF24L01. For compatibility with nRF2401A, nRF2402, nRF24E1, and nRF24E2 the air data rate must be set to 250kbps or 1Mbps.
occupies a bandwidth of less than 1MHz at 250kbps and 1Mbps and a bandwidth of less than 2MHz at 2Mbps. nRF24L01+ can operate on frequencies from 2.400GHz to 2.525GHz. The programming resolution of the RF channel frequency setting is 1MHz.
At 2Mbps the channel occupies a bandwidth wider than the resolution of the RF channel frequency setting. To ensure non-overlapping channels in 2Mbps mode, the channel spacing must be 2MHz or more. At 1Mbps and 250kbps the channel bandwidth is the same or lower than the resolution of the RF frequency. The RF channel frequency is set by the RF_CH register according to the following formula:
F0= 2400 + RF_CH [MHz]
You must program a transmitter and a receiver with the same RF channel frequency to communicate with each other.
|Fig 5. Table depicting the RF Power Amplifier output power setting bits in RF_PWR Register.|
Up to six nRF24L01+s configured as PTX can communicate with one nRF24L01+ configured as a PRX. Alldata 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.
• CRC enabled/disabled (CRC always enabled when Enhanced ShockBurst™ is enabled)
• CRC encoding scheme
• RX address width
• Frequency channel
• Air data rate
pipes 1-5 share the four most significant address bytes. The LSByte must be unique for all six pipes. Figure below is an example of how data pipes 0-5 are addressed.
|Fig 6. Data Pipe pairs to be adressed for Rx/Tx, Transmit and Recieve Data Pipes will be assigned unique adresses, Pipe 0 and Pipe 1 are enabled by default.|
The PRX, using MultiCeiver, receives packets from more than one PTX. To ensure that the ACK packet from the PRX is transmitted to the correct PTX, the PRX takes the data pipe address where it received the packet and uses it as the TX address when transmitting the ACK packet. Figure below, is an example of an address configuration for the PRX and PTX. On the PRX the RX_ADDR_Pn, defined as the pipe address, must be unique . On the PTX the TX_ADDR must be the same as the
RX_ADDR_P0 and as the pipe address for the designated pipe. Only when a data pipe receives a complete packet can other data pipes begin to receive data .
As, shown in the above example, the Central Node, PRX is assigned with the following Rx Data Pipe addresses,(there will also be corresponding Tx address assigned to the Central Node, but we will not be looking into that), the Rx addresses of the Rx/Tx DataPipe assigned to the Central Node are:
Addr Data Pipe 0 (PRX_ADDR_P0): 0x7878787878
Addr Data Pipe 1 (PRX_ADDR_P1): 0xB3B4B5B6F1
Addr Data Pipe 2 (PRX_ADDR_P2): 0xB3B4B5B6CD
Addr Data Pipe 3 (PRX_ADDR_P3): 0xB3B4B5B6A3
Addr Data Pipe 4 (PRX_ADDR_P4): 0xB3B4B5B60F
Addr Data Pipe 5 (PRX_ADDR_P5): 0xB3B4B5B605
Now, say there 6 Transmitters having nRF24L01+ modules, PTx1, PTx2, PTx3, PTx4, PTx5 and PTx6s. Say, for the time, we are using the DataPipe 0, in each of these Transmitting modules and we have to set Tx address of the Rx/Tx Data Pipe with the correct Rx unique address of the PRX DataPipe,so that the DataPipe_X recieves the data destined from corresponding PTx. No Tx addresses should be same among the PTx modules. The user has to take care of that aspect, in which case incorrect operation of logic can happen. The following way, the trasmission operation will take place between the 6 PTx Nodes and the PRx central node:
PTX2 (PTX2_ADDR_P2) : 0xB3B4B5B6CD ==> Data Pipe 2 (PRX_ADDR_P2): 0xB3B4B5B6CD
PTX3 (PTX3_ADDR_P3) : 0xB3B4B5B6A3 ==> Data Pipe 3 (PRX_ADDR_P3): 0xB3B4B5B6A3
PTX4 (PTX4_ADDR_P4) : 0xB3B4B5B60F ==> Data Pipe 4 (PRX_ADDR_P4): 0xB3B4B5B60F
PTX5 (PTX5_ADDR_P5) : 0xB3B4B5B605 ==> Data Pipe 5 (PRX_ADDR_P5): 0xB3B4B5B605
PTX6 (PTX6_ADDR_P6) : 0x7878787878 ==> Data Pipe 0 (PRX_ADDR_P0): 0x7878787878
SPI Commands for accessing and controlling nRF24L01+ Registers and for Read/Write.
Section 8.3 of nRF24L01P_Product_Specification_1_0.pdf, describes the SPI commands and the required Timing. The SPI commands are shown in Table below. Every new command must be started by a high to low transition on CSN. The STATUS register is serially shifted out on the MISO pin simultaneously to the SPI command word shifting to the MOSI pin.
The serial shifting SPI commands is in the following format:
<Command word: MSBit to LSBit (one byte)>
<Data bytes: LSByte to MSByte, MSBit in each byte first>
|Fig. 8 SPI Commands for accessing Status Registers, and Read/Write Operation|
SPI operation and timing is shown in Fig. below. nRF24L01+ must be in a standby or power down mode before writing to the configuration registers.
|Fig. 9 SPI Command timing diagram for Read/Write and reading configuration registers.|
Setting up the RaspberryPi's.
This section describes the setup of the nRF24L01+ Modules with RaspberryPis. Two RaspberryPi have been used here. Two nRF24l01+ Modules have been used. One nRF24L01+ Module has been interfaced with a RaspberryPi, and the other has been interfaced with one RaspberryPi2. Thus, i am using the Module nRF24L01+ to communicate between two RaspberryPis wirelessly.
The 1st Module nRF24L01+ is connected to RaspberryPi, Model B. Please see, the Fritzing diagram given below:
|Fig. 10 1st module, nRF24L01+ interfaced to RaspberryPi, Model B|
The second nRF24L01+ Module has been interfaced with a RaspberryPi2, Model B. Later, we will see, how we are using one RaspberryPi as Transmitter and the other RaspberryPi2 as Reciever, using nRF24L01+. The below Fritzing diagram shows the connection of nRF24L01+ Module with RaspberryPi2.
|Fig. 11 2nd Module, nRF24L01+ interfaced with RaspberryPi2|
The Fritzing project for RaspberryPi2 interfaced with nRF24L01+ can be found and downloaded from the link below, where i have shared the .fzz, file. Download latest cool Release of Fritzing Tool from the following link(http://fritzing.org/download/).
After, setting up the connections, we will now look into the nRF24L01 Application program and the Libraries required to configure SPI, nRF24L01+ Routines on RaspberryPi and RaspberryPi2. Firstly, we need to configure the GPIOs and SPI pins to enable the /dev/spidev0.0 and /dev/spidev1.0 device Node for SPI, spi_bcm2708 Driver.
A wonderful Library has been provided towards this end by Mike, which works well with both RaspberryPi and RaspberryPi2. My concern while using it, was if it would work with RaspberryPi2. The latest version, of the library, bcm2835-1.46.tar.gz works well with both RaspberryPi and RaspberryPi2. The following version can be downloaded from the link below:
or users can access my shared drive, to download it, of the above link is'nt working.
After, that follow the below instructions to install the library to your RaspberryPi and RaspberryPi2.
# download the latest version of the library, say bcm2835-1.xx.tar.gz, then:
tar zxvf bcm2835-1.xx.tar.gz cd bcm2835-1.xx
sudo make check
sudo make install
NOTE: Raspberry Pi 2 (RPI2)
For this library to work correctly on RPI2, you MUST have the device tree support enabled in the kernel.
You should also ensure you are using the latest version of Linux. The library has been tested on RPI2 with
2015-02-16-raspbian-wheezy and ArchLinuxARM-rpi-2 as of 2015-03-29.
When device tree suport is enabled, the file /proc/device-tree/soc/ranges will appear in the file system,
and the bcm2835 module relies on its presence to correctly run on RPI2 (it is optional for RPI1). Without
device tree support enabled and the presence of this file, it will not work on RPI2.
To enable device tree support:
sudo raspi-config under Advanced Options - enable Device Tree and Reboot.
Library Sources and Applications.
Next, we will now look into the Library sources and the Application, use the below nRF24L01+ library, that i have shared below(This is meant for Rpi2, hence download or copy it to your Rpi2 Root File system):
Firstly, unzip this library on Rpi2 and install this library, as shown in the screen shot below:
|Fig. 12 Installing the nRF24L01+ Library on RaspberryPi2|
I will briefly outline the steps involved in installing and building the library.
After, extracting the nRF24L01+ Library, untar the 'RF24.tar' and go inside 'RF24' folder,
- First, clean the sources, #make clean.
- After, that do, #make all, and build all the sources.
- After, that install the sources, using #make install, which will install the libraries librf24-bcm.so.
- After, that go inside the folder, 'examples_RPi', and build the applications for RaspberryPi2, that we are going to see just now, using #make all.
The Library allows users to override the BCM2835 Driver for SPIDEV, and use some other customized driver or some other platform, like BeagleBone Black by using the using the command during 'make all' and 'make install',
#sudo make all -B RF24_SPIDEV=1
#sudo make install -B RF24_SPIDEV=1
This is so, because if we look at the Makefile, present inside RF24 directory,as shown below:
|Fig. 13 RF24_SPIDEV Flag used to override the usage of BCM2835 Driver, spidev0.0/spidev1.0.|
As, shown above, in the Make Rule, ifeq "$(RF24_SPIDEV)" "1", then RPI variable is assigned '0'. Later below we are checking if this variable 'RPI' is set or not, based on which the Driver directory is picked inside the 'RF24/utility',
ifeq "$(RF24_MRAA)" "1" // For MRAA Board ?
< Pick the Driver for MRAA Board>
else ifeq "$(RPI)" "1" // Else for Rpi Board
< Pick the Driver for Rpi Board>
else // Else for BBB(BeagleBone Black board
< Pick the Driver for BBB Board>
Now, that we have built and installed the Libraries for SPI and nRF24L01+, its time to check the correctness of our Library. Before that, i would like to point out the minor changes and adjustments that had to be done in the Library sources. The CSN signal needs to be pulled HIGH after being pulled LOW, in RF24.cpp, as shown below(SEE: Timing Diagram, Fig. 9, CSN signal is Pulled LOW during the Transfer and Commands, and Pulled HIGH, after Transfer is over):
|Fig. 14 Making CSN Signal HIGH, after pulling it LOW, in the Library file, RF24.cpp, required otherwise NRF24L01+ Resets after 1st Transfer.|
Similarly, in other functions, the CSN Signal has to be pulled HIGH, after pulled down LOW, in RF24.cpp. The file, RF24.cpp is present inside /RF24 Directory.
uint8_t RF24::read_register(uint8_t reg, uint8_t* buf, uint8_t len)
status = SPI.transfer( R_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
*buf++ = SPI.transfer(0xff);
uint8_t RF24::write_register(uint8_t reg, const uint8_t* buf, uint8_t len)
status = SPI.transfer( W_REGISTER | ( REGISTER_MASK & reg ) );
while ( len-- )
Please refer the file RF24.cpp inside RF24 directory of the shared library sources zip, or refer the RF24.cpp file shared in my Google Drive path below:
Install the same Library,that i have shared above on RaspberryPi also. In the same way, and fashion, as described above. Thus, now we have installed the nRF24L01+ Library on RaspberryPi and RaspberryPi2.
Now, we shall look into making use of our Library. For, this we don't need to look any further. Examples aplenty are provided for RaspberryPi inside the folder, 'RF24/examples_RPi'. If, one needs to build it separately, one can do so, using #make all inside 'examples_RPi' directory.
The example that we will consider here is 'pingpair_dyn.cpp', present in '/RF24/examples_RPi' directory. What this Application does is, it Transfers and Recieves Payloads of varying(Dynamic) sizes. It sets up Radio Pipe addresses, to set up two Nodes/Pipes, one for Transmitting and the other for Receiving. The Application asks user to sets up the Role, as Transmitter or Receiver, and Transmits or Receives a chain of characters every time, in a continuous 'while' loop.
In the 'pingpair_dyn.cpp' application, we will see what configurations and pin mapping we are doing. When we are running this Application on RaspberryPi2, we will use this Pin mapping, as shown in the fig. below. The first thing, in this Application is the constructor call to create the RF24 'radio' object. This Initializes the SPI Pins, the SPI Mode, the SPI Speed and signal polarity and in accordance with the H/W SPI spidev0.0/spidev1.0 BCM2835 Driver. This is very very important. The Pin settings for the setup for Application 'pingpair_dyn.cpp' on Rpi2 should be,
// Setup for GPIO 15 CE and CE0 CSN with SPI Speed @ 8Mhz
RF24 radio(RPI_V2_GPIO_P1_15, RPI_V2_GPIO_P1_24, BCM2835_SPI_SPEED_8MHZ);
|Fig. 15 For RPi2, RF24 Radio object constructor to map the Pins used to the Hardware SPI driver and initialize the settings.|
In RaspberryPi1, RaspberryPi Model B, we will have the below setup, for the Application 'pingpair_dyn.cpp'. GPIO22 Pin will be setup as CE and CE0 Pin will be setup as CSN.
// Setup for GPIO 22 CE and CE0 CSN with SPI Speed @ 4Mhz
RF24 radio(RPI_V2_GPIO_P1_22, BCM2835_SPI_CS0, BCM2835_SPI_SPEED_4MHZ);
Please see the fig. below for the RF24 radio object constructor initialization for RaspberryPi, Model B(RPi1).
|Fig. 16 For RaspberryPi, Model B, RF24 Radio object constructor to map the Pins used to the Hardware SPI driver and initialize the settings.|
Now, for some configuration Register setting, i have disabled the CRC, as shown in the lines below, and since the two Raspberry Pis are communicating, thus the Transmitting Pipe Address of one RaspberryPi should be the same used by the Receiving Pipe of the other RaspberryPi.
|Fig. 17 CRC Checking has been disabled for the Application, and Pipe and Pipe are used interchangeably as Transmitting and corresponding Receiving Pipe.|
So, the Configuration looks basically like this, if we run the Application, 'pingpair_dyn' on RaspberryPi2
|Fig. 18 nRF24L01+ Configuration Register values and SPI settings for RaspberryPi2.|
Similarly, for RaspberryPi1(RaspeberryPi, Model B), the configuration looks something like this, as shown below in Fig 19. The Library and the Packages will be installed the same way, as described above, for RaspberryPi too. The same packages and library will be used for RaspberryPi, Model B(nRF24L01+ and BCM2835 Library). The only difference will be in the Application, 'pingpair_dyn.cpp' file. For, more Reference, please refer to the attached file, 'pingpair_dyn.cpp'. Replace the file 'pingpair_dyn.cpp' in '/examples_Rpi' directory with this file given in the link below on RaspberryPi, Model B.
|Fig. 20 nRF24L01+ Configuration Register values and SPI Settings for RaspberryPi, Model B.|
One thing to notice here are the values of the Register. The value of the CONFIG Register for RaspberryPi2 is 0x07, while for RaspberryPi, Model B, it is 0x06. If, we refer the Datasheet, "nRF24L01P_Product_Specification_1_0.pdf", at page no. 57, Section 9.1, we see that the last three bits are Read/Write which are for PRIM_RX, PWR_UP and CRC0. The fourth bit is for EN_CRC. Since, we are disabling the CRC checksum processing in our Application, using 'disableCRC()' call, hence the EN_CRC Bit will be 0, which means Disable CRC. In case of RaspberryPi2, CONFIG Register PRIM_RX Bit is High, signifying, when we ran this Application, pingpair_dyn, we were asked to select a Role, and we selected RaspberryPi2, to be acting as a Receiver, PRIM_RX -> HIGH which means it acts as PRX Node.
|Fig. 21 CONFIG Register Bit mapping, EN_CRC Bit set LOW, and PRIM_RX set '0' and '1' for Receiver and Transmitter.|
Similarly, if we wish to set the RF Channel Frequency, then we need to set the RF_CH Register. We have set the value in RF_CH Register as 0x4c, which is 76 in decimal, for both RaspberryPi, Model B as well as RaspberryPi2. The RF Channel Frequency is calculated using the below Relation:
F0= 2400 + RF_CH [MHz]
= 2400 + 76 = 2476 Mhz = 2.476 Ghz
Thus, our Center Frequency for our Radio Channel is 2.476Ghz.
For RaspberryPi, Model B, we have,
|Fig. 22 RaspberryPi, Model B setup as Transmitter, and sending Transmissions.|
RaspberryPi2 is setup as receiver, and we are getting the following output as shown below,
|Fig. 23 RaspberryPi2 setup as Receiver, with incoming reception as shown.|
Please find the following Resources shared in my Google drive:
- Link for BCM2835 Library from Mike. Install it on both RaspberryPi, ModelB and RaspberryPi2.
- Link for nRF24L01+ Library, install it for both RaspberryPi2 and RaspberryPi, Model B.
- Link for Application, pingpair_dyn.cpp file for RaspberryPi, ModelB.
- Link for Executable binary, pingpair_dyn for RaspberryPi, ModelB.
- Link for Application, pingpair_dyn.cpp file for RaspberryPi2.
- Link for Executable binary, pingpair_dyn file for RaspberryPi2.
Pics and Stuff.
Below are a few pics of my Setup. Hope you are inspired and rejuvenated by the effort and the show,
Here is the setup Pic of RaspberryPi, Model B with nRF24L01+
Here is the setup Pic of RaspberryPi2 with nRF24L01+, (u can see blur on my LCD, as Transmission and Reception was ongoing, when i snapped this pic up):
Here are my little bunnies, my nRF modules with the RaspberryPis.
And here is my small YouTube Video that i made showing the actual Reception and Transmission as it is happening up.
Enjoy everyone out there, and Comments and Thoughts most welcome !!