rf24Network Library Limitations?

I am working on building nrf24 modules Network using the RF24Network Library .
I need around 100 sensor_nodes to be in this Network sending their data to the Master which will then store their data to Cloud.
But I tested a network with 10 sensor_nodes to begin with , and I am unable to get data from all the nodes most of the times.
I have researched alot about the nrf24 modules and rf24Network Library, somewhere I read that you can connect upto 781 nodes while on few blog posts I read you can connect 30125 nodes on a single network.I know this is in ideal condition(which is never possible). But I thought I can atleast I would be able to connect 100 nodes in a network.
But I am starting to think even that is not possible.
can someone please clear why this is happening?
what might be the potential issues that this is not working?
the Masters code remains same while the nodes code changes slightly for every node.

  1. I am using esp8266 for now, but in future I am planning to use esp32 Microcontroller for all the nodes and master.
  2. After uploading the code for this testing, I powered them using a extension board which have around 7 USB ports in it and 2 mobile adapters .
  3. I kept them around 60-70 cm apart from each other.
  4. I tested this 10 nodes in my House. I did a test with 2 nrf24l01+PA+LNA modules in an open area and I got their range around 1.1 Km(I am really proud of that test).
  5. Master transmits a Multicast Message every 1 minute , and then each node after receiving the msg, transmit after a random_delay(0 to 6 seconds).
    My code:
//Master Node

#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>
/* Sketch to send message to MQTT Broker on Cloud */
#include <ESP8266WiFi.h>
#include <PubSubClient.h>

// These variables store the WiFi credentials and MQTT server information.
//const char* ssid        = "PRATIK";
//const char* password    = "asdfghjkl1231";
const char* mqtt_server = "dev.PRATIK.in";
int         mqtt_port   = 1883;

//  These objects are used to establish and manage connections to the WiFi network and MQTT broker.
WiFiClient wifiClient;
PubSubClient mqttClient(wifiClient);

#define CE_pin D0
#define CSN_pin D1

//  These objects are used for configuring and managing the NRF24L01+ radio module and the RF24Network layer respectively.
RF24 radio(CE_pin, CSN_pin);
RF24Network network(radio);                                                       // Include the radio in the network

#define RF_channel 120

const uint16_t this_node = 00;                                                    // Address of this node in Octal format ( 04,031, etc)

// Format the data to be sent in the desired structure
String formatData(String code, uint16_t from_node, String command, String message) {
    return code + "-" + String(from_node) + "-" + command + "-" + message + "$";
}

uint8_t level = 1;
String all = formatData("xYaZ", this_node, "rollcall", "get_data");

#define MAX_DATA_SIZE 32                                                         // Define a maximum data size to receive
char all_ack_buffer[MAX_DATA_SIZE] = "";                                         // RECEIVING VARIABLE when the msg multicasted to all

unsigned long currentTime = 0;
unsigned long lastTransmissionTime = 0;
const unsigned long transmissionTimeout = 1000;                                 // Timeout duration in milliseconds for turning OFF the LED

unsigned long Delay = 10;

#define redLED D3                                                               //if transmission done
#define blueLED D4                                                              // if reception done

void setup() {
  setupWifi();                                                                  // setup WiFi connection
  setupMqtt();                                                                  // setup mqtt connection

  SPI.begin();
  radio.begin();
  // Configure retries for more robust communication:
  radio.setRetries(10,5);                                                      // delay(microSeconds)(steps of 250us) , count
  // delay: How long to wait between each retry, in multiples of 250us, max is 15. 0 means 250us, 15 means 4000us, count: How many retries before giving up, max 15 
  network.begin(RF_channel, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);

  radio.setAutoAck(true);                                                 // Disable auto-acknowledgment for pipe 0 (multicast)

  radio.enableDynamicPayloads();                                                // Enable dynamic payloads:

  radio.setCRCLength(RF24_CRC_16);                                              // length: RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit Cyclic Redundancy Check (Error checking)
  
  Serial.begin(115200);
  //radio.printDetails();                                                       // Print detailed radio configuration
  pinMode(redLED, OUTPUT);
  pinMode(blueLED, OUTPUT);

}

