ICM42670 Portable Driver
Public API reference for the ICM-42670-P IMU driver
Loading...
Searching...
No Matches
Quick Start

This quick start covers the portable callback model first, then the two included adapter paths: ESP-IDF and STM32 HAL. The driver core is plain C and does not depend on either platform.

What You Need To Provide

Fill an ICM42670_Config with sensor ranges, output data rates, and a small transport layer.

Config Field Required Purpose
read_reg Yes Read one or more sensor registers
write_reg Yes Write one or more sensor registers
delay_ms Yes Blocking millisecond delay used during init and mode changes
handle Yes User pointer forwarded into read_reg and write_reg
accel_odr Recommended Accelerometer output data rate
accel_fs Recommended Accelerometer full-scale range
gyro_odr Recommended Gyroscope output data rate
gyro_fs Recommended Gyroscope full-scale range
gyro_offsets Optional Raw gyro offsets subtracted by ICM42670_ReadGyroDps()

1. Use The Portable Callback Path

If your platform does not use one of the included adapters, wire the callbacks directly.

static int8_t app_read_reg(void *handle, uint8_t reg, uint8_t *data,
uint16_t len) {
/* Call your I2C, SPI, or I3C register-read function here. */
return 0;
}
static int8_t app_write_reg(void *handle, uint8_t reg, const uint8_t *data,
uint16_t len) {
/* Call your I2C, SPI, or I3C register-write function here. */
return 0;
}
static void app_delay_ms(uint32_t ms) {
/* Call your platform delay function here. */
}
.accel_odr = ICM42670_ODR_100_HZ,
.accel_fs = ICM42670_ACCEL_FS_4G,
.gyro_odr = ICM42670_ODR_100_HZ,
.gyro_fs = ICM42670_GYRO_FS_500_DPS,
.handle = &your_bus_state,
.read_reg = app_read_reg,
.write_reg = app_write_reg,
.delay_ms = app_delay_ms,
};
if (ICM42670_Init(&imu) != ICM42670_OK) {
/* Check wiring, bus mode, and WHO_AM_I. */
}
ICM42670_Status_t ICM42670_Init(ICM42670_Config *config)
Initialize the device and enter 6-axis low-noise mode.
Definition ICM42670_driver.c:239
Core ICM-42670-P configuration and sensor read API.
@ ICM42670_OK
Definition ICM42670_driver.h:24
Platform-independent driver configuration.
Definition ICM42670_driver.h:172
ICM42670_Odr_t accel_odr
Definition ICM42670_driver.h:174

2. Read Accel, Gyro, And Temperature

ICM42670_Accel_t accel = {0};
ICM42670_Gyro_t gyro = {0};
float temp_c = 0.0f;
if (ICM42670_ReadAccelG(&imu, &accel) == ICM42670_OK &&
ICM42670_ReadGyroDps(&imu, &gyro) == ICM42670_OK &&
ICM42670_ReadTempC(&imu, &temp_c) == ICM42670_OK) {
/* Use accel.x_g, gyro.x_dps, and temp_c. */
}
ICM42670_Status_t ICM42670_ReadAccelG(const ICM42670_Config *config, ICM42670_Accel_t *accel)
Read accelerometer data converted to g.
Definition ICM42670_driver.c:343
ICM42670_Status_t ICM42670_ReadGyroDps(const ICM42670_Config *config, ICM42670_Gyro_t *gyro)
Read gyroscope data converted to degrees per second.
Definition ICM42670_driver.c:363
ICM42670_Status_t ICM42670_ReadTempC(const ICM42670_Config *config, float *temp_c)
Read temperature converted to degrees Celsius.
Definition ICM42670_driver.c:386
Scaled accelerometer sample in g.
Definition ICM42670_driver.h:32
Scaled gyroscope sample in degrees per second.
Definition ICM42670_driver.h:41

Raw read helpers are also available:

int16_t accel_raw[3] = {0};
int16_t gyro_raw[3] = {0};
int16_t temp_raw = 0;
ICM42670_ReadAccelRaw(&imu, accel_raw);
ICM42670_ReadGyroRaw(&imu, gyro_raw);
ICM42670_ReadTempRaw(&imu, &temp_raw);
ICM42670_Status_t ICM42670_ReadAccelRaw(const ICM42670_Config *config, int16_t accel_raw[3])
Read raw accelerometer counts.
Definition ICM42670_driver.c:288
ICM42670_Status_t ICM42670_ReadGyroRaw(const ICM42670_Config *config, int16_t gyro_raw[3])
Read raw gyroscope counts.
Definition ICM42670_driver.c:307
ICM42670_Status_t ICM42670_ReadTempRaw(const ICM42670_Config *config, int16_t *temp_raw)
Read the raw temperature register value.
Definition ICM42670_driver.c:326

