Arduino & Raspberry Pi talking wirelessly [Part 2]
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:
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:
If you want to do it from GitHub follow this steps:
To run it, no matter how you installed:
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
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):
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:
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:
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:
The output should be something like:
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 |
Line |
Raspberry Pi Pin |
Wire Color (Just for reference) |
1 |
GND |
GND |
Black |
2 |
3V3 |
3V3 |
Red |
3 |
CE |
GPIO22 |
Yellow |
4 |
CSN (SPI) |
CS0 |
Blue |
5 |
SCK (SPI) |
SCLK |
Brown |
6 |
MOSI (SPI) |
MOSI |
Green |
7 |
MISO (SPI) |
MISO |
White |
8 |
Interrupt |
- |
- |
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:
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:
2. Clone the RF24 repo:
3. Change to the new RF24 directory
4. Build the library, and run an example file:
If everything went ok you should get something like (again if you get all zeroes something is wrong):
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:
And messages like:
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:
And the Raspberry Pi messages like:
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.