nrf24L01 Recieving Multiple Pipes

Hi,

I have two transmitters (NRF24L01+UNO) both sending data on different pipe addresses to a reciever (NRF24L01+MEGA) but my data arrays are picking up mixed data.

Not sure if my programming method is correct, reciever code is below.
Any help or guidance would be appreciated.

#include <SPI.h>
#include <RF24.h>
#define CE_PIN   9
#define CSN_PIN 53
#define DHT11_PIN 11
#include <dht.h>

dht DHT;


const byte level_module_address = {0xF0F0F0F0E2LL};
const byte moisture_module_address = {0xF0F0F0F0E3LL};

RF24 radio(CE_PIN, CSN_PIN);

int level_data[5] = {0,0,0,0,0}; // Data from Link 1
int moisture_data[2] = {0,0};    // Data from Link 2
int ackData[2] = {0,0}; 
bool newData = false;


void setup() 
    {
    Serial.begin(250000);
    Serial.println("RF Comms Starting...");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    }


void loop(void) 
        {
        getData_level();    // Read RF Data from Link 1 
        getData_moisture(); // Read RF Data from link 2        
        showData();  
        }


void getData_level() {
     radio.openReadingPipe(0, level_module_address);
     radio.enableAckPayload();
     radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
     radio.startListening(); 
    
     if (radio.available() ) {
        radio.read( &level_data, sizeof(level_data) );
        newData = true;
        updateReplyData();  
    }
}

void getData_moisture() {
     radio.openReadingPipe(1, moisture_module_address);
     radio.enableAckPayload();
     radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
     radio.startListening(); 
    
    if (radio.available() ) {
        radio.read( &moisture_data, sizeof(moisture_data) );
        newData = true;
        updateReplyData(); 
    }
}

void showData() {
    if (newData == true) {
        //
        // Print actual data on serial monitor
        //
        Serial.println();
        Serial.println();
        Serial.print("Data Received from Module 1 (Level Sensor)");
        Serial.println();
        Serial.print("Temp = ");
        Serial.println(level_data[0]);
        Serial.print("Humidity = ");
        Serial.println(level_data[1]);
        Serial.print("Level = ");
        Serial.println(level_data[2]);
        Serial.print("Comms = ");
        Serial.println(level_data[3]);
        Serial.println();
        Serial.print("Data Received from Module 2 (Moisture Sensor)");
        Serial.println();
        Serial.print("Comms = ");
        Serial.println(moisture_data[0]);
        Serial.print("Moisture = ");
        Serial.println(moisture_data[1]);
        
        Serial.print("Acknowledge Payload Sent = ");
        Serial.print(ackData[0]);
        Serial.println();
        newData = false;

    }
}


void updateReplyData() {
     radio.writeAckPayload(0, &ackData, sizeof(ackData)); // load the payload for the next time
}

dudester:
Not sure if my programming method is correct.

Your results (mixed up data) show clearly that it is not.

You should keep two pipes open at the same time and differentiate the incoming packets by the pipe they were received on.

IMHO it makes life much easier to use the "receiving" Arduino as a "master" and have it send messages and get replies from the other two ("slaves") one at a time.

The second example in this Simple nRF24L01+ Tutorial can be extended to work with several slaves. And it does not need the complexity of multiple pipes.

Note that even when using multiple pipes it is not possible for two messages to be sent at the same time - that will just garble both messages.

...R

Whandall:
You should keep two pipes open at the same time and differentiate the incoming packets by the pipe they were received on.

I thought i was, thats why i dont understand what I am doing wrong..?

Robin2:
even when using multiple pipes it is not possible for two messages to be sent at the same time - that will just garble both messages.

I have no control over this, but have tried increasing the delay so one tx only sends every 10 seconds and the other 5 seconds but data still comes through being asigned to wrong variables..?

If I run the transmitters individually the data goes to correct variable with the zero's assigned to the variable of the transmitter which is off, but both together they are inter-mixed. How can that happen when they are on dedicated different pipes?

dudester:
I have no control over this,

You can take control of it if you turn the communication process around like I suggested. It is not going to affect the throughput.

...R

dudester:
I thought i was, thats why i dont understand what I am doing wrong..?

Nope.

You are opening one pipe, attach an ack-payload and startListening.
Then you look for a packet if one is there, process it.
The you open the other pipe, attach an ack-payload and startListening.
Then you look for a packet if one is there, process it.
You repeat that sequence over and over...

Calling startListening over and over without any stopListening is a strange usage.

Open both pipes (with ack-payload preload) call startListening (once) in setup,
and only process the received packets in loop.