void setupWifi() {                                                              //  Connects to the specified WiFi network.
  WiFi.begin(ssid, password);
  while ( WiFi.status() != WL_CONNECTED ) {
    delay(500); 
    Serial.print(".");
  }
}

void setupMqtt() {                                                              // This function is used to set up the MQTT connection with the broker and specify the callback function to handle incoming messages.
  mqttClient.setServer(mqtt_server, mqtt_port);
  // invoke "callback()" function when there is an incoming message
  mqttClient.setCallback(callback);   
}

void reconnect() {
   while ( !mqttClient.connected() ) {
      String clientId = String(ESP.getChipId());                                //  retrieves the ESP8266's chip ID using ESP.getChipId() and converts it into a string. The chip ID is typically a unique identifier for each ESP8266 device.
      if ( mqttClient.connect(clientId.c_str() ) ) {
        // attempts to connect to the MQTT broker using the previously generated client ID.
        // mqttClient.connect() is a method provided by the PubSubClient library to establish a connection to the broker. It returns true if the connection is successful.
        Serial.println("connected");
      }
      // subscribe to an MQTT topic   
      mqttClient.subscribe("node00");                                           // Subscribing to a topic allows the client to receive messages published to that topic by other clients.
  }
}

void loop() {
  if (!mqttClient.connected()) {
    reconnect();
  }
  network.update();
  print_all_ACK();
  mqttClient.loop();                                                            // This method is responsible for handling any incoming MQTT messages. When a message arrives, it triggers the callback function.
  delay(Delay);
}

void callback(char* topic, byte* payload, unsigned int length) {                // The callback function is invoked automatically whenever a message is received from the MQTT broker. 

  for (int i = 0; i < length; i++) {                                            // starts a for loop that iterates over each byte of the payload data.
    Serial.print((char)payload[i]);   
  }

  payload[length] = '\0';                                                       // adds a null terminator at the end of the payload data, effectively terminating it as a string. This step is necessary if you plan to treat the payload data as a C-style string.

  // act on the incoming command
  if(strcmp( ( (char *)payload ), "rollcall") == 0)  {                          // checks if the received message matches the string "rollcall".  
    // "strcmp" is a C standard library function used to compare strings. If the comparison returns 0 (indicating a match), the condition is true, and the code block inside the if statement is executed.
    //Send the message(Multicast) to all 
    send_all();
    delay(Delay);
  }
}

void print_all_ACK() {
  network.update();
  // Receiving all_ack_buffer //
  if (network.available()) {
    network.update();
    RF24NetworkHeader header;
    network.read(header, &all_ack_buffer, sizeof(all_ack_buffer));
    delay(10);
    digitalWrite(blueLED,HIGH);

    // Process the received data in a structured manner
    String receivedData = String(all_ack_buffer);
    int delimiterIndex = receivedData.indexOf('$');                                 //The indexOf() function returns the position of the first occurrence of '$' within the String. If the character '$' is not found, it returns -1.

    if(delimiterIndex != -1) {
        String parsedData = receivedData.substring(0, delimiterIndex);              // Extract the part before '$'

        // Split the parsed data using the '-' delimiter
        int hyphenIndex = parsedData.indexOf('-');
        String code = parsedData.substring(0, hyphenIndex);                         // extracts the "code" from the whole received String
        
        parsedData.remove(0, hyphenIndex + 1);                                      // Remove the part before the first hyphen
        hyphenIndex = parsedData.indexOf('-');                                      // Split the parsed data using the '-' delimiter
        String from_node_str = parsedData.substring(0, hyphenIndex);
        uint16_t from_node = from_node_str.toInt();                                 //Converts the 'to_node_str' String into an unsigned integer (uint16_t) value,

        parsedData.remove(0, hyphenIndex + 1);                                      // Remove the part before the second hyphen
        String command = parsedData;

        // Now 'code', 'from_node', 'command' variables contain the parsed values
        // You can use these variables as needed
        Serial.print("  Received from node: ");
        Serial.print(from_node);
        Serial.print(" | code: ");
        Serial.print(code);
        Serial.print(" | with command: ");
        Serial.println(command);

        if(code == "xYaZ") {
          //Serial.print("all_ACK Received: ");
          //Serial.println(all_ack_buffer);

          String value = String(all_ack_buffer);
          mqttClient.publish("node", value.c_str());
        }
      }
    lastTransmissionTime = millis();
  }
  // Check for timeout to clear the buffer
  currentTime = millis();                                                 //Updates currentTime1 with the current value of millis().
  if ((currentTime - lastTransmissionTime) > transmissionTimeout) {
    //  memset(void* ptr, int value, size_t num); SYNTAX
    memset(all_ack_buffer, 0, sizeof(all_ack_buffer));                    // uses the memset(memory set) function to set a block of memory with a specified value.
    digitalWrite(blueLED, LOW);
  }
}

