Using arrays with Ard IDE and nRF24L01+ (TX not Matching RX)

Hi Chaps!

My 1st project & my 1st post, so apologies in advance :slightly_smiling_face: if I’m doing something stupid!!!

I have a working code (So I know hardware is working well) but its unfinished as I wanted to add more to it as its soooo longgggg :frowning: , I just wanted to reduce it by using arrays wherever I could. So i created a new sketch using a simple 4 button project using 2 x nRF24L01+, a nano as the TX and Leo as the RX. (Dedicated 3.3v to the nRFs with a 10uf cap on each)

The TX monitor appears to show that the data that’s being sent is correct, but the RX is receiving garbage, well I say garbage but it’s not, its constantly receiving the same garbage :pleading_face:

Please see comments in the code but basically...

  1. it seems that the "sizeof(txmessage1[i]" is not correct so i altered it in the code to +1 so that it is.
  2. the transmitted RX messages is not matching the TX messages ie...
    //RX receiving | when the TX is Sending
    // -□1 | A0R
    // 1□5 | A1R
    // 5□9 | A2R ... more in the code.
    here is the TX code....
#include <SPI.h>
#include <RF24.h>
#include <nRF24L01.h>

RF24 radio(9, 10); // CE, CSN
const int InputPins[] {A0, A1, A2, A3};// Nano Pins Values (14,15,16 & 17)
const int PinsInUse = 4;
bool InputState[4] {false, false, false, false};
bool lastInputState[4] = {false, false, false, false};
const char* txmessage1[] = {"A0P", "A1P", "A2P", "A3P"};
const char* txmessage0[] = {"A0R", "A1R", "A2R", "A3R"};

void setup() {
  for (int i = 0; i < PinsInUse; i++) {
    pinMode(InputPins[i], INPUT_PULLUP);
  }
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(0xF0F0F0E1LL); // Set the transmitting address
  radio.setPALevel(RF24_PA_LOW); // Set power level (Low to save power)
}
void loop() {
  for (int i = 0; i < PinsInUse; i++) {
    InputState[i] = digitalRead(InputPins[i]);
  }
  for (int i = 0; i < PinsInUse; i++) {
    if (InputState[i] != lastInputState[i]) { //rem line to get repeated serial monitor results
      if (InputState[i] == LOW) {
        radio.write(&txmessage1[i], sizeof(txmessage1[i])+1);
        Serial.println(txmessage1[i]); //TX Serial Monitor displaying "A0P", "A1P", "A2P", "A3P"
        Serial.println(sizeof(txmessage0[i])+1); // Size in Serial monitor = 2 ????? why ??? forcing to 3 or 4 RX doesnt rec correct data
      }
      if (InputState[i] == HIGH) {
        radio.write(&txmessage0[i], sizeof(txmessage0[i])+1);
        Serial.println(txmessage0[i]); //TX Serial Monitor displaying "A0R", "A1R", "A2R", "A3R"
        Serial.println(sizeof(txmessage0[i])+1); // Size in Serial monitor = 2 ????? why ??? forcing to 3 or 4 RX doesnt rec correct data
      }
    lastInputState[i] = InputState[i]; //rem line to get repeated serial monitor results
    } //rem line to get repeated serial monitor results
  }
}

here is the RX Code...

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

RF24 radio(9, 10);    // CE, CSN

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(1, 0xF0F0F0E1LL);  //same address as the transmitter
  radio.setPALevel(RF24_PA_LOW);          // Set power level (Low to save power, High for greater distance)
  radio.startListening();
}

void loop() {
  if (radio.available()) {
    char text[3] = "";
    radio.read(&text, sizeof(text));
    Serial.println(text); //serial monitor results below----¬
    // Text being received by the RX is not same as what the TX is sending
    // RX receiving | when the TX is Sending
    //      -□1      |      A0R
    //      1□5      |      A1R
    //      5□9      |      A2R
    //      9□=      |      A3R
    //      =□A      |      A0P
    //      A□E      |      A1P
    //      E□I      |      A2P
    //      I□□      |      A3P
  } 
}

Any help in solving my issue would be appreciated.

Many thanks in advance.

