embassy_bme280_sensor/
bme280_rp.rs1use 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}