Sending data String with NRF24L01 (Solved)

Hello everyone,

For my home project i would like to transmit temperature and humidity values.
I had some issues sending these values right after the other (where the 2nd value is lost most of the times). Both modules work properly, the “hello world” message is send and received.

Now to solve this issue i had an idea to combine the values in a String and send them but i failed doing that too. Only some weird symbols are transmitted.

Is it possible to send a String across this transmitter? or is there a way i can transmit the 2 values sequential consistently? If both are possible what would be the best solution.

Transmitter

#include "DHT.h"
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#define DHTPIN 2    // modify to the pin we connected
#define DHTTYPE DHT22   // AM2301 
DHT dht(DHTPIN, DHTTYPE);

RF24 radio(9, 8);  // CE, CSN
const byte address[6] = "00001";

String h1 = " hum";
String t1 = " temp ";
 
void setup() 
{
 Serial.begin(9600); 
 dht.begin();
 radio.begin();
 radio.openWritingPipe(address);
 radio.stopListening();
}
 
void loop() 
{
 float h = dht.readHumidity();
 float t = dht.readTemperature();
 String stringh = String(h);
 String stringt = String(t);
 String b = stringt + t1 + stringh + h1;
 
 if (isnan(t) || isnan(h)) 
 {
   Serial.println("Failed to read from DHT");
   const char text[] = "No data";
   radio.write(&text, sizeof(text));
 } 
 else 
 {
  radio.write(&b, sizeof(b));
   delay(2000);
 }
}

Reciever

//Include Libraries
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

RF24 radio(9, 8);  // CE, CSN
const byte address[6] = "00001";

void setup()
{
  while (!Serial);
    Serial.begin(9600);
  
  radio.begin();
  radio.openReadingPipe(0, address);
  radio.startListening();
}

void loop()
{
  if (radio.available())
  {
    float text = 0;
    radio.read(&text, sizeof(text));
    delay(5);   
  }
}

I tried changing float to Char or int on the receiver side but i still have the same problem.

U5ED:
Now to solve this issue i had an idea to combine the values in a String and send them but i failed doing that too. Only some weird symbols are transmitted.

just put the float in a structure and send the structure in binary form.

Don't try to send an instance that way (would need to serialize it). For example just for your information, check what sizeof returns on your String when you dosizeof(b)

If you are not familiar with how to create a struct then you could put your two float values into an array and send the array. For example

float dataToSend[2];
dataToSend[0] = h;
dataToSend[1] = t;
radio.write(&dataToSend, sizeof(dataToSend));

and have an identical array on the receiving side

By the way DO NOT use single character variable names other than as the index in a FOR loop because it would be impossible to find (for example) all the instances of a variable called 't' in a program. Use meaningful variable names such as "temperatureValue" and "humidityValue"

...R
Simple nRF24L01+ Tutorial

Thank you Robin2 for your help,
With your comment and tutorial i have gained more insight in these transmitters.
Although i have to admit it does not work as i hoped.

For some reason when i put the NRF in place the Serial.print stops updating on the transmitter side.
And on the receiver side it only displays 0.00 over and over.
But i have a hard time finding my mistake, and i hope you’re or someone is able to help me.

Transmitter

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

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

RF24 radio(9, 8);
const byte slaveAddress[5] = {'R','x','A','A','A'};

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 2000;

void setup() {
  Serial.begin(9600);
  dht.begin();
  
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5);
  radio.openWritingPipe(slaveAddress);
}
//============== 
void loop() {
  currentMillis = millis();
  if (currentMillis - prevMillis >= txIntervalMillis) {
    send();
    prevMillis = millis();
  }
}
//==============
void send(){
  float humidityValue = dht.readHumidity();
  float temperatureValue = dht.readTemperature();
  
  if (isnan(temperatureValue) || isnan(humidityValue)) {
    Serial.println("Failed to read from Sensor");
//    const char text[] = "No data";
//    radio.write(&text, sizeof(text));
  } 
  else {
    float dataToSend[2];
    dataToSend[0] = temperatureValue;
    dataToSend[1] = humidityValue;
    
    Serial.println(dataToSend[0]);
    Serial.println(humidityValue);
    
    radio.write(&dataToSend, sizeof(dataToSend));
  }
}

