Arduino+nrf24l01 - multiple nodes - lost transmission

I'm using arduino mega with nrf24l01 as node 0 and arduino nano for node 1 and 2.
All nrf24l01 have wired capacitor-100 μF.

Problem with receiving sensor data from node 1 and node 2.
Success rate for node 1: is 4 failed of 10 transmissions
Success rate for node 2: is 7 failed of 10 transmissions

Node 0

#include <ArduinoJson.h>
#include <DHT.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24Network.h>
#include <Wire.h>

#define DHTPIN 2        // DHT22 data pin
#define DHTTYPE DHT22   // DHT22 sensor type
#define MQ2PIN A0       // MQ2 sensor analog pin
#define FLAME_PIN 6     // Flame sensor analog pin
#define LED_PIN 3       

DHT dht(DHTPIN, DHTTYPE);

struct MyData {
  byte h;
  byte t;
  byte flame;
};
MyData node00Data; // Sensor data from Node 00
MyData node01Data; // Sensor data from Node 01

struct MyData2 {
  byte humi;
  byte temp;
  int gas;
  bool flame;
};
MyData2 node02Data; // Sensor data from Node 02

unsigned long lastReadingTime = 0;
const unsigned long interval = 20000;    

bool flameDetected = false;

RF24 radio(7, 8);
RF24Network network(radio);

const uint16_t this_node = 00;
const uint16_t node01 = 01;
const uint16_t node02 = 02;

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200); // Set baud rate for ESP8266 communication
  pinMode(MQ2PIN, INPUT);
  pinMode(FLAME_PIN, INPUT); // Set flame sensor pin as input
  pinMode(LED_PIN, OUTPUT);
  dht.begin();

  radio.begin();
  delay(500);
  network.begin(/*channel*/ 90, /*node address*/ this_node);
}

void loop() {
  network.update();

  unsigned long currentTime = millis();
  if (currentTime - lastReadingTime >= interval) {
    // Update the last reading time
    lastReadingTime = currentTime;
    SensorReadings();
  }

  // Handle incoming network data
  if (network.available()) {
    RF24NetworkHeader header;
    network.peek(header); // Peek at the next available header
    if (header.from_node == node01) {
      handleNode1Response();
    } else if (header.from_node == node02) {
      handleNode2Response();
    }
  }
}

void sendRequest(uint16_t node, char command) {
  RF24NetworkHeader header(node);
  bool ok = network.write(header, &command, sizeof(command));
  if (ok) {
    Serial.print("Request '");
    Serial.print(command);
    Serial.print("' sent to Node ");
    Serial.println(node);
  } else {
    Serial.print("Failed to send request '");
    Serial.print(command);
    Serial.print("' to Node ");
    Serial.println(node);
  }
}

void handleNode1Response() {
  while (network.available()) {
    RF24NetworkHeader header;
    char jsonBuffer[200];
    network.read(header, jsonBuffer, sizeof(jsonBuffer));
    Serial.print("Received from node: ");
    Serial.println(header.from_node);
    Serial.print("Message: ");
    //Serial.println(jsonBuffer);

    StaticJsonDocument<200> jsonDocument;
    DeserializationError error = deserializeJson(jsonDocument, jsonBuffer);
    if (error) {
      Serial.print("Error parsing JSON: ");
      Serial.println(error.c_str());
    } else {
      node01Data.t = jsonDocument["temperature"];
      node01Data.h = jsonDocument["humidity"];
      Serial.print("Node 01 - Temperature: ");
      Serial.print(node01Data.t);
      Serial.print("    Node 01 - Humidity: ");
      Serial.println(node01Data.h);
    }
  }
}

void handleNode2Response() {
  while (network.available()) {
    RF24NetworkHeader header;
    char jsonBuffer[200];
    network.read(header, jsonBuffer, sizeof(jsonBuffer));
    Serial.print("Received from node: ");
    Serial.println(header.from_node);
    Serial.print("Message: ");
    //Serial.println(jsonBuffer);

    StaticJsonDocument<200> jsonDocument;
    DeserializationError error = deserializeJson(jsonDocument, jsonBuffer);
    if (error) {
      Serial.print("Error parsing JSON: ");
      Serial.println(error.c_str());
    } else {
      node02Data.temp = jsonDocument["temperature"];
      node02Data.humi = jsonDocument["humidity"];
      node02Data.gas = jsonDocument["gas"];
      node02Data.flame = jsonDocument["flame"];
      Serial.print("Node 02 - Temperature: ");
      Serial.print(node02Data.temp);
      Serial.print("   Node 02 - Humidity: ");
      Serial.print(node02Data.humi);
      Serial.print("   Node 02 - Gas: ");
      Serial.print(node02Data.gas);
      Serial.print("  Node 02 - Flame: ");
      Serial.println(node02Data.flame);
    }
  }
}

