1#![deny(missing_docs)]
6#![deny(warnings)]
7#![no_std]
8
9extern crate embedded_hal as ehal;
10
11use core::fmt;
12
13pub const 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<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
69impl<I2C: ehal::blocking::i2c::WriteRead> BMP280<I2C> {
70 fn read_calibration(&mut self) {
71 let mut data: [u8; 24] = [0; 24];
72 let _ = self
73 .com
74 .write_read(self.addr, &[Register::calib00 as u8], &mut data);
75
76 self.dig_t1 = ((data[1] as u16) << 8) | (data[0] as u16);
77 self.dig_t2 = ((data[3] as i16) << 8) | (data[2] as i16);
78 self.dig_t3 = ((data[5] as i16) << 8) | (data[4] as i16);
79
80 self.dig_p1 = ((data[7] as u16) << 8) | (data[6] as u16);
81 self.dig_p2 = ((data[9] as i16) << 8) | (data[8] as i16);
82 self.dig_p3 = ((data[11] as i16) << 8) | (data[10] as i16);
83 self.dig_p4 = ((data[13] as i16) << 8) | (data[12] as i16);
84 self.dig_p5 = ((data[15] as i16) << 8) | (data[14] as i16);
85 self.dig_p6 = ((data[17] as i16) << 8) | (data[16] as i16);
86 self.dig_p7 = ((data[19] as i16) << 8) | (data[18] as i16);
87 self.dig_p8 = ((data[21] as i16) << 8) | (data[20] as i16);
88 self.dig_p9 = ((data[23] as i16) << 8) | (data[22] as i16);
89 }
90
91 pub fn pressure(&mut self) -> f64 {
93 let mut data: [u8; 6] = [0, 0, 0, 0, 0, 0];
94 let _ = self
95 .com
96 .write_read(self.addr, &[Register::press as u8], &mut data);
97 let press = (data[0] as u32) << 12 | (data[1] as u32) << 4 | (data[2] as u32) >> 4;
98
99 let mut var1 = ((self.t_fine as f64) / 2.0) - 64000.0;
100 let mut var2 = var1 * var1 * (self.dig_p6 as f64) / 32768.0;
101 var2 += var1 * (self.dig_p5 as f64) * 2.0;
102 var2 = (var2 / 4.0) + ((self.dig_p4 as f64) * 65536.0);
103 var1 = ((self.dig_p3 as f64) * var1 * var1 / 524288.0 + (self.dig_p2 as f64) * var1)
104 / 524288.0;
105 var1 = (1.0 + var1 / 32768.0) * (self.dig_p1 as f64);
106 let mut pressure = 1048576.0 - (press as f64);
107 if var1 != 0.0 {
108 pressure = (pressure - (var2 / 4096.0)) * 6250.0 / var1;
109 var1 = (self.dig_p9 as f64) * pressure * pressure / 2147483648.0;
110 var2 = pressure * (self.dig_p8 as f64) / 32768.0;
111 pressure += (var1 + var2 + (self.dig_p7 as f64)) / 16.0;
112 }
113 pressure
114 }
115
116 pub fn pressure_one_shot(&mut self) -> f64 {
118 let pressure = self.pressure();
119 self.set_control(Control {
120 osrs_t: Oversampling::x2,
121 osrs_p: Oversampling::x16,
122 mode: PowerMode::Forced,
123 });
124
125 pressure
126 }
127
128 pub fn temp(&mut self) -> f64 {
130 let mut data: [u8; 6] = [0, 0, 0, 0, 0, 0];
131 let _ = self
132 .com
133 .write_read(self.addr, &[Register::press as u8], &mut data);
134 let _pres = (data[0] as u32) << 12 | (data[1] as u32) << 4 | (data[2] as u32) >> 4;
135 let temp = (data[3] as u32) << 12 | (data[4] as u32) << 4 | (data[5] as u32) >> 4;
136
137 let v1 = ((temp as f64) / 16384.0 - (self.dig_t1 as f64) / 1024.0) * (self.dig_t2 as f64);
138 let v2 = (((temp as f64) / 131072.0 - (self.dig_t1 as f64) / 8192.0)
139 * ((temp as f64) / 131072.0 - (self.dig_t1 as f64) / 8192.0))
140 * (self.dig_t3 as f64);
141 self.t_fine = (v1 + v2) as i32;
142
143 (v1 + v2) / 5120.0
144 }
145
146 pub fn config(&mut self) -> Config {
148 let config = self.read_byte(Register::config);
149 let t_sb = match (config & (0b111 << 5)) >> 5 {
150 x if x == Standby::ms0_5 as u8 => Standby::ms0_5,
151 x if x == Standby::ms62_5 as u8 => Standby::ms62_5,
152 x if x == Standby::ms125 as u8 => Standby::ms125,
153 x if x == Standby::ms250 as u8 => Standby::ms250,
154 x if x == Standby::ms500 as u8 => Standby::ms500,
155 x if x == Standby::ms1000 as u8 => Standby::ms1000,
156 x if x == Standby::ms2000 as u8 => Standby::ms2000,
157 x if x == Standby::ms4000 as u8 => Standby::ms4000,
158 _ => Standby::unknown,
159 };
160 let filter = match (config & (0b111 << 2)) >> 2 {
161 x if x == Filter::off as u8 => Filter::off,
162 x if x == Filter::c2 as u8 => Filter::c2,
163 x if x == Filter::c4 as u8 => Filter::c4,
164 x if x == Filter::c8 as u8 => Filter::c8,
165 x if x == Filter::c16 as u8 => Filter::c16,
166 _ => Filter::unknown,
167 };
168 Config {
169 t_sb,
170 filter,
171 }
172 }
173
174 pub fn set_config(&mut self, new: Config) {
176 let config: u8 = 0x00;
177 let t_sb = (new.t_sb as u8) << 5;
178 let filter = (new.filter as u8) << 2;
179 self.write_byte(Register::config, config | t_sb | filter);
180 }
181
182 pub fn set_control(&mut self, new: Control) {
184 let osrs_t: u8 = (new.osrs_t as u8) << 5;
185 let osrs_p: u8 = (new.osrs_p as u8) << 2;
186 let control: u8 = osrs_t | osrs_p | (new.mode as u8);
187 self.write_byte(Register::ctrl_meas, control);
188 }
189
190 pub fn control(&mut self) -> Control {
192 let config = self.read_byte(Register::ctrl_meas);
193 let osrs_t = match (config & (0b111 << 5)) >> 5 {
194 x if x == Oversampling::skipped as u8 => Oversampling::skipped,
195 x if x == Oversampling::x1 as u8 => Oversampling::x1,
196 x if x == Oversampling::x2 as u8 => Oversampling::x2,
197 x if x == Oversampling::x4 as u8 => Oversampling::x4,
198 x if x == Oversampling::x8 as u8 => Oversampling::x8,
199 _ => Oversampling::x16,
200 };
201 let osrs_p = match (config & (0b111 << 2)) >> 2 {
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 mode = match config & 0b11 {
210 x if x == PowerMode::Sleep as u8 => PowerMode::Sleep,
211 x if x == PowerMode::Forced as u8 => PowerMode::Forced,
212 x if x == PowerMode::Normal as u8 => PowerMode::Normal,
213 _ => PowerMode::Forced,
214 };
215
216 Control {
217 osrs_t,
218 osrs_p,
219 mode,
220 }
221 }
222
223 pub fn status(&mut self) -> Status {
225 let status = self.read_byte(Register::status);
226 Status {
227 measuring: 0 != (status & 0b00001000),
228 im_update: 0 != (status & 0b00000001),
229 }
230 }
231
232 pub fn id(&mut self) -> u8 {
234 self.read_byte(Register::id)
235 }
236
237 pub fn reset(&mut self) {
239 self.write_byte(Register::reset, 0xB6); }
241
242 fn write_byte(&mut self, reg: Register, byte: u8) {
243 let mut buffer = [0];
244 let _ = self
245 .com
246 .write_read(self.addr, &[reg as u8, byte], &mut buffer);
247 }
248
249 fn read_byte(&mut self, reg: Register) -> u8 {
250 let mut data: [u8; 1] = [0];
251 let _ = self.com.write_read(self.addr, &[reg as u8], &mut data);
252 data[0]
253 }
254}
255
256#[derive(Debug, Copy, Clone)]
257pub struct Control {
259 pub osrs_t: Oversampling,
261 pub osrs_p: Oversampling,
263 pub mode: PowerMode,
265}
266
267#[derive(Debug, Copy, Clone)]
268#[allow(non_camel_case_types)]
269pub enum Standby {
271 ms0_5 = 0b000,
273 ms62_5 = 0b001,
275 ms125 = 0b010,
277 ms250 = 0b011,
279 ms500 = 0b100,
281 ms1000 = 0b101,
283 ms2000 = 0b110,
285 ms4000 = 0b111,
287 unknown,
289}
290
291#[derive(Debug, Copy, Clone)]
292#[allow(non_camel_case_types)]
293pub enum Filter {
295 off = 0x00,
297 c2 = 0x01,
299 c4 = 0x02,
301 c8 = 0x03,
303 c16 = 0x04,
305 unknown,
307}
308
309#[derive(Debug, Copy, Clone)]
315pub struct Config {
316 pub t_sb: Standby,
318 pub filter: Filter,
320}
321
322#[derive(Debug, Copy, Clone)]
324pub struct Status {
325 measuring: bool,
327 im_update: bool,
329}
330
331impl fmt::Display for Status {
332 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
333 write!(
334 f,
335 "conversion is running: {}, NVM data being copied: {}",
336 self.measuring, self.im_update
337 )
338 }
339}
340
341#[derive(Debug, Copy, Clone)]
342#[allow(non_camel_case_types)]
343pub enum Oversampling {
345 skipped = 0b000,
347 x1 = 0b001,
349 x2 = 0b010,
351 x4 = 0b011,
353 x8 = 0b100,
355 x16 = 0b101,
357}
358
359#[derive(Debug, Copy, Clone)]
360pub enum PowerMode {
362 Sleep = 0b00,
364 Forced = 0b01,
366 Normal = 0b11,
368}
369
370#[allow(non_camel_case_types)]
371enum Register {
372 id = 0xD0,
373 reset = 0xE0,
374 status = 0xF3,
375 ctrl_meas = 0xF4,
376 config = 0xF5,
377 press = 0xF7,
378 calib00 = 0x88,
379}