tof_control/device/
bme280.rs1#![allow(unused)]
2use crate::constant::*;
3
4use i2cdev::core::*;
5use i2cdev::linux::{LinuxI2CDevice, LinuxI2CError};
6
7const ID: u16 = 0xD0;
9const RESET: u16 = 0xE0;
10const RESET_CODE: u16 = 0xB6;
11const CONFIG: u16 = 0xF5;
12const CTRL_HUM: u16 = 0xF2;
13const STATUS: u16 = 0xF3;
14const CTRL_MEAS: u16 = 0xF4;
15const HUM_LSB: u16 = 0xFE;
16const HUM_MSB: u16 = 0xFD;
17const TEMP_XLSB: u16 = 0xFC;
18const TEMP_LSB: u16 = 0xFB;
19const TEMP_MSB: u16 = 0xFA;
20const PRESS_XLSB: u16 = 0xF9;
21const PRESS_LSB: u16 = 0xF8;
22const PRESS_MSB: u16 = 0xF7;
23const TEMP_COMP: u16 = 0x88;
24const PRESS_COMP: u16 = 0x8E;
25const HUM_COMP_1: u16 = 0xA1;
26const HUM_COMP_2: u16 = 0xE1;
27const T_SB_0_5: u16 = 0x00; const T_SB_62_5: u16 = 0x20; const T_SB_125: u16 = 0x40; const T_SB_250: u16 = 0x60; const T_SB_500: u16 = 0x80; const T_SB_1000: u16 = 0xA0; const T_SB_10: u16 = 0xC0; const T_SB_20: u16 = 0xE0; const FILTER_OFF: u16 = 0x00; const FILTER_2: u16 = 0x04; const FILTER_4: u16 = 0x08; const FILTER_8: u16 = 0x0C; const FILTER_16: u16 = 0x10; const SPI3W_DI: u16 = 0x00; const SPI3W_EN: u16 = 0x01; const OSRS_H_S: u16 = 0x00; const OSRS_H_1: u16 = 0x01; const OSRS_H_2: u16 = 0x02; const OSRS_H_4: u16 = 0x03; const OSRS_H_8: u16 = 0x04; const OSRS_H_16: u16 = 0x05; const OSRS_T_S: u16 = 0x00; const OSRS_T_1: u16 = 0x20; const OSRS_T_2: u16 = 0x40; const OSRS_T_4: u16 = 0x60; const OSRS_T_8: u16 = 0x80; const OSRS_T_16: u16 = 0xA0; const OSRS_P_S: u16 = 0x00; const OSRS_P_1: u16 = 0x04; const OSRS_P_2: u16 = 0x08; const OSRS_P_4: u16 = 0x0C; const OSRS_P_8: u16 = 0x10; const OSRS_P_16: u16 = 0x14; const MODE_S: u16 = 0x00; const MODE_F: u16 = 0x01; const MODE_N: u16 = 0x03; pub struct BME280 {
68 bus: u8,
69 address: u16,
70}
71struct CompensateData {
72 dig_t: Vec<u16>,
73 dig_p: Vec<u16>,
74 dig_h: Vec<u16>,
75}
76
77impl BME280 {
78 pub fn new(bus: u8, address: u16) -> Self {
79 Self { bus, address }
80 }
81 pub fn configure(&self) -> Result<(), LinuxI2CError> {
82 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
83
84 self.ctrl_humidity(&mut dev)?;
85 self.ctrl_measurement(&mut dev)?;
86
87 let config = T_SB_250 | FILTER_OFF | SPI3W_DI;
88 dev.smbus_write_byte_data(CONFIG as u8, config as u8)?;
89
90 Ok(())
91 }
92 fn ctrl_humidity(&self, dev: &mut LinuxI2CDevice) -> Result<(), LinuxI2CError> {
93 dev.smbus_write_byte_data(CTRL_HUM as u8, OSRS_H_1 as u8)?;
94
95 Ok(())
96 }
97 fn ctrl_measurement(&self, dev: &mut LinuxI2CDevice) -> Result<(), LinuxI2CError> {
98 let config = OSRS_T_1 | OSRS_P_1 | MODE_N;
99 dev.smbus_write_byte_data(CTRL_MEAS as u8, config as u8)?;
100
101 Ok(())
102 }
103 fn reset(&self, dev: &mut LinuxI2CDevice) -> Result<(), LinuxI2CError> {
104 dev.smbus_write_byte_data(RESET as u8, RESET_CODE as u8)?;
105
106 Ok(())
107 }
108 fn read_compensate(&self, dev: &mut LinuxI2CDevice) -> Result<CompensateData, LinuxI2CError> {
109 let mut dig_t = Vec::new();
110 let mut dig_p = Vec::new();
111 let mut dig_h = Vec::new();
112
113 let dat_t = dev.smbus_read_i2c_block_data(TEMP_COMP as u8, 6)?;
114 dig_t.push(((dat_t[1] as u16) << 8) | (dat_t[0] as u16));
115 dig_t.push(((dat_t[3] as u16) << 8) | (dat_t[2] as u16));
116 dig_t.push(((dat_t[5] as u16) << 8) | (dat_t[4] as u16));
117 for i in 1..3 {
118 if dig_t[i] >= 0x8000 {
119 dig_t[i] = 0xFFFF - dig_t[i];
120 }
121 }
122
123 let dat_p = dev.smbus_read_i2c_block_data(PRESS_COMP as u8, 18)?;
124 dig_p.push(((dat_p[1] as u16) << 8) | (dat_p[0] as u16));
125 dig_p.push(((dat_p[3] as u16) << 8) | (dat_p[2] as u16));
126 dig_p.push(((dat_p[5] as u16) << 8) | (dat_p[4] as u16));
127 dig_p.push(((dat_p[7] as u16) << 8) | (dat_p[6] as u16));
128 dig_p.push(((dat_p[9] as u16) << 8) | (dat_p[8] as u16));
129 dig_p.push(((dat_p[11] as u16) << 8) | (dat_p[10] as u16));
130 dig_p.push(((dat_p[13] as u16) << 8) | (dat_p[12] as u16));
131 dig_p.push(((dat_p[15] as u16) << 8) | (dat_p[14] as u16));
132 dig_p.push(((dat_p[17] as u16) << 8) | (dat_p[16] as u16));
133 for i in 1..9 {
134 if dig_p[i] >= 0x8000 {
135 dig_p[i] = 0xFFFF - dig_p[i];
136 }
137 }
138
139 let dh = dev.smbus_read_byte_data(HUM_COMP_1 as u8)?;
140 dig_h.push(dh as u16);
141 let dat_h = dev.smbus_read_i2c_block_data(HUM_COMP_2 as u8, 8)?;
142 dig_h.push(((dat_h[1] as u16) << 8) | (dat_h[0] as u16));
143 dig_h.push(dat_h[2] as u16);
144 dig_h.push(((dat_h[3] as u16) << 4) | 0x0F & (dat_h[4] as u16));
145 dig_h.push(((dat_h[5] as u16) << 4) | (((dat_h[4] as u16) >> 4) & 0x0F));
146 dig_h.push(dat_h[6] as u16);
147 if dig_h[1] >= 0x8000 {
148 dig_h[1] = 0xFFFF - dig_h[1];
149 };
150 for i in 3..5 {
151 if dig_h[i] >= 0x800 {
152 dig_h[i] = 0xFFF - dig_h[i];
153 }
154 }
155 if dig_h[5] >= 0x80 {
156 dig_h[5] = 0xFF - dig_h[5];
157 };
158
159 Ok(
160 CompensateData {
161 dig_t,
162 dig_p,
163 dig_h,
164 }
165 )
166 }
167 pub fn read(&self) -> Result<[f32; 2], LinuxI2CError> {
168 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
169
170 let compensate_data = self.read_compensate(&mut dev)?;
171
172 let temp_measurement = self.read_temperature(&mut dev, compensate_data.dig_t)?;
173 let _temperature = temp_measurement[0];
174 let t_fine = temp_measurement[1];
175
176 let pressure = self
177 .read_pressure(&mut dev, t_fine, compensate_data.dig_p)
178 .expect("cannot read pressure from BME280");
179
180 let humidity = self
181 .read_humidity(&mut dev, t_fine, compensate_data.dig_h)
182 .expect("cannot read humidity from BME280");
183
184 let ph = [pressure, humidity];
185
186 Ok(ph)
187 }
188 pub fn read_all(&self) -> Result<[f32; 3], LinuxI2CError> {
189 let mut dev = LinuxI2CDevice::new(&format!("/dev/i2c-{}", self.bus), self.address)?;
190
191 let compensate_data = self.read_compensate(&mut dev)?;
192
193 let temp_measurement = self.read_temperature(&mut dev, compensate_data.dig_t)?;
194 let temperature = temp_measurement[0];
195 let t_fine = temp_measurement[1];
196
197 let pressure = self
198 .read_pressure(&mut dev, t_fine, compensate_data.dig_p)
199 .expect("cannot read pressure from BME280");
200
201 let humidity = self
202 .read_humidity(&mut dev, t_fine, compensate_data.dig_h)
203 .expect("cannot read humidity from BME280");
204
205 let tph = [temperature, pressure, humidity];
206
207 Ok(tph)
208 }
209 fn read_temperature(
210 &self,
211 dev: &mut LinuxI2CDevice,
212 dig_t: Vec<u16>,
213 ) -> Result<[f32; 2], LinuxI2CError> {
214 let temp_msb = dev.smbus_read_byte_data(TEMP_MSB as u8)?;
215 let temp_lsb = dev.smbus_read_byte_data(TEMP_LSB as u8)?;
216 let temp_xlsb = dev.smbus_read_byte_data(TEMP_XLSB as u8)?;
217
218 let temp_adc =
219 ((temp_msb as u32) << 12) | ((temp_lsb as u32) << 4) | ((temp_xlsb as u32) >> 4);
220 let temp_result = self.compensate_temperature(temp_adc, dig_t);
221 let temp = temp_result[0];
222 let t_fine = temp_result[1];
223
224 Ok([temp, t_fine])
225 }
226 fn compensate_temperature(&self, adc: u32, dig_t: Vec<u16>) -> [f32; 2] {
227 let var1 = ((adc as f32) / 8.0 - (dig_t[0] as f32) * 2.0) * (dig_t[1] as f32) / 2048.0;
228 let var2 = ((adc as f32) / 16.0 - (dig_t[0] as f32))
229 * ((adc as f32) / 16.0 - (dig_t[0] as f32))
230 / 4096.0
231 * (dig_t[2] as f32)
232 / 16384.0;
233 let t_fine = var1 + var2;
234
235 let temp = ((t_fine * 5.0 + 128.0) / 256.0) / 100.0;
236
237 [temp, t_fine]
238 }
239 fn read_pressure(
240 &self,
241 dev: &mut LinuxI2CDevice,
242 t_fine: f32,
243 dig_p: Vec<u16>,
244 ) -> Result<f32, LinuxI2CError> {
245 let press_msb = dev.smbus_read_byte_data(PRESS_MSB as u8)?;
246 let press_lsb = dev.smbus_read_byte_data(PRESS_LSB as u8)?;
247 let press_xlsb = dev.smbus_read_byte_data(PRESS_XLSB as u8)?;
248
249 let press_adc =
250 ((press_msb as u32) << 12) | ((press_lsb as u32) << 4) | ((press_xlsb as u32) >> 4);
251 let press = self.compensate_pressure(t_fine, press_adc, dig_p);
252
253 Ok(press)
254 }
255 fn compensate_pressure(&self, t_fine: f32, adc: u32, dig_p: Vec<u16>) -> f32 {
256 let mut var1 = t_fine - 128000.0;
257 let mut var2 = var1 * var1 * (dig_p[5] as f32);
258 var2 = var2 + ((var1 * (dig_p[4] as f32)) * 131072.0);
259 var2 = var2 + ((dig_p[3] as f32) * 34359738370.0);
260 var1 = ((var1 * var1 * (dig_p[2] as f32)) / 256.0) + (var1 * (dig_p[1] as f32)) * 4096.0;
261 var1 = (140737488400000.0 + var1) * ((dig_p[0] as f32) / 8589934592.0);
262
263 if var1 == 0.0 {
264 return 0.0;
265 }
266
267 let mut p = 1048576.0 - (adc as f32);
268 p = ((p * 2147483648.0 - var2) * 3125.0) / var1;
269
270 var1 = ((dig_p[8] as f32) * (p / 8192.0) * (p / 8192.0)) / 33554432.0;
271 var2 = ((dig_p[7] as f32) * p) / 524288.0;
272
273 p = (p + var1 + var2) / 256.0 + (dig_p[6] as f32) * 16.0;
274 p = p / 256.0 / 100.0;
275
276 p
277 }
278 fn read_humidity(
279 &self,
280 dev: &mut LinuxI2CDevice,
281 t_fine: f32,
282 dig_h: Vec<u16>,
283 ) -> Result<f32, LinuxI2CError> {
284 let hum_msb = dev.smbus_read_byte_data(HUM_MSB as u8)?;
285 let hum_lsb = dev.smbus_read_byte_data(HUM_LSB as u8)?;
286
287 let hum_adc = ((hum_msb as u16) << 8) | (hum_lsb as u16);
288 let humidity = self.compensate_humidity(t_fine, hum_adc, dig_h);
289
290 Ok(humidity)
291 }
292 fn compensate_humidity(&self, t_fine: f32, adc: u16, dig_h: Vec<u16>) -> f32 {
293 let mut var_h = t_fine - 76800.0;
294 var_h = ((adc as f32) - ((dig_h[3] as f32) * 64.0 + (dig_h[4] as f32) / 16384.0 * var_h))
295 * ((dig_h[1] as f32) / 65536.0
296 * (1.0
297 + (dig_h[5] as f32) / 67108864.0
298 * var_h
299 * (1.0 + (dig_h[2] as f32) / 67108864.0 * var_h)));
300 var_h = var_h * (1.0 - (dig_h[0] as f32) * var_h / 524288.0);
301
302 var_h
303 }
304}