void SensorReadings() {
  sendRequest(node01, 'A');
  delay(1000);
 sendRequest(node02, 'B');

  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();
  float readGas = analogRead(MQ2PIN);

  // Flame sensor debouncing
  const int flameReadingsCount = 5;
  int flameReadings[flameReadingsCount] = {0};
  int flameReadingSum = 0;

  for (int i = 0; i < flameReadingsCount; i++) {
    flameReadings[i] = digitalRead(FLAME_PIN);
    flameReadingSum += flameReadings[i];
    delay(30);
  }

  int flameValue = flameReadingSum < flameReadingsCount / 2 ? LOW : HIGH;

  node00Data.t = temperature;
  node00Data.h = humidity;
  node00Data.flame = flameValue;

  StaticJsonDocument<200> doc;
  doc["node"] = 0;
  doc["temperature"] = node00Data.t;
  doc["humidity"] = node00Data.h;
  doc["gas"] = readGas;
  doc["flame"] = flameValue;

  String jsonString;
  serializeJson(doc, jsonString);

  Serial1.println(jsonString);  // Send JSON string to ESP8266
  Serial.println(jsonString);
}

Report from Node 0:

Request 'A' sent to Node 1
Request 'B' sent to Node 2
{"node":0,"temperature":25,"humidity":61,"gas":11,"flame":0}
Received from node: 1
Message: Node 01 - Temperature: 24    Node 01 - Humidity: 61
Request 'A' sent to Node 1
Request 'B' sent to Node 2
{"node":0,"temperature":25,"humidity":61,"gas":12,"flame":0}
Request 'A' sent to Node 1
Request 'B' sent to Node 2
{"node":0,"temperature":25,"humidity":61,"gas":11,"flame":0}
Received from node: 1
Message: Node 01 - Temperature: 25    Node 01 - Humidity: 60
Received from node: 2
Message: Node 02 - Temperature: 23   Node 02 - Humidity: 67   Node 02 - Gas: 115  Node 02 - Flame: 1

Node 1

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

#define DHTPIN 2     // Pin connected to DHT sensor
#define DHTTYPE DHT11  // DHT sensor type (DHT11 or DHT22 or DHT21)
DHT dht(DHTPIN, DHTTYPE);

RF24 radio(7, 8); // CE, CSN
RF24Network network(radio);
const uint16_t thisNode = 1; // Node address
const uint16_t otherNode = 0; // Address of the other node in the mesh

void setup() {
  Serial.begin(115200);
  radio.begin();
  network.begin(/*channel=*/90, thisNode); // Begin the network, specify channel and node address
  dht.begin(); // Initialize DHT sensor
  Serial.println("Node 1 setup complete");
}

void loop() {
  network.update(); // Update the network regularly

  // Check for incoming data
  while (network.available()) {
    RF24NetworkHeader header;
    char txt_received[10] = "";
    network.read(header, &txt_received, sizeof(txt_received));
    Serial.print("Received from node: ");
    Serial.println(header.from_node);
    Serial.print("Message: ");
    Serial.println(txt_received);

    // If received message is 'A', send DHT sensor readings
    if (txt_received[0] == 'A') {
      float temperature = dht.readTemperature(); // Read temperature from DHT sensor
      float humidity = dht.readHumidity(); // Read humidity from DHT sensor

      // Create JSON object
      StaticJsonDocument<100> jsonDocument;
      jsonDocument["node"] = 1;
      jsonDocument["temperature"] = temperature;
      jsonDocument["humidity"] = humidity;

      // Serialize JSON object to char array
      char jsonBuffer[100];
      size_t jsonSize = serializeJson(jsonDocument, jsonBuffer);

      // Print the JSON data for debugging
      Serial.print("JSON Data: ");
      Serial.println(jsonBuffer);

      // Ensure there is a small delay before sending
      delay(100);

      // Send JSON data to Node 0
      RF24NetworkHeader header(otherNode); // Create a header specifying the destination node
      bool ok = network.write(header, jsonBuffer, jsonSize);
      if (ok) {
        Serial.println("Data sent to Node 0");
      } else {
        Serial.println("Failed to send data");
      }
    }
  }

  delay(1000); // Delay between iterations
}

Report from Node 1:

Received from node: 0
Message: A
JSON Data: {"node":1,"temperature":24.9,"humidity":61}
Data sent to Node 0
Received from node: 0
Message: A
JSON Data: {"node":1,"temperature":24.9,"humidity":60}
Failed to send data
Received from node: 0
Message: A
JSON Data: {"node":1,"temperature":25,"humidity":62}
Failed to send data

Node 2

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

#define DHTPIN 2     // Pin connected to DHT sensor
#define DHTTYPE DHT11  // DHT sensor type (DHT11 or DHT22 or DHT21)
DHT dht(DHTPIN, DHTTYPE);

