SizeOf Structure M5Stack Core2 vs NANO
-
I've been struggling with trying to pass a structure between an Arduino NANO and an M5Stack Core2 through Serial Comms.
I can get the structure to pass correctly between two Arduino UNOs or NANOs, but when I try to get it to use on my project between a NANO and the M5Stack Core2, it fails. (Serial comms passes strings just fine!)
I finally figured out that the sizeof the Structure is reported as 15 bytes on the NANO and 24 bytes on the M5Stack Core2.
I changed my declarations from:
byte to uint8_t
int to uint32_t
on the NANO and M5.I do also have a double in the structure:
//Use the same struct for comms both ways! struct AmpStruct { uint8_t bMode; uint16_t iBand; double dVolts; uint16_t iAmpTemp; uint16_t iFanOutput; uint16_t iFwdPower; uint16_t iRefPower; }; //Initialize the values to create the usable structure AmpStruct AmpData = {0, 0, 0, 0, 0, 0, 0};
Can anyone tell me what the difference is? Is there a way to make the structure the same between the two? There has to be way to declare the variables so they take up the same number of bytes on the two platorms.
I do have the comms working by passing strings, but I'd like to use the Structure within the communications.
Sir Michael
-
@SirMichael
The issue you're encountering is due to differences in data alignment and padding between the Arduino NANO (AVR architecture) and the M5Stack Core2 (ESP32 architecture). Here's why the sizeof your structure differs and how to fix it:Why the Size Differs
Data Alignment:
The ESP32 (Core2) aligns data to 4-byte boundaries by default for performance reasons, while the AVR (NANO) does not.
This causes the compiler to insert padding bytes between struct members to meet alignment requirements.Double Precision (double):
On AVR, double is typically 4 bytes (same as float).
On ESP32, double is 8 bytes (true IEEE 754 double precision).
This alone explains part of the size difference.Padding:
The ESP32 compiler may insert padding after uint16_t members to align the double to an 8-byte boundary.
How to Fix It
To ensure the struct has the same size and layout on both platforms, you can:Use #pragma pack:
Force the compiler to use 1-byte alignment (no padding) for the struct:#pragma pack(push, 1) // Disable padding
struct AmpStruct {
uint8_t bMode;
uint16_t iBand;
float dVolts; // Use float instead of double for consistency
uint16_t iAmpTemp;
uint16_t iFanOutput;
uint16_t iFwdPower;
uint16_t iRefPower;
};
#pragma pack(pop) // Restore default alignmentNote: Replace double with float to ensure consistency (4 bytes on both platforms).
Manually Pad the Struct:
If you must use double, manually add padding to match the ESP32 layout:struct AmpStruct {
uint8_t bMode;
uint8_t _pad1; // Manual padding
uint16_t iBand;
double dVolts;
uint16_t iAmpTemp;
uint16_t iFanOutput;
uint16_t iFwdPower;
uint16_t iRefPower;
};Use Serialization:
Instead of sending the raw struct, serialize it into a byte array with fixed sizes:uint8_t buffer[24]; // Adjust size as needed
buffer[0] = AmpData.bMode;
memcpy(&buffer[1], &AmpData.iBand, 2);
memcpy(&buffer[3], &AmpData.dVolts, 8); // Or use float
// ... repeat for other members
Serial.write(buffer, sizeof(buffer));Key Takeaways
Use float instead of double unless you need the extra precision.
Force 1-byte alignment with #pragma pack to avoid padding.
Test the struct size on both platforms after changes:Serial.print("Size of AmpStruct: ");
Serial.println(sizeof(AmpStruct));