embassy_bme280_sensor/
bme280_rp.rs

1use crate::calibration::CalibrationRegisters;
2use crate::configuration::{SamplingConfiguration, SensorMode};
3use crate::BME280Error::NotCalibrated;
4use crate::{
5    BME280Error, BME280Response, BME280_REGISTER_CHIPID,
6    BME280_REGISTER_CONFIG, BME280_REGISTER_CONTROL, BME280_REGISTER_CONTROLHUMID,
7    BME280_REGISTER_DATA_LENGTH, BME280_REGISTER_DATA_START, BME280_REGISTER_DIG_FIRST_LENGTH,
8    BME280_REGISTER_DIG_SECOND_LENGTH, BME280_REGISTER_SOFTRESET, BME280_REGISTER_STATUS,
9};
10use embassy_time::{with_timeout, Duration, Timer};
11use embedded_hal_async::i2c::I2c;
12
13pub struct BME280Sensor<'a, T: I2c> {
14    i2c: &'a mut T,
15    address: u8,
16    calibration_registers: Option<CalibrationRegisters>,
17}
18
19impl<'a, T: I2c> BME280Sensor<'a, T> {
20    pub fn new(i2c: &'a mut T, address: u8) -> Self {
21        Self {
22            i2c,
23            address,
24            calibration_registers: None,
25        }
26    }
27
28    pub async fn setup(
29        &mut self,
30        sampling_configuration: SamplingConfiguration,
31    ) -> Result<(), BME280Error> {
32        let chip_id = self.read_register_u8(BME280_REGISTER_CHIPID).await?;
33        if chip_id != 0x60 {
34            return Err(BME280Error::InvalidChipId(chip_id));
35        }
36        self.write_register_8u(BME280_REGISTER_SOFTRESET, 0x86)
37            .await?;
38        Timer::after(Duration::from_millis(10)).await;
39        let timeout = with_timeout(Duration::from_secs(1), async {
40            loop {
41                match self.is_reading_calibration().await {
42                    Ok(reading) => {
43                        if reading {
44                            Timer::after(Duration::from_millis(10)).await;
45                        } else {
46                            break;
47                        }
48                    }
49                    Err(_) => {
50                        break;
51                    }
52                }
53            }
54        })
55        .await;
56        if let Err(_) = timeout {
57            return Err(BME280Error::Timeout);
58        }
59
60        self.read_coefficients().await?;
61        self.set_sampling_configuration(sampling_configuration)
62            .await?;
63        Timer::after(embassy_time::Duration::from_millis(100)).await;
64        Ok(())
65    }
66
67    async fn is_reading_calibration(&mut self) -> Result<bool, BME280Error> {
68        let status = self.read_register_u8(BME280_REGISTER_STATUS).await?;
69        Ok((status & (1 << 3)) != 0)
70    }
71
72    async fn read_coefficients(&mut self) -> Result<(), BME280Error> {
73        let mut data = [0u8; BME280_REGISTER_DIG_FIRST_LENGTH + BME280_REGISTER_DIG_SECOND_LENGTH];
74        self.read_registers_bulk(0x88, &mut data[0..BME280_REGISTER_DIG_FIRST_LENGTH])
75            .await?;
76        self.read_registers_bulk(
77            0xE1,
78            &mut data[BME280_REGISTER_DIG_FIRST_LENGTH
79                ..BME280_REGISTER_DIG_FIRST_LENGTH + BME280_REGISTER_DIG_SECOND_LENGTH],
80        )
81        .await?;
82
83        self.calibration_registers = Some(data.into());
84
85        Ok(())
86    }
87
88    async fn set_sampling_configuration(
89        &mut self,
90        sampling_configuration: SamplingConfiguration,
91    ) -> Result<(), BME280Error> {
92        let (config, ctrl_meas, ctrl_hum) = sampling_configuration.to_low_level_configuration();
93
94        self.write_register_8u(BME280_REGISTER_CONTROL, SensorMode::Sleep as u8)
95            .await?;
96        self.write_register_8u(BME280_REGISTER_CONTROLHUMID, ctrl_hum.into())
97            .await?;
98        self.write_register_8u(BME280_REGISTER_CONFIG, config.into())
99            .await?;
100        self.write_register_8u(BME280_REGISTER_CONTROL, ctrl_meas.into())
101            .await?;
102        Ok(())
103    }
104
105    pub async fn read(&mut self) -> Result<BME280Response, BME280Error> {
106        let mut data: [u8; BME280_REGISTER_DATA_LENGTH] = [0; BME280_REGISTER_DATA_LENGTH];
107        self.read_registers_bulk(BME280_REGISTER_DATA_START, &mut data)
108            .await?;
109
110        let data_msb = (data[0] as u32) << 12;
111        let data_lsb = (data[1] as u32) << 4;
112        let data_xlsb = (data[2] as u32) >> 4;
113        let adc_p = data_msb | data_lsb | data_xlsb;
114
115        let data_msb = (data[3] as u32) << 12;
116        let data_lsb = (data[4] as u32) << 4;
117        let data_xlsb = (data[5] as u32) >> 4;
118        let adc_t = (data_msb | data_lsb | data_xlsb) as i32;
119
120        let data_msb = (data[6] as u32) << 8;
121        let data_lsb = data[7] as u32;
122        let adc_h = data_msb | data_lsb;
123
124        if let Some(cr) = &self.calibration_registers {
125            let t_fine = cr.compensate_temperature(adc_t);
126            let temperature = ((t_fine * 5 + 128) >> 8) as f32 / 100.0;
127            let humidity = cr.compensate_humidity(adc_h as u16, t_fine) as f32 / 1024.0;
128            let pressure = cr.compensate_pressure(adc_p, t_fine) as f32 / 256.0;
129
130            Ok(BME280Response {
131                temperature,
132                humidity,
133                pressure,
134            })
135        } else {
136            Err(NotCalibrated)
137        }
138    }
139
140    async fn read_register_u8(&mut self, register: u8) -> Result<u8, BME280Error> {
141        let mut buf = [0u8; 1];
142        self.i2c_write_read(&[register], &mut buf).await?;
143        Ok(buf[0])
144    }
145
146    async fn write_register_8u(&mut self, register: u8, data: u8) -> Result<(), BME280Error> {
147        self.i2c_write(&[register, data]).await?;
148        Ok(())
149    }
150
151    async fn read_registers_bulk(
152        &mut self,
153        register: u8,
154        read: &mut [u8],
155    ) -> Result<(), BME280Error> {
156        self.i2c_write_read(&[register], read).await?;
157        Ok(())
158    }
159
160    async fn i2c_write_read(&mut self, write: &[u8], read: &mut [u8]) -> Result<(), BME280Error> {
161        match self.i2c.write_read(self.address, write, read).await {
162            Ok(_) => Ok(()),
163            Err(_) => Err(BME280Error::I2CError),
164        }
165    }
166
167    async fn i2c_write(&mut self, write: &[u8]) -> Result<(), BME280Error> {
168        match self.i2c.write(self.address, write).await {
169            Ok(_) => Ok(()),
170            Err(_) => Err(BME280Error::I2CError),
171        }
172    }
173}