3. ESP-IDF I2C Adapter

In a normal ESP-IDF app, add the component dependency:

idf.py add-dependency "sleepypandas/icm42670_driver^0.1.2"
idf.py reconfigure

Then use the adapter to create the ESP-IDF bus/device and populate the portable driver config.

#include "driver/gpio.h"
#include "driver/i2c_master.h"
#include "esp_log.h"
static const char *TAG = "ICM42670";
void app_main(void) {
.accel_odr = ICM42670_ODR_100_HZ,
.accel_fs = ICM42670_ACCEL_FS_4G,
.gyro_odr = ICM42670_ODR_100_HZ,
.gyro_fs = ICM42670_GYRO_FS_500_DPS,
};
esp_err_t err = ICM42670_ESP_I2C_Init(&imu, &bus, I2C_NUM_0, GPIO_NUM_21,
GPIO_NUM_22, 0x68, 400000);
if (err != ESP_OK) {
ESP_LOGE(TAG, "I2C adapter init failed: %s", esp_err_to_name(err));
return;
}
if (ICM42670_Init(&imu) != ICM42670_OK) {
ESP_LOGE(TAG, "IMU init failed. Check wiring and address.");
return;
}
}
esp_err_t ICM42670_ESP_I2C_Init(ICM42670_Config *config, ICM42670_ESP_I2CBus *bus, int i2c_port, gpio_num_t sda_pin, gpio_num_t scl_pin, uint8_t device_addr, uint32_t scl_speed_hz)
Create an ESP-IDF I2C bus/device and populate ICM42670_Config.
Definition ICM42670_esp_idf.c:36
esp_err_t ICM42670_ESP_I2C_Deinit(ICM42670_ESP_I2CBus *bus)
Release ESP-IDF I2C resources owned by this adapter.
Definition ICM42670_esp_idf.c:106
ESP-IDF I2C and SPI transport adapters for the ICM-42670-P driver.
ESP-IDF I2C bus state used by the portable driver callbacks.
Definition ICM42670_esp_idf.h:27

If your application already owns the ESP-IDF I2C device handle, use ICM42670_ESP_I2C_AttachDevice() instead of creating another bus/device.

4. STM32 HAL Adapter

For STM32 projects, initialize the CubeMX-generated peripherals first, then let the adapter populate the same portable ICM42670_Config.

#include "main.h"
extern SPI_HandleTypeDef hspi1;
static ICM42670_Config imu = {
.accel_odr = ICM42670_ODR_100_HZ,
.accel_fs = ICM42670_ACCEL_FS_4G,
.gyro_odr = ICM42670_ODR_100_HZ,
.gyro_fs = ICM42670_GYRO_FS_500_DPS,
};
static ICM42670_STM32_SPIBus imu_spi = {0};
int main(void) {
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
if (ICM42670_STM32_SPI_INIT(&imu, &imu_spi, &hspi1, IMU_CS_GPIO_Port,
IMU_CS_Pin) != ICM42670_OK) {
Error_Handler();
}
if (ICM42670_Init(&imu) != ICM42670_OK) {
Error_Handler();
}
while (1) {
ICM42670_Accel_t accel = {0};
ICM42670_ReadAccelG(&imu, &accel);
HAL_Delay(100);
}
}
ICM42670_Status_t ICM42670_STM32_SPI_INIT(ICM42670_Config *config, ICM42670_STM32_SPIBus *bus, SPI_HandleTypeDef *hspi, GPIO_TypeDef *cs_port, uint16_t cs_pin)
Configure an ICM42670_Config for STM32 HAL SPI access.
Definition ICM42670_stm32_hal.c:66
STM32 HAL transport adapters for the ICM-42670-P driver.
STM32 SPI bus state used by the portable driver callbacks.
Definition ICM42670_stm32_hal.h:19

STM32 I2C and I3C helpers follow the same pattern when the matching HAL module is enabled.

5. Optional Features

Include only the optional module you need:

#include "ICM42670_apex.h"
#include "ICM42670_fifo.h"
#include "ICM42670_fsync.h"
Optional APEX motion feature API for the ICM-42670-P.
Simple FIFO and interrupt routing API for the ICM-42670-P.
Simple FSYNC API for the ICM-42670-P.

6. Bring-Up Checklist

  • Confirm the device address or SPI chip-select wiring.
  • Confirm WHO_AM_I reads 0x67.
  • Start at 100 Hz and moderate ranges such as 4 g and 500 dps.
  • For ESP-IDF I2C timeouts, re-check SDA/SCL pins, pullups, address, and bus ownership before changing driver code.
  • For STM32 SPI, drive chip select high before the first transfer and verify the SPI mode expected by the sensor.

Next