NRF24l01 Sensor network Issues

I'm trying to make a sensor network using 2 transmitter units and 1 receiver.

The transmitter units are consisting of:
1xArduino UNO
1xNRF24l01
3xCapacitive Soil moisture sensors

The receiver consists of:
1x ESP32 WROOM 32UE
1x NRF24l01

Transmitter code

// Simple Arduino code to predict volumetric
// water content in soil using a capacitive
// soil moisture sensor
//

#define soil_pin1  A0 // AOUT pin on sensor
#define soil_pin2  A1
#define soil_pin3  A2

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

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "00001";


float slope = 129.24; // slope from linear fit
float intercept = -62.03; // intercept from linear fit

float voltage1; // preallocate to approx. voltage and theta_v 
float voltage2; // preallocate to approx. voltage and theta_v
float voltage3; // preallocate to approx. voltage and theta_v

float node1Sensor1 = 0;
float node1Sensor2 = 0;
float node1Sensor3 = 0;

void setup() {
  Serial.begin(9600); // serial port setup
  analogReference(EXTERNAL); // set the analog reference to 3.3V
  
  radio.begin();
  radio.openWritingPipe(address);
  radio.setPALevel(RF24_PA_MAX);
  radio.stopListening();
}

void loop() {
  
  const char text[] = "Radio 1 ok";
  radio.write(&text, sizeof(text));
  delay(1000);

calculations();
radiosend();
printRAWvalues();
}

void calculations(){
  for (int i = 0; i <= 1000; i++) 
  { 
    node1Sensor1 = node1Sensor1 + analogRead(soil_pin1); 
    delay(1); 
  } 
  node1Sensor1 = node1Sensor1/1000.0; 

  for (int i = 0; i <= 1000; i++) 
  { 
    node1Sensor2 = node1Sensor2 + analogRead(soil_pin2); 
    delay(1); 
  } 
  node1Sensor2 = node1Sensor2/1000.0; 

  for (int i = 0; i <= 1000; i++) 
  { 
    node1Sensor3 = node1Sensor3 + analogRead(soil_pin3); 
    delay(1); 
  } 
  node1Sensor3 = node1Sensor3/1000.0; 
  
  voltage1 = (float(analogRead(soil_pin1))/1023.0)*3.3;
  node1Sensor1 = ((1.0/voltage1)*slope)+intercept; // calc of theta_v (vol. water content)
 
  voltage2 = (float(analogRead(soil_pin2))/1023.0)*3.3;
  node1Sensor2 = ((1.0/voltage2)*slope)+intercept; // calc of theta_v (vol. water content)
  
  voltage3 = (float(analogRead(soil_pin3))/1023.0)*3.3;
  node1Sensor3 = ((1.0/voltage3)*slope)+intercept; // calc of theta_v (vol. water content)

}
  
void radiosend(){
  
  radio.write(&node1Sensor1, sizeof(node1Sensor1));
  radio.write(&node1Sensor2, sizeof(node1Sensor2));  
  radio.write(&node1Sensor3, sizeof(node1Sensor3));

} 

void printToSerial() {
  Serial.println("Sensor 1");  
  Serial.print("Voltage: ");
  Serial.print(voltage1); // read sensor
  Serial.print(" V, Theta_v: "); 
  Serial.print(node1Sensor1);
  Serial.println(" cm^3/cm^3"); // cm^3/cm^3
  delay(1000); // slight delay between readings

  
  Serial.println("________________________________");
  Serial.println("Sensor 2");
  
  Serial.print("Voltage: ");
  Serial.print(voltage2); // read sensor
  Serial.print(" V, Theta_v: "); 
  Serial.print(node1Sensor2);
  Serial.println(" cm^3/cm^3"); // cm^3/cm^3
  delay(1000); // slight delay between readings

  
  Serial.println("________________________________");
  
  Serial.println("Sensor 3");  
  Serial.print("Voltage: ");
  Serial.print(voltage3); // read sensor
  Serial.print(" V, Theta_v: "); 
  Serial.print(node1Sensor3);
  Serial.println(" cm^3/cm^3"); // cm^3/cm^3
  delay(1000); // slight delay between readings

  
Serial.println("________________________________");
}

void printRAWvalues(){
  Serial.print(" Sensor 1: ");
  Serial.print(node1Sensor1);
  delay(500);  
  Serial.print(" Sensor 2: ");
  Serial.print(node1Sensor2);
  delay(500);  
  Serial.print(" Sensor 3: ");
  Serial.print(node1Sensor3);
  delay(500);
  Serial.println("          ");
}

