bmp180_driver/
lib.rs

1#![doc = include_str!("../README.md")]
2use coefficients::Coefficients;
3use embedded_hal::delay::DelayNs;
4use embedded_hal::i2c::I2c;
5use error::CustomError;
6
7mod coefficients;
8pub mod error;
9
10/// Represents the resolution settings of the BMP180 sensor.
11#[derive(Copy, Clone)]
12pub enum Resolution {
13    UltraLowPower = 0,
14    Standard = 1,
15    HighResolution = 2,
16    UltraHighResolution = 3,
17}
18
19enum Register {
20    ChipId = 0xD0,
21    SoftReset = 0xE0,
22    MeasurementControl = 0xF4,
23    DataOutputStart = 0xF6,
24    CalibrationOutStart = 0xAA,
25}
26
27enum Command {
28    Temperature = 0x2E,
29    Pressure = 0x34,
30    SoftReset = 0xB6,
31}
32
33/// A trait representing common functionalities shared between [BMP180] and [InitializedBMP180].
34pub trait Common<T: I2c> {
35    /// Reads the chip identifier.
36    ///
37    /// The returned value is hardcoded by the manufacturer and should be equivalent to `0x55`.
38    fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>>;
39
40    /// Tests the connection to the device.
41    ///
42    /// It checks whether the device responds with the expected identifier `0x55`.
43    fn check_connection(&mut self) -> Result<(), CustomError<T::Error>> {
44        match self.read_chip_id() {
45            Ok(0x55) => Ok(()),
46            Err(error) => Err(error),
47            _ => Err(CustomError::InvalidDeviceIdentifier),
48        }
49    }
50
51    /// Resets the device.
52    fn reset(&mut self) -> Result<(), CustomError<T::Error>>;
53}
54
55/// Represents an uninitialized version of the sensor.
56pub struct BMP180<T, D> {
57    address: u8,
58    i2c: T,
59    delay: D,
60}
61
62/// Represents an initialized version of the sensor.
63pub struct InitializedBMP180<T, D> {
64    inner: BMP180<T, D>,
65    data: Coefficients,
66}
67
68impl<T: I2c, D: DelayNs> Common<T> for InitializedBMP180<T, D> {
69    /// Reads the chip identifier.
70    ///
71    /// The returned value is hardcoded by the manufacturer and should be equivalent to `0x55`.
72    fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>> {
73        self.inner.write_and_read_single_byte(&[Register::ChipId as u8])
74    }
75
76    /// Resets the device.
77    fn reset(&mut self) -> Result<(), CustomError<T::Error>> {
78        self.inner.write(&[Register::SoftReset as u8, Command::SoftReset as u8])?;
79        self.inner.delay.delay_ms(5);
80
81        Ok(())
82    }
83}
84
85impl<T: I2c, D: DelayNs> Common<T> for BMP180<T, D> {
86    /// Reads the chip identifier.
87    ///
88    /// The returned value is hardcoded by the manufacturer and should be equivalent to `0x55`.
89    fn read_chip_id(&mut self) -> Result<u8, CustomError<T::Error>> {
90        self.write_and_read_single_byte(&[Register::ChipId as u8])
91    }
92
93    /// Resets the device.
94    fn reset(&mut self) -> Result<(), CustomError<T::Error>> {
95        self.write(&[Register::SoftReset as u8, Command::SoftReset as u8])?;
96        self.delay.delay_ms(5);
97
98        Ok(())
99    }
100}
101
102impl<T: I2c, D: DelayNs> InitializedBMP180<T, D> {
103    /// Reads uncompensated temperature.
104    fn read_uncompensated_temperature(&mut self) -> Result<u16, CustomError<T::Error>> {
105        self.inner.write(&[Register::MeasurementControl as u8, Command::Temperature as u8])?;
106        self.inner.delay.delay_ms(5);
107
108        Ok(u16::from_be_bytes(self.inner.write_and_read_exact_bytes(&[Register::DataOutputStart as u8])?))
109    }
110
111    /// Reads uncompensated pressure.
112    fn read_uncompensated_pressure(&mut self, resolution: Resolution) -> Result<i32, CustomError<T::Error>> {
113        let oss = resolution as u8;
114        let mut buffer = [0u8; 4];
115
116        self.inner.write(&[Register::MeasurementControl as u8, Command::Pressure as u8 + (oss << 6)])?;
117
118        self.inner.delay.delay_ms(match resolution {
119            Resolution::UltraLowPower => 5,
120            Resolution::Standard => 8,
121            Resolution::HighResolution => 14,
122            Resolution::UltraHighResolution => 26,
123        });
124
125        self.inner.write_and_read_range(&[Register::DataOutputStart as u8], &mut buffer[1..4])?;
126
127        Ok(i32::from_be_bytes(buffer) >> (8 - oss))
128    }
129
130    /// Measures temperature.
131    pub fn temperature(&mut self) -> Result<f32, CustomError<T::Error>> {
132        let uncompensated_temperature = self.read_uncompensated_temperature()?;
133        let (temperature, _) = self.data.calculate_temperature(uncompensated_temperature as i32);
134
135        Ok(temperature)
136    }
137
138    /// Measures pressure.
139    pub fn pressure(&mut self, resolution: Resolution) -> Result<i32, CustomError<T::Error>> {
140        let uncompensated_temperature = self.read_uncompensated_temperature()?;
141        let (_, b5) = self.data.calculate_temperature(uncompensated_temperature as i32);
142
143        let uncompensated_pressure = self.read_uncompensated_pressure(resolution)?;
144        let pressure = self.data.calculate_pressure(b5, uncompensated_pressure, resolution);
145
146        Ok(pressure)
147    }
148
149    /// Calculates altitude.
150    pub fn altitude(&mut self, resolution: Resolution) -> Result<f32, CustomError<T::Error>> {
151        let pressure = self.pressure(resolution)?;
152
153        Ok(self.data.calculate_altitude(pressure))
154    }
155
156    /// Reads all data including temperature, pressure, and altitude.
157    pub fn read_all(&mut self, resolution: Resolution) -> Result<(f32, i32, f32), CustomError<T::Error>> {
158        let uncompensated_temperature = self.read_uncompensated_temperature()?;
159        let uncompensated_pressure = self.read_uncompensated_pressure(resolution)?;
160
161        let (temperature, b5) = self.data.calculate_temperature(uncompensated_temperature as i32);
162
163        let pressure = self.data.calculate_pressure(b5, uncompensated_pressure, resolution);
164        let altitude = self.data.calculate_altitude(pressure);
165
166        Ok((temperature, pressure, altitude))
167    }
168}
169
170impl<T: I2c, D: DelayNs> BMP180<T, D> {
171    /// Creates a new instance of BMP180 sensor.
172    pub fn new(i2c: T, delay: D) -> Self {
173        Self {
174            address: 0b111_0111,
175            delay,
176            i2c,
177        }
178    }
179
180    /// Initializes the BMP180 sensor.
181    pub fn initialize(mut self) -> Result<InitializedBMP180<T, D>, CustomError<T::Error>> {
182        let mut buffer = [0u8; 22];
183
184        self.i2c.write_read(self.address, &[Register::CalibrationOutStart as u8], &mut buffer)?;
185
186        let calibration = Coefficients::new(buffer)?;
187
188        Ok(InitializedBMP180 {
189            inner: self,
190            data: calibration,
191        })
192    }
193
194    /// Sets the I2C address of the sensor.
195    pub fn set_address(&mut self, address: u8) {
196        self.address = address;
197    }
198
199    /// Writes data to the sensor and reads back exactly the specified number of bytes.
200    pub fn write_and_read_exact_bytes<const BYTES: usize>(&mut self, command: &[u8]) -> Result<[u8; BYTES], CustomError<T::Error>> {
201        let mut buffer = [0u8; BYTES];
202
203        self.i2c.write_read(self.address, command, &mut buffer)?;
204
205        Ok(buffer)
206    }
207
208    /// Writes data to the sensor and reads back a range of bytes.
209    pub fn write_and_read_range(&mut self, command: &[u8], buffer: &mut [u8]) -> Result<(), CustomError<T::Error>> {
210        self.i2c.write_read(self.address, command, buffer)?;
211
212        Ok(())
213    }
214
215    /// Write and read a single byte back.
216    pub fn write_and_read_single_byte(&mut self, command: &[u8]) -> Result<u8, CustomError<T::Error>> {
217        let mut buffer = [0u8; 1];
218
219        self.i2c.write_read(self.address, command, &mut buffer)?;
220
221        Ok(buffer[0])
222    }
223
224    /// Writes data to the sensor.
225    pub fn write(&mut self, command: &[u8]) -> Result<(), CustomError<T::Error>> {
226        self.i2c.write(self.address, command)?;
227
228        Ok(())
229    }
230}