Bergsonne Labs

Sense.I.9

9-DOF IMU driver for the Sense.I.9 tile (rev c).

Tile Details

Embeds the TDK InvenSense ICM-20948: 6-DOF IMU (accel + gyro) with co-packaged AK09916 3-DOF magnetometer.

Sensor specifications:
  - Accelerometer:  16-bit, ±2/4/8/16 G, up to 4.5 kHz ODR
  - Gyroscope:      16-bit, ±250/500/1000/2000 DPS, up to 9 kHz ODR
  - Magnetometer:   16-bit, ±4900 µT, up to 100 Hz ODR
  - Temperature:    on-chip sensor
0x690x680x0CAK09916 magnetometer address (fixed, accessed via I2C bypass).

Quick Start

Quick start

tiles_hal_core_cfg_t cfg = { .i2c = &hi2c1, .buses = TILES_BUS_I2C };
tiles_hal_t hal;
tiles_hal_core_init(&hal, &cfg);

tile_t imu;
tile_sense_i_9_init(&hal, 0, &imu);
if (tile_is_ready(&imu)) {
    int16_t accel[3], gyro[3], mag[3];
    tile_sense_i_9_get_raw_accels(&imu, accel);
    tile_sense_i_9_get_raw_gyros(&imu, gyro);
    tile_sense_i_9_get_raw_mags(&imu, mag);
}

Two tiles on one bus

tile_t imu_a, imu_b;
tile_sense_i_9_init(&hal, 0, &imu_a);  // pad 2 floating (0x69)
tile_sense_i_9_init(&hal, 1, &imu_b);  // pad 2 grounded (0x68)

Types & Enums

sense_i_9_accel_range_t

Accelerometer full-scale range.

Sensitivity (LSB/g) for each range: SENSE_I_9_ACCEL_2G → 16384, SENSE_I_9_ACCEL_4G → 8192, SENSE_I_9_ACCEL_8G → 4096, SENSE_I_9_ACCEL_16G → 2048

ValueHexDescription
SENSE_I_9_ACCEL_2G0x00
SENSE_I_9_ACCEL_4G0x02bits [2:1] of ACCEL_CONFIG
SENSE_I_9_ACCEL_8G0x04
SENSE_I_9_ACCEL_16G0x06

sense_i_9_gyro_range_t

Gyroscope full-scale range.

Sensitivity (LSB/°/s) for each range: SENSE_I_9_GYRO_250DPS → 131.0, SENSE_I_9_GYRO_500DPS → 65.5, SENSE_I_9_GYRO_1000DPS → 32.8, SENSE_I_9_GYRO_2000DPS → 16.4

ValueHexDescription
SENSE_I_9_GYRO_250DPS0x00
SENSE_I_9_GYRO_500DPS0x02bits [2:1] of GYRO_CONFIG
SENSE_I_9_GYRO_1000DPS0x04
SENSE_I_9_GYRO_2000DPS0x06

sense_i_9_mag_mode_t

Magnetometer operating mode.

Single-measurement mode requires re-triggering for each read. Continuous modes free-run at the specified rate.

ValueHexDescription
SENSE_I_9_MAG_POWER_DOWN0x00
SENSE_I_9_MAG_SINGLE0x01
SENSE_I_9_MAG_CONTINUOUS_10HZ0x02
SENSE_I_9_MAG_CONTINUOUS_20HZ0x04
SENSE_I_9_MAG_CONTINUOUS_50HZ0x06
SENSE_I_9_MAG_CONTINUOUS_100HZ0x08

Initialization

uint8_t tile_sense_i_9_find(tiles_hal_t* hal, uint8_t instance);

Check whether a Sense.I.9 is present on the I2C bus.

Performs an address-level probe only (no register reads).

Parameters
hal
Platform HAL handle
instance
Instance index (0 = default, see mapping table)
Returns

1 if device ACKs, 0 otherwise

void tile_sense_i_9_init(tiles_hal_t* hal, uint8_t instance, tile_t* tile);

Initialize the ICM-20948 and AK09916.

Performs a soft reset, verifies WHO_AM_I, wakes the device, enables all accel + gyro axes, enables I2C bypass for direct magnetometer access, and starts the magnetometer in continuous 100 Hz mode.

Parameters
hal
Platform HAL handle
instance
Instance index (0 = default, see mapping table)
tile
Pointer to tile handle (populated by this function)

Blocks for ~50 ms during reset. Call once at startup.

Configuration

void tile_sense_i_9_set_accel_range(tile_t* tile, sense_i_9_accel_range_t range);

