1

Using two boards of similar architecture I would like to send the contents of a struct from the sending board to the receiving board. I am using UART to transfer.

My plan was to populate an array with the starting structs data. Transfer that, than un-package the array onto the receiving boards struct.

I'm not sure this is a possible option. Unpacking the array seems sort of rigid, as I would be assigning each struct variable to the array index. It might work but I'm not really convinced I should do it this way.

Here's what my sending sketch looks like.

Send:

typedef struct NWK_DataReq_t
{
 uint8_t      state;
 uint8_t      options;
} NWK_DataReq_t;

//Instance struct
NWK_DataReq_t dataRequest;

void setup() 
{
  //Give it some values
  dataRequest.state = 2;
  dataRequest.options = 4;

  Serial.begin(9600);
}

void loop() 
{  
  //set variable array to struct length
  uint8_t payload[sizeof(dataRequest)];

  //copy struct to variable array
  memcpy(payload,&dataRequest,sizeof(dataRequest));

  //send each item of struct, now contained in payload array
  for(int i=0;i < sizeof(payload);i++)
  {
    //Serial.print(i);
    //Serial.print(":");
    Serial.println(payload[i]);
  }

  Serial.println("");
  delay(1000);
}

Receive:

typedef struct NWK_DataReq_t
{
 uint8_t      state;
 uint8_t      options;
} NWK_DataReq_t;

//Instance struct
NWK_DataReq_t dataRequest;
uint8_t incomingPayload[sizeof(dataRequest)];

void setup() 
{
  Serial.begin(9600);
  Serial.print("Recieve started");
}

void loop() 
{

  if (Serial.available())
  {
    //add incoming data to array
    for(int i=0;i<sizeof(dataRequest);i++)
    {
      uint8_t incomingByte = Serial.read();
      incomingPayload[i] = incomingByte;
    }
  }

  //set array values to structs
  for (int i= 0;i < sizeof(dataRequest);i++)
  {
    structIndexPosition = incomingPayload[i];
  }
}

structIndexPosition is not attached as I wasn't sure how I might index the struct, or if this is an okay approach.

  • You might want to look at my ICSC library. It handles this kind of transfer very cleanly and reliably. Feel free to use it, abuse it, rip it to bits, steal bits from it, learn from it, get ideas from it, whatever: github.com/MajenkoLibraries/ICSC – Majenko Mar 24 '16 at 23:05
1

I think you are over-complicating it to send two bytes. Just send them as straight ASCII with a newline after, and decode it on the receiving end.

eg.

42,87

However if the question was just an example of something much more complex, then you may need to do more work. You need to have the receiving end know when a packet of data starts, and ends, and preferably have some validation that it wasn't corrupted. If you want to pursue that idea, see my thread about sending data via RS485 which has a library that does that sort of thing.

  • Thanks for the link, Nick. It will be more complex than this. I'll be looking into validation shortly, just wanted to get some basics straight. – SensationSama Mar 24 '16 at 22:32
1

The simplest possible way of sending the struct's data is:

Serial.write((const uint8_t *)&myData, sizeof(myData));

Get the address of myData, cast it to an unsigned int pointer, and starting at that address write the number of bytes specified by sizeof(myData). That will transfer the raw data of the struct through the serial with no messing with copying of data into other arrays, assigning pointers, etc.

However: it won't work.

Sending raw binary data over serial like that, where serial has no concept of anything other than bytes, it is just not possible to know where in the stream of data you are. Which of the myriad of bytes coming in is which within a struct? Who can tell?

So you need to write a protocol. A method whereby one end tells the other end "This is the start of the data. This is the data. This is the end of the data." But also you need to be able to say "This bit, that looks the same as the 'start of the data' message is actually a bit of the data, not the start of the data". You see, it's quite an involved task really.

0

Why go over the bridge for water?

It is possible to access the data in the struct as a character pointer. No need to transfer to a buffer etc.

void loop() 
{ 
  ...
  ...
  const char* dp = (const char*) &dataRequest;
  for (int i = 0; i < sizeof(dataRequest); i++) Serial.print(*dp++);
  Serial.println();
  delay(1000);
  ...
  ...
 }

It might be hard to extrapolate how to receive this?

void loop() 
{ 
  if (Serial.available() > sizeof(dataRequest)) {
     char* dp = (char*) &dataRequest;
     for (int i = 0; i < sizeof(dataRequest); i++) *dp++ = Serial.read(); 
     Serial.read();
     ...
     ...
  }
}

The Serial.println() and extra Serial.read() could be replaced by a "frame marker" and/or a check-sum.

Cheers!

  • Okay, but how would I populate the new struct with dp? – SensationSama Mar 24 '16 at 21:29
  • It appears to be working, some of the time. I have a Serial.print(dataRequest.options) line to confirm. It sometimes reaches 4, but also reaches a couple other numbers in a looping pattern. – SensationSama Mar 24 '16 at 22:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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