0

I am using RadioHead library for the communication between nrf24l01. I am sharing the snippet of my code below because the code is too huge. The problem i am facing here is on the receiver side i am not be able see the data i am sending , it is showing squares and not the proper characters. my output showing to me is :

name :?!

skill :

Sender Code :

struct DataHolder {
  String name;
  String skill;
};

DataHolder dh;

RH_NRF24 nrf24(10, 9);


//THIS METHOD I AM USING TO SEND DATA FROM SENDER NRF
void sendtonrf(){

 dh.name = "xyz";
 dh.skill = "classA";

 nrf24.send((uint8_t *)&dh, sizeof(dh));

}

receiver code:

struct DataHolder {
String name;
String skill;
};

 DataHolder dh;

 void loop{

 if (nrf24.available()) {

  uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];
  uint8_t len = sizeof(buf);

    if (nrf24.recv(buf, &len)) {

    String str1 = (((DataHolder*)buf))->name;
    String str2 = ((DataHolder*)buf)->skill;
    Serial.println("name :" + str1);
    Serial.println("skill :" + str2);

    }
 }
}

1 Answer 1

2

Your problem is that you are working with pointers. You have a pointer to a block of memory with some text in it, then you take that pointer, get the address of the variable that stores it, convert it to a pointer to an 8-bit value, and send that. Which of course won't work.

Instead you need to send the content of the memory the pointer points to:

nrf24.send((uint8_t *)strm, strlen(strm));

strm is already a pointer, you don't need to convert it to a pointer with & - that just confuses things and gives you a pointer to a pointer, which in this context is garbage.

A struct made up of String objects will not do what you think it does. A String object does not contain the string itself. Instead it just allocates an external block of RAM (from the heap) using malloc() and holds a pointer to that memory. If you try transferring a struct which contains String objects all you will be sending is the data associated directly with those String objects, including the pointer to the string content, which is completely meaningless to the remote end.

Instead you will either have to send the strings separately along with their length and some identifier to say what the string is, or rebuild the string content into a fixed size buffer.

Personally I would use a fixed size buffer. In this method you change your struct so it contains two character arrays with a fixed size. For instance:

struct DataHolder {
    char name[10]; // Room for 9 characters + NULL
    char skill[10]; // Room for 9 characters + NULL
};

Then copy your string data into it:

struct DataHolder data;

strncpy(data.name, "Fred", 10); // Maximum 10 bytes
strncpy(data.skill, "ClassA", 10); // Again, max 10 bytes.

Now you can send the struct in its entirety:

nrf24.send((uint8_t *)&data, sizeof(struct DataHolder));

The data sent (and indeed the data held in the Arduino's RAM) will be:

Fred\0\?\?\?\?\?ClassA\0\?\?\?

Where \? represents any possible character (undefined, basically, and depends on how the variable was created - if it's global it'll be all 0, if it's on the stack then it will be whatever was in that block of memory beforehand) and \0 is the standard C end of string NULL character (ASCII 0).

For receiving it's exactly the same. Use the same struct, and go:

struct DataHolder data;

int len;
if (nrf24.recv((uint8_t *)&data, &len)) {
    // Do something with data.name and data.skill
}

Or you can use a buffer and a pointer, which may be safer since you have no chance of overrunning the buffer with a message coming in that is bigger than the data structure size:

struct DataHolder *data;
uint8_t buf[RH_NRF24_MAX_MESSAGE_LEN];

if (nrf24.recv(buf, &len)) {
    data = (struct DataHolder *)buf;
    // Do something with data->name and data->skill
}

Note the change from . to -> for the struct access since it's now a pointer.

Also note that you don't want your struct to be any bigger than your maximum packet size. To send anything bigger you will have to chunk the data up and send it in little bits.

8
  • i changed it. but still getting the garbage but different this time. Sep 26, 2017 at 9:57
  • Well, you're sending a String but trying to receive a struct. That's not going to work. You have to receive what you send. If you send the content of a character array you have to receive the content of a character array. BTW, a struct of String won't contain the String content, only the objects which don't themselves contain the string content, only a pointer to it.
    – Majenko
    Sep 26, 2017 at 10:03
  • hi . i cannot share the full code. but i have changed the code above. Also i really appreciate for the quick response brother. can you check the code again. Also i am very very new to arduino and c,c++ , where i can learn this casting and deep things. Sep 26, 2017 at 10:09
  • 2
    If you want to use pointers, structs, casting, I advice to read a book about C. It does not have to be related to Arduino. Sep 26, 2017 at 10:15
  • 1
    It is not an easy topic. It took me years to master the finer points.
    – Majenko
    Sep 26, 2017 at 10:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.