use embedded_devices_derive::sensor;
use embedded_interfaces::TransportError;
use uom::si::f64::{Pressure, ThermodynamicTemperature};
use super::bme280::{
MeasurementError,
registers::{BurstMeasurementsPT, Config, ControlMeasurement, IIRFilter, Oversampling, SensorMode},
};
#[cfg(feature = "async")]
use super::bme280::BME280CommonAsync;
#[cfg(feature = "sync")]
use super::bme280::BME280CommonSync;
#[derive(Debug, embedded_devices_derive::Measurement)]
pub struct Measurement {
#[measurement(Temperature)]
pub temperature: ThermodynamicTemperature,
#[measurement(Pressure)]
pub pressure: Option<Pressure>,
}
#[cfg(feature = "sync")]
pub type BMP280Sync<D, I> = BME280CommonSync<D, I, false>;
#[cfg(feature = "async")]
pub type BMP280Async<D, I> = BME280CommonAsync<D, I, false>;
#[derive(Debug, Clone)]
pub struct Configuration {
pub temperature_oversampling: Oversampling,
pub pressure_oversampling: Oversampling,
pub iir_filter: IIRFilter,
}
impl Default for Configuration {
fn default() -> Self {
Self {
temperature_oversampling: Oversampling::X_1,
pressure_oversampling: Oversampling::X_1,
iir_filter: IIRFilter::Disabled,
}
}
}
#[sensor(Temperature, Pressure)]
#[maybe_async_cfg::maybe(
idents(hal(sync = "embedded_hal", async = "embedded_hal_async"), RegisterInterface),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> BME280Common<D, I, false> {
pub async fn configure(&mut self, config: Configuration) -> Result<(), TransportError<(), I::BusError>> {
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
self.write_register(
reg_ctrl_m
.with_temperature_oversampling(config.temperature_oversampling)
.with_pressure_oversampling(config.pressure_oversampling),
)
.await?;
let mut reg_config = self.read_register::<Config>().await?;
reg_config.write_filter(config.iir_filter);
self.write_register(reg_config).await?;
Ok(())
}
}
#[maybe_async_cfg::maybe(
idents(
hal(sync = "embedded_hal", async = "embedded_hal_async"),
RegisterInterface,
OneshotSensor
),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::OneshotSensor
for BME280Common<D, I, false>
{
type Error = MeasurementError<I::BusError>;
type Measurement = Measurement;
async fn measure(&mut self) -> Result<Self::Measurement, Self::Error> {
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
self.write_register(reg_ctrl_m.with_sensor_mode(SensorMode::Forced))
.await?;
let o_t = reg_ctrl_m.read_temperature_oversampling();
let o_p = reg_ctrl_m.read_pressure_oversampling();
let mut max_measurement_delay_us = 1250 + 2300 * o_t.factor();
if o_p.factor() > 0 {
max_measurement_delay_us += 575 + 2300 * o_p.factor();
}
self.delay.delay_us(max_measurement_delay_us).await;
let raw_data = self.read_register::<BurstMeasurementsPT>().await?;
let Some(ref cal) = self.calibration_data else {
return Err(MeasurementError::NotCalibrated);
};
let (temperature, t_fine) = cal.compensate_temperature(raw_data.read_temperature_value());
let pressure = cal.compensate_pressure(raw_data.read_pressure_value(), t_fine);
Ok(Measurement { temperature, pressure })
}
}
#[maybe_async_cfg::maybe(
idents(
hal(sync = "embedded_hal", async = "embedded_hal_async"),
RegisterInterface,
ContinuousSensor
),
sync(feature = "sync"),
async(feature = "async")
)]
impl<D: hal::delay::DelayNs, I: embedded_interfaces::registers::RegisterInterface> crate::sensor::ContinuousSensor
for BME280Common<D, I, false>
{
type Error = MeasurementError<I::BusError>;
type Measurement = Measurement;
async fn start_measuring(&mut self) -> Result<(), Self::Error> {
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
self.write_register(reg_ctrl_m.with_sensor_mode(SensorMode::Normal))
.await?;
Ok(())
}
async fn stop_measuring(&mut self) -> Result<(), Self::Error> {
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
self.write_register(reg_ctrl_m.with_sensor_mode(SensorMode::Sleep))
.await?;
Ok(())
}
async fn measurement_interval_us(&mut self) -> Result<u32, Self::Error> {
let reg_config = self.read_register::<Config>().await?;
let t_standby_us = reg_config.read_standby_time().time_us();
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
let o_t = reg_ctrl_m.read_temperature_oversampling();
let o_p = reg_ctrl_m.read_pressure_oversampling();
let mut t_measure_us = 1250 + 2300 * o_t.factor();
if o_p.factor() > 0 {
t_measure_us += 575 + 2300 * o_p.factor();
}
Ok(t_measure_us + t_standby_us)
}
async fn current_measurement(&mut self) -> Result<Option<Self::Measurement>, Self::Error> {
let reg_ctrl_m = self.read_register::<ControlMeasurement>().await?;
let o_p = reg_ctrl_m.read_pressure_oversampling();
let raw_data = self.read_register::<BurstMeasurementsPT>().await?;
let Some(ref cal) = self.calibration_data else {
return Err(MeasurementError::NotCalibrated);
};
let (temperature, t_fine) = cal.compensate_temperature(raw_data.read_temperature_value());
let pressure = (o_p != Oversampling::Disabled)
.then(|| cal.compensate_pressure(raw_data.read_pressure_value(), t_fine))
.flatten();
Ok(Some(Measurement { temperature, pressure }))
}
async fn is_measurement_ready(&mut self) -> Result<bool, Self::Error> {
Ok(true)
}
async fn next_measurement(&mut self) -> Result<Self::Measurement, Self::Error> {
let interval = self.measurement_interval_us().await?;
self.delay.delay_us(interval).await;
self.current_measurement().await?.ok_or_else(|| {
MeasurementError::Transport(TransportError::Unexpected(
"measurement was not ready even though we expected it to be",
))
})
}
}