#![no_std]
use libm::pow;
use esp_hal::i2c::master::I2c;
use embassy_time::{Duration, Timer};
#[cfg(feature = "defmt")]
use defmt::Format;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(Format))]
pub struct AccelData {
pub x: i16,
pub y: i16,
pub z: i16,
}
impl AccelData {
pub fn to_g(&self) -> (f32, f32, f32) {
const SCALE: f32 = 1.0 / 16384.0; (
self.x as f32 * SCALE,
self.y as f32 * SCALE,
self.z as f32 * SCALE,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(Format))]
pub struct GyroData {
pub x: i16,
pub y: i16,
pub z: i16,
}
impl GyroData {
pub fn to_dps(&self) -> (f32, f32, f32) {
const SCALE: f32 = 1.0 / 131.0; (
self.x as f32 * SCALE,
self.y as f32 * SCALE,
self.z as f32 * SCALE,
)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(Format))]
pub struct SensorData {
pub accel: AccelData,
pub gyro: GyroData,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(Format))] pub enum Bmi160Error {
I2cError,
InvalidChipId(u8),
NoResponse,
}
pub struct Bmi160 {
i2c: I2c<'static, esp_hal::Async>,
address: u8,
}
impl Bmi160 {
const CHIP_ID_REG: u8 = 0x00;
const CMD_REG: u8 = 0x7E;
const ACCEL_DATA_REG: u8 = 0x12;
const GYRO_DATA_REG: u8 = 0x0C;
const SOFT_RESET_CMD: u8 = 0xB6;
const ACCEL_NORMAL_MODE: u8 = 0x11;
const GYRO_NORMAL_MODE: u8 = 0x15;
const EXPECTED_CHIP_ID: u8 = 0xD1;
pub const ADDRESS_LOW: u8 = 0x68;
pub const ADDRESS_HIGH: u8 = 0x69;
pub fn new(i2c: I2c<'static, esp_hal::Async>, address: u8) -> Self {
Self { i2c, address }
}
pub fn new_default(i2c: I2c<'static, esp_hal::Async>) -> Self {
Self::new(i2c, Self::ADDRESS_LOW)
}
pub async fn init(&mut self) -> Result<(), Bmi160Error> {
self.write_register(Self::CMD_REG, Self::SOFT_RESET_CMD).await?;
Timer::after(Duration::from_millis(10)).await;
self.write_register(Self::CMD_REG, Self::ACCEL_NORMAL_MODE).await?;
Timer::after(Duration::from_millis(4)).await;
self.write_register(Self::CMD_REG, Self::GYRO_NORMAL_MODE).await?;
Timer::after(Duration::from_millis(80)).await;
let chip_id = self.read_chip_id().await?;
if chip_id == Self::EXPECTED_CHIP_ID {
Ok(())
} else {
Err(Bmi160Error::InvalidChipId(chip_id))
}
}
pub async fn read_chip_id(&mut self) -> Result<u8, Bmi160Error> {
let mut buffer = [0u8; 1];
self.i2c
.write_read_async(self.address, &[Self::CHIP_ID_REG], &mut buffer)
.await
.map_err(|_| Bmi160Error::I2cError)?;
Ok(buffer[0])
}
pub async fn read_accel(&mut self) -> Result<AccelData, Bmi160Error> {
let mut buffer = [0u8; 6];
self.i2c
.write_read_async(self.address, &[Self::ACCEL_DATA_REG], &mut buffer)
.await
.map_err(|_| Bmi160Error::I2cError)?;
Ok(AccelData {
x: i16::from_le_bytes([buffer[0], buffer[1]]),
y: i16::from_le_bytes([buffer[2], buffer[3]]),
z: i16::from_le_bytes([buffer[4], buffer[5]]),
})
}
pub async fn read_gyro(&mut self) -> Result<GyroData, Bmi160Error> {
let mut buffer = [0u8; 6];
self.i2c
.write_read_async(self.address, &[Self::GYRO_DATA_REG], &mut buffer)
.await
.map_err(|_| Bmi160Error::I2cError)?;
Ok(GyroData {
x: i16::from_le_bytes([buffer[0], buffer[1]]),
y: i16::from_le_bytes([buffer[2], buffer[3]]),
z: i16::from_le_bytes([buffer[4], buffer[5]]),
})
}
pub async fn read_all(&mut self) -> Result<SensorData, Bmi160Error> {
let accel = self.read_accel().await?;
let gyro = self.read_gyro().await?;
Ok(SensorData { accel, gyro })
}
async fn write_register(&mut self, reg: u8, value: u8) -> Result<(), Bmi160Error> {
self.i2c
.write_async(self.address, &[reg, value]) .await
.map_err(|_| Bmi160Error::I2cError)
}
}