sending packet over serial

I'm working on a project where I get some readings from a cube satellite (readings vary from float to int values mostly) and I need to transmit these readings from arduino to labview using the serial.
My problem is that I want to send them using a packet format.

I want to use the struct method but I wasn't able to make it work.
What is needed is to send the size of the packet (because labview should expect to receive a certain size) and to send the packet itself.
(reading from sensors and receiving from labview is handled, just writing the struct on the serial is the problem)

What I've tried is to just create a struct called packet_data, save my values in this struct and then serial.write / serial.print the struct but I don't think this is the proper way to do that. (plus it didn't work)

1 Like

Whether or not it is the "proper way", it works. I have done it many times. There is some error in your design or code.

This does not work

struct dataDef
{
  byte x = 123;
  byte y = 101;
} aStruct;

void setup()
{
  Serial.begin(115200);
  while (!Serial);
  Serial.print(aStruct.x);
  Serial.println(aStruct.y);
  Serial.print(aStruct);
}

void loop()
{
}
no matching function for call to 'print(dataDef*)'

I have done it many times

What is the secret ?

UKHeliBob:
What is the secret ?

If you want to send binary:

Serial.write((uint8_t *) &aStruct, sizeof(aStruct));

Thanks

I don't actually need/want to do it but it is good to know how to do it just in case it comes in useful at some time

The secret is that the members of the variable aStruct are stored in an array whose beginning address must be loaded into a pointer variable (byte *ptr) and then we have to read byte-by-byte all the data items of the array being pointed by ptr.

struct dataDef
{
  byte x = 123; 
  byte y = 101; 
} aStruct;

void setup()
{
  Serial.begin(9600);
  byte *ptr;
  ptr = (byte*)&aStruct;
  byte count = sizeof(aStruct);
  do
  {
    byte x = *ptr;
    Serial.println(x);
    ptr++;
    count--;
  }
  while (count !=  0);
}

void loop()
{
}

smnz.png

smnz.png

It's unclear what the value added would be of printing the contents of each of the struct's bytes in decimal ASCII.

There is no extra value added by sending ASCIIs; this is done just to see that data are being retrieved correctly. One can execute Serial.write(x) in the do-while loop of Post#5 or to use the following compact code of Post#3 to send binary:

Serial.write((uint8_t *) &aStruct, sizeof(aStruct));

However, the execution of Serial.write(x) might show some garbage charcaters on the Serial Monitor when there is no matching ASCII code. In this case, Serial.print(x) could be an added advantage in showing intelligible charcaters on the Serial Monitor.

You can use SerialTransfer.h to automatically packetize and parse your data for inter-Arduino communication without the headace. The library is installable through the Arduino IDE and includes many examples.

Here are the library's features:

This library:

  • can be downloaded via the Arduino IDE's Libraries Manager (search "SerialTransfer.h")
  • works with "software-serial" libraries
  • is non blocking
  • uses packet delimiters
  • uses consistent overhead byte stuffing
  • uses CRC-8 (Polynomial 0x9B with lookup table)
  • allows the use of dynamically sized packets (packets can have payload lengths anywhere from 1 to 255 bytes)
  • can transfer bytes, ints, floats, and even structs!!

Example TX Arduino Sketch:

#include "SerialTransfer.h"


SerialTransfer myTransfer;

struct STRUCT {
  char z;
  float y;
} testStruct;

uint16_t arr[3] = {0, 1, 2};


void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);

  testStruct.z = '|';
  testStruct.y = 4.5;
}


void loop()
{
  // use this variable to keep track of how many
  // bytes we're stuffing in the transmit buffer
  uint16_t sendSize = 0;

  ///////////////////////////////////////// Stuff buffer with individual bytes
  myTransfer.txBuff[0] = 'h';
  myTransfer.txBuff[1] = 200;
  sendSize += 2;

  ///////////////////////////////////////// Stuff buffer with struct
  myTransfer.txObj(testStruct, sizeof(testStruct), sendSize);
  sendSize += sizeof(testStruct);

  ///////////////////////////////////////// Stuff buffer with array
  myTransfer.txObj(arr, sizeof(arr), sendSize);
  sendSize += sizeof(arr);

  ///////////////////////////////////////// Send buffer
  myTransfer.sendData(sendSize);
  delay(100);
}

Example RX Arduino Sketch:

#include "SerialTransfer.h"


SerialTransfer myTransfer;

struct STRUCT {
  char z;
  float y;
} testStruct;

uint16_t arr[3] = {};


void setup()
{
  Serial.begin(115200);
  Serial1.begin(115200);
  myTransfer.begin(Serial1);
}


void loop()
{
  if(myTransfer.available())
  {
    // use this variable to keep track of how many
    // bytes we've processed from the receive buffer
    uint16_t recSize = 0;

    Serial.print(myTransfer.rxBuff[0]);
    Serial.print(' ');
    Serial.print(myTransfer.rxBuff[1]);
    Serial.print(" | ");
    recSize += 2;

    myTransfer.rxObj(testStruct, sizeof(testStruct), recSize);
    Serial.print(testStruct.z);
    Serial.print(' ');
    Serial.print(testStruct.y);
    Serial.print(" | ");
    recSize += sizeof(testStruct);

    myTransfer.rxObj(arr, sizeof(arr), recSize);
    Serial.print(arr[0]);
    Serial.print(' ');
    Serial.print(arr[1]);
    Serial.print(' ');
    Serial.println(arr[2]);
    Serial.println();
  }
  else if(myTransfer.status < 0)
  {
    Serial.print("ERROR: ");
    Serial.println(myTransfer.status);
  }
}
1 Like