const int MQ135_PIN = A0; // Analog pin for MQ135 sensor
const int FLAME_PIN = 6;  // Digital pin for flame sensor

RF24 radio(7, 8); // CE, CSN
RF24Network network(radio);
const uint16_t thisNode = 2; // Node address
const uint16_t otherNode = 0; // Address of the other node in the mesh

void setup() {
  Serial.begin(115200);
  radio.begin();
  network.begin(/*channel=*/90, thisNode); // Begin the network, specify channel and node address
  dht.begin(); // Initialize DHT sensor
  pinMode(MQ135_PIN, INPUT);
  pinMode(FLAME_PIN, INPUT);
  Serial.println("Node 2 setup complete");
}

void loop() {
  network.update(); // Update the network regularly

  // Check for incoming data
  while (network.available()) {
    RF24NetworkHeader header;
    char txt_received[10] = "";
    network.read(header, &txt_received, sizeof(txt_received));
    Serial.print("Received from node: ");
    Serial.println(header.from_node);
    Serial.print("Message: ");
    Serial.println(txt_received);

    // If received message is 'A', send DHT sensor readings
    if (txt_received[0] == 'B') {
      float temperature = dht.readTemperature(); // Read temperature from DHT sensor
      float humidity = dht.readHumidity(); // Read humidity from DHT sensor
      int gas = analogRead(MQ135_PIN); // Read gas level from MQ135 sensor
      bool flame = digitalRead(FLAME_PIN); // Read flame sensor

      // Create JSON object
      StaticJsonDocument<200> jsonDocument;
      jsonDocument["node"] = 2;
      jsonDocument["temperature"] = temperature;
      jsonDocument["humidity"] = humidity;
      jsonDocument["gas"] = gas;
      jsonDocument["flame"] = flame;

      // Serialize JSON object to char array
      char jsonBuffer[200];
      size_t jsonSize = serializeJson(jsonDocument, jsonBuffer);

      // Print the JSON data for debugging
      Serial.print("JSON Data: ");
      Serial.println(jsonBuffer);

      // Ensure there is a small delay before sending
      delay(100);

      // Send JSON data to Node 0
      RF24NetworkHeader header(otherNode); // Create a header specifying the destination node
      bool ok = network.write(header, jsonBuffer, jsonSize);
      if (ok) {
        Serial.println("Data sent to Node 0");
      } else {
        Serial.println("Failed to send data");
      }
    }
  }

  delay(1000); // Delay between iterations
}

Report from Node 2:

Received from node: 0
Message: B
JSON Data: {"node":2,"temperature":23.8,"humidity":67,"gas":115,"flame":true}
Failed to send data
Received from node: 0
Message: B
JSON Data: {"node":2,"temperature":23.8,"humidity":67,"gas":115,"flame":true}
Data sent to Node 0
Received from node: 0
Message: B
JSON Data: {"node":2,"temperature":23.8,"humidity":67,"gas":114,"flame":true}
Failed to send data
Received from node: 0
Message: B
JSON Data: {"node":2,"temperature":23.8,"humidity":67,"gas":114,"flame":true}
Failed to send data

Such are the woes of RF communication. Send small packets and perform checks to verify correctness and completeness of received messages, and deploy a protocol that corrects errors as they occur. The one thing you can never assume with RF communications is that data transfer will be flawless.

Proper hardware choices and layout help a lot, too. These NRF24 modules work best with an external antenna.

I dont't know distance between nodes in one meter(for testing) , it should have greater success rate , maybe problem is in my code?

Possibly; at risk of sounding lazy, but I have some trouble decyphering the code you're using to test this. It's mostly because of the complexity of 3 nodes and in particular the layering of the communications stack. My own approach to this would be to make a test setup of only two stations, a sender and a receiver, and only use the RF24 library to transmit data from one end to another, with some error checking on the receiver end. Then experiment with different parameters (hardware + software) to figure out what causes the transmission errors, and also to establish a baseline for what's feasible in terms of reliable transfers.

I'm not familiar with (but aware of) the RF24Network library; I can see how it's useful, but it also adds a layer of complexity (and indeed, obfuscation in a sense) that makes it harder to figure out what's going on exactly. I'd strip off that layer for now and just try and getting simple one-on-one transfers working.

Btw, I've done networks of several devices without needing to use the Network library, but in these instances there is a clear master-slave architecture with a single master and a couple of slaves. If your application requires something that more resembles a peer-to-peer network, you may have to rely on more complicated protocols to get this to work (reliably). I'd still start with a single setup of two devices and a master/slave role for testing, though.

Do you mean by this that the stations are at a distance of one meter from each other? In this case, it apparently happens sometimes that having the sender transmit at full power results in packet loss; the signal's being 'blown out' in a way in this case.

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