Sending Multiple Messages with the NRF24L01+

I have been using the NRF24L01+ with the RF24 library for some time now. They have been working fine, apart from some transmission and power issues, for sending wireless information between Arduino’s. I am building a project that requires a lot of information to be sent over these modules, and from looking online have realized that the NRF’s only send 32 bytes of data at a time.

I have tried to use the setPaylaodSize() command, but it seems that you cannot increase the payload past this 32 byte limit, only lower it. So I have tried to send the all the information as two different messages. I got the information to technically transmit, but its gets garbled a lot, and will switch the variables from the first packet with the second.

Can someone explain to me why this is happening? From my research I think it might have something to do with the pipes getting mixed messages, but there seems to be only 1 write pipe on the NRF. I will post the transmitting code in this post, and the receiving code in the next.

The transmitting code is as follows:

/*-----( Import needed libraries )-----*/
#include <SPI.h>   // Comes with Arduino IDE
#include "RF24.h"  // Download and Install (See above)
#include "printf.h" // Needed for "printDetails" Takes up some memory
/*-----( Declare Constants and Pin Numbers )-----*/
#define  CE_PIN  7   // The pins to be used for CE and SN
#define  CSN_PIN 8

/*-----( Declare objects )-----*/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus (usually) pins 7 & 8 (Can be changed) */
RF24 radio(CE_PIN, CSN_PIN);

/*-----( Declare Variables )-----*/
byte addresses[][6] = {"1Node", "2Node"}; // These will be the names of the "Pipes"

unsigned long timeNow;  // Used to grab the current time, calculate delays
unsigned long started_waiting_at;
boolean timeout;       // Timeout? True or False


/**
  Create a data structure for transmitting and receiving data
  This allows many variables to be easily sent and received in a single transmission
  See http://www.cplusplus.com/doc/tutorial/structures/
*/
struct dataStruct {
  unsigned long _micros;  // to save response times

  double transmit_1;
  double transmit_2;
  double transmit_3;
  double transmit_4;
  double transmit_5;
  double transmit_6;
  double transmit_7;
} myData;                 // This can be accessed in the form:  myData.Xposition  etc.

struct dataStruct1 {
  double transmit_8;
  double transmit_9;
  double transmit_10;
} myData1;

#define TELEMETRY

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(115200);  // MUST reset the Serial Monitor to 115200 (lower right of window )
  printf_begin(); // Needed for "printDetails" Takes up some memory

  radio.begin();          // Initialize the nRF24L01 Radio
  radio.setChannel(108);  // Above most WiFi frequencies
  radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range

  // PALevelcan be one of four levels: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  //radio.setPALevel(RF24_PA_LOW);
    radio.setPALevel(RF24_PA_MAX);

  // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[0]);
  radio.openReadingPipe(1, addresses[1]);

  // Start the radio listening for data
  radio.startListening();
  

//  radio.printDetails(); //Uncomment to show LOTS of debugging information
}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
  
  /////////////////////////Transmission 1/////////////////////////////////////
  radio.stopListening();                                    // First, stop listening so we can talk.

    myData.transmit_1 = 1;  // Send some known fake data
    myData.transmit_2 = 2;
    myData.transmit_3 = 3;
    myData.transmit_4 = 4;
    myData.transmit_5 = 5;
    myData.transmit_6 = 6;
    myData.transmit_7 = 7;
    
  myData._micros = micros();  // Send back for timing

  Serial.print("Now sending  -  ");

  if (!radio.write( &myData, sizeof(myData) )) {            // Send data, checking for error ("!" means NOT)
    Serial.println("Transmit failed ");
  }

  radio.startListening();                                    // Now, continue listening
  started_waiting_at = micros();               // timeout period, get the current microseconds
  timeout = false;                            //  variable to indicate if a response was received or not

  while ( ! radio.available() ) {                            // While nothing is received
    if (micros() - started_waiting_at > 200000 ) {           // If waited longer than 200ms, indicate timeout and exit while loop
      timeout = true;
      break;
    }
  }

  if ( timeout )
  { // Describe the results
    Serial.println("Response timed out -  no Acknowledge.");
  }
  else
  {
    // Grab the response, compare, and send to Serial Monitor
    radio.read( &myData, sizeof(myData) );
    timeNow = micros();
  }

    ///////////////////////////////Transmisson 2///////////////////////////
    #ifdef TELEMETRY
    radio.stopListening(); 
    
    myData1.transmit_8 = 8;
    myData1.transmit_9 = 9;
    myData1.transmit_10 = 10;

  if (!radio.write( &myData1, sizeof(myData1) )) {            // Send data, checking for error ("!" means NOT)
    Serial.println("Transmit failed Packet 2 ");
  }

  radio.startListening();                                    // Now, continue listening
  started_waiting_at = micros();               // timeout period, get the current microseconds
  timeout = false;                            //  variable to indicate if a response was received or not

  while ( ! radio.available() ) {                            // While nothing is received
    if (micros() - started_waiting_at > 200000 ) {           // If waited longer than 200ms, indicate timeout and exit while loop
      timeout = true;
      break;
    }
  }

  if ( timeout )
  { // Describe the results
    Serial.println("Response timed out -  no Acknowledge (2).");
  }
  else
  {
    // Grab the response, compare, and send to Serial Monitor
    radio.read( &myData1, sizeof(myData1) );
  }
  #endif


  
    ///////////////////////////////////////////////////////////////////////

    // Show it
    Serial.print("Sent ");
    Serial.print(timeNow);
    Serial.print(", Got response ");
    Serial.print(myData._micros);
    Serial.print(", Round-trip delay ");
    Serial.print(timeNow - myData._micros);
    Serial.println(" microseconds ");
}//--(end main loop )---

The receving code:

