bb_sensor_bmi323
Beam Bots integration for the Bosch BMI323 6-DoF inertial measurement unit (accelerometer + gyroscope) over I2C.
Operates the chip in either polling mode (periodic register reads) or
interrupt mode (FIFO watermark on INT1) and publishes
BB.Message.Sensor.Imu messages with angular velocity (rad/s) and linear
acceleration (m/s²).
The BMI323 has no magnetometer, so orientation is published as the
identity quaternion. You almost always want to pair this sensor with an
orientation estimator such as
bb_estimator_ahrs.
Choosing a mode
| ODR ≤ 200 Hz | ODR > 200 Hz |
|---|---|
mode: :polling — simple, no GPIO | mode: :interrupt — needs INT1 wired |
| Low jitter, low overhead | Reliable up to the chip's 6.4 kHz ODR |
| No FIFO, samples read one at a time |
FIFO-buffered, samples arrive in bursts of watermark_frames |
In interrupt mode, a watermark_frames: 8 setting at ODR 800 Hz means
batches every 10 ms. Downstream consumers (AHRS estimators, kinematics
filters) typically cope with bursts naturally since each sample's dt is
read from its own monotonic timestamp.
Usage
Polling mode
defmodule MyRobot do
use BB
topology do
link :base do
sensor :imu, {BB.Sensor.BMI323,
bus: "i2c-1",
address: 0x68,
mode: :polling,
accelerometer_range: 8,
accelerometer_odr: 200,
gyroscope_range: 2000,
gyroscope_odr: 200,
publish_rate: ~u(100 hertz)
}
end
end
endInterrupt mode
Wire the chip's INT1 pin to a GPIO and let the on-chip FIFO buffer samples:
topology do
link :base do
sensor :imu, {BB.Sensor.BMI323,
bus: "i2c-1",
address: 0x68,
mode: :interrupt,
int1_pin: 17,
accelerometer_range: 8,
accelerometer_odr: 800,
gyroscope_range: 2000,
gyroscope_odr: 800,
watermark_frames: 8
}
end
endPairing with an AHRS estimator
The whole point of the identity orientation field is that an estimator
fills it in:
topology do
link :base do
sensor :imu, {BB.Sensor.BMI323, bus: "i2c-1", ...} do
estimator :orientation, {BB.Estimator.Ahrs.Madgwick, beta: 0.1}
end
end
end
The estimator subscribes to the sensor's Imu messages, replaces the
identity quaternion with a fused orientation, and republishes. See
bb_estimator_ahrs for the three available algorithms (Madgwick, Mahony,
Complementary) and their tuning options.
Subscribe to the final stream:
BB.subscribe(MyRobot, [:sensor, :base, :imu])Coordinate frame
Axes are the chip's own +X / +Y / +Z silkscreen (see the BMI323 datasheet §3.2). The BB topology entity this sensor attaches to is its coordinate frame — orient the IMU on the link as appropriate and apply a static transform downstream if the chip mounting doesn't match link axes.
Options
| Option | Default | Description |
|---|---|---|
bus | required |
I2C bus name (e.g. "i2c-1") |
address | 0x68 |
I2C address (0x68 SDO→GND, 0x69 SDO→VDDIO) |
mode | :polling | :polling or :interrupt |
accelerometer_range | 8 |
g (2, 4, 8, 16) |
accelerometer_odr | 200 |
Hz (12.5..6400) |
accelerometer_mode | :normal | :normal, :low_power, :high_performance, :disabled |
gyroscope_range | 2000 |
°/s (125, 250, 500, 1000, 2000) |
gyroscope_odr | 200 | Hz |
gyroscope_mode | :normal | as for accelerometer |
publish_rate | ~u(100 hertz) | Polling rate (polling mode only) |
int1_pin | required if mode: :interrupt | GPIO pin number wired to BMI323 INT1 |
watermark_frames | 8 | FIFO frames per interrupt (interrupt mode only) |
Setting accelerometer_mode or gyroscope_mode to :disabled powers
that axis down — the IMU will publish constant / invalid values for it
until the mode is changed back.
Runtime parameter changes
Live (no restart):
publish_rate(polling mode) — interval is recomputed.accelerometer_*/gyroscope_*— chip is reconfigured.
Triggers {:stop, :reconfigure} (supervisor restarts with new params):
mode,bus,address,int1_pin,watermark_frames.
Troubleshooting
{:chip_id_mismatch, got: id, expected: 0x43}— the device at the configured I2C address isn't a BMI323. Checkaddress(0x68SDO→GND,0x69SDO→VDDIO), the bus, and that the chip is powered.:no_such_bus— thebusstring doesn't match any/dev/i2c-*device. On Linux:i2cdetect -l.:int1_pin_required_for_interrupt_mode—mode: :interruptwas set without anint1_pin.- GPIO acquire failure in interrupt mode — pin may already be exported, owned by another process, or not exist on this board.
- Constant / silently-wrong samples after changing
*_mode— make sure you didn't leave an axis on:disabled.
See BB.Sensor.BMI323 for full module documentation.