Saturday, February 07, 2015

Plain English Wireless Communication between Arduino and RPi

Chatting in numbers was fun last time, but my MCU boards have evolved to speak English.

A few days ago I got my Arduino Mini Pro to communicate with RPi using the NRF24L01+ by sending each other system time integers. This was done by using the modified RF24 library currently under development by TMRh20. That was great and all, but can they speak plain English? Why yes.

This library, as far as I have researched, is the only library that supplies both libraries for RPi and Arduino (and some Attiny85 boards) but also under active development. Looking for libraries when you're starting out with this NRF24L01+ chip can be an unnerving experience for newbies. There are several out there and developers will often tout theirs as the best or what not. I'm just a hobbyist, I don't care what's best or the license and what not. I just need it to work. TMRh20's library worked for me so I'm just going to stick with it.

Here I'm going to describe how I got everything to work and then move on to my current progress on modifying the communication to send string texts. My plan is to have them eventually speak JSON strings.

The parts needed are:

  • Arduino Mini Pro ($1.80 USD)
  • Raspberry Pi Model B ($35 USD)
  • NRF24L01+ modules ($1.10 USD per piece)
  • Dupont jumper wires ($0.99 USD per 40 piece)

You can opt your Arduino for any other Arduino (Nano, Uno, Mega, Micro, whatever). Now obviously, I purchased many of the parts from Chinese sellers from Aliexpress and Ebay so don't expect your costs to be as low as mine unless you order from China as well. Don't be surprised by 3~5 week delivery time though. Also, what's surprising about the cost is that you can clearly see it's easy to build a Wifi-enabled Arduino for less than $6 (I'm assuming the ESP8266 module rather than the NRF24L01+ here as the ESP8266 can actually connect to your home Wifi, those modules will cost about $4.00 USD). So those kickstarter campaigns promising you wifi-enabled Arduinos for $40+ are really just scams. Anyway, I'm digressing here.

TMRh20 has developed multiple libraries on top of the RF24 library but I have only used the basic RF24 library. You can follow his instructions on the github website to use a bash script to install the libraries, but I would just run a git clone on RF24. The install script really isn't any easier other than to download all the other libraries. So get the library and build the example files:

git clone https://github.com/tmrh20/RF24.git
cd RF24/examples_RPi
make

Let it build and leave it at that. Now the wiring. Just follow TMRh20's instructions.

PIN NRF24L01 RPI RPi -P1 Connector
1 GND rpi-gnd (25)
2 VCC rpi-3v3 (17)
3 CE rpi-gpio22 (15)
4 CSN rpi-gpio8 (24)
5 SCK rpi-sckl (23)
6 MOSI rpi-mosi (19)
7 MISO rpi-miso (21)
8 IRQ - -

Done? Check your wiring. Okay? Check it again. Are you sure it's alright? Do a final check. I made a lot of mistakes here because I was looking at the pins at an angle and would shove the wires to the wrong header pin. Okay. Now we're done for the RPi and let's put it aside for now.

Onto the Arduino. Add the library to the Arduino IDE. If you don't remember how, here's how..

  1. Download a copy of the same RF24 Library to your IDE development machine.
  2. Rename the file from RF24-master to RF24.zip.
  3. Open the RF24.zip without extracting the files and rename the root folder from RF24-master to RF24 using any archiving tool. Close and save the archive.
  4. (In Arduino IDE) Sketch > Import Library > "Add Library..", and proceed to choose the downloaded RF24.zip

For the pin connections, also follow TMRh20's instructions on the github webpage. Here's a copy:

PIN NRF24L01 Arduino UNO
1 GND GND
2 VCC 3.3V
3 CE digIO 7
4 CSN digIO 8
5 SCK digIO 13
6 MOSI digIO 11
7 MISO digIO 12
8 IRQ -

Note: If you were playing with Maniacbug's Arduino RF24 library, you'll need to change the CE/CSN pin from 9/10 to 7/8. Again, triple check your connections. Now load the RF24 "GettingStarted" example by selecting File > Examples > RF24 > GettingStarted in the Arduino IDE.

Upload the Arduino sketch to your Arduino and turn on the serial monitor (Alt + Shift + M). By default it is set to the receiving mode. It waits for incoming messages and sends a response. Leave it at that. SSh back into your RPi and run the example GettingStarted for RPi via:

sudo ./gettingstarted

Then you should get a response that looks something like this..

RF24/examples/GettingStarted/
================ SPI Configuration ================
CSN Pin    = CE0 (PI Hardware Driven)
CE Pin    = Custom GPIO22
Clock Speed  = 8 Mhz
================ NRF Configuration ================
STATUS   = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
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) 
>

If you see a bunch of 0's (0x00) in the details then you likely have bad connections so check your wiring. On the RPi inputting 0 will put you into receiving mode and 1 will put you into an endless looping transmit mode where it transmits the current system time. Put 1 in for now and return to your serial monitor on your Arduino and hopefully everything will have worked. You should see "Sent response ___.." messages whenever the RPi sends a message. If it doesn't, check your wires. Jiggle your jumper cables. Use a multimeter to test to see that all pins going to your NRF24L01+ isn't shorted.

When you get it working, try putting the Arduino into transmit mode and the RPi in receive mode. Lastly, try putting them into transmit mode. You'll know when it's not working.

Okay. Transmitting time is fun and all, but it's not really useful. I want to build a DIY Belkin Wemo and it's not going to be possible just by sending integers. So let's move on to making it sending strings. Let's start with the RPi side. Open up the gettingstarted.cpp in the examples_RPi folder on the RPi and look for

bool ok = radio.write( &time, sizeof(unsigned long));

This is the function that sends out the current time as a long to the Arduino. We want to modify the type of the message sent out as a string (or a char array) so I've made it into something like this:

unsigned char message[16] = "Hello, Arduino!";
bool ok = radio.write( &message, sizeof(unsigned char) * 16);

This says I'm going to be sending a message string of 16 characters and the string is "Hello, Arduino!". Now save this and run a make. After it finishes. Run it and put it into transmit mode. Return to your Arduino sketch and look for the similar line under the "************************ Pong Back Role **********************" segment. I've modified my snippet to:

    if( radio.available()){
      while (radio.available()) {  
        char message[16];
        radio.read( &message, sizeof(char) * 16); 
        Serial.print(F("Got message: "));
        Serial.println(String(message));
      }
      
      radio.stopListening(); 
      radio.startListening();   
   }

So this is similar to the RPi where now we're receiving char array message of 16 characters and we'll send it through the serial to your monitor. Upload it, and put your Arduino in receiving mode by inputting "R" followed by the enter key. Now you should see your RPi saying hello in plain English to your Arduino!

5 comments :

  1. Thank you! Various links to different pin configurations got confusing, but yours works with the gettingstarted that I got today (2015_08_10) from the tmrh20 RF24 git.

    ReplyDelete
  2. Hi, this is looking so easy but can't get it to work. I'm not using a Pi but 2 Arduinos. I have the original GettingStarted example working on both Arduinos and send and receive are working fine.
    I copied your changes to send strings but it's not working for me. I'm using Arduino IDE 1.6.5 Maybe it's the IDE version because I found several other examples sending strings (but much more complicated) which are not working either.
    Will try again later.

    ReplyDelete
    Replies
    1. I have not yet tried sending from one Arduino to another, but what shows up on the other end?

      Delete
    2. Make sure you set one of the arduinos to 1 in the first few lines of the set up. It resolved all my conflicts...not all, realizing that I was plugging the MISO into the IRQ on the wifi chip resolved the other!

      Delete
    3. Make sure you set one of the arduinos to 1 in the first few lines of the set up. It resolved all my conflicts...not all, realizing that I was plugging the MISO into the IRQ on the wifi chip resolved the other!

      Delete