/*-----( Import needed libraries )-----*/
#include <SPI.h>   // Comes with Arduino IDE
#include "RF24.h"  // Download and Install (See above)
#include "printf.h" // Needed for "printDetails" Takes up some memory

/*-----( Declare Constants and Pin Numbers )-----*/
#define  CE_PIN  12   // The pins to be used for CE and SN
#define  CSN_PIN 8

/*-----( Declare objects )-----*/
/* Hardware configuration: Set up nRF24L01 radio on SPI bus plus (usually) pins 7 & 8 (Can be changed) */
RF24 radio(CE_PIN, CSN_PIN);

/*-----( Declare Variables )-----*/
byte addresses[][6] = {"1Node", "2Node"}; // These will be the names of the "Pipes"

/**
  Create a data structure for transmitting and receiving data
  This allows many variables to be easily sent and received in a single transmission
  See http://www.cplusplus.com/doc/tutorial/structures/
*/
struct dataStruct {
  unsigned long _micros;  // to save response times

  double transmit_1;
  double transmit_2;
  double transmit_3;
  double transmit_4;
  double transmit_5;
  double transmit_6;
  double transmit_7;
} myData;                 // This can be accessed in the form:  myData.Xposition  etc.

struct dataStruct1 {
  double transmit_8;
  double transmit_9;
  double transmit_10;
} myData1;                // This can be accessed in the form:  myData.Xposition  etc.

#define TELEMETRY

void setup()   /****** SETUP: RUNS ONCE ******/
{
  Serial.begin(115200);   // MUST reset the Serial Monitor to 115200 (lower right of window )
  printf_begin(); // Needed for "printDetails" Takes up some memory

  radio.begin();          // Initialize the nRF24L01 Radio
  radio.setChannel(108);  // 2.508 Ghz - Above most Wifi Channels
  radio.setDataRate(RF24_250KBPS); // Fast enough.. Better range

//  radio.enableDynamicPayloads();
//  radio.setPayloadSize(64); ///set payload size from 32 to 64 bytes
  
  // PALevelcan be one of four levels: RF24_PA_MIN, RF24_PA_LOW, RF24_PA_HIGH and RF24_PA_MAX
  //radio.setPALevel(RF24_PA_LOW);
     radio.setPALevel(RF24_PA_MAX);

  // Open a writing and reading pipe on each radio, with opposite addresses
  radio.openWritingPipe(addresses[1]);
  radio.openReadingPipe(1, addresses[0]);

  // Start the radio listening for data
  radio.startListening();
//  radio.printDetails(); //Uncomment to show LOTS of debugging information
}//--(end setup )---


void loop()   /****** LOOP: RUNS CONSTANTLY ******/
{
//////////////////Transmisson 1////////////////////
  if ( radio.available())
  {

    while (radio.available())   // While there is data ready to be retrieved from the receive pipe
    {
      radio.read( &myData, sizeof(myData) );             // Get the data
    }

    radio.stopListening();                               // First, stop listening so we can transmit
    radio.write( &myData, sizeof(myData) );              // Send the received data back.
    radio.startListening();                              // Now, resume listening so we catch the next packets.
    
    Serial.println();
    Serial.print(myData._micros);
    Serial.print("\tT 1: ");
    Serial.print(myData.transmit_1);
    Serial.print("\tT 2: ");
    Serial.print(myData.transmit_2);
    Serial.print("\tT 3: ");
    Serial.print(myData.transmit_3);
    Serial.print("\tT 4: ");
    Serial.print(myData.transmit_4);
    Serial.print("\tT 5: ");
    Serial.print(myData.transmit_5);
    Serial.print("\tT 6: ");
    Serial.print(myData.transmit_6);
    Serial.print("\tT 7: ");
    Serial.print(myData.transmit_7);
    } 
  

////////////////////Transmisson 2///////////////////////
  #ifdef TELEMETRY
  if ( radio.available())
  {

    while (radio.available())   // While there is data ready to be retrieved from the receive pipe
    {
      radio.read( &myData1, sizeof(myData1) );             // Get the data
    }

    radio.stopListening();                               // First, stop listening so we can transmit
    radio.write( &myData1, sizeof(myData1) );              // Send the received data back.
    radio.startListening();
    
    Serial.print("\tT 8: ");
    Serial.print(myData1.transmit_8);
    Serial.print("\tT 9: ");
    Serial.print(myData1.transmit_9);
    Serial.print("\tT 10: ");
    Serial.print(myData1.transmit_10);
  }
  #endif
    //Serial.print("Packet Received - Sent response ");  // Print the received packet data
////////////////////////////////Print Options///////////////////////////////////
    
}//--(end main loop )---

Your Slave code seems to send the message back to the Master after every message. Getting that to work reliably while sending several messages will require some complex code on both sides to keep track of whereabouts in the process both parties are.

Much simpler would be to send all the parts of a message with a simple auto-acknowledgement at the end of each part and have the Slave store them appropriately. When the slave has all the parts you could, if you want, send the entire message back.

It would be a good idea to have a byte in each message that identifies that message’s place in the sequence.

Even then, receiving a message in several parts is not going to be straightforward because the Slave must have code to deal with the situation where it is expecting 4 parts but only 3 arrive.

Separately … In your Master code you seem to have the line

if (!radio.write( &myData, sizeof(myData) )) {

in two places.

Your code will be much easier to manage if you only have one line like that and loop through it as many times as necessary.

If you want to send (say) 150 bytes (150 / 32 = 4.7 approx - rounds up to 5) then something like

for (byte n = 0; n < 5; n++) {
    if ( ! radio.write( &myData[n], sizeof(myData[n])) {
        // deal with error
    }
}

I may not have the syntax perfect, but it should illustrate the idea

…R
Simple nRF24L01+ Tutorial