Nrf24l01 does not show all characters in the receiver

Hello everyone. I am using Arduin mega (with RTC and DH22) and I wanna receive this values in receiver (UNO R4). The main problem is that in the receiver serial monitor does show all characters. When I increase the size of the payload or text in both, does not make change. Here are my code: The only way to include humidity and the rest of the characters is to delete some of the previous characters for example deleting Data or time or some of the empty characters in between.

[#include](tg://search_hashtag?hashtag=include) <SPI.h>
[#include](tg://search_hashtag?hashtag=include) <nRF24L01.h>
[#include](tg://search_hashtag?hashtag=include) <RF24.h>
[#include](tg://search_hashtag?hashtag=include) <DHT.h>
[#include](tg://search_hashtag?hashtag=include) <RtcDS1302.h>

RF24 radio(33, 32); // CE, CSN

const byte address[6] = "00001";

[#define](tg://search_hashtag?hashtag=define) DHTPIN 35     // Digital pin connected to the DHT sensor 
[#define](tg://search_hashtag?hashtag=define) DHTTYPE    DHT22     // DHT 22 (AM2302)

DHT dht(DHTPIN, DHTTYPE);

ThreeWire myWire(39, 41, 37); // IO, SCLK, CE
RtcDS1302<ThreeWire> Rtc(myWire);

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

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

  dht.begin();

  Rtc.Begin();

  Serial.print("compiled: ");
  Serial.print(DATE);
  Serial.println(TIME);

  RtcDateTime compiled = RtcDateTime(DATE, TIME);
  printDateTime(compiled);
  Serial.println();

  if (!Rtc.IsDateTimeValid()) {
    Serial.println("RTC lost confidence in the DateTime!");
    Rtc.SetDateTime(compiled);
  }

  if (Rtc.GetIsWriteProtected()) {
    Serial.println("RTC was write protected, enabling writing now");
    Rtc.SetIsWriteProtected(false);
  }

  if (!Rtc.GetIsRunning()) {
    Serial.println("RTC was not actively running, starting now");
    Rtc.SetIsRunning(true);
  }

  RtcDateTime now = Rtc.GetDateTime();
  if (now < compiled) {
    Serial.println("RTC is older than compile time!  (Updating DateTime)");
    Rtc.SetDateTime(compiled);
  } else if (now > compiled) {
    Serial.println("RTC is newer than compile time. (this is expected)");
  } else if (now == compiled) {
    Serial.println("RTC is the same as compile time! (not expected but all is fine)");
  }
}

void loop() {
  float temperature = dht.readTemperature();
  float humidity = dht.readHumidity();

  RtcDateTime now = Rtc.GetDateTime();

  // Convert temperature, humidity, date, and time to strings
  char temperatureStr[6];
  dtostrf(temperature, 4, 2, temperatureStr); // Format: "%.2f"

  char humidityStr[6];
  dtostrf(humidity, 4, 2, humidityStr); // Format: "%.2f"

  char dateString[12];
  sprintf(dateString, "%04u/%02u/%02u", now.Year(), now.Month(), [now.Day](https://now.day/)());

  char timeString[9];
  sprintf(timeString, "%02u:%02u:%02u", now.Hour(), now.Minute(), now.Second());

  // Print date, time, temperature, and humidity in one line
  Serial.print(dateString);
  Serial.print(" ");
  Serial.print(timeString);
  Serial.print(" T:");
  Serial.print(temperatureStr);
  Serial.print("°C H:");
  Serial.print(humidityStr);
  Serial.println("%");

  // Construct message payload
  char payload[500];
  sprintf(payload, "%s %s T:%s°C H:%s%%", dateString, timeString, temperatureStr, humidityStr);

  // Send payload via NRF24L01
  radio.write(&payload, sizeof(payload));


  delay(1000); // Adjust delay as needed
}

void printDateTime(const RtcDateTime& dt) {
  char datestring[50];
  snprintf_P(datestring, 
            sizeof(datestring),
            PSTR("%04u/%02u/%02u %02u:%02u:%02u"),
            dt.Year(),
            dt.Month(),
            [dt.Day](https://dt.day/)(),
            dt.Hour(),
            dt.Minute(),
            dt.Second() );
  Serial.print(datestring);
}

My Reciever:

[#include](tg://search_hashtag?hashtag=include) <SPI.h>
[#include](tg://search_hashtag?hashtag=include) <nRF24L01.h>
[#include](tg://search_hashtag?hashtag=include) <RF24.h>

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

const byte address[6] = "00001";

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

void loop() {
  if (radio.available()) {
    char text[500] = ""; // Increase the buffer size to ensure it can hold the entire payload
    [radio.read](https://radio.read/)(&text, sizeof(text));

    
    // Print the received payload
    Serial.println(text);

  }
}

Serial monitor:
Sender:
2024/05/07 15:02:07 T:25.90°C H:48.90%

reciever:
2024/05/07 15:02:12 T:25.90°C H

Does this actually compile?
Where's the code that receives the RF data?

Why would you want to send such a long, formatted string? Why not just send data in smaller packets and in a numerical value instead? Smaller packets = less chance of data corruption. Numerical data = smaller size than a formatted text string, so again less chance of problems.

I've never tried sending hundreds of bytes at a time through RF24. Try something like 16 bytes at a time or so.

Thank you so much for your reply. I am begginer. Could you please help me how can I send them as integer not string? The project will have 12 sensors that I need to send them all to the UNO as a receiver.

One thing you could do is store the sensor values in a 'struct' and then send that struct to the other side. Unpack it on the receiver side and display/use the values as you see fit.

Google turns up e.g. this:

The rf24 has only 32 byte transmit and receive buffers. Any bytes beyond that will be lost.

You may wish to look into the HC12. Similar range and speed, uses serial port (2 pins), larger buffers.

1 Like

Hello everyone. I had to send more than 32 bytes using nrf24L01, which is why I have used the following in the transmitter and receiver. The main problem is that the data are character (not float) and also print in the serial monitor and SD are printed in three line for each time step:
However, I would like to see them in line and be separate in Excel. Can anyone please help me? Thank you so much in advance.

2024/5/9 15:0:15, 26.38, 26.63,
26.56, 26.75, 27.13, 26.63
2024/5/9 15:0:16, 26.38, 26.63,
26.56, 26.69, 27.13, 26.69
2024/5/9 15:0:18, 26.38, 26.63,
26.56, 26.81, 27.06, 26.69

The transmitter:

// Construct data packet
    String dataPacket = String(dt.Year()) + "/" + String(dt.Month()) + "/" + String(dt.Day()) + " " +
                        String(dt.Hour()) + ":" + String(dt.Minute()) + ":" + String(dt.Second()) + ", " +
                        String(temperature1) +
                        ", " + String(temperature2) +
                        ", " + String(temperature3) +
                        ", " + String(temperature4) +
                        ", " + String(temperature5) +
                        ", " + String(temperature6) ;

    // Send data packet in smaller chunks
    for (int i = 0; i < dataPacket.length(); i += maxPacketSize) {
        radio.write(dataPacket.substring(i, i + maxPacketSize).c_str(), maxPacketSize);
        delay(10); // Delay between sending chunks, adjust if needed

The receiver:

#include <Arduino.h>
#include <WiFiS3.h>
#include <SPI.h>
#include <RF24.h>
#include <SD.h>

// WiFi credentials
char ssid[] = "Buffalo-G-E92E";     // Your WiFi network SSID
char pass[] = "n5n37dfe4enr3"; // Your WiFi network password

// NRF24L01 pins
#define CE_PIN 7
#define CSN_PIN 8

#define SD_CS_PIN 10 // Choose a free pin for SD card chip select (CS)

RF24 radio(CE_PIN, CSN_PIN);

const uint64_t pipe = 0xE8E8F0F0E1LL; // Pipe address for the NRF24 module

File dataFile; // File object for SD card
bool sdCardPresent = true; // Flag to track if SD card is present

void setup() {
    Serial.begin(9600);  // Initialize serial communication

    // Connect to WiFi network
    WiFi.begin(ssid, pass);

    Serial.print("Connecting to ");
    Serial.println(ssid);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    // Initialize SD card
    if (!SD.begin(SD_CS_PIN)) {
        Serial.println("SD card initialization failed!");
        sdCardPresent = false;
    } else {
        Serial.println("SD card initialized.");
    }

    // Setup NRF24L01
    radio.begin();
    radio.openReadingPipe(1, pipe);
    radio.setPALevel(RF24_PA_LOW);
    radio.startListening();
}

void loop() {
    if (sdCardPresent) {
        if (radio.available()) {
            char receivedData[32]; // Buffer to store received data
            radio.read(&receivedData, sizeof(receivedData)); // Read the received data
            Serial.print(receivedData); // Print the received data without newline
            Serial.println(); // Print newline after each transmission

            // Write received data to SD card
            writeDataToSD(receivedData);
        }
    } else {
        // Check if SD card is reinserted
        if (SD.begin(SD_CS_PIN)) {
            Serial.println("SD card reinserted.");
            sdCardPresent = true;
        }
    }
}

void writeDataToSD(char* data) {
    // If the SD card is not present, return without writing
    if (!sdCardPresent) {
        return;
    }

    // Open or create a file on the SD card
    dataFile = SD.open("data.txt", FILE_WRITE);
    
    // If the file opened successfully, write data to it
    if (dataFile) {
        dataFile.println(data);
        dataFile.close();
    } else {
        Serial.println("Error opening data file.");
        sdCardPresent = false; // Mark SD card as not present
    }
}

Maybe try including the line-end character '\n' in the string that the transmitter sends.

In the receiver code, use .print() instead of .println() when printing the received characters.

Thank you so much dear Paul, could you please just edit those two lines? do I need to do both?

Why do you convert the data into text form before sending it? This is very inefficient. Send a digital data in binary form and convert it to text after receiving.

Compare - now your string takes up 60 bytes:

"2024/5/9 15:0:15, 26.38, 26.63,26.56, 26.75, 27.13, 26.63"

while in binary form it is only 16:

2024/5/9 15:0:15  - unix timestamp 4 bytes
6 temperatures multiplied by 100 as int16_t = 6 x 2  = 12 bytes

or, for simplicity - just code every field of date-time as byte - it will take a 6 bytes. With 6 temperature values it takes a 18 bytes total - a three times less than text.

This will give you the ability to send a whole dataPacket at a time.

2 Likes

Sorry, I don't have the time. Make an attempt and post what you tried here if it does not work as you wanted (and describe what did happen).

Both what?

1 Like

This line is causing the new line to be saved.

dataFile.println(data);

Change it to

dataFile.print(data);

Then add

dataFile.println();

after all data chunks for the massage have been saved

1 Like

It seems that it is the best way but I was not able to do it. It was out of my knowledge I think. Thank you so much.

I did, but still, the same format was saved!

Post the sketch that you changed

It is my whole receiver code: Do you need transmitter also? It is too long code.

#include <Arduino.h>
#include <WiFiS3.h>
#include <SPI.h>
#include <RF24.h>
#include <SD.h>

// WiFi credentials
char ssid[] = "Buffalo-G-E92E";     // Your WiFi network SSID
char pass[] = "n5n37dfe4enr3"; // Your WiFi network password

// NRF24L01 pins
#define CE_PIN 7
#define CSN_PIN 8

#define SD_CS_PIN 10 // Choose a free pin for SD card chip select (CS)

RF24 radio(CE_PIN, CSN_PIN);

const uint64_t pipe = 0xE8E8F0F0E1LL; // Pipe address for the NRF24 module

File dataFile; // File object for SD card
bool sdCardPresent = true; // Flag to track if SD card is present

void setup() {
    Serial.begin(9600);  // Initialize serial communication

    // Connect to WiFi network
    WiFi.begin(ssid, pass);

    Serial.print("Connecting to ");
    Serial.println(ssid);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }

    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    // Initialize SD card
    if (!SD.begin(SD_CS_PIN)) {
        Serial.println("SD card initialization failed!");
        sdCardPresent = false;
    } else {
        Serial.println("SD card initialized.");
    }

    // Setup NRF24L01
    radio.begin();
    radio.openReadingPipe(1, pipe);
    radio.setPALevel(RF24_PA_LOW);
    radio.startListening();
}

void loop() {
    if (sdCardPresent) {
        if (radio.available()) {
            char receivedData[32]; // Buffer to store received data
            radio.read(&receivedData, sizeof(receivedData)); // Read the received data
            Serial.print(receivedData); // Print the received data without newline
            Serial.println(); // Print newline after each transmission

            // Write received data to SD card
            writeDataToSD(receivedData);
        }
    } else {
        // Check if SD card is reinserted
        if (SD.begin(SD_CS_PIN)) {
            Serial.println("SD card reinserted.");
            sdCardPresent = true;
        }
    }
}

void writeDataToSD(char* data) {
    // If the SD card is not present, return without writing
    if (!sdCardPresent) {
        return;
    }

    // Open or create a file on the SD card
    dataFile = SD.open("data.txt", FILE_WRITE);
    
    // If the file opened successfully, write data to it
    if (dataFile) {
        dataFile.print(data);      //changed line
        dataFile.println();          //new line
        dataFile.close();
    } else {
        Serial.println("Error opening data file.");
        sdCardPresent = false; // Mark SD card as not present
    }
}
        dataFile.print(data);  //changed line
        dataFile.println();    //new line
        dataFile.close();

You are saving a newline after each chunk

What I suggested was

Transmitter code:

struct {
  uint8_t date[6];
  int16_t temperature[6];
} data_packet;

// Construct data packet
    data_packet.date[0] = dt.Year() % 100;
    data_packet.date[1] = dt.Month();
    data_packet.date[2] = dt.Day();
    data_packet.date[3] = dt.Hour();
    data_packet.date[4] = dt.Minute();
    data_packet.date[5] = dt.Second();

    data_packet.temperature[0] = temperature1 * 100;
    data_packet.temperature[1] = temperature2 * 100;
    data_packet.temperature[2] = temperature3 * 100;
    data_packet.temperature[3] = temperature4 * 100;
    data_packet.temperature[4] = temperature5 * 100;
    data_packet.temperature[5] = temperature6 * 100;
// Send data packet
    radio.write(&data_packet, sizeof(data_packet);
    delay(10);

Receiver code:

// Structure to store received data
struct {
  uint8_t date[6];
  int16_t temperature[6];
} data_packet;

if (radio.available()) {
  radio.read(&data_packet, sizeof(data_packet)); // Read the received data
  String receivedData = String(data_packet.date[0] + 2000) + "/"
                      + String(data_packet.date[1]) + 
                  "/" + String(data_packet.date[2]) + 
                  " " + String(data_packet.date[3]) +
                  ":" + String(data_packet.date[4]) +
                  ":" + String(data_packet.date[5]) + ", " +

                        String(data_packet.temperature[0] / 100.0) +
                 ", " + String(data_packet.temperature[1] / 100.0) +
                 ", " + String(data_packet.temperature[2] / 100.0) +
                 ", " + String(data_packet.temperature[3] / 100.0) +
                 ", " + String(data_packet.temperature[4] / 100.0) +
                 ", " + String(data_packet.temperature[5] / 100.0) ;

    Serial.print(receivedData); // Print the received data without newline
    Serial.println(); // Print newline after each transmission

     // Write received data to SD card
     writeDataToSD(receivedData);
        }

Do you mean at the end of the loop? Could you please tell me after which line should I add it? So sorry for my many questions.

And as also suggested in your previous thread on the same issue, my recommendation is to not send big formatted strings/character arrays because there's no need to do this, and it just makes your radio communications complicated.

Send the individual parameters over the radio and then format them as desired on the other end. You can pack a few variables together (e.g. 4 floats or so), but it's probably simpler if you just send the variables one by one. You can make data packets that consists of a variable ID that tells the other side which kind of data are being transmitted and a payload.

1 Like

No, I don't mean at the end of loop()

You break the message into chunks then save each chunk. When you have saved all of the chunks of a message it is then that you need to save the newline