Which "nano" exactly? There are multiple Arduino boards with that family name and they are very different.

The variable 'txmessage1[i]' is a pointer. So, sizeof() will give you the size of a pointer on your particular processor, not the size of the character string in pointing to. This size is a constant.

@gfvalvo
Thanks for reply.
The Nano was from amazon im guessing its a generic one as its not branded.

If I leave the code as radio.write(&txmessage1[i], sizeof(txmessage1[i])); then the RX only displays 2 characters ie..
"-□" instead of "A0R" ; "1□" instead of "A1R"; "5□" instead of "A2R" and so on.
May be then, sizeof(txmessage1[i]) is not an issue?

In most cases a simple test program helps to find the bug (which @gfvalvo already explained):

const char* txmessage1[] = {"A0P", "A1PP", "A2PPP", "A3PPPP", "A4PPPPP"};
constexpr byte noOfMsgs = sizeof txmessage1 / sizeof txmessage1[0];

void setup() {
  Serial.begin(115200);
  Serial.print("No of Messages: ");
  Serial.println(noOfMsgs);
  wrong();
  correct();
}

void loop() {
}

void wrong() {
  Serial.println("\n========== Wrong Method =======================");
  Serial.println("\nLength\tMessage");
  for (int i = 0; i < noOfMsgs; i++) {
    Serial.print(sizeof(txmessage1[i])); //
    Serial.print("\t");
    Serial.println(txmessage1[i]);
  }
}

void correct() {
  Serial.println("\n========== Correct Method =======================");
  Serial.println("\nLength\tMessage");
  for (int i = 0; i < noOfMsgs; i++) {
    Serial.print(strlen(txmessage1[i])); //
    Serial.print("\t");
    Serial.println(txmessage1[i]);
  }
}

Output:

No of Messages: 5

========== Wrong Method =======================

Length	Message
2	A0P
2	A1PP
2	A2PPP
2	A3PPPP
2	A4PPPPP

========== Correct Method =======================

Length	Message
3	A0P
4	A1PP
5	A2PPP
6	A3PPPP
7	A4PPPPP

However the wrong characters received seem to be different problem ...

It's absolutely an issue. There may be others.

@ec2021 @gfvalvo
thanks for that so issue 1 solved as per your post.
FYI strleng() is now reported as "3" , which is correct (presumably data sent to the RX was always correct, just not in the serial monitor), apologies for my lack of knowledge :frowning:
i have removed the +1 so that now its radio.write(&txmessage1[i], sizeof(txmessage1[i])); and radio.write(&txmessage0[i], sizeof(txmessage0[i]));
it just the 2nd more problematic issue left.

What happens if you try this

  radio.write(txmessage1[i], strlen(txmessage1[i])); 

?

Edit: Better try this:

radio.write(*txmessage1[i], strlen(txmessage1[i])); 

!!!!!

Better, as explained when removing the +1 was only showing 2 characters on the RX side. now with this code mod its showing 3 as per the original # 1st post

See my correction above!

Just checked that the library is using an untyped pointer. Therefore using the * should solve the issue.

using...

gives me some stange value thats the same for all button releases...
image

radio.write(&txmessage0[i], strlen(txmessage0[i])); 

This does not, same as per the original post...
image

TX code now ...

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

RF24 radio(9, 10); // CE, CSN
const int InputPins[] {A0, A1, A2, A3};// Nano Pins Values (14,15,16 & 17)
const int PinsInUse = 4;
bool InputState[4] {false, false, false, false};
bool lastInputState[4] = {false, false, false, false};
const char* txmessage1[] = {"A0P", "A1P", "A2P", "A3P"};
const char* txmessage0[] = {"A0R", "A1R", "A2R", "A3R"};

