1#![deny(missing_docs)]
6#![deny(warnings)]
7#![no_std]
8
9extern crate embedded_hal as ehal;
10
11use core::fmt;
12
13const DEFAULT_ADDRESS: u8 = 0x76;
15
16pub struct BMP280<I2C: ehal::blocking::i2c::WriteRead> {
18 com: I2C,
19 addr: u8,
20 dig_t1: u16,
22 dig_t2: i16,
23 dig_t3: i16,
24 t_fine: i32,
25 dig_p1: u16,
27 dig_p2: i16,
28 dig_p3: i16,
29 dig_p4: i16,
30 dig_p5: i16,
31 dig_p6: i16,
32 dig_p7: i16,
33 dig_p8: i16,
34 dig_p9: i16,
35}
36
37impl<I2C: ehal::blocking::i2c::WriteRead> BMP280<I2C> {
38 pub fn new_with_address<E>(i2c: I2C, addr: u8) -> Result<BMP280<I2C>, E>
40 where
41 I2C: ehal::blocking::i2c::WriteRead<Error = E>,
42 {
43 let mut chip = BMP280 {
44 com: i2c,
45 addr,
46 dig_t1: 0,
47 dig_t2: 0,
48 dig_t3: 0,
49 t_fine: 0,
50 dig_p1: 0,
51 dig_p2: 0,
52 dig_p3: 0,
53 dig_p4: 0,
54 dig_p5: 0,
55 dig_p6: 0,
56 dig_p7: 0,
57 dig_p8: 0,
58 dig_p9: 0,
59 };
60
61 if chip.id() == 0x58 {
62 chip.read_calibration();
63 }
64
65 Ok(chip)
66 }
67
68 pub fn new<E>(i2c: I2C) -> Result<BMP280<I2C>, E>
70 where
71 I2C: ehal::blocking::i2c::WriteRead<Error = E>
72 {
73 Self::new_with_address(i2c, DEFAULT_ADDRESS)
74 }
75}
76
77impl<I2C: ehal::blocking::i2c::WriteRead> BMP280<I2C> {
78 fn read_calibration(&mut self) {
79 let mut data: [u8; 24] = [0; 24];
80 let _ = self
81 .com
82 .write_read(self.addr, &[Register::calib00 as u8], &mut data);
83
84 self.dig_t1 = ((data[1] as u16) << 8) | (data[0] as u16);
85 self.dig_t2 = ((data[3] as i16) << 8) | (data[2] as i16);
86 self.dig_t3 = ((data[5] as i16) << 8) | (data[4] as i16);
87
88 self.dig_p1 = ((data[7] as u16) << 8) | (data[6] as u16);
89 self.dig_p2 = ((data[9] as i16) << 8) | (data[8] as i16);
90 self.dig_p3 = ((data[11] as i16) << 8) | (data[10] as i16);
91 self.dig_p4 = ((data[13] as i16) << 8) | (data[12] as i16);
92 self.dig_p5 = ((data[15] as i16) << 8) | (data[14] as i16);
93 self.dig_p6 = ((data[17] as i16) << 8) | (data[16] as i16);
94 self.dig_p7 = ((data[19] as i16) << 8) | (data[18] as i16);
95 self.dig_p8 = ((data[21] as i16) << 8) | (data[20] as i16);
96 self.dig_p9 = ((data[23] as i16) << 8) | (data[22] as i16);
97 }
98
99 pub fn pressure(&mut self) -> f64 {
101 let mut data: [u8; 6] = [0, 0, 0, 0, 0, 0];
102 let _ = self
103 .com
104 .write_read(self.addr, &[Register::press as u8], &mut data);
105 let press = (data[0] as u32) << 12 | (data[1] as u32) << 4 | (data[2] as u32) >> 4;
106
107 let mut var1 = ((self.t_fine as f64) / 2.0) - 64000.0;
108 let mut var2 = var1 * var1 * (self.dig_p6 as f64) / 32768.0;
109 var2 += var1 * (self.dig_p5 as f64) * 2.0;
110 var2 = (var2 / 4.0) + ((self.dig_p4 as f64) * 65536.0);
111 var1 = ((self.dig_p3 as f64) * var1 * var1 / 524288.0 + (self.dig_p2 as f64) * var1)
112 / 524288.0;
113 var1 = (1.0 + var1 / 32768.0) * (self.dig_p1 as f64);
114 let mut pressure = 1048576.0 - (press as f64);
115 if var1 != 0.0 {
116 pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
117 var1 = (self.dig_p9 as f64) * pressure * pressure / 2147483648.0;
118 var2 = pressure * (self.dig_p8 as f64) / 32768.0;
119 pressure += (var1 + var2 + (self.dig_p7 as f64)) / 16.0;
120 }
121 pressure
122 }
123
124 pub fn pressure_one_shot(&mut self) -> f64 {
126 let pressure = self.pressure();
127 self.set_control(Control {
128 osrs_t: Oversampling::x2,
129 osrs_p: Oversampling::x16,
130 mode: PowerMode::Forced,
131 });
132
133 pressure
134 }
135
136 pub fn temp(&mut self) -> f64 {
138 let mut data: [u8; 6] = [0, 0, 0, 0, 0, 0];
139 let _ = self
140 .com
141 .write_read(self.addr, &[Register::press as u8], &mut data);
142 let _pres = (data[0] as u32) << 12 | (data[1] as u32) << 4 | (data[2] as u32) >> 4;
143 let temp = (data[3] as u32) << 12 | (data[4] as u32) << 4 | (data[5] as u32) >> 4;
144
145 let v1 = ((temp as f64) / 16384.0 - (self.dig_t1 as f64) / 1024.0) * (self.dig_t2 as f64);
146 let v2 = (((temp as f64) / 131072.0 - (self.dig_t1 as f64) / 8192.0)
147 * ((temp as f64) / 131072.0 - (self.dig_t1 as f64) / 8192.0))
148 * (self.dig_t3 as f64);
149 self.t_fine = (v1 + v2) as i32;
150
151 (v1 + v2) / 5120.0
152 }
153
154 pub fn config(&mut self) -> Config {
156 let config = self.read_byte(Register::config);
157 let t_sb = match (config & (0b111 << 5)) >> 5 {
158 x if x == Standby::ms0_5 as u8 => Standby::ms0_5,
159 x if x == Standby::ms62_5 as u8 => Standby::ms62_5,
160 x if x == Standby::ms125 as u8 => Standby::ms125,
161 x if x == Standby::ms250 as u8 => Standby::ms250,
162 x if x == Standby::ms500 as u8 => Standby::ms500,
163 x if x == Standby::ms1000 as u8 => Standby::ms1000,
164 x if x == Standby::ms2000 as u8 => Standby::ms2000,
165 x if x == Standby::ms4000 as u8 => Standby::ms4000,
166 _ => Standby::unknown,
167 };
168 let filter = match (config & (0b111 << 2)) >> 2 {
169 x if x == Filter::off as u8 => Filter::off,
170 x if x == Filter::c2 as u8 => Filter::c2,
171 x if x == Filter::c4 as u8 => Filter::c4,
172 x if x == Filter::c8 as u8 => Filter::c8,
173 x if x == Filter::c16 as u8 => Filter::c16,
174 _ => Filter::unknown,
175 };
176 Config {
177 t_sb,
178 filter,
179 }
180 }
181
182 pub fn set_config(&mut self, new: Config) {
184 let config: u8 = 0x00;
185 let t_sb = (new.t_sb as u8) << 5;
186 let filter = (new.filter as u8) << 2;
187 self.write_byte(Register::config, config | t_sb | filter);
188 }
189
190 pub fn set_control(&mut self, new: Control) {
192 let osrs_t: u8 = (new.osrs_t as u8) << 5;
193 let osrs_p: u8 = (new.osrs_p as u8) << 2;
194 let control: u8 = osrs_t | osrs_p | (new.mode as u8);
195 self.write_byte(Register::ctrl_meas, control);
196 }
197
198 pub fn control(&mut self) -> Control {
200 let config = self.read_byte(Register::ctrl_meas);
201 let osrs_t = match (config & (0b111 << 5)) >> 5 {
202 x if x == Oversampling::skipped as u8 => Oversampling::skipped,
203 x if x == Oversampling::x1 as u8 => Oversampling::x1,
204 x if x == Oversampling::x2 as u8 => Oversampling::x2,
205 x if x == Oversampling::x4 as u8 => Oversampling::x4,
206 x if x == Oversampling::x8 as u8 => Oversampling::x8,
207 _ => Oversampling::x16,
208 };
209 let osrs_p = match (config & (0b111 << 2)) >> 2 {
210 x if x == Oversampling::skipped as u8 => Oversampling::skipped,
211 x if x == Oversampling::x1 as u8 => Oversampling::x1,
212 x if x == Oversampling::x2 as u8 => Oversampling::x2,
213 x if x == Oversampling::x4 as u8 => Oversampling::x4,
214 x if x == Oversampling::x8 as u8 => Oversampling::x8,
215 _ => Oversampling::x16,
216 };
217 let mode = match config & 0b11 {
218 x if x == PowerMode::Sleep as u8 => PowerMode::Sleep,
219 x if x == PowerMode::Forced as u8 => PowerMode::Forced,
220 x if x == PowerMode::Normal as u8 => PowerMode::Normal,
221 _ => PowerMode::Forced,
222 };
223
224 Control {
225 osrs_t,
226 osrs_p,
227 mode,
228 }
229 }
230
231 pub fn status(&mut self) -> Status {
233 let status = self.read_byte(Register::status);
234 Status {
235 measuring: 0 != (status & 0b00001000),
236 im_update: 0 != (status & 0b00000001),
237 }
238 }
239
240 pub fn id(&mut self) -> u8 {
242 self.read_byte(Register::id)
243 }
244
245 pub fn reset(&mut self) {
247 self.write_byte(Register::reset, 0xB6); }
249
250 fn write_byte(&mut self, reg: Register, byte: u8) {
251 let mut buffer = [0];
252 let _ = self
253 .com
254 .write_read(self.addr, &[reg as u8, byte], &mut buffer);
255 }
256
257 fn read_byte(&mut self, reg: Register) -> u8 {
258 let mut data: [u8; 1] = [0];
259 let _ = self.com.write_read(self.addr, &[reg as u8], &mut data);
260 data[0]
261 }
262}
263
264#[derive(Debug, Copy, Clone)]
265pub struct Control {
267 pub osrs_t: Oversampling,
269 pub osrs_p: Oversampling,
271 pub mode: PowerMode,
273}
274
275#[derive(Debug, Copy, Clone)]
276#[allow(non_camel_case_types)]
277pub enum Standby {
279 ms0_5 = 0b000,
281 ms62_5 = 0b001,
283 ms125 = 0b010,
285 ms250 = 0b011,
287 ms500 = 0b100,
289 ms1000 = 0b101,
291 ms2000 = 0b110,
293 ms4000 = 0b111,
295 unknown,
297}
298
299#[derive(Debug, Copy, Clone)]
300#[allow(non_camel_case_types)]
301pub enum Filter {
303 off = 0x00,
305 c2 = 0x01,
307 c4 = 0x02,
309 c8 = 0x03,
311 c16 = 0x04,
313 unknown,
315}
316
317#[derive(Debug, Copy, Clone)]
323pub struct Config {
324 pub t_sb: Standby,
326 pub filter: Filter,
328}
329
330#[derive(Debug, Copy, Clone)]
332pub struct Status {
333 measuring: bool,
335 im_update: bool,
337}
338
339impl fmt::Display for Status {
340 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
341 write!(
342 f,
343 "conversion is running: {}, NVM data being copied: {}",
344 self.measuring, self.im_update
345 )
346 }
347}
348
349#[derive(Debug, Copy, Clone)]
350#[allow(non_camel_case_types)]
351pub enum Oversampling {
353 skipped = 0b000,
355 x1 = 0b001,
357 x2 = 0b010,
359 x4 = 0b011,
361 x8 = 0b100,
363 x16 = 0b101,
365}
366
367#[derive(Debug, Copy, Clone)]
368pub enum PowerMode {
370 Sleep = 0b00,
372 Forced = 0b01,
374 Normal = 0b11,
376}
377
378#[allow(non_camel_case_types)]
379enum Register {
380 id = 0xD0,
381 reset = 0xE0,
382 status = 0xF3,
383 ctrl_meas = 0xF4,
384 config = 0xF5,
385 press = 0xF7,
386 calib00 = 0x88,
387}