send struct to esp8266 from arduino

Im writing data to the arduino over serial from esp8266,

struct testStruct{
  int var0 =123;
  float var1 = 9.50;
  unsigned long var2 = 123321;
};
testStruct ts;

byte testArray[(sizeof(ts))];

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

void loop() {
  testFunction();
}

void testFunction(){
     for (byte i = 0; i < sizeof(testStruct); i++) {   
         testArray[i] = ((byte*)&ts)[i];   
      }
      testWrite();
      delay (2000);
}

void testWrite(){
  Serial.write((byte*)&testArray,sizeof(testArray));
}

Then i receive it on arduino like this,

struct testStruct
{
  int var0 = 0;
  float var1 = 0;
  unsigned long var2 = 0;
};
testStruct ts;

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

void loop()
{
  testReadData();
}

void testReadData()
{
  byte *ptr = (byte*)&ts;
  if (Serial.available() >= sizeof ts)
  {
    for (byte lp = 0; lp < sizeof ts; lp++)
    {
      ptr[lp] = Serial.read();
    }
    Serial.println("print vars");
    Serial.println(ts.var0);
    Serial.println(ts.var1);
    Serial.println(ts.var2);
  }
}

however the output from the arduino serial console looks like this,

print vars
-7751
0.00
0
print vars
16664
0.00
123
print vars
0
ovf
8060929
print vars
0
9.50
123321
print vars
123
0.00
3787014424
print vars
1
0.00
1092091904
print vars
-7751
0.00
0
print vars
16664
0.00
123
print vars
0
ovf
8060929
print vars
0
9.50
123321
print vars
123
0.00
3787014424
print vars
1
0.00
1092091904
print vars
-7751
0.00
0
print vars
16664
0.00
123
print vars
0
ovf
8060929
print vars
0
9.50
123321
print vars
123
0.00
3787014424

what causing this?

I thought that int on the esp8266 was 32bits but 16bits on soe Arduinos - not all.

Use the int8_t, int16_t, int32_t, int64_t types on both to avoid problems with the size of datatypes.

countrypaul:
I thought that int on the esp8266 was 32bits but 16bits on soe Arduinos - not all.

Use the int8_t, int16_t, int32_t, int64_t types on both to avoid problems with the size of datatypes.

well i tried this to i “think” fix the size issue,

Sender,

struct testStruct{
  int8_t    var0 =123;
//  float var1 = 9.50;
  uint32_t var2 = 123321;
};
testStruct ts;

byte testArray[(sizeof(ts))];

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

void loop() {
  testFunction();
}

void testFunction(){
     for (byte i = 0; i < sizeof(testStruct); i++) {   
         testArray[i] = ((byte*)&ts)[i];   
      }
      testWrite();
      delay (2000);
}

void testWrite(){
  Serial.write((byte*)&testArray,sizeof(testArray));
}

rec,

struct testStruct
{
  int8_t  var0 = 0;
  //float var1 = 0;
  uint32_t var2 = 0;
};
testStruct ts;

void setup()
{
  Serial.begin(115200);
  Serial.println("booting");
}

void loop()
{
  testReadData();
}

void testReadData()
{
  byte *ptr = (byte*)&ts;
  if (Serial.available() >= sizeof ts)
  {
    for (byte lp = 0; lp < sizeof ts; lp++)
    {
      ptr[lp] = Serial.read();
    }
    Serial.println("print vars");
    Serial.println(ts.var0);
   // Serial.println(ts.var1);
    Serial.println(ts.var2);
  }
}

but it did not help; seems like the first time it comes in var0 is right then the reset is random. the unsigned variable var2 is never right

If i change them all to uint16_t then var0 always is correct but the var2 is not. var2 is unsinged long i tried uint32_t but it didnt work?

Can you try at 9600 baud rather than 115200 ust to be sure it is not a timing issue?

countrypaul:
Can you try at 9600 baud rather than 115200 ust to be sure it is not a timing issue?

changing the baud rate has seem to have no effect

result,