Receiver Code

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

#include <WiFi.h>
#include <WiFiAP.h>
#include <WiFiClient.h>
#include <WiFiGeneric.h>
#include <WiFiMulti.h>
#include <WiFiScan.h>
#include <WiFiServer.h>
#include <WiFiSTA.h>
#include <WiFiType.h>
#include <WiFiUdp.h>
#include <ThingSpeak.h>

#define CHANNEL_ID 1825464
#define CHANNEL_API_KEY "5FNV78UZAP4MDQ2Z"

#define CE_PIN  4
#define CSN_PIN 5

WiFiClient client;

#define WIFI_TIMEOUT_MS 20000
#define WIFI_NETWORK "SM-G950W1006"
#define WIFI_PASSWORD "cjck8186"

int counter = 0;

const byte address[6] = "00001";

RF24 radio(CE_PIN, CSN_PIN);

float node1Sensor1;
float node1Sensor2;
float node1Sensor3;

float node2Sensor1;
float node2Sensor2;
float node2Sensor3;

void setup() {
  Serial.begin(9600);
  connectToWiFi();

  ThingSpeak.begin(client);
 
  radio.begin();
  radio.openReadingPipe(1, address);
  radio.setPALevel(RF24_PA_MAX);
  radio.startListening();
  
  Serial.print("Receiver Starting");
  
}

void loop() {  
  
  counter++;
  radioRead();
  serialPrint();
  thingSpeakSend();
  
  if (radio.available()) {
    char text[32] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text);
    
    char text2[32] = "";
    radio.read(&text2, sizeof(text2));
    Serial.println(text2);
  }
  }

void radioRead(){

  radio.read(&node1Sensor1, sizeof(node1Sensor1));
  radio.read(&node1Sensor2, sizeof(node1Sensor2));
  radio.read(&node1Sensor3, sizeof(node1Sensor3));

  radio.read(&node2Sensor1, sizeof(node2Sensor1));
  radio.read(&node2Sensor2, sizeof(node2Sensor2));
  radio.read(&node2Sensor3, sizeof(node2Sensor3));
  
 
}

void serialPrint(){
Serial.print(" | Node 1 |");     
Serial.print(" Sensor 1: ");
  Serial.print(node1Sensor1);

  Serial.print(" Sensor 2: ");
  Serial.print(node1Sensor2);
 
  Serial.print(" Sensor 3: ");
  Serial.print(node1Sensor3);

Serial.print(" | Node 2 |");
Serial.print(" Sensor 1: ");
  Serial.print(node2Sensor1);
 
  Serial.print(" Sensor 2: ");
  Serial.print(node2Sensor2);

  Serial.print(" Sensor 3: ");
  Serial.print(node2Sensor3);
  Serial.print("|");


  Serial.println("          ");
delay(1000);

}
 
void thingSpeakSend(){  
  ThingSpeak.setField(1, node1Sensor1);
  ThingSpeak.setField(2, node1Sensor2);
  ThingSpeak.setField(3, node1Sensor3);
  ThingSpeak.setField(4, WiFi.RSSI());
  ThingSpeak.setField(5, counter);
  ThingSpeak.writeFields(CHANNEL_ID, CHANNEL_API_KEY);
  delay(15000);

}

void connectToWiFi(){
Serial.print ("Connecting to WiFi");
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);


unsigned long startAttemptTime = millis ();


while(WiFi.status()!= WL_CONNECTED && millis() - startAttemptTime < WIFI_TIMEOUT_MS){
  Serial.print(".");
  delay(100);

}
if (WiFi.status() != WL_CONNECTED){
  Serial.println("Failed!");

}else{
  Serial.print("Connected!");
  Serial.print(WiFi.localIP());


}
}

As you can see from the code, the plan is to get the readings, transmit them using the NRF24l01 modules and then upload them to Thingspeak, now there are some issues.

  1. Not all data is being received (See serial monitor output image, COM14 is Receiver, COM 6 is Node 1, COM4 is node 2)

  2. When data is being received, some of it is garbled.

Afaik my connections are good since there is some data being sent, i'm worried that it is a problem with my code.

What would be a more efficient way to write my code?
My coding and electrical knowledge mostly ends with this project so pls be nice, and I would appreciate any resources to improve/learn more.

Thanks in advance

Please advise

You are using 3 separate sends to send the data and reads to receive the data. I would put the 3 floats of each sender in an array or struct and then use only one send and read for each transmitter. 3 floats is only 12 bytes so well under the 32 byte limit.

You for() loop collects 1001 samples so your average is not correct.

