Sending structs through serial.

Zadiq:
My problem now is that I don't know how to send and receive struct through serial. And is there an alternative way that is better than struct to send multiple command and data.

J-M-L:
The idea of a struct is good. Your variable holding the struct is a pointer to the first byte of the struct and the sizeof() function will tell you how many bytes are in the struct.

So what you can do is have a byte pointer variable pointing to the address of the struct and iterate for each byte in struct and write that byte to serial. This way you dump the memory structure in binary onto the serial port. On the receiving side you read it the same way and populate the bytes of a similarly declared structure. (you can use a union to make such code looks better than arbitrarily casting pointers)

The following is an approximate coding translation of what has been described by @J-M-L in the above quote:
1. The given struct is:

struct button
{
   int HEX_VALUE; /*each button has its own hex value that I created*/
   int analog;
};

button state;

2. Initialize HEX_VALUE and analog with arbitrary example data:

state.HEX_VALU = 0x4567;
state.analog = 0x1234;

3. During compilation process, an array is created in RAM memory to hold the values of variables. The following codes could be executed to know the beginning address of the array and the number of bytes present in the array.

byte *ptr;     //ptr is a pointer variables 
ptr = (byte*)&state;   //ptr hold the address of the beginning location of a byte organized array

byte counter = sizeof(state);    //counter holds how many bytes the array contains (here: 4)

4. Now, execute the following codes to transfer all the bytes of the array using soft UART Port.

do
{
   byte m = (byte*)*ptr;   //read the 1st byte (it is 0x67 and not [edit]0x45) and the next byte and the next byte...
   mySerial.write(m);
   ptr++;                        //point to the location of the next byte of array
   counter--;                   //1-byte is read and transmitted
}
while(counter !=0);        //continue until all the bytes of array are read and transmitted

3. Combine the above codes to create sketch.
NANO is transmitting your struct button{}; with values for the members using soft UART Port; MEGA receives those over UART2 Port and reconstructs the structure.

MEGA Receiver:

struct button
{
  int HEX_VALUE;
  int analog;
};
button state;

byte myData[20];
bool flag = false;

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

void loop()
{
  byte n = Serial2.available();
  if (n != 0 )
  {
    if (flag == false)
    {
      char x = Serial2.read();
      if (x == '<')
      {
        flag =  true;   //struct data is coming
      }
    }
    else
    {
      Serial2.readBytesUntil('>', myData, 20);
      //--- recreate structure-------
      state.HEX_VALUE = (myData[1]<<8)|myData[0];
      state.analog = (myData[3]<<8)|myData[2];
      Serial.println(state.HEX_VALUE, HEX);
      Serial.println(state.analog, HEX);
      flag = false;
    }
  }
}

NANO Transmitting a struct data item:

#include<SoftwareSerial.h>
SoftwareSerial mySerial(3, 4);  //SRX = 3, STX = 4

struct button
{
  int HEX_VALUE;
  int analog;
};

button state;

void setup()
{
  Serial.begin(9600);
  mySerial.begin(9600);
  state.HEX_VALUE = 0x4567;
  state.analog = 0x1234;
}

void loop()
{
  byte *ptr;
  ptr = (byte*)&state;
  byte counter = sizeof(state);
  mySerial.print('<');   //beginning of struct data
  do
  {
    byte m = (byte*)*ptr;
    mySerial.write(m);
    Serial.print(m, HEX);
    ptr++;
    counter--;
  }
  while(counter != 0);
  mySerial.write('>');   //end of strauct data
  Serial.println();
  delay(2000);
}

Transmitted Data Bytes of struct:
smNano1.png
Figure-1:

Reconstructed Data Bytes of struct:
smMega1.png
Figure-2:

smNano1.png

smMega1.png

1 Like