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};
12pub 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}