nRF24l01 multiple transmitters to one receiver

Hello Guys,
I have been trying this for weeks. My goal is to set up 3 transmitters and 1 receiver. Basically each transmitter will read and send one set of data (pressure, temperature and status) to the receiver. I have one transmitter to one receiver setup. It works like charm, and setup second transmitter to the receiver, it also worked. When I tried to use on e receiver to receive the data from both transmitters, it only received one. The other one are reading all zeros.

I suspected the address(pipe #) wasn’t setup right but tried different ways, it still only read one set of data.

Please help!

/*
 * this is a working transmitting program that will send digital data out
 */

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

#include <Wire.h>

int address = 0x28; // 28 is the address
byte byte1, byte2, byte3, byte4;

RF24 radio (8, 10);
float p1 [10];
float t1 [10];
float s1 [10];


const uint64_t pipes[3] = {0xF0F0F0F0E1LL,0xB3B4B5B6CD,0xB3B4B5B6A3};

void setup()
{
  Wire.begin();
  radio.begin();
  Serial.begin(9600);
  
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(pipes[1]);
 
  radio.stopListening();

}

void loop()
{
   Wire.requestFrom(address, 4); // byte is 4;

  if (Wire.available()<=4 <=4) {//
    byte1 = Wire.read();
    byte2 = Wire.read();
    byte3 = Wire.read();
    byte4 = Wire.read();
  }

  long unsigned p_counts = (long unsigned)byte1 << 8
                           | (long unsigned)byte2;
  long unsigned t_counts = (long unsigned)byte3 << 8
                           | (long unsigned)byte4;
                            
   p1[0] = ((p_counts%16384-1638.0)/13107.0*20.0)-10.0;
   t1[0] = ((t_counts/32.0*200.0)/2047.0-50.0);
   s1[0] = (p_counts/16384);
   
   
   bool ok=radio.write(&p1, sizeof(p1));
    ok=radio.write(&t1, sizeof(t1));
    ok=radio.write(&s1, sizeof(s1));
   
     if(ok)
       {
 
          Serial.println("Pipe 1");
          Serial.println(p1[0]);
          Serial.println(t1[0]);
          Serial.println(s1[0]);
          
       }
      else
       {
          Serial.println("it failed to send");
       }
   delay(500);

the second transmitter is the same besides the pipe change to pipe2, parameters are p2, t2, and s2.

The receiver code look like this:

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio (8, 10);

float p1[10],p2[10],p3[10];
float t1[10],t2[10],t3[10];
float s1[10],s2[10],s3[10];

const uint64_t pipes[3] = {0xF0F0F0F0E1LL,0xB3B4B5B6CD,0xB3B4B5B6A3};

void setup()
{
  
  radio.begin();
  Serial.begin(9600); 
  radio.setDataRate(RF24_250KBPS);
  
  radio.openReadingPipe(1,pipes[0]);
  radio.openReadingPipe(2,pipes[1]);

   
  radio.startListening();
delay(1000);
}

void loop()
{
    if (radio.available()) 
    { 
       delay(100);
       radio.read(p1, sizeof(p1));
       radio.read(t1, sizeof(t1));
       radio.read(s1, sizeof(s1));

       delay(100);
       radio.read(p2, sizeof(p2));
       radio.read(t2, sizeof(t2));
       radio.read(s2, sizeof(s2));
       
       Serial.print ("Pressure   ");
       Serial.print ("Temperature   ");
       Serial.println ("Status");
       
       Serial.println("Pipe1");  
       Serial.println(p1[0]);
       Serial.println(t1[0]);  
       Serial.println(s1[0]);

       delay(100);
       Serial.println("Pipe2");
       radio.read(p2, sizeof(p2));
       radio.read(t2, sizeof(t2));
       radio.read(s2, sizeof(s2));
       
  /*       
       Serial.print ("Pressure    ");
       Serial.print ("Temperature=    ");
       Serial.println ("Status=    ");*/
             
       Serial.println(p2[0]);
       Serial.println(t2[0] );  
       Serial.println(s2[0] );
     
  /*     delay(100);
      
      }
  else
  {
    Serial.println("it failed to read");
  }
  delay(2500);
}

Output look like this:

Pressure Temperature Status
Pipe1
0.02
24.17
0.00
Pipe2
0.00
0.00
0.00
Pressure Temperature Status
Pipe1
0.02
24.17
0.00
Pipe2
0.02
24.17
0.00
Pressure Temperature Status
Pipe1
0.02
24.27
0.00
Pipe2
0.00
0.00
0.00
Pressure Temperature Status
Pipe1
0.03
24.27
0.00
Pipe2
0.00
0.00
0.00

Start simple.

Can you get something working where each of the senders transmits one byte and the receiver gets it properly?

Then try sending and receiving a float.

The nRF24s send and receive a series of bytes. I have never experimented with floats but I wonder if it will work the way you are trying or if you need to use a union to map the float array into a byte array.

Also note that the nRF24 sends data in 32 byte chunks and an array of 10 floats is much bigger than that.

You seem to have a huge delay() in your receiver code. Doesn't that mean that the senders overwhelm it with data.

Unless there a good reason for the system you are trying I would prefer a system in which the Master polls each slave in turn. That way the Master has control of the timing and there is no risk of the data from different slaves getting mixed up.

The pair of programs in this link may be useful. The master program can easily be extended to poll several slaves.

...R

A float can be sent by constructing a pointer to the first byte then sending sizeof(float_var).

I send a two layered array of double uint16_t as a structure in 32 byte packets. The pointer is advanced into the array so that each packet is a continuous sequence of 32 bytes. The array comes from Arduino code and ends up in Lazarus Pascal code. The byte order matches so the receiver doesn't know the path was serial/radio/serial.

Take a look at this code and see of it works for ya. i just added some of your code to one i had working in another project so some of it might be unnecessary but take a look and see.

Transmitter:

/*
 * this is a working transmitting program that will send digital data out
 */

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"

#include <Wire.h>

int address = 0x28; // 28 is the address
byte byte1, byte2, byte3, byte4;

RF24 radio (8, 10); //yours
//RF24 radio(7,8); //mine


struct dataStruct{
float p1;
float t1;
float s1; 
}transmitter1_data;

unsigned char ADDRESS0[5]  = 
{
  0xb1,0x43,0x88,0x99,0x45
}; // Define a static TX address
//just change b1 to b2 or b3 to send to other pip on resciever

void setup()
{
 // Wire.begin();
  radio.begin();
  Serial.begin(115200);
  printf_begin();
  radio.setRetries(15,15);
  radio.enableDynamicPayloads();
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(ADDRESS0);
  radio.openReadingPipe(0,ADDRESS0);
  radio.stopListening();
radio.printDetails();
}

void loop()
{
 /* 
   Wire.requestFrom(address, 4); // byte is 4;

  if (Wire.available()<=4 <=4) {//
    byte1 = Wire.read();
    byte2 = Wire.read();
    byte3 = Wire.read();
    byte4 = Wire.read();
  }

  long unsigned p_counts = (long unsigned)byte1 << 8
                           | (long unsigned)byte2;
  long unsigned t_counts = (long unsigned)byte3 << 8
                           | (long unsigned)byte4;
                           
   p1[0] = ((p_counts%16384-1638.0)/13107.0*20.0)-10.0;
   t1[0] = ((t_counts/32.0*200.0)/2047.0-50.0);
   s1[0] = (p_counts/16384);
   
   */
   transmitter1_data.p1=1002.36;
   transmitter1_data.t1=27.33;
   transmitter1_data.s1=15.9;
   
   bool ok=radio.write(&transmitter1_data, sizeof(transmitter1_data));

   
     if(ok)
       {
 
          Serial.println("Pipe 1");
          Serial.println(transmitter1_data.p1);
          Serial.println(transmitter1_data.t1);
          Serial.println(transmitter1_data.s1);
         
       }
      else
       {
          Serial.println("it failed to send");
       }
   delay(1000);
   
   
   
   
   
}

and receiver

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "printf.h"

RF24 radio (8, 10);//yours
//RF24 radio(9,10);//mine

#define PLOAD_WIDTH  32  // 32 unsigned chars TX payload
byte pip;
byte pload_width_now;
byte newdata;
unsigned char rx_buf[PLOAD_WIDTH]= {0};
struct dataStruct1{
float p1;
float t1;
float s1; 
}transmitter1_data;

struct dataStruct2{
float p1;
float t1;
float s1; 
}transmitter2_data;

struct dataStruct3{
float p1;
float t1;
float s1; 
}transmitter3_data;

unsigned char ADDRESS2[1]= {0xb2};	
unsigned char ADDRESS3[1]= {0xb3};	
unsigned char ADDRESS4[1]= {0xb4};	
unsigned char ADDRESS5[1]= {0xb5};	


unsigned char ADDRESS1[5]  = 
{
   0xb1,0x43,0x88,0x99,0x45
}; // Define a static TX address

unsigned char ADDRESS0[5]  = 
{
  0xb0,0x43,0x88,0x99,0x45
}; // Define a static TX address

void setup()
{
 
  radio.begin();
   printf_begin();
  Serial.begin(115200);
  radio.setDataRate(RF24_250KBPS);
 radio.enableDynamicPayloads();
  radio.openWritingPipe(ADDRESS0);
  radio.openReadingPipe(0,ADDRESS0);
   radio.openReadingPipe(1,ADDRESS1);
   radio.openReadingPipe(2,ADDRESS2);
   radio.openReadingPipe(3,ADDRESS3);
   radio.openReadingPipe(4,ADDRESS4);
   radio.openReadingPipe(5,ADDRESS5);

   
  radio.startListening();
  radio.printDetails();
delay(1000);
}

void loop()
{
 if ( radio.available(&pip) )
    {

      // Fetch the payload, and see if this was the last one.
      pload_width_now = radio.getDynamicPayloadSize();

      // If a corrupt dynamic payload is received, it will be flushed
      if(!pload_width_now){
        
      }
        else
        {
       
      radio.read( rx_buf, pload_width_now );

     newdata=1;

      // Spew it
      Serial.print(F("Data on pip= "));
      Serial.print(pip);
      Serial.print(F(" Got data size="));
      Serial.print(pload_width_now);
      Serial.print(F(" data="));
      for(byte i=0; i<pload_width_now; i++)
      {
          Serial.print(" ");
          Serial.print(rx_buf[i]);                              // print rx_buf
      }
      Serial.print(" ");
      }
    }
   if(newdata==1)
  {
  newdata=0;

if(pip==1&&pload_width_now==sizeof(transmitter1_data))
  {
   memcpy(&transmitter1_data, rx_buf, sizeof(transmitter1_data)); 
     
 
          
          Serial.print(" Pressure//temp//status ");
          Serial.print(transmitter1_data.p1);
          Serial.print(" // ");
          Serial.print(transmitter1_data.t1);
          Serial.print(" // ");
          Serial.print(transmitter1_data.s1);
   
   }
   
   if(pip==2&&pload_width_now==sizeof(transmitter2_data))
  {
   memcpy(&transmitter2_data, rx_buf, sizeof(transmitter2_data)); 
     
 
          
          
          Serial.print(" Pressure//temp//status ");
          Serial.print(transmitter2_data.p1);
          Serial.print(" // ");
          Serial.print(transmitter2_data.t1);
          Serial.print(" // ");
          Serial.print(transmitter2_data.s1);
   
   }
   
   if(pip==3&&pload_width_now==sizeof(transmitter3_data))
  {
   memcpy(&transmitter3_data, rx_buf, sizeof(transmitter3_data)); 
     
 
          
          
          Serial.print(" Pressure//temp//status ");
          Serial.print(transmitter3_data.p1);
          Serial.print(" // ");
          Serial.print(transmitter3_data.t1);
          Serial.print(" // ");
          Serial.print(transmitter3_data.s1);
   
   }



Serial.println("");
  }

delay(100);

}

@swe-dude: Its not working. It shows sa lot of nonsense characteristics

Thank you though

@Arctic_Eddie: How to setup pointer to array? I am not programming person. I send float before, it works. Just not work with more than one set of data

I changed the serial from 9600 to 115200, have you changed speed in serial monitor?

The TX example in post #3 performs that task.

bool ok=radio.write(&transmitter1_data, sizeof(transmitter1_data));

The & symbol gives it the value contained in a pointer and sizeof() is the byte quantity. This is what radio.write needs to send the data. The structure can contain about anything you want and that line would work. The same structure definition is needed on the RX end so that the bytes land in the same order and have the same meaning.

@swe-dude. Now I see what you mean by changing speed. Yes, it works with your program. But your data is fixed numbers, when I change it into read a array, it did not send data.

@Swe-dude:
instead of using:
/*
transmitter1_data.p1 = 1002.36;
transmitter1_data.t1 = 27.33;
transmitter1_data.s1 = 15.9;*/

I used to read data from my device and change them in to float as shown below by still using your transmitter1.data.p1 format… it did not receive any data. I change all p, t, s to allay p1[10], t1[10], etc, it still did not receive data. Any help here?

Wire.requestFrom(address, 4); // byte is 4;

if (Wire.available()<=4 <=4) {//
byte1 = Wire.read();
byte2 = Wire.read();
byte3 = Wire.read();
byte4 = Wire.read();
}

long unsigned p_counts = (long unsigned)byte1 << 8
| (long unsigned)byte2;
long unsigned t_counts = (long unsigned)byte3 << 8
| (long unsigned)byte4;

transmitter1_data.p1 = ((p_counts%16384-1638.0)/13107.020.0)-10.0;
transmitter1_data.t1 = ((t_counts/32.0
200.0)/2047.0-50.0);
transmitter1_data.s1 = (p_counts/16384);

@swe-dude:
Hi Thank you so very much! It works now.

The setting is much more professional and beyond my ability. :slight_smile:
I have a few questions in receiver file:

  1. I saw most people setup address with using “0xF0F0F0F0E1LL” style. so for different pipe, you change the last byte. In yours, with (0xb1, …), you change b1 to b2 b3 as you mentioned in yoru file. Can you explain a bit more on setting address?

  2. you setup two static TX address, why do we need two? Isnt this one way communication only?

3.I guess that my data was saved in the buffer (rx_buf)? what is pload? What does payload used for? I thought payload is combination of address+data from a sensor

  1. What is “data” or new data? It print out six pair of numbers, but what are they? How “data” related to my data?

Anyway, the important thing is that it works. I will spend more time to study these files. I have been reading so many demos on how to do multi device communication, none of them do as nearly good as this one.

Thank you again!!!

I am happy its finally working for you, i will try to answer the best i can.

pip 0-1 have 5 byte addresses , pip 2-5 share the most significant bytes with pip 1 and you only change LSB like this:

unsigned char ADDRESS1[5] =
{
0xb1,0x43,0x88,0x99,0x45
}; // Define a static TX address

unsigned char ADDRESS2[1]= {0xb2};
unsigned char ADDRESS3[1]= {0xb3};
unsigned char ADDRESS4[1]= {0xb4};
unsigned char ADDRESS5[1]= {0xb5};

That means pip 2 have address 0xb2,0x43,0x88,0x99,0x45
That means pip 3 have address 0xb3,0x43,0x88,0x99,0x45 …and so on

so if you change the address on the transmitter from: 0xb1,0x43,0x88,0x99,0x45 to 0xb2,0x43,0x88,0x99,0x45 you will send data to pip 2 on receiver instead of 1

This was a copy and paste job and i forgot to rename it should be RX address hehe sorry

3,4.
#define PLOAD_WIDTH 32 // 32 unsigned chars TX payload
byte pload_width_now;
unsigned char rx_buf[PLOAD_WIDTH]= {0};

Pload_with is the maximum number of bytes the nrf can send or receive (32)
pload_width_now is the size of the received payload so we know how many bytes to read from nrf
rx_buff is where the received data is stored before we take that data and put it into the dataStruct

for(byte i=0; i<pload_width_now; i++)
{
Serial.print(" ");
Serial.print(rx_buf*); // print rx_buf*

  • }*
  • Serial.print(" ");*
    This prints out all the bytes of data you just received, the bytes that gets combined into the data you sent, maybe not needed in your case but can be useful when something are not working right
  • if(newdata==1)*
  • {*
  • newdata=0;*
    This is just used to let the data sorting part of the code know there is new data to handle, also a bit of a leftover from the copy and paste
    I hope this helps a bit at least. and good luck with the rest of the project!!!

You are sooooo good! I wish I can always find you when I need help with Arduino stuff. I have almost read all the documents on multi device communication, but really disappointed because they are either not working at all or not exactly what I needed. The best one I liked is from Force Tronics, but a bit disappointed with random number generator. Again, thank you very very much! hope to see you around here.

Hello there,

I have trouble for receiving the data when I added touch screen to the setup. Basically for touch screen, it required to use pin 9, 10 besides 11, 12, 13 (SPI pins). For RF 24, I used pin 7,8 and CE, and CSN pins. 11, 12, and 13 were shared between two devices. When I tried to run either RF24 or touch screen separately, everything worked fine. After I hardwired the two devices together, I dont get rf reading anymore. In Touch screen, only get zero, on serial port, what confused me is that status changed. By the way, I used digitalWrite(chipSelectPin, LOW) and digitalWrite(chipSelectPin, HIGH); to turn slave pin on and off for RF device. digitalWrite(TFT_CS, LOW) and digitalWrite(TFT_CS, HIGH) to turn TFT on and off.

Here is status when only RF device connecting to Arduino.

STATUS = 0x0e RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=7 TX_FULL=0 RX_ADDR_P0-1 = 0x45998843b0 0x45998843b1 RX_ADDR_P2-5 = 0xb2 0xb3 0xb4 0xb5 TX_ADDR = 0x45998843b0 RX_PW_P0-6 = 0x20 0x20 0x20 0x20 0x20 0x20 EN_AA = 0x3f EN_RXADDR = 0x3f RF_CH = 0x4c RF_SETUP = 0x27 CONFIG = 0x0f DYNPD/FEATURE = 0x3f 0x04 Data Rate = 250KBPS Model = nRF24L01+ CRC Length = 16 bits PA Power = PA_MAX

Following is status after I connect both RF device and touch screen SPI pins together.

STATUS = 0x06 RX_DR=0 TX_DS=0 MAX_RT=0 RX_P_NO=3 TX_FULL=0 RX_ADDR_P0-1 = 0x0088800190 0x0088800190 RX_ADDR_P2-5 = 0x90 0x91 0x90 0x90 TX_ADDR = 0x0088800190 RX_PW_P0-6 = 0x00 0x00 0x00 0x00 0x00 0x00 EN_AA = 0x1f EN_RXADDR = 0x00 RF_CH = 0x04 RF_SETUP = 0x00 CONFIG = 0x00 DYNPD/FEATURE = 0x1f 0x00 Data Rate = 1MBPS Model = nRF24L01 CRC Length = 8 bits PA Power = PA_MIN

This Simple nRF24L01+ Tutorial may be of interest.

...R

linargonne: @swe-dude: Hi Thank you so very much! It works now.

The setting is much more professional and beyond my ability. :) I have a few questions in receiver file:

  1. I saw most people setup address with using "0xF0F0F0F0E1LL" style. so for different pipe, you change the last byte. In yours, with (0xb1, ...), you change b1 to b2 b3 as you mentioned in yoru file. Can you explain a bit more on setting address?

  2. you setup two static TX address, why do we need two? Isnt this one way communication only?

3.I guess that my data was saved in the buffer (rx_buf)? what is pload? What does payload used for? I thought payload is combination of address+data from a sensor

  1. What is "data" or new data? It print out six pair of numbers, but what are they? How "data" related to my data?

Anyway, the important thing is that it works. I will spend more time to study these files. I have been reading so many demos on how to do multi device communication, none of them do as nearly good as this one.

Thank you again!!!

Hey bro, how did you do to make it work woithout using fixed numbers?

NiceParrot: Hey bro, how did you do to make it work woithout using fixed numbers?

Have a look at my examples in the link in Reply #13. They use a simpler addressing system and you should easily see how you can change the address dynamically.

In my examples the array slaveAddress[] is created as a const. Obviously you need to drop that if you wish to be able to change the values.

...R

Robin2: Have a look at my examples in the link in Reply #13. They use a simpler addressing system and you should easily see how you can change the address dynamically.

In my examples the array slaveAddress[] is created as a const. Obviously you need to drop that if you wish to be able to change the values.

...R

Thank you for reply, i dont get it pal. My code just doesnt work :(, can give me a hand with this?.

NiceParrot:
Thank you for reply, i dont get it pal. My code just doesnt work :(, can give me a hand with this?.

As you have not posted your code yet I cannot comment on it.

You also need to explain in detail what you are trying to do.

Did you try the addressing system in my examples?

…R

linargonne: @swe-dude: Hi Thank you so very much! It works now.

The setting is much more professional and beyond my ability. :) I have a few questions in receiver file:

  1. I saw most people setup address with using "0xF0F0F0F0E1LL" style. so for different pipe, you change the last byte. In yours, with (0xb1, ...), you change b1 to b2 b3 as you mentioned in yoru file. Can you explain a bit more on setting address?

  2. you setup two static TX address, why do we need two? Isnt this one way communication only?

3.I guess that my data was saved in the buffer (rx_buf)? what is pload? What does payload used for? I thought payload is combination of address+data from a sensor

  1. What is "data" or new data? It print out six pair of numbers, but what are they? How "data" related to my data?

Anyway, the important thing is that it works. I will spend more time to study these files. I have been reading so many demos on how to do multi device communication, none of them do as nearly good as this one.

Thank you again!!!

Hi, I have the same requirement whe I will have 1 Master and 4 slaves. Sometimes the 4 slaves will send data at the same time. Have you done this? Im new with this device and in case you recommend it to me I will buy 5 of them to try what I want to do. Appreciate it

Unless you mean "the same time" as the same millisecond you will probably be fine i think it can handle around 1 message every 2 to 3 ms, as long as you deal with incoming data fast.