ESPHome external component for the TDK InvenSense ICM-42670-P and ICM-42607-P 6-axis IMU sensors.
- Full 6-axis IMU support (3-axis accelerometer + 3-axis gyroscope)
- Temperature sensor
- Configurable accelerometer range (2G, 4G, 8G, 16G)
- Configurable gyroscope range (250, 500, 1000, 2000 DPS)
- Multiple output data rate options (1.5625 Hz to 1600 Hz)
- Low power and low noise power modes
- Software-based motion detection with configurable threshold
- Device orientation detection (face_up, face_down, portrait, landscape, etc.)
- Hardware Wake-on-Motion (WoM) with interrupt support
- Pitch and roll angle calculation
- Automation triggers for motion and orientation changes
- Auto-detection of ICM-42607-P and ICM-42670-P variants
| Device | WHO_AM_I | Package |
|---|---|---|
| ICM-42607-P | 0x60 | 14-pin LGA |
| ICM-42670-P | 0x67 | 14-pin LGA |
Both devices share the same register map and functionality. The component automatically detects which variant is connected.
Add this to your ESPHome configuration:
external_components:
- source:
type: git
url: https://github.com/Djelibeybi/esphome-icm42670
components: [icm42670]Or for local development:
external_components:
- source:
type: local
path: components
components: [icm42670]i2c:
sda: GPIO8
scl: GPIO9
icm42670:
id: imu_sensor
address: 0x68 # 0x68 (AD0 low) or 0x69 (AD0 high)
update_interval: 1s # Use faster rates (100ms) for responsive motion detection
accel_range: 2G # 2G, 4G, 8G, 16G (see Range Options below)
gyro_range: 250DPS # 250DPS, 500DPS, 1000DPS, 2000DPS (see Range Options below)
accel_odr: 100HZ # 1.5625HZ to 1600HZ
gyro_odr: 100HZ # 12.5HZ to 1600HZ
accel_power_mode: LOW_NOISE # OFF, LOW_POWER, LOW_NOISE (see Power Modes below)
gyro_power_mode: LOW_NOISE # OFF, STANDBY, LOW_NOISE (see Power Modes below)- id (Optional, ID): Manually specify the ID for this component.
- address (Optional, int): I2C address. Default is
0x68. Use0x69if AD0 pin is high. - update_interval (Optional, Time): How often to read sensor data. Default is
60s. - accel_range (Optional, string): Accelerometer full-scale range. Default is
2G. - gyro_range (Optional, string): Gyroscope full-scale range. Default is
2000DPS. - accel_odr (Optional, string): Accelerometer output data rate. Default is
100HZ. - gyro_odr (Optional, string): Gyroscope output data rate. Default is
100HZ. - accel_power_mode (Optional, string): Accelerometer power mode. Default is
LOW_NOISE. - gyro_power_mode (Optional, string): Gyroscope power mode. Default is
LOW_NOISE.
| Range | Best For | Notes |
|---|---|---|
| 2G | Orientation, tilt detection | Highest resolution for subtle movements |
| 4G | General motion tracking | Good balance of range and resolution |
| 8G | Active motion, gestures | Captures faster movements |
| 16G | Impacts, drops, vibration | Lowest resolution but captures violent motion |
Lower ranges provide better precision for detecting small changes. For typical desk/stationary use (like the ESP32-S3-BOX-3), 2G is recommended.
| Range | Best For | Notes |
|---|---|---|
| 250DPS | Slow rotations, stabilization | Highest resolution |
| 500DPS | Normal device handling | Good general-purpose setting |
| 1000DPS | Active rotation tracking | For faster movements |
| 2000DPS | Fast spinning, sports | Lowest resolution but widest range |
For typical use cases, 250-500 DPS provides sufficient range with good precision.
| Mode | Power | Description |
|---|---|---|
| OFF | 0 | Accelerometer disabled |
| LOW_POWER | ~9μA | Duty-cycled sampling, slightly increased noise |
| LOW_NOISE | ~21μA | Continuous sampling, best accuracy |
| Mode | Power | Description |
|---|---|---|
| OFF | 0 | Gyroscope disabled |
| STANDBY | ~200μA | Maintains calibration, fast wake-up, no measurements |
| LOW_NOISE | ~1.1mA | Active measurement mode, best accuracy |
For mains-powered devices, use LOW_NOISE for best accuracy. For battery-powered devices, consider LOW_POWER for the accelerometer.
sensor:
- platform: icm42670
icm42670_id: imu_sensor
accel_x:
name: "Accelerometer X"
accel_y:
name: "Accelerometer Y"
accel_z:
name: "Accelerometer Z"
gyro_x:
name: "Gyroscope X"
gyro_y:
name: "Gyroscope Y"
gyro_z:
name: "Gyroscope Z"
temperature:
name: "IMU Temperature"
pitch:
name: "Pitch"
roll:
name: "Roll"- accel_x/y/z (Optional): Acceleration in m/s^2
- gyro_x/y/z (Optional): Angular velocity in degrees/second
- temperature (Optional): Die temperature in Celsius
- pitch (Optional): Pitch angle in degrees (calculated from accelerometer)
- roll (Optional): Roll angle in degrees (calculated from accelerometer)
binary_sensor:
- platform: icm42670
icm42670_id: imu_sensor
motion:
name: "Motion Detected"
threshold: 0.5 # m/s^2 deviation from gravity (0.1 to 10.0)binary_sensor:
- platform: icm42670
icm42670_id: imu_sensor
wom:
name: "Wake on Motion"
threshold: 25 # 4mg per LSB (1-255), 25 = 100mg
pin: GPIO10 # Connect to INT1 or INT2 of the sensor
interrupt: 1 # 1 for INT1, 2 for INT2text_sensor:
- platform: icm42670
icm42670_id: imu_sensor
orientation:
name: "Device Orientation"Orientation values: face_up, face_down, portrait, portrait_inverted, landscape_left, landscape_right, unknown
icm42670:
id: imu_sensor
on_motion:
threshold: 0.5
then:
- logger.log: "Motion detected!"
on_orientation_change:
then:
- logger.log:
format: "Orientation: %s"
args: ['orientation.c_str()']| Setting | Rate |
|---|---|
| 1600HZ | 1600 Hz |
| 800HZ | 800 Hz |
| 400HZ | 400 Hz |
| 200HZ | 200 Hz |
| 100HZ | 100 Hz |
| 50HZ | 50 Hz |
| 25HZ | 25 Hz |
| 12.5HZ | 12.5 Hz |
| 6.25HZ | 6.25 Hz |
| 3.125HZ | 3.125 Hz |
| 1.5625HZ | 1.5625 Hz |
| Setting | Rate |
|---|---|
| 1600HZ | 1600 Hz |
| 800HZ | 800 Hz |
| 400HZ | 400 Hz |
| 200HZ | 200 Hz |
| 100HZ | 100 Hz |
| 50HZ | 50 Hz |
| 25HZ | 25 Hz |
| 12.5HZ | 12.5 Hz |
At high update rates, the sensor data can overwhelm Home Assistant's recorder. Use filters to reduce the data:
sensor:
- platform: icm42670
icm42670_id: imu_sensor
# Option 1: Mark as internal (not sent to HA)
accel_x:
internal: true
# Option 2: Throttle updates
gyro_x:
name: "Gyroscope X"
filters:
- throttle_average: 5s
# Option 3: Only send on significant change
temperature:
name: "Temperature"
filters:
- delta: 0.5
# Option 4: Combine throttle and delta
pitch:
name: "Pitch"
filters:
- delta: 1.0
- throttle: 5s| ICM-42670-P Pin | ESP32 Pin |
|---|---|
| VDD | 3.3V |
| GND | GND |
| SDA | GPIO8 (or your I2C SDA) |
| SCL | GPIO9 (or your I2C SCL) |
| AD0 | GND (for 0x68) or VDD (for 0x69) |
| ICM-42670-P Pin | ESP32 Pin |
|---|---|
| INT1 | Any GPIO |
| INT2 | Any GPIO (alternative) |
The ESP32-S3-BOX-3 includes an onboard ICM-42607-P IMU sensor. The following configuration is specific to this device.
| Signal | GPIO |
|---|---|
| I2C SDA | GPIO8 |
| I2C SCL | GPIO18 |
| I2C Address | 0x68 (fixed) |
Note: The AD0 pin is tied to GND on the PCB, so the I2C address is fixed at 0x68 and cannot be changed.
The INT1 and INT2 interrupt pins of the ICM-42607-P are not connected to any GPIO on the ESP32-S3-BOX-3. This means:
- Hardware Wake-on-Motion (WoM) is not available - the
wombinary sensor requires an interrupt pin - Use the software-based
motionbinary sensor instead for motion detection
i2c:
sda: GPIO8
scl: GPIO18
icm42670:
id: imu_sensor
address: 0x68
update_interval: 1s
accel_range: 2G
gyro_range: 250DPS
sensor:
- platform: icm42670
icm42670_id: imu_sensor
accel_x:
name: "Accelerometer X"
accel_y:
name: "Accelerometer Y"
accel_z:
name: "Accelerometer Z"
temperature:
name: "IMU Temperature"
pitch:
name: "Pitch"
roll:
name: "Roll"
# Software-based motion detection (hardware WoM not available on BOX-3)
binary_sensor:
- platform: icm42670
icm42670_id: imu_sensor
motion:
name: "Motion Detected"
threshold: 0.5
text_sensor:
- platform: icm42670
icm42670_id: imu_sensor
orientation:
name: "Device Orientation"Universal Permissive License (UPL) 1.0 - See LICENSE file for details.