embedded_drivers/
bmp180.rs1use embedded_hal::blocking::delay::DelayMs;
5use embedded_hal::blocking::i2c::{Read, Write, WriteRead};
6use num_traits::Pow;
7
8const BMP180_I2CADDR: u8 = 0x77;
10
11const BMP180_CAL_AC1: u8 = 0xAA; const BMP180_CAL_AC2: u8 = 0xAC; const BMP180_CAL_AC3: u8 = 0xAE; const BMP180_CAL_AC4: u8 = 0xB0; const BMP180_CAL_AC5: u8 = 0xB2; const BMP180_CAL_AC6: u8 = 0xB4; const BMP180_CAL_B1: u8 = 0xB6; const BMP180_CAL_B2: u8 = 0xB8; const BMP180_CAL_MB: u8 = 0xBA; const BMP180_CAL_MC: u8 = 0xBC; const BMP180_CAL_MD: u8 = 0xBE; const BMP180_CONTROL: u8 = 0xF4;
24const BMP180_TEMPDATA: u8 = 0xF6;
25const BMP180_PRESSUREDATA: u8 = 0xF6;
26
27const BMP180_READTEMPCMD: u8 = 0x2E;
28const BMP180_READPRESSURECMD: u8 = 0x34;
29
30#[repr(u8)]
32#[derive(Copy, Clone)]
33pub enum Mode {
34 UltraLowPower = 0,
35 Standard,
36 HighResolution,
37 UltraHighResolution,
38}
39
40impl Mode {
41 fn oversampling_settings(&self) -> u8 {
42 *self as u8
43 }
44
45 fn wait_conversion<D: DelayMs<u8>>(&self, delay: &mut D) {
46 let ms = match self {
47 Mode::UltraLowPower => 5,
48 Mode::Standard => 8,
49 Mode::HighResolution => 14,
50 Mode::UltraHighResolution => 26,
51 };
52 delay.delay_ms(ms);
53 }
54}
55
56pub struct BMP180<I> {
58 device: I,
59 mode: Mode,
60 ac1: i16,
61 ac2: i16,
62 ac3: i16,
63 ac4: u16,
64 ac5: u16,
65 ac6: u16,
66 b1: i16,
67 b2: i16,
68 mb: i16,
69 mc: i16,
70 md: i16,
71}
72
73impl<I: Write + WriteRead + Read> BMP180<I> {
74 pub fn new(i2c: I) -> Self {
76 BMP180 {
77 device: i2c,
78 mode: Mode::UltraHighResolution,
79 ac1: 408,
80 ac2: -72,
81 ac3: -14383,
82 ac4: 32741,
83 ac5: 32757,
84 ac6: 23153,
85 b1: 6190,
86 b2: 4,
87 mb: -32767,
88 mc: -8711,
89 md: 2868,
90 }
91 }
92
93 pub fn init(&mut self) {
95 self.ac1 = self.read_i16(BMP180_CAL_AC1);
96 self.ac2 = self.read_i16(BMP180_CAL_AC2);
97 self.ac3 = self.read_i16(BMP180_CAL_AC3);
98
99 self.ac4 = self.read_u16(BMP180_CAL_AC4);
100 self.ac5 = self.read_u16(BMP180_CAL_AC5);
101 self.ac6 = self.read_u16(BMP180_CAL_AC6);
102
103 self.b1 = self.read_i16(BMP180_CAL_B1);
104 self.b2 = self.read_i16(BMP180_CAL_B2);
105 self.mb = self.read_i16(BMP180_CAL_MB);
106 self.mc = self.read_i16(BMP180_CAL_MC);
107 self.md = self.read_i16(BMP180_CAL_MD);
108 }
109
110 #[inline]
112 fn get_ut<D: DelayMs<u8>>(&mut self, delay: &mut D) -> i32 {
113 self.write(&[BMP180_CONTROL, BMP180_READTEMPCMD]);
114 delay.delay_ms(5);
115 self.read_i16(BMP180_TEMPDATA) as i32
116 }
117
118 #[inline]
120 fn get_up<D: DelayMs<u8>>(&mut self, delay: &mut D) -> i32 {
121 let oss = self.mode.oversampling_settings();
122 self.write(&[BMP180_CONTROL, BMP180_READPRESSURECMD + (oss << 6)]);
123 self.mode.wait_conversion(delay);
124
125 let msb = self.read_u8(BMP180_PRESSUREDATA) as i32;
126 let lsb = self.read_u8(BMP180_PRESSUREDATA + 1) as i32;
127 let xlsb = self.read_u8(BMP180_PRESSUREDATA + 2) as i32;
128
129 ((msb << 16) + (lsb << 8) + xlsb) >> (8 - oss)
130 }
131
132 pub fn get_temperature<D: DelayMs<u8>>(&mut self, delay: &mut D) -> f32 {
134 let ut = self.get_ut(delay);
135
136 let x1 = ((ut - self.ac6 as i32) * self.ac5 as i32) >> 15;
137 let x2 = ((self.mc as i32) << 11) / (x1 + self.md as i32);
138 let b5 = x1 + x2;
139 ((b5 + 8) >> 4) as f32 / 10.0
140 }
141
142 pub fn get_pressure<D: DelayMs<u8>>(&mut self, delay: &mut D) -> i32 {
144 let oss = self.mode.oversampling_settings();
145
146 let ut = self.get_ut(delay);
147 let up = self.get_up(delay);
148
149 let x1 = ((ut - self.ac6 as i32) * self.ac5 as i32) >> 15;
150 let x2 = ((self.mc as i32) << 11) / (x1 + self.md as i32);
151 let b5 = x1 + x2;
152
153 let b6 = b5 - 4000;
154 let x1 = ((self.b2 as i32) * ((b6 * b6) >> 12)) >> 11;
155 let x2 = ((self.ac2 as i32) * b6) >> 11;
156 let x3 = x1 + x2;
157 let b3: i64 = ((((self.ac1 as i64) * 4 + x3 as i64) << oss) + 2) / 4;
159
160 let x1 = ((self.ac3 as i32) * b6) >> 13;
161 let x2 = ((self.b1 as i32) * ((b6 * b6) >> 12)) >> 16;
162 let x3 = ((x1 + x2) + 2) >> 2;
163 let b4: u32 = (self.ac4 as u32) * ((x3 + 32768) as u32) >> 15;
164
165 let b7 = (up as i64 - b3 as i64) * (50000 >> oss);
166
167 let p = if b7 < 0x80000000 {
168 (b7 * 2) / (b4 as i64)
169 } else {
170 (b7 / (b4 as i64)) * 2
171 };
172
173 let x1 = (p >> 8) * (p >> 8);
174 let x1 = (x1 * 3038) >> 16;
175 let x2 = (-7357 * p) >> 16;
176 let p = p + ((x1 + x2 + 3791) >> 4);
177
178 p as i32
179 }
180
181 pub fn calculate_altitude<D: DelayMs<u8>>(&mut self, delay: &mut D, sealevel_pa: f32) -> f32 {
183 let pa = self.get_pressure(delay) as f32;
184 44330.0 * (1.0 - (pa / sealevel_pa).pow(1.0 / 5.255))
185 }
186
187 pub fn calculate_sealevel_pressure<D: DelayMs<u8>>(
189 &mut self,
190 delay: &mut D,
191 altitude_m: f32,
192 ) -> u32 {
193 let pressure = self.get_pressure(delay) as f32;
194 let p0 = pressure / (1.0 - altitude_m / 44330.0).pow(5.255);
195 p0 as u32
196 }
197
198 pub fn release(self) -> I {
199 self.device
200 }
201
202 fn write(&mut self, data: &[u8]) {
203 let _ = self.device.write(BMP180_I2CADDR, data);
204 }
205
206 fn read_u8(&mut self, reg: u8) -> u8 {
207 let mut buf = [0u8];
208 let _ = self.device.write_read(BMP180_I2CADDR, &[reg], &mut buf[..]);
209 buf[0]
210 }
211
212 fn read_i16(&mut self, reg: u8) -> i16 {
213 let mut buf = [0u8; 2];
214 let _ = self.device.write_read(BMP180_I2CADDR, &[reg], &mut buf[..]);
217 i16::from_be_bytes(buf)
218 }
219
220 fn read_u16(&mut self, reg: u8) -> u16 {
221 let mut buf = [0u8; 2];
222 let _ = self.device.write_read(BMP180_I2CADDR, &[reg], &mut buf[..]);
225 u16::from_be_bytes(buf)
226 }
227}