void send_all() {
  network.update();
  RF24NetworkHeader header1;                                                // (Address where the data is going)
  bool ok = network.multicast(header1, &all[0], all.length(), level);       // Send the data
  delay(10);
  digitalWrite(redLED, HIGH);
  //Serial.println(all.length());                                           // Print the size of the transmitted message

  if (ok) {
    Serial.print("   sent: ");
    Serial.println(all);
  } else {
    Serial.println("failed");
    digitalWrite(redLED,LOW);
  }
}
//Node01
#include <RF24Network.h>
#include <RF24.h>
#include <SPI.h>

#define CE_pin D0
#define CSN_pin D1

RF24 radio(CE_pin, CSN_pin);
RF24Network network(radio);      // Include the radio in the network

#define RF_channel 120

const uint16_t this_node = 01;        // Address of this node in Octal format
// Format the data to be sent in the desired structure
String getdata(String code, uint16_t from_node, String command ) {
    return code + "-" + String(from_node) + "-" + command + "$";
}

String gaveData = getdata("xYaZ", 1, "rollcall");

// Define the addresses of the child nodes
const uint16_t child_nodes[5] = {011, 021, 03, 041, 051};             // The addresses of the child nodes are defined in the child_nodes array.
//const int num_child_nodes = sizeof(child_nodes) / sizeof(uint16_t);       // The number of child nodes is calculated using the size of the child_nodes array(10 bytes) divided by the size of uint16_t(2 bytes).

const uint16_t master_node = 00;                                            // Address of master node in Octal format

unsigned long currentTime = 0;
unsigned long lastTransmissionTime = 0;
const unsigned long transmissionTimeout = 2000;   // Timeout duration in milliseconds 

char received_msg[32] = "";
uint8_t level = 2; // level where we want to Mulicast the message

#define ledPin D4

void setup() {
  SPI.begin();
  radio.begin();
  // Configure retries for more robust communication:
  radio.setRetries(8,5); // delay(microSeconds)(steps of 250us) , count
  network.begin(RF_channel, this_node);
  radio.setDataRate(RF24_250KBPS);
  radio.setPALevel(RF24_PA_MAX);

  // Enable dynamic payloads:
  radio.enableDynamicPayloads();

  radio.setCRCLength(RF24_CRC_16);                                              // length: RF24_CRC_8 for 8-bit or RF24_CRC_16 for 16-bit Cyclic Redundancy Check (Error checking)
  
  Serial.begin(115200);
  //radio.printDetails();  // Print detailed radio configuration
  pinMode(ledPin, OUTPUT);
}

void loop() {

  received_then_sent();
  delay(10);

}