10:39:56.037 -> 0
10:39:56.037 -> 123321
10:39:56.037 -> print vars
10:39:56.037 -> 123
10:39:56.037 -> 3786997760
10:39:56.037 -> print vars
10:39:56.037 -> 1
10:39:56.037 -> 123
10:39:56.084 -> print vars
10:39:56.084 -> 57785
10:39:56.084 -> 8060929
10:39:56.084 -> print vars
10:39:56.084 -> 0
10:39:56.084 -> 123321
10:39:56.084 -> print vars
10:39:56.084 -> 123
10:39:56.084 -> 3786997760
10:39:56.084 -> print vars
10:39:56.084 -> 1
10:39:56.084 -> 123
10:39:56.084 -> print vars
10:39:56.084 -> 57785
10:39:56.084 -> 8060929
10:39:56.084 -> print vars
10:39:56.084 -> 0
10:39:56.084 -> 123321
10:39:56.084 -> print vars
10:39:56.084 -> 123
10:39:56.084 -> 3786997760

If i define them all as the same size datatype uint32_t then the data is correct? i will be needing to send float values in this struct

Looking at the nubers you are printing out, the same ones are repeated which suggests that the problem is not a completely random one.

Could anything else be writing to serial during the execution of the code such that there is an extra byte somewhere?

Could you print out the values for each byte on the two platforms and see if they sequence of bytes give us any clues?

At least float is also 32bits.

in a struct such as

struct testStruct{
  int8_t    var0 =123;
//  float var1 = 9.50;
  uint32_t var2 = 123321;
};
testStruct ts;

some processors pad to a 16 bit boundary (adding an extra byte after var0) some don't
try adding another byte after var0?

for example

typedef struct{
  uint8_t id;
  uint16_t temperature;
}
temp;

void setup() {
  while(!Serial);
  delay(1000);
  Serial.begin(115200);
  Serial.print("sizeof struct ");
  Serial.println(sizeof(temp));

}

void loop() {
}

results

  1. ESP32 sizeof struct 4
  2. UNO sizeof struct 3

horace:
in a struct such as

struct testStruct{

int8_t    var0 =123;
//  float var1 = 9.50;
  uint32_t var2 = 123321;
};
testStruct ts;



some processors pad to a 16 bit boundary (adding an extra byte after var0) some don't
try adding another byte after var0?

for the time being i seem to have it working by define data size to uint32_t and the float works. i just have to make sure the receiving side dont corrupt the struct. im trying to think of how to add a tag to the beginning and end of the bytes sort of how i do with my udp communication.

i do this with udp to provide some integrity check,

void recPacket() {
  int packetSize = Udp.parsePacket();
  if (packetSize) {
    int len = Udp.read(incomingPacket, 2000);
    char verifyStart[7]; //NODEC1 plus null
    char verifyEnd[7]; //C1NODE plus null
    char _data[5];
    strncpy (verifyStart, (char*)incomingPacket, 6);//6 bytes
    strncpy (verifyEnd, (char *)incomingPacket + len - 6 , 6 );//6 bytes
    verifyStart[6] = 0; //null terminate
    verifyEnd[6] = 0; //null terminate
    if (strcmp(verifyStart, "NODEUV") == 0) {
      if (strcmp(verifyEnd, "VUNODE") == 0) {
        memcpy(&_uvStruct, incomingPacket + 6 , sizeof(_uvStruct)); //copy 4 bytes to _data
        Serial.println("uv packet");
      }
    }

and i write it like this,

        Udp.beginPacket(Client5, ServerPort);
        Udp.write("T1ONDE");
        Udp.write((byte*)&valon, sizeof(valon)); //cast to bytes
        Udp.write("UDT1ON");
        Udp.endPacket();

how can i do something like this with these serial bytes?
i guess pretty much the same way

I guess checking the number of bytes received would be a first step.

You could try something simple like ANDing the first 3 longs and including the 4th long which is the AND of the first 3. Or even use the 4th long as a parity of the first 3, so that if the first 3 have one or 3 bits on for a given position the parity long has that bit on, but if there are 0 or 2 then the parity is zero. Lots of ways to do this - no idea whic is best.

you could have structure along the lines of

struct testStruct{
   uint8_t  seq;                // sequence number
  int8_t    var0 =123;
  float     var1 = 9.50;
  uint32_t var2 = 123321;
  uint16_t crc;                 // CRC16 check
};

you have an incrementing sequence number so you can check for lost or duplicate data and a CRC16 check set by the transmitter enabling the receiver to check for errors
if you wish to send a number of structures at the same time you could create a frame encoded so (with DLEs in the data being byte stuffed)
SYN DLE STX byte stuffed data CRC DLE ETX
the receiver looks for the start of a frame SYN DLE STX and reads data until frame terminator DLE ETX
the frame has its own CRC and the data and CRC is byte stuffed converting DLE to DLE DLE