Skip to main content

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