Receiver

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

RF24 radio(9, 8);
const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

float temperatureValue;
float humidityValue;
bool newData = false;
    
void setup(){
  Serial.begin(9600);
  
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();
}

void loop(){
  getData();
  showData();
}

void getData(){
  if (radio.available()){
    float dataToReceive[2];
    dataToReceive[0] = temperatureValue;
    dataToReceive[1] = humidityValue;
    radio.write(&dataToReceive, sizeof(dataToReceive));
    newData = true;
  }
}
    
void showData(){
  if (newData == true){ 
    Serial.print(temperatureValue);
    Serial.print("\t");
    Serial.println(humidityValue);
    newData = false;
  }
}

why would you do a write() to RECEIVE data?

void getData(){
  if (radio.available()){
    float dataToReceive[2];
    dataToReceive[0] = temperatureValue;   // <<==== where does this value come from? 
    dataToReceive[1] = humidityValue;   // <<==== where does this value come from? 
    radio.write(&dataToReceive, sizeof(dataToReceive));  // <<==== ????
    newData = true;
  }

remember in the first code you were doing something like this when data was available:    radio.read(&text, sizeof(text));what has changed? what should you be receiving?

void getData(){
  if (radio.available()){
    float dataToReceive[2];
    dataToReceive[0] = temperatureValue;
    dataToReceive[1] = humidityValue;
    radio.write(&dataToReceive, sizeof(dataToReceive));
    newData = true;
  }
}

That is a very strange way to try to receive something.

Copy&Paste went horribly wrong.

Whandall:
Copy&Paste went horribly wrong.

It sure did…
Well now i’m at least receiving something every 2 seconds, although it’s only 0.00…

Is this because of the transmitter or does the receiver pick up the unchanged defined floats?

J-M-L:
remember in the first code you were doing something like this when data was available:

    radio.read(&text, sizeof(text));

what has changed? what should you be receiving?

I want to receive 2 values one temperature value (for example 15.45) and one humidity value (for example 50.64).
The text was partly for the text that i wanted to send, but i figured i could add that later on the receiver side.

I meant in that code you rightly use radio.read() to receive something, not radio.write()...(hint :slight_smile: )

We have to see your code if you change something, so post the new version(s).

Hints don't seem to work.

My apologies, hereby the updated code.
When i test the transmitter (without the NRF) the serial.print returns the values but once i connect the NRF (reconnect usb as well) the serial.print does not return anything.

Transmitter

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

#define DHTPIN 2
#define DHTTYPE DHT22

DHT dht(DHTPIN, DHTTYPE);

RF24 radio(9, 8);
const byte slaveAddress[5] = {'R','x','A','A','A'};

unsigned long currentMillis;
unsigned long prevMillis;
unsigned long txIntervalMillis = 2000;

void setup() {
  Serial.begin(9600);
  dht.begin();
  
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.setRetries(3,5);
  radio.openWritingPipe(slaveAddress);
}
//============== 
void loop() {
  currentMillis = millis();
  if (currentMillis - prevMillis >= txIntervalMillis) {
    send();
    prevMillis = millis();
  }
}
//==============
void send(){
  float humidityValue = dht.readHumidity();
  float temperatureValue = dht.readTemperature();
  
  if (isnan(temperatureValue) || isnan(humidityValue)) {
    Serial.println("Failed to read from Sensor");
//    const char text[] = "No data";
//    radio.write(&text, sizeof(text));
  } 
  else {
    float dataToSend[2];
    dataToSend[0] = temperatureValue;
    dataToSend[1] = humidityValue;
    
    Serial.println(dataToSend[0]);
    Serial.println(humidityValue);
    
    radio.write(&dataToSend, sizeof(dataToSend));
  }
}

Receiver

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

RF24 radio(9, 8);
const byte thisSlaveAddress[5] = {'R','x','A','A','A'};

float temperatureValue;
float humidityValue;
bool newData = false;
    
void setup(){
  Serial.begin(9600);
  
  radio.begin();
  radio.setDataRate( RF24_250KBPS );
  radio.openReadingPipe(1, thisSlaveAddress);
  radio.startListening();
}

void loop(){
  getData();
  showData();
}

void getData(){
  if (radio.available()){
    float dataToReceive[2];
    dataToReceive[0] = temperatureValue;
    dataToReceive[1] = humidityValue;
    radio.read(&dataToReceive, sizeof(dataToReceive));
    newData = true;
  }
}
    
void showData(){
  if (newData == true){ 
    Serial.print(temperatureValue);
    Serial.print("\t");
    Serial.println(humidityValue);
    newData = false;
  }
}

Your receiver code is odd. I'm not sure if it's just a copy & paste issue or a misconception around array usage. Anyway, rather than this:

    dataToReceive[0] = temperatureValue;
    dataToReceive[1] = humidityValue;
    radio.read(&dataToReceive, sizeof(dataToReceive));

Do this:

    radio.read(&dataToReceive, sizeof(dataToReceive));
    temperatureValue = dataToReceive[0];
    humidityValue = dataToReceive[1];
void getData(){
  if (radio.available()){
    float dataToReceive[2];  //declare a new variable that contains random data
    dataToReceive[0] = temperatureValue;  //put two variables set to zero when declared in the array
    dataToReceive[1] = humidityValue;
    radio.read(&dataToReceive, sizeof(dataToReceive));  //now get the real data
    newData = true;
  }
}
void showData(){
  if (newData == true){ 
    Serial.print(temperatureValue);  //print the unchanged zero value of 2 variables
    Serial.print("\t");
    Serial.println(humidityValue);
    newData = false;
  }
}

Note my added comments

What you need to do is to receive the array then copy its 0 and 1 levels into the 2 variables before printing them, or don't bother copying them and just print them from the array

void showData()
{
  if (newData == true)
  {
    Serial.print("Data received\t");
    Serial.print("Temperature : ");
    Serial.print(dataReceived[0]);
    Serial.print("\tHumidity : ");
    Serial.println(dataReceived[1]);
    newData = false;
  }
}

You can't just blindly cut & paste. Think about what you are writing, line by line. Otherwise you are just a parrot, repeating what you hear with no understanding.

Look at this:

 if (radio.available()){
    float dataToReceive[2];
    dataToReceive[0] = temperatureValue;
    dataToReceive[1] = humidityValue;
    radio.read(&dataToReceive, sizeof(dataToReceive));
    newData = true;

Then try this:

 if (radio.available()){
    float dataToReceive[2];
    radio.read(&dataToReceive, sizeof(dataToReceive));
    temperatureValue = dataToReceive[0];
    humidityValue = dataToReceive[1];
    newData = true;

Read that and imagine in your head what each line is doing, one line at a time. Then go back and read your code from before and imagine what that does, line by line. Explain to us why the former code was wrong, so we know you understand.

Thank you both for your help, it is working now. obviously :o ...
I don't know why but i was overthinking it :confused:.

In order to write something on the receiver side you first have to receive something. Only after this it can transfer the received array into the float variables.

UKHeliBob:
What you need to do is to receive the array then copy its 0 and 1 levels into the 2 variables before printing them, or don’t bother copying them and just print them from the array

void showData()

{
  if (newData == true)
  {
    Serial.print(“Data received\t”);
    Serial.print("Temperature : “);
    Serial.print(dataReceived[0]);
    Serial.print(”\tHumidity : ");
    Serial.println(dataReceived[1]);
    newData = false;
  }
}

This does make more sense. Cheers

well done :slight_smile: