Intro
In this blog post I will describe how I used the SPI interface of the Raspberry Pi 2 (and Raspberry Pi) to communicate with an Arduino board.
Both the RPi and Arduino are connected to a nRF24L01+ chip to communicate with each other via the SPI interface.
I will describe the practical details of the setup and will also share the sources which were used.
The GPIO usage on the Raspberry Pi 2 is exactly the same as on the Raspberry Pi B(+). In practice it might be that some expansion boards which fit on the Raspberry Pi B do not fit on the RPiB+ or RPi2 because pins 27,28 are right next to pins 25,26.
Setup
To use the GPIO pins on the Raspberry Pi 2 I used some (additional) electronic parts. I did the same tests with Raspberry Pi B Rev. 2.0 and Raspberry Pi 2 B.
The most important parts I used:
2x nRF24L01+
1x Raspberry Pi 2 / 1x Raspberry Pi B
1x Arduino UNO R3
2x Capacitor 220uF(*) (for the power to the nRF24L01+ chip)
To connect to the nRF24L01+ chip I used a straight 20 pin ribbon cable and for connecting to the GPIO pins of the Raspberry Pi an old IDE40 cable. (Note that if you try this yourself, you should pay attention that you have 40 pin cable without any shorts, a 80-wire / 40 pin cable will most likely have shorts to reduce crosstalk.)
(*) I still had this capacitor laying around, probably 10uF would have been sufficient.
Raspberry Pi (2) GPIO PINs
For both Raspberry Pi's the pins that I use are the same.
P01 : 3.3V : dark orange (*)
P25 : GND : black
P15 : GPIO22 : white (CE)
P19 : MOSI : yellow
P21 : MISO : green
P23 : SCLK : orange (*)
P24 : CSN : blue
We connect the pins from the RPi(2) to the nRF24L01+ chip. Vcc is 3.3V and for CE we use pin 15 (GPIO22) on the RPi(2). (For the rest we connect the MOSI of the RPi to the MOSI of the nRF24L01+ chip, ... )
In the test setup I used an old IDE40 cable. On both the RPi2 and RPi, pin 1 and 2 are at the edge of the board. Since some pins of the IDE cable are next to the board you will see that the wires on the other side of the IDE cable are inserted in a different position.
(*) It might not be that easy to see the difference between dark orange and orange in the pictures, but the dark orange is the "lonely" cable (7 pins next to the white cable).
IDE40 color | RPi(2) function | RPi(2) pin | nRF24L01+ pin | nRF24L01+ function | 20-pin color |
---|---|---|---|---|---|
dark orange | 3.3V | 01 | 2 | Vcc / 3.3V | yellow |
black | GND | 25 | 1 | GND | white |
white | GPIO22 | 15 | 3 | CE | white |
yellow | MOSI | 19 | 6 | MOSI | yellow |
green | MISO | 21 | 7 | MISO | green |
orange | SCLK | 23 | 5 | SCK | orange |
blue | CSN | 24 | 4 | CSN | blue |
Raspberry Pi 2 B:
The following table tries to show the relation between the pins on the RPi2 and the pins on the IDE40 cable:
__ | __ | __ | __ | __ | __ | __ | __ | __ | --- | --- | __ | __ | __ | __ | __ | __ | __ | __ | __ |
40 | 38 | 36 | 34 | 32 | 30 | 28 | 26 | 24 | 22 | 20 | 18 | 16 | 14 | 12 | 10 | 8 | 6 | 4 | 2 |
39 | 37 | 35 | 33 | 31 | 29 | 27 | 25 | 23 | 21 | 19 | 17 | 15 | 13 | 11 | 9 | 7 | 5 | 3 | 1 |
The "---" in the middle represents the notch in the midlle of the IDE cable (see pictures "RPi2: IDE40 ribbon cable / dupont wires").
{gallery} Raspberry Pi 2 IDE40 |
---|
RPi2: IDE40 ribbon cable |
RPi2: IDE40 ribbon cable / dupont wires |
Raspberry Pi B:
The following table tries to show the relation between the pins on the RPi and the pins on the IDE40 cable (xx means not used; pins sticking out next to the board):
__ | __ | __ | __ | __ | __ | __ | __ | __ | --- | --- | __ | __ | __ | __ | __ | __ | __ | __ | __ |
26 | 24 | 22 | 20 | 18 | 16 | 14 | 12 | 10 | 8 | 6 | 4 | 2 | xx | xx | xx | xx | xx | xx | xx |
25 | 23 | 21 | 19 | 17 | 15 | 13 | 11 | 9 | 7 | 5 | 3 | 1 | xx | xx | xx | xx | xx | xx | xx |
{gallery} Raspberry Pi IDE40 |
---|
RPi: IDE40 ribbon cable |
RPi: IDE40 ribbon cable / dupont wires |
nRF24L01+
"Top" view of the nRF24L01+ chip
|__ | |__ | |__ | |__ | |-- |
|__ | ___ | ___ | ___ | |
||| | ||||
||| | ||||
||| | ||||
2 | 4 | 6 | 8 | |
1 | 3 | 5 | 7 |
1 : GND
2 : VCC (3.3V)
3 : CE : white
4 : CSN : blue
5 : SCK : orange
6 : MOSI : yellow
7 : MISO : green
8 : IRQ : xx
The following table tries to show the relation between the nRF24L01+ pins and the pins on the 20-pin ribbon cable (xx means not used):
__ | __ | __ | __ | --- | --- | __ | __ | __ | __ |
2 | 4 | 6 | 8 | xx | xx | xx | xx | xx | xx |
1 | 3 | 5 | 7 | xx | xx | xx | xx | xx | xx |
{gallery} nRF24L01+ |
---|
nRF24L01+: chip |
nRF24L01+: dupont |
Software
By default SPI is not enabled on Raspbian to load it during the boot process execute sudo raspi-config then select Advanced and then enable the SPI kernel module.
You can also do sudo modprobe spi-bcm2708.
For both the RPi and Arduino, I used the TMRh20 library available on github (some RPi specific info).
If you download the library and do not follow the installation procedure, then you'll need to do sudo make and sudo make install to install the library.
The modified sources are just to transmit data between RPi and Arduino. By default this Arduino sketch will start in transmit mode, by pressing d it will go in "dump" mode, where it will dump the contents of the data array when it's received.
Arduino Sketch:
/* 2015-04-06 : Johan Boeckx - Arduino/RPi(2) nRF24L01+ : Arduino UNO R3 code Tested on Arduino UNO R3 and Raspberry Pi B Rev. 2.0 and Raspberry Pi 2 B TMRh20 2014 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. */ /** Reliably transmitting large volumes of data with a low signal or in noisy environments * This example demonstrates data transfer functionality with the use of auto-retry and auto-reUse functionality enabled. This sketch demonstrates how a user can extend the auto-retry functionality to any chosen time period, preventing data loss and ensuring the consistency of data. This sketh demonstrates use of the writeBlocking() functionality, and extends the standard retry functionality of the radio. Payloads will be auto-retried until successful or the extended timeout period is reached. */ #include <SPI.h> #include "nRF24L01.h" #include "RF24.h" #include "printf.h" /************* USER Configuration *****************************/ RF24 radio(7,8); // Set up nRF24L01 radio on SPI bus plus pins 7 & 8 unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15). // With a timeout period of 1000, the radio will retry each payload for up to 1 second before giving up on the transmission and starting over /***************************************************************/ const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. byte data[32] = {"_This is a message via NRF24L+!"}; //Data buffer volatile unsigned long counter; unsigned long rxTimer,startTime, stopTime, payloads = 0; //bool TX=1,RX=0,role=0, transferInProgress = 0; bool transferInProgress = 0; unsigned int TX=1,RX=0,role=1,lastrole=0,SKIP=2,RXPRINT=3,RXDUMP=4; unsigned int offset=0; void setup(void) { Serial.begin(57600); printf_begin(); radio.begin(); // Setup and configure rf radio radio.setChannel(1); // Set the channel radio.setPALevel(RF24_PA_HIGH); radio.setDataRate(RF24_250KBPS); //radio.setDataRate(RF24_2MBPS); radio.setAutoAck(1); // Ensure autoACK is enabled radio.setRetries(2,15); // Optionally, increase the delay between retries. Want the number of auto-retries as high as possible (15) radio.setCRCLength(RF24_CRC_16); // Set CRC length to 16-bit to ensure quality of data if (role == RX) { radio.openWritingPipe(pipes[0]); // Open the default reading and writing pipe radio.openReadingPipe(1,pipes[1]); radio.startListening(); // Start listening } else{ radio.openWritingPipe(pipes[1]); // Open the default reading and writing pipe radio.openReadingPipe(1,pipes[0]); radio.stopListening(); } radio.printDetails(); // Dump the configuration of the rf unit for debugging printf("\n\rRF24/examples/Transfer Rates/\n\r"); printf("*** PRESS 'T' to begin transmitting to the other node\n\r"); /* randomSeed(analogRead(0)); //Seed for random number generation for(int i=0; i<32; i++){ data[i] = random(255); //Load the buffer with random data } */ radio.powerUp(); //Power up the radio } void showData(void) { printf("Data: "); for(int i=0; i<32; i++){ if(isprint(data[i])) printf("%c", data[i]); else printf("."); } printf("\n\r"); } void loop(void){ if(role == TX){ delay(500); // Pause for a couple seconds between transfers printf("Initiating Extended Timeout Data Transfer\n\r"); unsigned long cycles = 1000; // Change this to a higher or lower number. This is the number of payloads that will be sent. unsigned long transferCMD[] = {'H','S',cycles }; // Indicate to the other radio that we are starting, and provide the number of payloads that will be sent radio.writeFast(&transferCMD,12); // Send the transfer command if(radio.txStandBy(timeoutPeriod)){ // If transfer initiation was successful, do the following startTime = millis(); // For calculating transfer rate boolean timedOut = 0; // Boolean for keeping track of failures for(int i=0; i<cycles; i++){ // Loop through a number of cycles data[0] = i; // Change the first byte of the payload for identification if(!radio.writeBlocking(&data,32,timeoutPeriod)){ // If retries are failing and the user defined timeout is exceeded timedOut = 1; // Indicate failure counter = cycles; // Set the fail count to maximum break; // Break out of the for loop } } stopTime = millis(); // Capture the time of completion or failure //This should be called to wait for completion and put the radio in standby mode after transmission, returns 0 if data still in FIFO (timed out), 1 if success if(timedOut){ radio.txStandBy(); } //Partially blocking standby, blocks until success or max retries. FIFO flushed if auto timeout reached else{ radio.txStandBy(timeoutPeriod); } //Standby, block until FIFO empty (sent) or user specified timeout reached. FIFO flushed if user timeout reached. }else{ Serial.println("Communication not established"); //If unsuccessful initiating transfer, exit and retry later counter = cycles+1; } if (counter <= cycles ) { float rate = cycles * 32 / (stopTime - startTime); //Display results: Serial.print("Transfer complete at "); Serial.print(rate); printf(" KB/s \n\r"); Serial.print(counter); Serial.print(" of "); Serial.print(cycles); Serial.println(" Packets Failed to Send"); //if (counter == 0) showData(); } counter = 0; Serial.print("------------------------------------------------------------\r\n\r\n"); } if(role == RX){ if(!transferInProgress){ // If a bulk data transfer has not been started if(radio.available()){ //Serial.print("Rx\r\n"); //Serial.print("."); radio.read(&data,32); //Read any available payloads for analysis if(data[0] == 'H' && data[4] == 'S'){ // If a bulk data transfer command has been received payloads = data[8]; // Read the first two bytes of the unsigned long. Need to read the 3rd and 4th if sending more than 65535 payloads payloads |= data[9] << 8; // This is the number of payloads that will be sent counter = 0; // Reset the payload counter to 0 transferInProgress = 1; // Indicate it has started startTime = rxTimer = millis(); // Capture the start time to measure transfer rate and calculate timeouts } } }else{ if(radio.available()){ // If in bulk transfer mode, and a payload is available //Serial.print("Rx\r\n"); radio.read(&data,32); // Read the payload rxTimer = millis(); // Reset the timeout timer counter++; // Keep a count of received payloads }else if(millis() - rxTimer > timeoutPeriod){ // If no data available, check the timeout period Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer transferInProgress = 0; //Serial.print("!\r\n"); }else if(counter >= payloads){ // If the specified number of payloads is reached, transfer is completed //Serial.print("!\r\n"); startTime = millis() - startTime; // Calculate the total time spent during transfer float numBytes = counter*32; // Calculate the number of bytes transferred Serial.print("Rate: "); // Print the transfer rate and number of payloads Serial.print(numBytes/startTime); Serial.println(" KB/s"); printf("Payload Count: %d (%c)\n\r", counter, (char* )data[1]); showData(); transferInProgress = 0; // End the transfer as complete } } } if(role == RXDUMP){ if(radio.available()){ radio.read(&data,32); //Read any available payloads for analysis showData(); } } if(role == RXPRINT){ if(!transferInProgress){ // If a bulk data transfer has not been started if(radio.available()){ //Serial.print("Rx\r\n"); Serial.print("."); radio.read(&data,32); //Read any available payloads for analysis if(data[0] == 'H' && data[4] == 'S'){ // If a bulk data transfer command has been received payloads = data[8]; // Read the first two bytes of the unsigned long. Need to read the 3rd and 4th if sending more than 65535 payloads payloads |= data[9] << 8; // This is the number of payloads that will be sent counter = 0; // Reset the payload counter to 0 transferInProgress = 1; // Indicate it has started startTime = rxTimer = millis(); // Capture the start time to measure transfer rate and calculate timeouts } } }else{ if(radio.available()){ // If in bulk transfer mode, and a payload is available Serial.print("."); radio.read(&data,32); // Read the payload rxTimer = millis(); // Reset the timeout timer counter++; // Keep a count of received payloads }else if(millis() - rxTimer > timeoutPeriod){ // If no data available, check the timeout period Serial.println("Transfer Failed"); // If per-payload timeout exceeeded, end the transfer transferInProgress = 0; Serial.print("!\r\n"); }else if(counter >= payloads){ // If the specified number of payloads is reached, transfer is completed Serial.print("!\r\n"); startTime = millis() - startTime; // Calculate the total time spent during transfer float numBytes = counter*32; // Calculate the number of bytes transferred Serial.print("Rate: "); // Print the transfer rate and number of payloads Serial.print(numBytes/startTime); Serial.println(" KB/s"); printf("Payload Count: %d (%c)\n\r", counter, (char* )data[1]); showData(); transferInProgress = 0; // End the transfer as complete delay(500); } } } if(role == SKIP){ } // // Change roles // if ( Serial.available() ) { char c = toupper(Serial.read()); printf("*** SERIAL : %c %d\n\r", c, c); if ( c == 'C' && role == SKIP) { role = lastrole; printf("*** CONTINUING PREVIOUS ROLE\n\r"); } else if ( c == 'D' && (role != RXDUMP )) { radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); radio.startListening(); printf("*** CHANGING TO RECEIVE DUMP ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); role = RXDUMP; // Become the primary receiver (pong back) } else if ( c == 'T' && (role != TX )) { printf("*** CHANGING TO TRANSMIT ROLE -- PRESS 'R' TO SWITCH BACK\n\r"); radio.openWritingPipe(pipes[1]); radio.openReadingPipe(1,pipes[0]); radio.stopListening(); role = TX; // Become the primary transmitter (ping out) } else if ( c == 'P' && (role != RXPRINT ) ) { radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); radio.startListening(); printf("*** CHANGING TO RECEIVE PRINT ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); role = RXPRINT; // Become the primary receiver (pong back) } else if ( c == 'R' && (role == RX) ) { radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); radio.startListening(); printf("*** CHANGING TO RECEIVE ROLE -- PRESS 'T' TO SWITCH BACK\n\r"); role = RX; // Become the primary receiver (pong back) } else if ( c == 'S' && role != SKIP) { lastrole = role; role = SKIP; showData(); printf("*** WAITING -- PRESS 'C' TO CONTINUE\n\r"); } else if ( c == 'M' ){ offset = 1; while ( c != 13 ) { if ( Serial.available() ) { c = Serial.read(); if ( c != 13 ){ offset++; if (offset>=32) offset = 1; data[offset] = c; printf("*** SERIAL : %c data[%d]=(%c)\n\r", c, offset, data[offset]); } } } } } }
Raspberry Pi (2) c code:
/* 2015-04-06 : Johan Boeckx - Arduino/RPi(2) nRF24L01+ : Raspberry Pi (2) code Tested on Arduino UNO R3 and Raspberry Pi B Rev. 2.0 and Raspberry Pi 2 B Copyright (C) 2011 J. Coliz <maniacbug@ymail.com> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License version 2 as published by the Free Software Foundation. 03/17/2013 : Charles-Henri Hallard (http://hallard.me) Modified to use with Arduipi board http://hallard.me/arduipi Changed to use modified bcm2835 and RF24 library TMRh20 2014 - Updated to work with optimized RF24 Arduino library */ #include <cstdlib> #include <iostream> #include <sstream> #include <string> #include <RF24/RF24.h> using namespace std; // // Hardware configuration // Configure the appropriate pins for your connections /****************** Raspberry Pi ***********************/ // Radio CE Pin, CSN Pin, SPI Speed // See http://www.airspayce.com/mikem/bcm2835/group__constants.html#ga63c029bd6500167152db4e57736d0939 and the related enumerations for pin information. // 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); // NEW: Setup for RPi B+ //RF24 radio(RPI_BPLUS_GPIO_J8_15,RPI_BPLUS_GPIO_J8_24, BCM2835_SPI_SPEED_8MHZ); // 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); // RPi generic: RF24 radio(22,0); /*** RPi Alternate ***/ //Note: Specify SPI BUS 0 or 1 instead of CS pin number. // See http://tmrh20.github.io/RF24/RPi.html for more information on usage //RPi Alternate, with MRAA //RF24 radio(15,0); //RPi Alternate, with SPIDEV - Note: Edit RF24/arch/BBB/spi.cpp and set 'this->device = "/dev/spidev0.0";;' or as listed in /dev //RF24 radio(22,0); /****************** Linux (BBB,x86,etc) ***********************/ // See http://tmrh20.github.io/RF24/pages.html for more information on usage // See http://iotdk.intel.com/docs/master/mraa/ for more information on MRAA // See https://www.kernel.org/doc/Documentation/spi/spidev for more information on SPIDEV // Setup for ARM(Linux) devices like BBB using spidev (default is "/dev/spidev1.0" ) //RF24 radio(115,0); //BBB Alternate, with mraa // CE pin = (Header P9, Pin 13) = 59 = 13 + 46 //Note: Specify SPI BUS 0 or 1 instead of CS pin number. //RF24 radio(59,0); /********** User Config *********/ // Assign a unique identifier for this node, 0 or 1 // 0 Rx / 1 Tx bool radioNumber = 0; unsigned long timeoutPeriod = 3000; // Set a user-defined timeout period. With auto-retransmit set to (15,15) retransmission will take up to 60ms and as little as 7.5ms with it set to (1,15). /********************************/ // Radio pipe addresses for the 2 nodes to communicate. // const uint8_t pipes[][6] = {"1Node","2Node"}; const uint64_t pipes[2] = { 0xABCDABCD71LL, 0x544d52687CLL }; // Radio pipe addresses for the 2 nodes to communicate. char data[32] = {"_A message from RPi w/ NRF24L+!"}; //Data buffer void showData(void) { printf("Data: "); for(int i=0; i<32; i++){ if(isprint(data[i])) printf("%c", data[i]); else printf("."); } printf("\n\r"); } int main(int argc, char** argv){ const int role_rx=0, role_tx=1; int role=role_rx; /********* Role chooser ***********/ printf("\n ************ Role Setup ***********\n"); string input = ""; char myChar = {0}; cout << "Choose a role: Enter 0 for Rx, 1 for Tx (CTRL+C to exit) \n>"; getline(cin,input); if(input.length() == 1) { myChar = input[0]; if(myChar == '0'){ cout << "Role: Rx " << endl << endl; }else{ cout << "Role: Tx " << endl << endl; role = role_tx; } } switch(role) { case role_rx : radioNumber=0; break; case role_tx : radioNumber=1; break; } /***********************************/ // Setup and configure rf radio radio.begin(); // optionally, increase the delay between retries & # of retries radio.setRetries(15,15); // Set the channel radio.setChannel(1); // Set the data rate //radio.setDataRate(RF24_2MBPS); radio.setDataRate(RF24_250KBPS); //radio.setPALevel(RF24_PA_MAX); radio.setPALevel(RF24_PA_MIN); if ( !radioNumber ) { radio.openWritingPipe(pipes[0]); radio.openReadingPipe(1,pipes[1]); memset(&data,'\0',sizeof(data)); radio.startListening(); } else { radio.openWritingPipe(pipes[1]); radio.openReadingPipe(1,pipes[0]); radio.stopListening(); } // Dump the configuration of the rf unit for debugging radio.printDetails(); printf("Start loop:\n"); // forever loop while (1) { if (radioNumber) { if (radio.writeBlocking(&data,sizeof(data),timeoutPeriod)) { printf("."); } else { printf("?"); } fflush(stdout); //printf("\n"); } else { // // Receive each packet, dump it // if(radio.available()){ // Read any available payloads for analysis radio.read(&data,32); // Dump the printable data of the payload showData(); fflush(stdout); } } delay(5); } // forever loop return 0; }
Raspberry Pi (2) output
Receive mode
When we receive a message, dump the data.
************ Role Setup ***********
Choose a role: Enter 0 for Rx, 1 for Tx (CTRL+C to exit)
>0
Role: Rx
================ 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 = 0xabcdabcd71 0x544d52687c
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0xabcdabcd71
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x02
RF_CH = 0x01
RF_SETUP = 0x21
CONFIG = 0x0f
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MIN
Start loop:
Data: H...S...........................
Data: .This is a message via NRF24L+!.
Transmit mode
If the write succeeds write a "." else a "?".
************ Role Setup ***********
Choose a role: Enter 0 for Rx, 1 for Tx (CTRL+C to exit)
>1
Role: Tx
================ 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 = 0x544d52687c 0xabcdabcd71
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0x544d52687c
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x01
RF_SETUP = 0x21
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_MIN
Start loop:
...????................................................................................................................................................................................................................................................................................................^C
Arduino Output
By default the Arduino starts in Transmit mode. When you press "d" it goes to "dump" mode, which means just dump the packet which is received.
STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0
RX_ADDR_P0-1 = 0x544d52687c 0xabcdabcd71
RX_ADDR_P2-5 = 0xc3 0xc4 0xc5 0xc6
TX_ADDR = 0x544d52687c
RX_PW_P0-6 = 0x20 0x20 0x00 0x00 0x00 0x00
EN_AA = 0x3f
EN_RXADDR = 0x03
RF_CH = 0x01
RF_SETUP = 0x25
CONFIG = 0x0e
DYNPD/FEATURE = 0x00 0x00
Data Rate = 250KBPS
Model = nRF24L01+
CRC Length = 16 bits
PA Power = PA_HIGH
Transmit mode
The Arduino sketch which was taken as basis, was meant to send a header packet and then x times a payload packet.
When we stop listening on the RPi to the packets coming from the Arduino, we will see errors on the serial output of the Arduino:
Initiating Extended Timeout Data Transfer
Transfer complete at 5.00 KB/s
0 of 1000 Packets Failed to Send
Data: .This is a message via NRF24L+!.
------------------------------------------------------------
Initiating Extended Timeout Data Transfer
Communication not established
------------------------------------------------------------
Dump mode
Data: _A message from RPi w/ NRF24L+!.
Sources
Github : https://github.com/TMRh20/RF24
Class documentation : Optimized High Speed NRF24L01+ Driver Class Documenation: Optimized High Speed Driver for nRF24L01(+) 2.4GHz Wireless Tr…
Raspberry Pi info : Optimized High Speed NRF24L01+ Driver Class Documenation: Raspberry Pi
Ethernet library : RF24Ethernet - TCP/IP over RF24Network: RF24Ethernet library: TCP/IP over RF24Network
Top Comments