Could you write an example code for me? I'm having a hard time understanding.

Here is the code with data put into a struct that holds an ID to identify which sensor that the data belongs to, a 15 character (+ terminating null = 16) for whatever and the 3 float values. All of those go into one struct so one send. On the receiver side the data is received in the struct then the ID is checked to see which sensor the data belongs to and then put into the proper variables. I have no way to test the code so it is untested and really just meant to illustrate how to packetize and unpack the data so one send and one receive is needed.

Sender (each sender should have a unique ID assigned). Compiles for Uno, but untested.

// Simple Arduino code to predict volumetric
// water content in soil using a capacitive
// soil moisture sensor
//

#define soil_pin1  A0 // AOUT pin on sensor
#define soil_pin2  A1
#define soil_pin3  A2

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

RF24 radio(7, 8); // CE, CSN

const byte address[6] = "00001";


float slope = 129.24; // slope from linear fit
float intercept = -62.03; // intercept from linear fit

float voltage1; // preallocate to approx. voltage and theta_v
float voltage2; // preallocate to approx. voltage and theta_v
float voltage3; // preallocate to approx. voltage and theta_v

float node1Sensor1 = 0;
float node1Sensor2 = 0;
float node1Sensor3 = 0;

// ***** define payload struct
struct Payload
{
   char ID;  // **** to distinguish between sensor data sets
   char text[16];
   float node1;
   float node2;
   float node3;
};

Payload payload; // ***** create insance of payload struct

void setup()
{
   Serial.begin(9600); // serial port setup
   analogReference(EXTERNAL); // set the analog reference to 3.3V

   radio.begin();
   radio.openWritingPipe(address);
   radio.setPALevel(RF24_PA_MAX);
   radio.stopListening();
}

void loop()
{

   calculations();
   radiosend();
   printRAWvalues();
}

void calculations()
{
   for (int i = 0; i <= 1000; i++)
   {
      node1Sensor1 = node1Sensor1 + analogRead(soil_pin1);
      delay(1);
   }
   node1Sensor1 = node1Sensor1 / 1000.0;

   for (int i = 0; i <= 1000; i++)
   {
      node1Sensor2 = node1Sensor2 + analogRead(soil_pin2);
      delay(1);
   }
   node1Sensor2 = node1Sensor2 / 1000.0;

   for (int i = 0; i <= 1000; i++)
   {
      node1Sensor3 = node1Sensor3 + analogRead(soil_pin3);
      delay(1);
   }
   node1Sensor3 = node1Sensor3 / 1000.0;

   voltage1 = (float(analogRead(soil_pin1)) / 1023.0) * 3.3;
   node1Sensor1 = ((1.0 / voltage1) * slope) + intercept; // calc of theta_v (vol. water content)

   voltage2 = (float(analogRead(soil_pin2)) / 1023.0) * 3.3;
   node1Sensor2 = ((1.0 / voltage2) * slope) + intercept; // calc of theta_v (vol. water content)

   voltage3 = (float(analogRead(soil_pin3)) / 1023.0) * 3.3;
   node1Sensor3 = ((1.0 / voltage3) * slope) + intercept; // calc of theta_v (vol. water content)

}

void radiosend()
{
   // ***** set ID so you know where the data came from
   payload.ID = 'A'; // **** make it 'B' for second sensor
   // **** populate string
   strncpy(payload.text, "Radio 1 ok", 16);
   // ***** fill payload struct
   payload.node1 = node1Sensor1;
   payload.node2 = node1Sensor2;
   payload.node3 = node1Sensor3;
   // ***** send 3 values with one send
   radio.write(&payload, sizeof(payload));
}

void printToSerial()
{
   Serial.println("Sensor 1");
   Serial.print("Voltage: ");
   Serial.print(voltage1); // read sensor
   Serial.print(" V, Theta_v: ");
   Serial.print(node1Sensor1);
   Serial.println(" cm^3/cm^3"); // cm^3/cm^3
   delay(1000); // slight delay between readings


   Serial.println("________________________________");
   Serial.println("Sensor 2");

   Serial.print("Voltage: ");
   Serial.print(voltage2); // read sensor
   Serial.print(" V, Theta_v: ");
   Serial.print(node1Sensor2);
   Serial.println(" cm^3/cm^3"); // cm^3/cm^3
   delay(1000); // slight delay between readings


   Serial.println("________________________________");

   Serial.println("Sensor 3");
   Serial.print("Voltage: ");
   Serial.print(voltage3); // read sensor
   Serial.print(" V, Theta_v: ");
   Serial.print(node1Sensor3);
   Serial.println(" cm^3/cm^3"); // cm^3/cm^3
   delay(1000); // slight delay between readings


   Serial.println("________________________________");
}

