NRF24L01 Conflicting Information

Hi,
Some of the information being received from the transmitters is getting mixed. What is being displayed on the OLED seems to be the same data from different transmitters, if I unplug one of them the receiver continues to display the information for both transmitters however if I unplug both, then it displays an "error" string. Any ideas what is happening here?
Thanks.

Receiver code is below.

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


#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#include <OneWire.h> 

#define ONE_WIRE_BUS 2 

OneWire oneWire(ONE_WIRE_BUS); 




#define SCREEN_WIDTH 128 
#define SCREEN_HEIGHT 64 
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);






float temp1, temp2;
String ID = "TP2 ";

RF24 radio(9, 10);
const uint64_t pipes[3] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL};


void setup(void) 
{
Serial.begin(9600);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);


radio.begin();
radio.setDataRate(RF24_250KBPS);
radio.openReadingPipe(1,pipes[1]);
radio.openReadingPipe(3, pipes[2]);
radio.startListening();


  
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(5, 20);
  // Display static text
  display.clearDisplay();
  display.println("connecting....");
  display.display();    
  delay(1000);
  
}

void loop(void)
    {  
      display.clearDisplay();
      delay(500);
   if ( radio.available() )
        {
      
        delay(50);
        radio.read(&temp1, sizeof(temp1));
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(9, 20);
        display.println(temp1);
        display.display(); 

     
        }
         if ( radio.available() )
        {
      
        delay(50);
        radio.read(&temp2, sizeof(temp2));
        display.setTextSize(2);
        display.setTextColor(WHITE);
        display.setCursor(9, 40);
        display.println(temp2);
        display.display(); 

     
        }

else
  {
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(9, 0);
    display.println("Error");
    display.display(); 

  }
delay(1000);
}

Transmitter TX1 code below.

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

float temp1;

RF24 radio(9, 10);
const uint64_t pipes[3] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL };

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

void loop(void)
{
sensors.requestTemperatures();
temp1 = sensors.getTempCByIndex(0);
radio.write(&temp1, sizeof(temp1));
delay(10);
}

Transmitter TX2 code below.

#include <SPI.h>
#include "nRF24L01.h"
#include "RF24.h"
#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS 2

OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

float temp2;

RF24 radio(9, 10);
const uint64_t pipes[3] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0E2LL, 0xF0F0F0F0E3LL };

void setup(void) {
Serial.begin(9600);
sensors.begin();
radio.begin();
radio.setDataRate(RF24_250KBPS);
radio.openWritingPipe(pipes[2]);
radio.stopListening();
}

void loop(void)
{
sensors.requestTemperatures();
temp2 = sensors.getTempCByIndex(0);
radio.write(&temp2, sizeof(temp2));
delay(10);
}

Some of this is code modified from here.

Get rid of any delay, if you need timed events, use millis.

Do not expect any sequence of packets, packets get lost.

Examining the return code of central routines like radio.write
can help to detect and/or correct transmission errors.

Since you use two different pipes for your satellites,
you could use radio.available(&pipe).
https://nrf24.github.io/RF24/classRF24.html#ace7dd139fabc16b77cb8325faa07620f

Hi,
following your guidance, as stated above.
No significant difference? the same issue persists.

If you are trying to use multiple NRF24 modules I suggest using the RF24Network library. It provides a simple interface for communication between multiple modules. Documentation is here.
https://nrf24.github.io/RF24Network/
I put together a simple demo with two nodes sending temperature data to a root node. The transmit node code is identical except for the address and sample rate. The code is for the second node, for the first node change the two lines

const unsigned long SAMPLE_INTERVAL = 11000L; // sample interval in ms
const uint16_t this_node = 02;   // Address of our node in Octal format

to

const unsigned long SAMPLE_INTERVAL = 7000L; // sample interval in ms
const uint16_t this_node = 01;   // Address of our node in Octal format

I used different prime numbers for the sample times to make it easier to tell them apart since most of the time they would not occur together.

Receive code

/**
 * Example of using RF24Network with DS18B20 temperature sensor
 * 
 * Based on RF24Network/examples/helloworld_rx
 *
 * RECEIVER NODE
 * Listens for messages from the transmitters and prints them out.
 */
#include <Streaming.h>
#include <SPI.h>
#include <RF24.h>
#include <RF24Network.h>

RF24 radio(7,8);  // nRF24L01(+) radio CE and CS pins

RF24Network network(radio);      // Network uses that radio
const uint16_t this_node = 00;   // Address of our node in Octal format (04, 031, etc)

void setup(void) {
  Serial.begin(115200);
  while (!Serial) {
    // some boards need this because of native USB capability
  }

  if (!radio.begin()) {
    Serial.println(F("Radio hardware not responding!"));
    while (1) {
      // hold in infinite loop
    }
  }
  radio.setChannel(90);
  network.begin(/*node address*/ this_node);
}