Set the accelerometer full-scale range.

Parameters
tile
Pointer to tile handle
range
One of the sense_i_9_accel_range_t values
void tile_sense_i_9_set_gyro_range(tile_t* tile, sense_i_9_gyro_range_t range);

Set the gyroscope full-scale range.

Parameters
tile
Pointer to tile handle
range
One of the sense_i_9_gyro_range_t values
void tile_sense_i_9_set_mag_mode(tile_t* tile, sense_i_9_mag_mode_t mode);

Set the magnetometer operating mode.

Parameters
tile
Pointer to tile handle
mode
One of the sense_i_9_mag_mode_t values

Switching modes resets the AK09916 measurement cycle.

void tile_sense_i_9_set_accel_odr(tile_t* tile, uint16_t divider);

Set the accelerometer output data rate.

ODR = 1125 / (1 + divider) Hz. Examples: divider = 0 → 1125 Hz divider = 4 → 225 Hz divider = 10 → ~102 Hz divider = 44 → 25 Hz

Parameters
tile
Pointer to tile handle
divider
11-bit sample rate divider (0–4095)
void tile_sense_i_9_set_gyro_odr(tile_t* tile, uint8_t divider);

Set the gyroscope output data rate.

ODR = 1100 / (1 + divider) Hz.

Parameters
tile
Pointer to tile handle
divider
8-bit sample rate divider (0–255)
void tile_sense_i_9_reset(tile_t* tile);

Perform a software reset.

Resets all registers to defaults. Blocks for ~50 ms. You must call tile_sense_i_9_init() again after reset.

Parameters
tile
Pointer to tile handle

Data

uint8_t tile_sense_i_9_data_ready(tile_t* tile);

Check if new IMU data is available.

Reads the ICM-20948 interrupt status register.

Parameters
tile
Pointer to tile handle
Returns

1 if new data is available, 0 otherwise

void tile_sense_i_9_get_raw_accels(tile_t* tile, int16_t* buffer);

Read raw accelerometer data (3-axis).

Returns signed 16-bit ADC counts. Convert to milli-g using the sensitivity for the configured range (e.g. ±2 G → 1 LSB ≈ 0.061 mg).

Parameters
tile
Pointer to tile handle
buffer
Output array, minimum 3 × int16_t [X, Y, Z]
void tile_sense_i_9_get_raw_gyros(tile_t* tile, int16_t* buffer);

Read raw gyroscope data (3-axis).

Returns signed 16-bit ADC counts. Convert to °/s using the sensitivity for the configured range (e.g. ±250 DPS → 131 LSB/°/s).

Parameters
tile
Pointer to tile handle
buffer
Output array, minimum 3 × int16_t [X, Y, Z]
void tile_sense_i_9_get_raw_6dof(tile_t* tile, int16_t* buffer);

Read raw accelerometer + gyroscope data in a single burst.

More efficient than calling get_raw_accels + get_raw_gyros separately (one I2C transaction instead of two). Data is time-coherent.

Parameters
tile
Pointer to tile handle
buffer
Output array, minimum 6 × int16_t [AX, AY, AZ, GX, GY, GZ]
void tile_sense_i_9_get_raw_mags(tile_t* tile, int16_t* buffer);

Read raw magnetometer data (3-axis).

Returns signed 16-bit ADC counts from the AK09916. Sensitivity: 0.15 µT/LSB (all axes).

Parameters
tile
Pointer to tile handle
buffer
Output array, minimum 3 × int16_t [X, Y, Z]

Automatically reads the ST2 register to release the magnetometer data lock, enabling the next measurement.

int16_t tile_sense_i_9_get_temperature(tile_t* tile);

Read the on-chip temperature sensor.

Convert raw value to °C: temp_degC = (raw / 333.87) + 21.0

Parameters
tile
Pointer to tile handle
Returns

Raw signed 16-bit temperature value

Power Management

void tile_sense_i_9_sleep(tile_t* tile);

Enter low-power sleep mode.

Stops all sensor sampling. Current draw drops to ~8 µA. Call tile_sense_i_9_wake() to resume.

Parameters
tile
Pointer to tile handle
void tile_sense_i_9_wake(tile_t* tile);

Wake from sleep mode and resume sampling.

Restores auto clock selection. Previously configured ranges and ODRs are preserved across sleep/wake cycles.

Parameters
tile
Pointer to tile handle

Auto-generated from tile_sense_i_9.h v2.0.0 — last synced 3/26/2026