void printRAWvalues()
{
   Serial.print(" Sensor 1: ");
   Serial.print(node1Sensor1);
   delay(500);
   Serial.print(" Sensor 2: ");
   Serial.print(node1Sensor2);
   delay(500);
   Serial.print(" Sensor 3: ");
   Serial.print(node1Sensor3);
   delay(500);
   Serial.println("          ");
}

Receiver. I do not have all the libraries so cannot verify or test. Code untested.

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

#include <WiFi.h>
#include <WiFiAP.h>
#include <WiFiClient.h>
#include <WiFiGeneric.h>
#include <WiFiMulti.h>
#include <WiFiScan.h>
#include <WiFiServer.h>
#include <WiFiSTA.h>
#include <WiFiType.h>
#include <WiFiUdp.h>
#include <ThingSpeak.h>

#define CHANNEL_ID 1825464
#define CHANNEL_API_KEY "5FNV78UZAP4MDQ2Z"

#define CE_PIN  4
#define CSN_PIN 5

WiFiClient client;

#define WIFI_TIMEOUT_MS 20000
#define WIFI_NETWORK "SM-G950W1006"
#define WIFI_PASSWORD "cjck8186"

int counter = 0;

const byte address[6] = "00001";

RF24 radio(CE_PIN, CSN_PIN);

float node1Sensor1;
float node1Sensor2;
float node1Sensor3;

float node2Sensor1;
float node2Sensor2;
float node2Sensor3;

// ***** define payload struct
struct Payload
{
   char ID;
   char text[16];
   float node1;
   float node2;
   float node3;
};

Payload payload; // ***** create insance of payload struct

void setup()
{
   Serial.begin(9600);
   connectToWiFi();

   ThingSpeak.begin(client);

   radio.begin();
   radio.openReadingPipe(1, address);
   radio.setPALevel(RF24_PA_MAX);
   radio.startListening();

   Serial.print("Receiver Starting");
}

void loop()
{
   counter++;
   radioRead();
   serialPrint();
   thingSpeakSend();

   if (radio.available())
   {
      radio.read(&payload, sizeof(payload));
      if (payload.ID = 'A')
      {
         Serial.print(payload.text);
         node1Sensor1 = payload.node1;
         node1Sensor2 = payload.node2;
         node1Sensor3 = payload.node3;
      }
      else if (payload.ID = 'B')
      {
         Serial.print(payload.text);
         node2Sensor1 = payload.node1;
         node2Sensor2 = payload.node2;
         node2Sensor3 = payload.node3;
      }
      else
      {
         Serial.println("Invalid ID");
      }
   }
}

void serialPrint()
{
   Serial.print(" | Node 1 |");
   Serial.print(" Sensor 1: ");
   Serial.print(node1Sensor1);

   Serial.print(" Sensor 2: ");
   Serial.print(node1Sensor2);

   Serial.print(" Sensor 3: ");
   Serial.print(node1Sensor3);

   Serial.print(" | Node 2 |");
   Serial.print(" Sensor 1: ");
   Serial.print(node2Sensor1);

   Serial.print(" Sensor 2: ");
   Serial.print(node2Sensor2);

   Serial.print(" Sensor 3: ");
   Serial.print(node2Sensor3);
   Serial.print("|");


   Serial.println("          ");
   delay(1000);
}

void thingSpeakSend()
{
   ThingSpeak.setField(1, node1Sensor1);
   ThingSpeak.setField(2, node1Sensor2);
   ThingSpeak.setField(3, node1Sensor3);
   ThingSpeak.setField(4, WiFi.RSSI());
   ThingSpeak.setField(5, counter);
   ThingSpeak.writeFields(CHANNEL_ID, CHANNEL_API_KEY);
   delay(15000);
}

void connectToWiFi()
{
   Serial.print ("Connecting to WiFi");
   WiFi.mode(WIFI_STA);
   WiFi.begin(WIFI_NETWORK, WIFI_PASSWORD);

   unsigned long startAttemptTime = millis ();

   while (WiFi.status() != WL_CONNECTED && millis() - startAttemptTime < WIFI_TIMEOUT_MS)
   {
      Serial.print(".");
      delay(100);
   }
   if (WiFi.status() != WL_CONNECTED)
   {
      Serial.println("Failed!");
   }
   else
   {
      Serial.print("Connected!");
      Serial.print(WiFi.localIP());
   }
}

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