void received_then_sent() {
  network.update();
  // Receiving //
  //Serial.println("before available");
  if(network.available() ) {

    //Serial.println("before read");

    digitalWrite(ledPin, HIGH);

    network.update();
    RF24NetworkHeader header;
    network.read(header, &received_msg, sizeof(received_msg) );
    //Serial.println("after read");
    delay(10);

    // Multicast the received message to the child nodes
    for (int i = 0; i < 5; i++) {
      RF24NetworkHeader child_header(child_nodes[i]);
      bool ok1 = network.write(child_header, &received_msg, sizeof(received_msg));
      delay(10);
      //String sent_to = String(child_nodes[i]);
      if (ok1) {
        Serial.print("Sent to node: ");
        Serial.print(child_nodes[i]);
        Serial.print(": ");
        Serial.println(received_msg);
      } else {
        Serial.print("Failed to send to node: ");
        Serial.println(child_nodes[i]);
      }
    }

    // Process the received data in a structured manner
    String receivedData = String(received_msg);
    int delimiterIndex = receivedData.indexOf('$'); //The indexOf() function returns the position of the first occurrence of '$' within the String. If the character '$' is not found, it returns -1.

    if(delimiterIndex != -1) {
      String parsedData = receivedData.substring(0, delimiterIndex); // Extract the part before '$'
      
      //Serial.println(" inside delimiter loop ");

      // Split the parsed data using the '-' delimiter
      int hyphenIndex = parsedData.indexOf('-');
      String code = parsedData.substring(0, hyphenIndex);   // extracts the "code" from the whole received String

      parsedData.remove(0, hyphenIndex + 1); // Remove the part before the first hyphen
      hyphenIndex = parsedData.indexOf('-'); // Split the parsed data using the '-' delimiter
      String from_node_str = parsedData.substring(0, hyphenIndex);
      uint16_t from_node = from_node_str.toInt();  //Converts the 'to_node_str' String into an unsigned integer (uint16_t) value

      parsedData.remove(0, hyphenIndex + 1); // Remove the part before the second hyphen
      hyphenIndex = parsedData.indexOf('-'); // Split the parsed data using the '-' delimiter
      String command = parsedData.substring(0, hyphenIndex);

      parsedData.remove(0, hyphenIndex + 1); // Remove the part before the third hyphen
      String message = parsedData;

      // Now 'code', 'from_node', 'command', 'message' variables contain the parsed values
      // You can use these variables as needed
      Serial.print(this_node);
      Serial.print("  ");
      Serial.print("Received from node: ");
      Serial.print(from_node);
      Serial.print(" | code: ");
      Serial.print(code);
      Serial.print(" | with command: ");
      Serial.print(command);
      Serial.print(" | and message: ");
      Serial.println(message);

      if(code == "xYaZ") {
        int r_delay = random(0,6000);
        delay(r_delay);
        Serial.println(r_delay);
        if(command == "rollcall") {
          sendData();
        }
      }
    }

    lastTransmissionTime = millis();
  }
  // Check for timeout to clear the buffer
  currentTime = millis();
  if(currentTime - lastTransmissionTime > transmissionTimeout) {
      //Serial.println("Connection Lost!!");
      digitalWrite(ledPin, LOW);
  }
}

void sendData() {
  network.update();
  RF24NetworkHeader header2(master_node);
  bool ok = network.write(header2, &gaveData[0], gaveData.length() );
  if(ok) {
    Serial.print("Done!! ");
    Serial.println(gaveData);
    //Serial.print(" ");
    //Serial.println( gaveData.length() ); // Print the size of the transmitted message
  }
  else{
    Serial.println("Failed!!!");
    bool ok = network.write(header2, &gaveData[0], gaveData.length() );
  }
}```

have a read of how-to-get-the-best-out-of-this-forum
e.g.

  1. what host microcontrollers are you using in the nodes?
  2. how do you power the nodes and the NRF24 devices?
  3. how far apart are the nodes?
  4. what is the environment? urban, countryside, trees, hills, ??
  5. how often do the nodes transmit data?

Sorry I should have added this in the question above to, I will edit it

  1. I am using esp8266 for now, but in future I am planning to use esp32 Microcontroller for all the nodes and master. I thought just using any microcontroller which can supply enough power to the nrf modules should work fine, am I wrong here to think like that?
  2. after uploading the code for this testing, I powered them using a extension board which have around 7 USB ports in it and 2 mobile adapters .
  3. I kept them around 60-70 cm apart from each other.
  4. I tested this 10 nodes in my House. I did a test with 2 nrf24l01+PA+LNA modules in an open area and I got their range around 1.1 Km(I am really proud of that test).
  5. Master transmits a Multicast Message every 1 minute , and then each node after receiving the msg, transmit after a random_delay(0 to 6 seconds).

I have used ESP32 to drive a nrf24l01 without problems using a 10uF capacitor across the power line
the node transmission may be corrupting each other - possibly try polling the nodes?

I have also added a 10uF capacitor across the nrf24 Modules, and I am even using the recommended adapter module for powering them.
I am kinda doing polling in my code I provided above.
how many have you connected on single network using this nrf24 modules?
and can you please also answer my above questions if possible

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