One library, any board
Video coming soon
The driver talks to the IMU only through three small board functions: read, write and delay. So the same two driver files run on the STM32 and on the ESP32, and only those three functions change.
In this lesson · 6 steps
1The problem: every board talks I2C its own way
- The sensor is always the same: same address, same registers, same bytes.
- STM32:
HAL_I2C_Mem_Read(&hi2c1, address << 1, reg, …) - ESP32 (Arduino):
Wire.beginTransmission,Wire.write,Wire.requestFrom,Wire.read - Our code from 2.3 calls HAL directly, so it only runs on the STM32.
2The idea: the layers
- Your code calls only
ism330dhcx_initandism330dhcx_read. - The driver knows the registers. It never calls HAL or Wire, only the three functions in
imu_t. - The board functions are the only board code. You write them once per board: 2.6 (STM32), 2.6b (ESP32).
Why?
Function pointer: a variable that holds a function. The driver calls
imu->read(…), and whatever function you put there runs: stm32_read or esp32_read.3The three board functions
- read(address, reg, data, length): reads
lengthbytes, starting at registerreg.
STM32:HAL_I2C_Mem_Read· ESP32:Wire.write(reg),endTransmission(false),requestFrom - write(address, reg, value): puts one value into register
reg.
STM32:HAL_I2C_Mem_Write· ESP32:Wire.write(reg),Wire.write(value),endTransmission() - delay(ms): waits
msmilliseconds, for example after the reset.
STM32:HAL_Delay· ESP32:delay
Why?
Return values: the board functions return
0 when they worked. The driver functions (ism330dhcx_init, ism330dhcx_read) return true when they worked.4imu_t: the link between driver and board
ism330dhcx.h · the top block (already in the file from 2.5: read it, don't paste it)
Three function types and one struct: the same block is in every driver header.
/* the three functions your board provides (return 0 = OK) */ typedef int (*imu_read_fn) (uint8_t address, uint8_t reg, uint8_t *data, uint16_t length); typedef int (*imu_write_fn)(uint8_t address, uint8_t reg, uint8_t value); typedef void (*imu_delay_fn)(uint32_t ms); /* one sensor: its I2C address + the three board functions */ typedef struct { uint8_t address; /* 7-bit I2C address */ imu_read_fn read; imu_write_fn write; imu_delay_fn delay; } imu_t;
Why?
address is the 7-bit I2C address (0x6A or 0x6B). Your board fills the struct once (2.6, 2.6b) and passes &imu to every driver call.5The files
ism330dhcx.h: theimu_tblock, the address, the rate and range settings, and the two driver functions.ism330dhcx.c: the registers,ism330dhcx_initandism330dhcx_read. No HAL, no Wire.main.c(STM32) orch2_imu.ino(ESP32): your three board functions and theimustruct.- Other IMU? Open only your two files (in 2.5 and 2.6b):
lsm6dsox,mpu6050,mpu9250,icm20948oricm42688(.h + .c). Sameimu_t, same board functions.
Why?
ESP32: the sketch is C++, the driver is C. The
extern "C" lines in the header let them link without changes.6One read, twelve bytes
ism330dhcx_readcallsimu->read(address, 0x22, b, 12): start atOUTX_L_G(0x22), read 12 bytes.- Order: gx, gy, gz, then ax, ay, az. Each value is two bytes, low byte first.
(int16_t)(b[1] << 8 | b[0])joins two bytes into one signed number.
Why?
Why one read? All six values come from the same moment, and one transfer is faster than twelve. The sensor moves to the next register by itself:
ism330dhcx_init turns that on.