void loop(void) {
  float temperature;
  network.update();  // Check the network regularly

  while (network.available()) {  // Is there anything ready for us?

    RF24NetworkHeader header;  // If so, grab it and print it out
    network.read(header, &temperature, sizeof(temperature));
    Serial << F("relative time ms ")<< millis() << F(" source address=") << _OCT(header.from_node)
      << F("  Received temperature=") << temperature <<endl;
  }
}

Transmit code

 /**
 * Example of using RF24Network with DS18B20 temperature sensor
 * 
 * Based on RF24Network/examples/helloworld_tx
 *
 * TRANSMITTER NODE
 * Every SAMPLE_INTERVAL, send temperature to the base node.
 */

const unsigned long SAMPLE_INTERVAL = 11000L; // sample interval in ms
const uint16_t this_node = 02;   // Address of our node in Octal format

//  DS18B20 Temperature Sensor
// Use adjacent I/O pins for power to minimize wireing for demo
const byte sensorGnd = 3;
const byte sensorVcc = 4;
const byte sensorData = 5;
#include <OneWire.h>
#include <DallasTemperature.h>
OneWire  onewire(sensorData);  // on pin 5 (a 4.7K resistor to vcc is necessary)
// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&onewire);


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

RF24 radio(7, 8);  // nRF24L01(+) radio CE and CS pins

RF24Network network(radio);  // Network uses that radio

const uint16_t other_node = 00;  // Address of the base node in Octal format

unsigned long last_sent = 0;     // When did we last send?
bool startUp = true; 
const byte errorPin = 6;
void setup(void) {
  // set up I/O pins  
  pinMode(errorPin,OUTPUT); 
  pinMode(sensorGnd,OUTPUT);
  pinMode(sensorVcc,OUTPUT);
  digitalWrite(sensorGnd,LOW);
  digitalWrite(sensorVcc,HIGH);
 
  Serial.begin(115200);
  while (!Serial) {
    // some boards need this because of native USB capability
  }
 

  if (!radio.begin()) {
    Serial.println(F("Radio hardware not responding!"));
    while (1) {
      // hold in infinite loop
    }
  }
  radio.setChannel(90);
  network.begin(/*node address*/ this_node);
}

void loop() {
  float temperature;
  network.update();  // Check the network regularly

  unsigned long curTime = millis();

  // If it's time to send a message, send it!
  if ((curTime - last_sent >= SAMPLE_INTERVAL) || startUp){
    last_sent = curTime;
    startUp = false;
    // call sensors.requestTemperatures() to issue a global temperature 
    // request to all devices on the bus (a bit overkill for one device)
    sensors.requestTemperatures(); // Send the command to get temperatures
    // We use the function ByIndex, and as an example get the temperature from the first sensor only.
    temperature = sensors.getTempCByIndex(0); 

    RF24NetworkHeader header(/*to node*/ other_node);
    bool ok = network.write(header, &temperature, sizeof(temperature));
    if(!ok){
      digitalWrite(errorPin,HIGH);  // data send failed - turn on LED
    } else {
      digitalWrite(errorPin,LOW);  
    }
  }
}

Some output from the demo. Guess which sensor is in ice water.
relative time ms 4492 source address=1 Received temperature=18.31
relative time ms 6078 source address=2 Received temperature=9.25
relative time ms 11492 source address=1 Received temperature=18.31
relative time ms 17098 source address=2 Received temperature=9.13
relative time ms 18493 source address=1 Received temperature=18.31
relative time ms 25493 source address=1 Received temperature=18.31
relative time ms 28090 source address=2 Received temperature=9.13
relative time ms 32492 source address=1 Received temperature=18.31
relative time ms 39492 source address=1 Received temperature=18.31
relative time ms 46493 source address=1 Received temperature=18.31
relative time ms 50069 source address=2 Received temperature=9.00
relative time ms 53494 source address=1 Received temperature=18.31

For extra credit change the transmit address from 02 to 011. This will cause the module to be a leaf from module 01. See the documentation picture. This will cause node 01 to be an intermediate node between node 011 and the base node 0. The advantage is that node 011 only has to be within radio range of node 01 and not the base node. The disadvantage is if node 01 is down node 011 cannot reach the base node 0.

Hi @oldcurmudgeon,
Thanks for this, looks great!
Whats the main difference between utilising the network library instead of thr generic nrf24l01 libraries?
Thanks.

The networking library is built on top of the generic support to provide communication between the nodes while hiding the details of routing, ACKs, retries etc. This allows you can get on with what you were actually wanting to do.

An extreme example is here

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.