Use bool available (uint8_t *pipe_num)to get the pipe on which the packet was received.

OK, I have it coded like this now but just have zeroes being returned as the pipe address?

#include <SPI.h>
#include <RF24.h>
#define CE_PIN   9
#define CSN_PIN 53
#define DHT11_PIN 11
#include <dht.h>

dht DHT;


const byte level_module_address = {0xF0F0F0F0E2LL};
const byte moisture_module_address = {0xF0F0F0F0E3LL};

RF24 radio(CE_PIN, CSN_PIN);

int level_data[5] = {0,0,0,0,0}; // Data from Link 1
int moisture_data[2] = {0,0};    // Data from Link 2
int ackData[2] = {0,0}; 
bool newData = false;
byte pipe_num = 0;
byte data = 0;


void setup() 
    {
    Serial.begin(250000);
    Serial.println("RF Comms Starting...");
    radio.begin();
    radio.setDataRate( RF24_250KBPS );
    }


void loop(void) 
        {
        radio.openReadingPipe(0, level_module_address);
        radio.enableAckPayload();
        radio.writeAckPayload(1, &ackData, sizeof(ackData)); // pre-load data
        radio.startListening(); 
     
        getData_level();    // Read RF Data from Link 1 
        delay(5000);
        getData_moisture(); // Read RF Data from link 2        
        showData();  
        }


void getData_level() {
       if (radio.available() ) {
        radio.read( &level_data, sizeof(level_data) );
        newData = true;
         
        bool available (uint8_t *pipe_num);
        Serial.print ("Pipe = ");
        Serial.println (pipe_num);
        updateReplyData();  
    }
}

void getData_moisture() {
        if (radio.available() ) {
        radio.read( &moisture_data, sizeof(moisture_data) );
        newData = true;
        bool available (uint8_t *pipe_num);
        Serial.print ("Pipe = ");
        Serial.println (pipe_num);
        updateReplyData(); 
    }
}

void showData() {
    if (newData == true) {
        //
        // Print actual data on serial monitor
        //
        Serial.println();
        Serial.println();
        Serial.print("Data Received from Module 1 (Level Sensor)");
        Serial.println();
        Serial.print("Temp = ");
        Serial.println(level_data[0]);
        Serial.print("Humidity = ");
        Serial.println(level_data[1]);
        Serial.print("Level = ");
        Serial.println(level_data[2]);
        Serial.print("Comms = ");
        Serial.println(level_data[3]);
        Serial.println();
        Serial.print("Data Received from Module 2 (Moisture Sensor)");
        Serial.println();
        Serial.print("Comms = ");
        Serial.println(moisture_data[0]);
        Serial.print("Moisture = ");
        Serial.println(moisture_data[1]);
        
        Serial.print("Acknowledge Payload Sent = ");
        Serial.print(ackData[0]);
        Serial.println();
        newData = false;

    }
}


void updateReplyData() {
     radio.writeAckPayload(0, &ackData, sizeof(ackData)); // load the payload for the next time
}

What a crap. You should use the function, not declare it (this is already done in the .h file).

How about

void getData_level() {
    if (radio.available(&pipe_num) ) {
        radio.read( &level_data, sizeof(level_data) );
        newData = true;
        Serial.print ("Pipe = ");
        Serial.println (pipe_num);
        updateReplyData(); 
    }
}

You will probably want different ack-payloads for the two pipes, so passing to updateReplyData would be a good idea (and it should be used there).

Why is pipe_num global?

Whandall:
Why is pipe_num global?

Please bare with me, i am a begiiner so really have no idea how to code this.
I have used the code you suggested but that still displays zeroes as the pipe.
How should pipe_num be declared?

Your main problem seems to be, that you do not read (or care) what I write.

Whandall:
Open both pipes (with ack-payload preload) call startListening (once) in setup,
and only process the received packets in loop.

Does your latest code behave like that?

I give you an example how (parts of) loop could look like:

void loop() {
byte pipe_num = 0;
  if (radio.available(&pipe_num)) {
    if (pipe_num == 0) {
      radio.read(level_data, sizeof(level_data));
    } else {
      radio.read(moisture_data, sizeof(moisture_data));
    }
    radio.writeAckPayload(pipe_num, ackData, sizeof(ackData));
    newData = true;
    Serial.print(F("Pipe = "));
    Serial.println(pipe_num);
  }
}

The same constant ack-payload for both pipes is rather senseless,
the sending station can detect the successful transmission without receiving a constant back (wasting bandwidth).

Having two different newData flags for two the different messages would be more logical.

Thanks for your help, its working nicely now.