1

i'm trying to send data from a C++ program over serial communication to an Arduino. I formed a struct for sending the data as an object:

typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;

I'm using this Serial library: http://wjwwood.github.com/serial/ for sending the data like this:

    MachineParameters mp;
    mp.width = 100;
    mp.height = 200;
    mp.passBoard = true;

    ser.write((const uint8_t *)&mp, sizeof(mp));

The library makes it possible to send the data as uint8_t, std::vector or std::string.

The Arduino does receive data, but i don't know how to parse the data into the struct. I'm using the same struct as in the cpp code.

// In Arduio

MachineParameters mp;
int byte_size = 24;

loop() {
   if(Serial.available() >= 24) {
     Serial.readBytes((char*) &mp , 24);
   } 
}

// Goal: Read received mp data just like
// mp.width or mp.height

After hours of trying, i still cannot figure it out, how to send this struct to the arduino successfully. Is there another way of sending this data to the arduino? It worked sending the data as string, but that did not seem right.

I am pretty new to programming with C++, so please excuse any obvious questions...

Thank you for helping!


UPDATE: Working solution below

After a view more tries and thanks to your tips, i figured it out. Here is the code, which worked for me. I found out that my problem was the wrong byte size, used for parsing the buffer. The size of the struct in C++ is 12, whereas on the arduino it's 9. Using the original size (12) for parsing the buffer on the Arduino, the struct was parsed correctly.

/* --- C++ CODE --- */
typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;
// sizeof(MachineParameters) returns 12.


MachineParameters mp;
mp.width = 11.1;
mp.passBoard = false;
mp.height = 22.2;

ser.write((uint8_t *)&mp, sizeof(mp));
/* --- END OF C++ --- */



/* --- Arduino Code --- */
#define   BYTE_SIZE   12
char messageBuffer[BYTE_SIZE];

typedef struct
{
   double width;
   double height;
   bool passBoard;
} MachineParameters;

MachineParameters mp;

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

void loop() {

  if (Serial.available() >= BYTE_SIZE) {
    Serial.readBytes(messageBuffer , BYTE_SIZE);
    memcpy(&mp, &messageBuffer, BYTE_SIZE);

    // mp.width returns 11.1
    // Success :)
  }
}
/* --- END OF ARDUINO --- */
8
  • 1
    Please show us how you're trying to send the data, not just a description thereof. We can't tell you what's wrong if we don't know what you're doing. Commented Jan 11, 2018 at 17:20
  • Are you sending the structure verbatim or each field independently? Are you sending in binary or text? Commented Jan 11, 2018 at 18:05
  • Sorry, when i wrote the question, i was quite in a hurry. I edited the question now, hoping you can understand my problem now. Commented Jan 11, 2018 at 19:11
  • 1
    How do you know that the Arduino receives the data? And what happens when you try to deserialize the data (tat is, parse it back into the struct) on the same machine that you use to serialize it, without involving the Arduino? And have you tried sending simpler data to the Arduino by this method? Commented Jan 11, 2018 at 21:18
  • Yeah, I'd like to see a better description of why you think the code doesn't work and what you did to debug. What is Serial.available() returning after you send the data from your computer? If you read in all the available bytes and just look at the raw values of those bytes, what are they? Your Arduino program has no output so how do you know it's not working? What is sizeof(MachineParameters) on both systems? You might need to make the struct be packed so thare is no padding added by either compiler. Commented Jan 12, 2018 at 0:48

1 Answer 1

0

on the arduino you receive the data in a buffer as raw bytes

now you have to parse this, you can do this using memcpy to copy the data in the struct

however for doing this the data has to be aligned meaning that you have to know exactly where it begins. so you should send a synchronization byte ( start / stop bytes ) to be able to fix where the data begins

then you can use the code in parsing buffer data into struct :

struct abc {
    char a;
    char b;
    char c;
    char d[2];
};

int main() {

    char arr[5] = { 'a', 'b', 'c', 'd', 'e' };
    struct abc sa;
    memcpy(&sa, arr, 5);


    return 0;
}

here arr is incoming buffer, and with memcpy all the contents are copied appropriately.

ser.write((const uint8_t *)&mp, sizeof(mp)); is correct

you can create an identical structure mp_arduino on the arduino and copy the content of the receive buffer into this structure with

memcpy ( &mp_arduino, receive_buffer+n, sizeof(mp_arduino) ); where n indicates the position / byte in receive_buffer where your data begins and receive_buffer is defined as uint8_t receive_buffer[] ( or uint8_t* receive_buffer is the same... )

( http://www.cplusplus.com/reference/cstring/memcpy/ )

this is how a struct is stored in memory : How is a struct stored in memory?

on both systems a float should be 32 bit https://www.arduino.cc/reference/en/language/variables/data-types/float/

Sign up to request clarification or add additional context in comments.

1 Comment

So do you think that sending the data with ser.write((const uint8_t *)&mp, sizeof(mp)); is correct?

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.