void setup() {
  for (int i = 0; i < PinsInUse; i++) {
    pinMode(InputPins[i], INPUT_PULLUP);
  }
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(0xF0F0F0E1LL); // Set the transmitting address
  radio.setPALevel(RF24_PA_LOW); // Set power level (Low to save power)
}
void loop() {
  for (int i = 0; i < PinsInUse; i++) {
    InputState[i] = digitalRead(InputPins[i]);
  }
  for (int i = 0; i < PinsInUse; i++) {
    //if (InputState[i] != lastInputState[i]) { //rem line to get repeated serial monitor results
      if (InputState[i] == LOW) {
        //radio.write(&txmessage1[i], sizeof(txmessage1[i]));
        radio.write(&txmessage1[i], strlen(txmessage1[i]));
        Serial.println(txmessage1[i]); //TX Serial Monitor displaying "A0P", "A1P", "A2P", "A3P"
        Serial.println(strlen(txmessage1[i])); //TX Monitor displaying "3" for all button presses.
      }
      if (InputState[i] == HIGH) {
        //radio.write(&txmessage0[i], sizeof(txmessage0[i]));
        radio.write(&txmessage0[i], strlen(txmessage0[i]));
        Serial.println(txmessage0[i]); //TX Serial Monitor displaying "A0R", "A1R", "A2R", "A3R"
        Serial.println(strlen(txmessage0[i])); //TX Monitor displaying "3" for all button Releases.
      }
    //lastInputState[i] = InputState[i]; //rem line to get repeated serial monitor results
    //} //rem line to get repeated serial monitor results
  }
}

TX Code (Transmitter):

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

RF24 radio(9, 10); // CE, CSN
const int InputPins[] = {A0, A1, A2, A3};
const int PinsInUse = 4;
bool InputState[4] = {false, false, false, false};
bool lastInputState[4] = {false, false, false, false};
const char* txmessage1[] = {"A0P", "A1P", "A2P", "A3P"};
const char* txmessage0[] = {"A0R", "A1R", "A2R", "A3R"};

void setup() {
  for (int i = 0; i < PinsInUse; i++) {
    pinMode(InputPins[i], INPUT_PULLUP);
  }
  Serial.begin(9600);
  radio.begin();
  radio.openWritingPipe(0xF0F0F0E1LL);
  radio.setPALevel(RF24_PA_LOW);
}

void loop() {
  for (int i = 0; i < PinsInUse; i++) {
    InputState[i] = digitalRead(InputPins[i]);
    if (InputState[i] != lastInputState[i]) {
      if (InputState[i] == LOW) {
        radio.write(txmessage1[i], strlen(txmessage1[i]) + 1);
        Serial.println(txmessage1[i]);
      } else {
        radio.write(txmessage0[i], strlen(txmessage0[i]) + 1);
        Serial.println(txmessage0[i]);
      }
      lastInputState[i] = InputState[i];
    }
  }
}

Explanation of Fixes:

  1. Calculate Message Length:

    • We calculate the message length using strlen() to include the null terminator, ensuring the entire message is sent.
  2. Removed Redundant Serial Prints:

    • Removed the extra Serial.println(sizeof(txmessage0[i]) + 1); lines that were not necessary.

RX Code (Receiver):

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

RF24 radio(9, 10);

void setup() {
  Serial.begin(9600);
  radio.begin();
  radio.openReadingPipe(1, 0xF0F0F0E1LL);
  radio.setPALevel(RF24_PA_LOW);
  radio.startListening();
}

void loop() {
  if (radio.available()) {
    char text[4] = ""; // Increased the buffer size to 4 to accommodate the null terminator.
    radio.read(&text, sizeof(text));
    Serial.println(text);
  }
}

Explanation of Fixes:

  1. Correct Buffer Size:

    • Increased the buffer size to 4 to accommodate the null terminator.
  2. Removed Comments:

    • Removed comments from the RX code as they were no longer necessary.

These fixes should ensure that your transmitter sends messages with the proper size, and your receiver reads and prints the received messages correctly. The null terminator '\0' is essential for C-style strings, and by addressing these issues, you should have a more reliable communication between the transmitter and receiver.

1 Like

@codingapacalyspe

Brilliant!!!! Thats fixed the issue. What a team you all are and thank you!

The main fixer was changing TX from radio.write(&txmessage1[i], sizeof(txmessage1[i])+1); to...
radio.write(txmessage1[i], strlen(txmessage1[i]) + 1);
and
RX to char text[4] = "";

FYI i will need to change the else statement to an if as i have more equipment to add to this base code. i hope i dont f it up :slight_smile:

Lol well good luck with that thanks for stopping by.

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