This is the second part of my last post. In case you haven't read it yet, I suggest you do it before reading this one. If you aren't interested in the Arduino part, just read the introduction, the description of the modules and the SPI background. In this part I'll prepare de Raspberry Pi and test its communication with the Arduino.

Using the Rasbperry Pi from your computer

I'll be using a Raspberry Pi Model B with Raspbian. As I don't have an extra monitor and I don't want to be switching keyboards, I'll be using it from my PC through ssh. To do this you need a ssh client like PuTTY and your Raspberry Pi IP address. In case it has a static IP, you should already know it. In case it's using DHCP, you can check your router o search for a lan scanner software. Once you have the address all you have to do is put it in your client. When you are asked for user and password just use the same you use to log in to the Raspberry Pi (By default the user "pi" and the password "raspberry"). In case this is not working you may have an old Raspbian's image, you can search a solution for your specific image or just use a new one.

First step: Update

Before doing anything, you should update your Raspberry Pi with the latest packages. To do this you just have to execute this two commands:

sudo apt-get update
sudo apt-get upgrade

In case you have no idea what they do, the first one updates de package list, while de second one updates your installed packages to the latest version.

Software SPI vs Hardware SPI

In my previous post I said that we were going to use SPI communication. As in any communication protocol, the SPI protocol defines many tasks needed to be done, as synchronization and timing. One way to implement this functions is called bit banging and means that they will be implemented on software. The states of the wires from the bus will be set and sampled by software directly, which will be responsible for all the parameters of the signal. The other way is to use dedicated hardware. This hardware will handle all the signaling, giving the software a higher level interface through the driver.

Bit banging usually comes in handy when you don't have dedicated hardware and you can't incorporate it to your embeded system or you don't want to spend money. Although it has its disadvantages: it consumes a lot more CPU cycles (all the changes in the signals are made with CPU instructions) and it's usually less reliable, specially with high speeds.

Why bother explaining this? The Raspberry Pi has a Broadcom BCM2835 SoC (System-on-a-Chip) which includes CPU, GPU and many peripherals, including hardware SPI. If you want to see the chip, you won't find it because it's under the RAM chip... well, you can see its sides. Unfortunately, Raspbian image usually comes with hardware SPI disabled (I'm not sure in the latest versions, but you could check) and most examples use bit-banging. So why would we want to use software SPI if we have hardware available? Let's enable it.

Enabling Hardware SPI

These are the steps that worked for me, but if you have a recent Raspbian image maybe you can't ignore the first ones. You may try from step 4 and if it's already working you may continue with the guide without the previous steps. If not you can try following the guide from step 2. If it works go on, if it doesn't do all the steps. If you aren't sure of what to do just follow the entire guide and there won't (there shouldn't) be a problem.

1. Get and run rpi-update. You can do it from GitHub or from the repositories. I did it from the repositories and all worked fine:

sudo apt-get install rpi-update

If you want to do it from GitHub follow this steps:

sudo apt-get install git
sudo wget -O /usr/bin/rpi-update && sudo chmod +x /usr/bin/rpi-update

To run it, no matter how you installed:

sudo rpi-update

This will update your Raspberry Pi firmware, it make take a while but you usually won't have problems with it.

2. Enable the SPI driver by using raspi-config

sudo raspi-config

On the menu go to 9. Advanced Options and then A6 SPI. When the confirmation dialog asks you if you want to enable the SPI interface select Yes (really). When it asks you if you want the module to be loaded by default select Yes again.

You may also need to remove the driver from the blacklist. To do it open the file /etc/modprobe.d/raspi-blacklist.conf as root with your favourite editor (if you are unsure, use nano):

sudo nano /etc/modprobe.d/raspi-blacklist.conf

and add a # before spi-bcm2708, like this:


If the file doesn't exist don't worry, you are OK.

3. Reboot by selecting Yes when raspi-config asks you, or on the console with:

sudo reboot now

4. Check if the driver is loaded. For that go to your /dev folder and check if the SPI devices are there (spidev0.0 and spidev0.1). You can do this running:

ls /dev | grep spidev

and you should get both lines.


5. Check the SPI bus by connecting the MISO and MOSI pins (we'll make a loopback) with a cable and running the following test:

gcc -o spidev_test spidev_test.c
./spidev_test -D /dev/spidev0.0

The output should be something like:

spi mode: 0
bits per word: 8<
max speed: 500000 Hz (500 KHz)
40 00 00 00 00 95
F0 0D

Connecting the module to the Raspberry Pi

This step is similar to the Arduino one, just connecting the module pins to the right RaspberryPi pins. Having a breakout board or at least a cable for the Raspberry Pi IO pings makes this step a lot easier. The connections are:

nRF24L01+ Pin


Raspberry Pi Pin

Wire Color (Just for reference)

































I'm not including the mapping to physical pin numbers since they change between Raspberry Pi versions, so search them with the model you are using.

Getting the library

On the software side we'll be using the same library as on the Arduino. First you need to install Git if you don't have it yet:

sudo apt-get install git

Then follow the instructions on the official docs to get the library and run the example. I'm replicating here the manual instal instructions which are the ones I followed:

1. Make a directory to contain the RF24 and possibly RF24Network lib and enter it:

mkdir ~/rf24libs
cd ~/rf24libs

2. Clone the RF24 repo:

git clone RF24

3. Change to the new RF24 directory

cd RF24

4. Build the library, and run an example file:

sudo make install
cd examples_RPi
sudo ./gettingstarted

If everything went ok you should get something like (again if you get all zeroes something is wrong):

================ SPI Configuration ================
CSN Pin = CE0 (PI Hardware Driven)
CE Pin = Custom GPIO22
Clock Speed = 8 Mhz
================ NRF Configuration ================
RX_ADDR_P0-1 = 0x65646f4e32 0x65646f4e31
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0x65646f4e32
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x4c
RF_SETUP = 0x07
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 1MBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MAX
************ Role Setup ***********
Choose a role: Enter 0 for pong_back, 1 for ping_out (CTRL+C to exit)

The Final Test

So everything seems to be working but... is it? Plug in your Arduino, run the same sketch from the previous post and open the serial monitor. By default the Arduino example works as a receiver until you toggle it, so we will leave it like that for now. Now plug in your Raspberry Pi and run the same example as before, when it asks you to choose a role enter 1 for ping_out (transmitter).
You should start getting on the Raspberry Pi shell messages like:

Now sending...
Got response 624553, round-trip delay: 2

And messages like:

Sent response 624553

on the Arduino Serial Monitor.
With this example the Raspberry Pi is emitting messages, the Arduino receives them and answers them.

To test the communication in the other way, stop the Raspberry Pi test (Ctrl+C) and run it again, but this time select 0 for pong_back. The on the Arduino shell send a T to swith to transmitter. Instantly the Arduino should start showing messages like:

Now sending
Sent 341998704, Got response 341998704, Round-trip delay 1724 microseconds

And the Raspberry Pi messages like:

Got payload(4) 341998704...

With this, you've got your to boards communicating. Now you should explore the library docs and the examples to find how to send and receive your own data. If you are feeling adventurous you can even check how to make more complex networks with many devices or things like that.

I hope you liked the post (and sorry for the delay between the two parts). I'll try to keep this blog more up to date.