Arduino serial data transfer with C structs


            

While doing some tests with a 9-axis sensor I wnated to read all the values and send them all via an Arduino (or any other μ-controller) serial interface. You generate that data at point “A”, the sensor, and you want that data to arrive at point “B” with minimal delay, for example a computer software that is processing all that info. Let’s assume that timing is quite critical, i.e. you want value from axis 1 to be read, sent and arrive at same time (or very close to) with value from axis 9.
Below is an adaptation of this concept for a 9-axis IMU sensor (for example, an MPU-9250 or LSM9DS1) that provides:

  • 3-axis accelerometer (Ax, Ay, Az)
  • 3-axis gyroscope (Gx, Gy, Gz)
  • 3-axis magnetometer (Mx, My, Mz)
  • plus a timestamp (optional)

On Arduino side, I am using the following C struct to store data from the accelerometer:

struct IMUData {
  float ax, ay, az;   // accelerometer (m/s^2)
  float gx, gy, gz;   // gyroscope (deg/s)
  float mx, my, mz;   // magnetometer (µT)
  uint32_t timestamp; // milliseconds since start
};

IMUData imu;

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

void loop() {
  // Simulate sensor readings (replace with actual IMU readings)
  imu.ax = 0.0 + random(-100, 100) * 0.01;
  imu.ay = 0.0 + random(-100, 100) * 0.01;
  imu.az = 9.81 + random(-100, 100) * 0.01;

  imu.gx = random(-180, 180) * 0.5;
  imu.gy = random(-180, 180) * 0.5;
  imu.gz = random(-180, 180) * 0.5;

  imu.mx = random(-50, 50) * 0.1;
  imu.my = random(-50, 50) * 0.1;
  imu.mz = random(-50, 50) * 0.1;

  imu.timestamp = millis();

  // Send struct as binary data
  Serial.write((uint8_t*)&imu, sizeof(IMUData));

  delay(100); // send at 10 Hz
}

On the receiver side, I am using a Python script to read the struct data over serial and decodes it using the same struct layout:

import serial
import struct

# Match Arduino serial port and baudrate
ser = serial.Serial('COM3', 115200)

# Struct format: <ffBBBBH
# < = little endian
# f = float (4 bytes)
# B = unsigned char (1 byte)
# H = unsigned short (2 bytes)
fmt = "<ffBBBBH"
size = struct.calcsize(fmt)

while True:
    data = ser.read(size)
    temperature, humidity, hour, minute, second, day, month, year = struct.unpack(fmt, data)
    print(f"Temp: {temperature:.2f} °C | Hum: {humidity:.2f} % | "
          f"Time: {hour:02}:{minute:02}:{second:02} | Date: {day:02}/{month:02}/{year}")

Results:

(sensor_test) tom@MacBook-Pro-Miron StructCommunication1 % python3 src/read.py
Temp: 23.40 °C | Hum: 50.30 % | Time: 12:34:00 | Date: 08/11/2025
Temp: 24.00 °C | Hum: 52.10 % | Time: 12:34:01 | Date: 08/11/2025
Temp: 23.70 °C | Hum: 50.90 % | Time: 12:34:03 | Date: 08/11/2025
Temp: 23.10 °C | Hum: 52.10 % | Time: 12:34:04 | Date: 08/11/2025
…

Further reading:

Categories: Python Tags: , ,

Python: not enough values to unpack

While creating some code for the Arduino and C struct post, I ran into this issue “not enough values to unpack” and this has to do with Python’s struct format.

Adalm Pluto ? Don’t think so

I have a love-hate relationship with Adalm Pluto. I bought it from Mouser in 2020 when it was roughly 100 euros (now it is almost double that price !) and I never managed to do anything useful with it.

Comments are closed.