rsiot/drivers_i2c/bmp180/
mod.rs1mod calculate_values;
4
5use std::{sync::Arc, time::Duration};
6
7use serde::{Deserialize, Serialize};
8use tokio::{sync::Mutex, time::sleep};
9use tracing::{info, trace, warn};
10
11use crate::{
12 executor::CmpInOut,
13 message::{Message, MsgDataBound, PhyQuantity},
14};
15
16use super::{I2cSlaveAddress, RsiotI2cDriverBase};
17
18use calculate_values::calculate_values;
19
20pub struct BMP180<TMsg>
21where
22 TMsg: MsgDataBound,
23{
24 pub address: I2cSlaveAddress,
25 pub fn_output: fn(BMP180Data) -> Vec<Message<TMsg>>,
26 pub oversampling: BMP180Oversampling,
27 pub cmp_in_out: CmpInOut<TMsg>,
28}
29
30impl<TMsg> BMP180<TMsg>
31where
32 TMsg: MsgDataBound,
33{
34 pub async fn fn_process(&self, driver: Arc<Mutex<impl RsiotI2cDriverBase>>) {
35 let calibration_data: CalibrationData = loop {
36 let calibration_data = request_calibration_data(driver.clone(), self.address).await;
37 match calibration_data {
38 Ok(calibration_data) => break calibration_data.into(),
39 Err(err) => {
40 warn!("Error getting calibration data for sensor BMP180: {}", err);
41 sleep(Duration::from_secs(2)).await;
42 continue;
43 }
44 }
45 };
46
47 loop {
48 let temperature = request_temperature(driver.clone(), self.address).await;
49 let Ok(temperature) = temperature else {
50 warn!("Error reading temperature from BMP180: {temperature:?}");
51 sleep(Duration::from_secs(2)).await;
52 continue;
53 };
54
55 let pressure = request_pressure(driver.clone(), self.address, self.oversampling).await;
56 let Ok(pressure) = pressure else {
57 warn!("Error reading pressure from BMP180: {pressure:?}");
58 sleep(Duration::from_secs(2)).await;
59 continue;
60 };
61
62 let values = calculate_values(
63 &calibration_data,
64 &temperature,
65 &pressure,
66 self.oversampling,
67 );
68 let msgs = (self.fn_output)(values);
69 for msg in msgs {
70 self.cmp_in_out.send_output(msg).await.unwrap();
71 }
72 sleep(Duration::from_secs(2)).await;
73 }
74 }
75}
76
77async fn request_calibration_data(
79 driver: Arc<Mutex<impl RsiotI2cDriverBase>>,
80 address: I2cSlaveAddress,
81) -> Result<ResponseCalibrationData, String> {
82 let mut response;
83 {
84 let mut driver = driver.lock().await;
85 response = driver
86 .write_read(address, &[0xAA], 22, Duration::from_secs(2))
87 .await?;
88 }
89 swap_msb_lsb(&mut response);
90 let response =
91 bincode::deserialize::<ResponseCalibrationData>(&response).map_err(|e| e.to_string())?;
92 info!("Calibration data BMP180: {response:?}");
93 Ok(response)
94}
95
96async fn request_temperature(
98 driver: Arc<Mutex<impl RsiotI2cDriverBase>>,
99 address: I2cSlaveAddress,
100) -> Result<ResponseUncompensatedTemperature, String> {
101 let mut response;
102 {
103 let mut driver = driver.lock().await;
104 driver
105 .write(address, &[0xF4, 0x2E], Duration::from_secs(2))
106 .await?;
107 }
108 sleep(Duration::from_millis(5)).await;
109 {
110 let mut driver = driver.lock().await;
111 response = driver
112 .write_read(address, &[0xF6], 2, Duration::from_secs(2))
113 .await?;
114 }
115 swap_msb_lsb(&mut response);
116 let response = bincode::deserialize::<ResponseUncompensatedTemperature>(&response)
117 .map_err(|e| e.to_string())?;
118 trace!("BMP180 temperature: {response:?}");
119 Ok(response)
120}
121
122#[allow(non_snake_case)]
124async fn request_pressure(
125 driver: Arc<Mutex<impl RsiotI2cDriverBase>>,
126 address: I2cSlaveAddress,
127 oversampling: BMP180Oversampling,
128) -> Result<ResponseUncompensatedPressure, String> {
129 let response;
130 let oversampling_command = match oversampling {
131 BMP180Oversampling::UltraLowPower => 0x34,
132 BMP180Oversampling::Standard => 0x74,
133 BMP180Oversampling::HighResolution => 0xB4,
134 BMP180Oversampling::UltraHighResolution => 0xF4,
135 };
136 {
137 let mut driver = driver.lock().await;
138 driver
139 .write(
140 address,
141 &[0xF4, oversampling_command],
142 Duration::from_secs(2),
143 )
144 .await?;
145 }
146 sleep(Duration::from_millis(26)).await;
147 {
148 let mut driver = driver.lock().await;
149 response = driver
150 .write_read(address, &[0xF6], 3, Duration::from_secs(2))
151 .await?;
152 }
153 let UP = (((response[0] as u32) << 16) + ((response[1] as u32) << 8) + response[2] as u32)
154 >> (8 - oversampling as u8);
155 let response = ResponseUncompensatedPressure { UP };
156 trace!("BMP180 pressure: {response:?}");
157 Ok(response)
158}
159
160#[allow(non_snake_case)]
161#[derive(Debug, Deserialize, Serialize)]
162struct ResponseCalibrationData {
163 AC1: i16,
164 AC2: i16,
165 AC3: i16,
166 AC4: u16,
167 AC5: u16,
168 AC6: u16,
169 B1: i16,
170 B2: i16,
171 MB: i16,
172 MC: i16,
173 MD: i16,
174}
175
176#[allow(non_snake_case)]
177struct CalibrationData {
178 AC1: f64,
179 AC2: f64,
180 AC3: f64,
181 AC4: f64,
182 AC5: f64,
183 AC6: f64,
184 B1: f64,
185 B2: f64,
186 #[allow(dead_code)]
187 MB: f64,
188 MC: f64,
189 MD: f64,
190}
191
192impl From<ResponseCalibrationData> for CalibrationData {
193 fn from(value: ResponseCalibrationData) -> Self {
194 CalibrationData {
195 AC1: value.AC1 as f64,
196 AC2: value.AC2 as f64,
197 AC3: value.AC3 as f64,
198 AC4: value.AC4 as f64,
199 AC5: value.AC5 as f64,
200 AC6: value.AC6 as f64,
201 B1: value.B1 as f64,
202 B2: value.B2 as f64,
203 MB: value.MB as f64,
204 MC: value.MC as f64,
205 MD: value.MD as f64,
206 }
207 }
208}
209
210#[allow(non_snake_case)]
211#[derive(Debug, Deserialize, Serialize)]
212struct ResponseUncompensatedTemperature {
213 UT: u16,
214}
215
216#[allow(non_snake_case)]
217#[derive(Debug, Deserialize, Serialize)]
218struct ResponseUncompensatedPressure {
219 UP: u32,
220}
221
222fn swap_msb_lsb(ve: &mut [u8]) {
223 let mut index = 0;
224 while index < ve.len() {
225 ve.swap(index, index + 1);
226 index += 2;
227 }
228}
229
230#[derive(Debug)]
231pub struct BMP180Data {
232 pub temperature: PhyQuantity,
233 pub pressure: PhyQuantity,
234 pub altitude: PhyQuantity,
235}
236
237#[derive(Clone, Copy, Debug)]
239pub enum BMP180Oversampling {
240 UltraLowPower = 0,
242 Standard = 1,
244 HighResolution = 2,
246 UltraHighResolution = 3,
248}