ms8607/
lib.rs

1//! ms8607.rs
2//!
3//! This is a library for the MS8607 Pressure, Temperature, and Humidity Sensor from TE Connectivity
4//!
5//! Based on the Adafruit_MS8607 library from Adafruit and the
6//! [datasheet](https://www.te.com/commerce/DocumentDelivery/DDEController?Action=srchrtrv&DocNm=MS8607-02BA01&DocType=DS&DocLang=English) for the MS8607 sensor from Tyco Electronics.
7//!
8//! Author: Antoine Raulin, 2023
9
10#![no_std]
11#![allow(unused)]
12use embedded_hal::blocking::{i2c, delay::DelayMs};
13
14
15/// Enum containing all possible types of errors when interacting with the sensor
16#[derive(Debug)]
17pub enum Error<E> {
18    CommunicationError(E),
19    SensorDetectFailed,
20    RegisterReadFailed,
21    RegisterWriteFailed,
22    CrcCheckFailed,
23    InvalidResolution,
24}
25
26// Allow converting the Error type from the I2C device to the error enum
27impl<E> From<E> for Error<E> {
28    fn from(e: E) -> Self {
29        Error::CommunicationError(e)
30    }
31}
32/// A platform agnostic Rust driver for the MS8607 Pressure, Temperature, and Humidity Sensor from TE Connectivity.
33/// 
34/// ## Example
35/// ```rust
36/// // Create a new instance of the MS8607 driver
37/// let mut ms8607 = MS8607::new(i2c);
38/// // Initialize and calibrate the sensor
39/// let begin = ms8607.begin(&mut delay);
40/// // Init OK, sensor foun
41///
42/// // Get measurements
43/// let (pres, temp, hum) = ms8607.get_measurements(&mut delay).unwrap();
44/// hprintln!("Pressure: {pres:.2} Pa, Temperature: {temp:.2} C, Humidity: {hum:.2} %RH\r");
45/// ```
46pub struct MS8607<I2C>
47{
48    i2c: I2C,
49    // calibration constants
50    press_sens: u16,
51    press_offset: u16,
52    press_sens_temp_coeff: u16,
53    press_offset_temp_coeff: u16,
54    ref_temp: u16,
55    temp_temp_coeff: u16,
56    /// The current I2C mode to use for humidity reads
57    hum_sensor_i2c_read_mode: Ms8607HumidityClockStretch,
58    psensor_resolution_osr: Ms8607PressureResolution,
59    /// The current pressure measurement
60    _pressure: f64,
61    /// The current temperature measurement
62    _temperature: f64,
63    /// The current humidity measurement
64    _humidity: f64,
65}
66
67impl<I2C, E> MS8607<I2C>
68where
69    I2C: i2c::Write<Error = E> + i2c::WriteRead<Error = E>,
70{
71    /// Create a new MS8607 instance
72    pub fn new(i2c:I2C) -> Self {
73        MS8607 {
74            i2c,
75            press_sens: 0,
76            press_offset: 0,
77            press_sens_temp_coeff: 0,
78            press_offset_temp_coeff: 0,
79            ref_temp: 0,
80            temp_temp_coeff: 0,
81            hum_sensor_i2c_read_mode: Ms8607HumidityClockStretch::Ms8607I2cHold,
82            psensor_resolution_osr: Ms8607PressureResolution::Osr4096,
83            _pressure: 0.0,
84            _temperature: 0.0,
85            _humidity: 0.0,
86        }
87    }
88
89    /// Sets up the hardware and initializes I2C
90    pub fn begin<Delay>(&mut self, delay:&mut Delay) -> Result<(), Error<E>> where
91    Delay: DelayMs<u16> {
92        self.reset(delay)?;
93        self.init()?;
94        Ok(())
95    }
96
97    /// Initializer for post i2c/spi init
98    pub fn init(&mut self) -> Result<(), Error<E>>{
99        self._fetch_temp_calibration_values()?;
100        self.enable_humidity_clock_stretching(false);
101
102        self.set_humidity_resolution( Ms8607HumidityResolution::Osr12b)?;
103
104        self.set_pressure_resolution(Ms8607PressureResolution::Osr4096);
105
106        Ok(())
107    }
108
109    /// Allow the MS8607 to hold the clock line low until it completes the
110    /// requested measurements
111    ///
112    /// ## Arguments
113    /// enable_stretching: true to enable clock stretching, false to disable
114    pub fn enable_humidity_clock_stretching(&mut self, enable_stretching: bool) {
115        if enable_stretching {
116            self.hum_sensor_i2c_read_mode = Ms8607HumidityClockStretch::Ms8607I2cHold;
117        } else {
118            self.hum_sensor_i2c_read_mode = Ms8607HumidityClockStretch::Ms8607I2cNoHold;
119        }
120    }
121
122    /// Set the resolution for humidity readings
123    ///
124    /// ## Arguments
125    /// resolution: the resolution to set
126    pub fn set_humidity_resolution(
127        &mut self,
128        resolution: Ms8607HumidityResolution,
129    )  -> Result<(), Error<E>> {
130        let mut reg_value = self._read_humidity_user_register()?;
131
132        // unset current value
133        reg_value &= _MS8607::HSENSOR_USER_REG_RESOLUTION_MASK;
134        // set new value
135        reg_value |= resolution as u8 & _MS8607::HSENSOR_USER_REG_RESOLUTION_MASK;
136
137        self._write_humidity_user_register( reg_value)
138    }
139
140    /// Set the resolution for pressure readings
141    ///
142    /// ## Arguments
143    /// resolution: the resolution to set
144    pub fn set_pressure_resolution(&mut self, resolution: Ms8607PressureResolution) {
145        self.psensor_resolution_osr = resolution;
146    }
147
148    /// Get the currently set resolution for humidity readings
149    pub fn get_humidity_resolution(&mut self) -> Result<Ms8607HumidityResolution, Error<E>>{
150        let reg_value = self._read_humidity_user_register()?;
151        let resolution = reg_value & _MS8607::HSENSOR_USER_REG_RESOLUTION_MASK;
152        match resolution {
153            0 => Ok(Ms8607HumidityResolution::Osr12b),
154            1 => Ok(Ms8607HumidityResolution::Osr8b),
155            2 => Ok(Ms8607HumidityResolution::Osr10b),
156            3 => Ok(Ms8607HumidityResolution::Osr11b),
157            _ => Err(Error::InvalidResolution),
158        }
159    }
160
161    /// Get the currently set resolution for pressure readings
162    pub fn get_pressure_resolution(&self) -> Ms8607PressureResolution {
163        self.psensor_resolution_osr
164    }
165
166    pub fn get_measurements<Delay>(&mut self,delay:&mut Delay) -> Result<(f64, f64, f64), Error<E>> where
167    Delay: DelayMs<u16> {
168        self._read( delay)?;
169        self._read_humidity()?;
170        Ok((self._pressure, self._temperature, self._humidity))
171    }
172
173    /**
174    Read the current pressure and temperature
175    */
176    fn _read<Delay>(&mut self, delay:&mut Delay) -> Result<(), Error<E>> where
177     Delay: DelayMs<u16> {
178        let mut cmd = [0u8; 1];
179        let mut buffer = [0u8; 3];
180
181        // First read temperature
182        cmd[0] = self.psensor_resolution_osr as u8 * 2;
183        cmd[0] |= _MS8607::PSENSOR_START_TEMPERATURE_ADC_CONVERSION;
184        self.i2c.write(_MS8607::PT_ADDRESS, &cmd).map_err(Error::from)?;
185        
186        // wait 18ms
187        delay.delay_ms(20);
188
189        cmd = [_MS8607::PSENSOR_READ_ADC];
190        self.i2c.write_read(_MS8607::PT_ADDRESS, &cmd, &mut buffer).map_err(Error::from)?;
191        
192        let raw_temp = ((buffer[0] as u32) << 16) | ((buffer[1] as u32) << 8) | (buffer[2] as u32);
193        delay.delay_ms(20);
194        // Now read pressure
195        cmd[0] = self.psensor_resolution_osr as u8 * 2;
196        cmd[0] |= _MS8607::PSENSOR_START_PRESSURE_ADC_CONVERSION;
197        self.i2c.write(_MS8607::PT_ADDRESS, &cmd).map_err(Error::from)?;
198       
199        // wait 18ms
200        delay.delay_ms(20);
201        buffer = [0u8; 3];
202
203        cmd = [_MS8607::PSENSOR_READ_ADC];
204        self.i2c.write_read(_MS8607::PT_ADDRESS, &cmd, &mut buffer).map_err(Error::from)?;
205        
206        let raw_pressure =
207            ((buffer[0] as u32) << 16) | ((buffer[1] as u32) << 8) | (buffer[2] as u32);
208        self._apply_ptcorrections(raw_temp as i32, raw_pressure as i32);
209        Ok(())
210    }
211
212    /**
213    humidity user register value: 0b10
214    humidity resolution raw value: 0x0
215    Temperature: 29.85 degrees C
216    Pressure: 1008.94 hPa
217    Relative Humidity: 25.94 %rH
218    */
219    fn _read_humidity(&mut self) -> Result<(), Error<E>> {
220        let mut buffer = [0u8; 3];
221        self.get_humidity_resolution()?;
222        let cmd = [Ms8607HumidityClockStretch::Ms8607I2cHold as u8];
223        self.i2c.write_read(_MS8607::HUM_ADDRESS, &cmd, &mut buffer).map_err(Error::from)?;
224        
225        let raw_hum: u16 = (buffer[0] as u16) << 8 | (buffer[1] as u16);
226        let crc = buffer[2];
227        self._hsensor_crc_check(raw_hum, crc)?;
228        self._humidity = ((raw_hum as f32) * _MS8607::MS8607_RH_LSB) as f64;
229        self._humidity -= 6.0;
230        Ok(())
231    }
232
233    /**
234    A function that applies pressure and temperature corrections to the raw sensor data
235
236    ## Arguments
237    * `raw_temp` - raw temperature data from the sensor
238    * `raw_pressure` - raw pressure data from the sensor
239    */
240    fn _apply_ptcorrections(&mut self, raw_temp: i32, raw_pressure: i32) {
241        let mut off: i64;
242        let mut sens: i64;
243        let t2: i64;
244        let mut off2: i64;
245        let mut sens2: i64;
246
247        let d_t = raw_temp - ((self.ref_temp as i32) << 8);
248
249        // Actual temperature = 2000 + dT * TEMPSENS
250        let temp = (2000 + (((d_t as i64) * (self.temp_temp_coeff as i64)) >> 23)) as i32;
251
252        // Second order temperature compensation
253        if temp < 2000 {
254            t2 = (3 * ((d_t as i64) * (d_t as i64))) >> 33;
255            off2 = 61 * ((temp as i64) - 2000) * ((temp as i64) - 2000) / 16;
256            sens2 = 29 * ((temp as i64) - 2000) * ((temp as i64) - 2000) / 16;
257
258            if temp < -1500 {
259                off2 += 17 * ((temp as i64) + 1500) * ((temp as i64) + 1500);
260                sens2 += 9 * ((temp as i64) + 1500) * ((temp as i64) + 1500);
261            }
262        } else {
263            t2 = (5 * ((d_t as i64) * (d_t as i64))) >> 38;
264            off2 = 0;
265            sens2 = 0;
266        }
267
268        // OFF = OFF_T1 + TCO * dT
269        off = ((self.press_offset as i64) << 17)
270            + (((self.press_offset_temp_coeff as i64) * (d_t as i64)) >> 6);
271        off -= off2;
272
273        // Sensitivity at actual temperature = SENS_T1 + TCS * dT
274        sens = ((self.press_sens as i64) << 16)
275            + (((self.press_sens_temp_coeff as i64) * (d_t as i64)) >> 7);
276        sens -= sens2;
277
278        // Temperature compensated pressure = D1 * SENS - OFF
279        let p = ((((raw_pressure as i64) * sens) >> 21) - off) >> 15;
280
281        self._temperature = ((temp as f64) - t2 as f64) / 100.0;
282        self._pressure = p as f64 / 100.0;
283    }
284
285    /**
286    Write to the humidity sensor's user register
287
288    ## Parameters
289
290    * `new_reg_value` - The new value to set the user register to
291
292    ## Return
293
294     Returns `Ok(())` if the write is successful, `Err("Failed to write to I2C")` if the I2C write fails
295    */
296    fn _write_humidity_user_register(&mut self, new_reg_value: u8) -> Result<(), Error<E>>{
297        let buffer = [_MS8607::HSENSOR_WRITE_USER_REG_COMMAND, new_reg_value];
298        self.i2c.write(_MS8607::HUM_ADDRESS, &buffer).map_err(Error::from)?;
299        Ok(())
300    }
301
302    /**
303    Reads the user register from the humidity sensor of the MS8607 sensor
304    ## Errors
305    Returns an error if it fails to write to the I2C bus or fails to read from the I2C bus
306
307    ## Returns
308    Returns the value of the user register as a `u8` if successful.
309    */
310    fn _read_humidity_user_register(&mut self) -> Result<u8, Error<E>> {
311        let mut cmd = [_MS8607::HSENSOR_READ_USER_REG_COMMAND];
312        let mut buffer = [0u8; 1];
313
314
315        self.i2c.write_read(_MS8607::HUM_ADDRESS, &cmd, &mut buffer).map_err(Error::from)?;
316        
317        Ok(buffer[0])
318    }
319
320    /**
321    Fetches the temperature calibration values from the sensor's PROM memory
322    and stores them in the corresponding fields of the struct.
323
324    ## Errors
325
326    Returns an error if the CRC check of the retrieved data fails.
327    */
328    fn _fetch_temp_calibration_values(&mut self) -> Result<(), Error<E>> {
329        let mut offset: u8 = 0;
330        let mut buffer = [0u16; 8];
331        let mut tmp_buffer = [0u8; 2];
332
333        buffer
334            .iter_mut()
335            .enumerate()
336            .take(7usize)
337            .for_each(|(i, v)| {
338                offset = 2 * (i as u8);
339                let cmd = [_MS8607::PROM_ADDRESS_READ_ADDRESS_0 + offset];
340                let req = self.i2c.write_read(_MS8607::PT_ADDRESS, &cmd,&mut tmp_buffer);
341                if req.is_err() {
342                    return;
343                }
344                *v = (tmp_buffer[0] as u16) << 8;
345                *v |= tmp_buffer[1] as u16;
346            });
347        // check if every address has been read
348        if offset != 12 {
349            return Err(Error::RegisterReadFailed);
350        }
351        // let buffer_slice = &mut buffer[..];
352        self._psensor_crc_check(&mut buffer)?;
353
354        self.press_sens = buffer[1];
355        self.press_offset = buffer[2];
356        self.press_sens_temp_coeff = buffer[3];
357        self.press_offset_temp_coeff = buffer[4];
358        self.ref_temp = buffer[5];
359        self.temp_temp_coeff = buffer[6];
360        Ok(())
361    }
362
363    /**
364    Function that performs the CRC check on the PROM data of the pressure sensor.
365    It takes in the pointer to the PROM data array, and the expected CRC value as inputs.
366    It returns Ok(()) if the check passes, and an error message "CRC check failed" otherwise.
367
368    ## Arguments
369
370    * `n_prom` - A mutable reference to an array of u16, containing the PROM data of the pressure sensor.
371    * `crc` - A u8, representing the expected CRC value of the PROM data.
372
373    # Example
374    ```rust
375    let mut n_prom = [0u16; 8];
376    let crc = 0u8;
377    let result = self._psensor_crc_check(&mut n_prom, crc);
378    ```
379    */
380    fn _psensor_crc_check(&mut self, n_prom: &mut [u16; 8]) -> Result<(), Error<E>> {
381        let mut n_rem = 0;
382        let crc = ((n_prom[0] & 0xF000) >> 12) as u8;
383        n_prom[0] &= 0x0FFF; // Mask off CRC bits
384        n_prom[7] = 0; // Subsidiary value, set to 0
385        for cnt in 0..16 {
386            // operation is performed on bytes
387            // choose LSB or MSB
388            if cnt % 2 == 1 {
389                n_rem ^= (n_prom[cnt >> 1] & 0x00FF);
390            } else {
391                n_rem ^= n_prom[cnt >> 1] >> 8;
392            }
393            for n_bit in 0..8 {
394                if n_rem & 0x8000 != 0 {
395                    n_rem = (n_rem << 1) ^ 0x3000;
396                } else {
397                    n_rem <<= 1;
398                }
399            }
400        }
401        n_rem = (n_rem >> 12) & 0x000F; // final 4-bit reminder is CRC code
402        if n_rem != crc as u16 {
403            return Err(Error::CrcCheckFailed);
404        }
405        Ok(())
406    }
407
408    /**
409    This function checks the validity of the given value using the Cyclic Redundancy Check (CRC) algorithm.
410
411    ## Arguments
412    * `value`: The value to check the validity of.
413    * `crc`: The expected cyclic redundancy check value.
414
415    ## Returns
416    `Ok(())` if the value is valid and `Err("CRC check failed")` if the value is not valid.
417    */
418    fn _hsensor_crc_check(&mut self, value: u16, crc: u8) -> Result<(), Error<E>> {
419        let mut polynom: u32 = 0x988000; // x^8 + x^5 + x^4 + 1
420        let mut msb: u32 = 0x800000;
421        let mut mask: u32 = 0xFF8000;
422        let mut result: u32 = (value as u32) << 8; // Pad with zeros as specified in spec
423
424        while msb != 0x80 {
425            // Check if msb of current value is 1 and apply XOR mask
426            if result & msb != 0 {
427                result = ((result ^ polynom) & mask) | (result & !mask);
428            }
429
430            // Shift by one
431            msb >>= 1;
432            mask >>= 1;
433            polynom >>= 1;
434        }
435        if (result) as u8 != crc {
436            return Err(Error::CrcCheckFailed);
437        }
438        Ok(())
439    }
440
441    /// Reset the sensors to their initial state
442    pub fn reset<Delay>(&mut self, delay: &mut Delay) -> Result<(), Error<E>> where Delay: DelayMs<u16> {
443        let cmd = [_MS8607::P_T_RESET];
444        self.i2c.write(_MS8607::PT_ADDRESS, &cmd).map_err(Error::from)?;
445        
446        let cmd = [_MS8607::HSENSOR_RESET_COMMAND];
447        self.i2c.write(_MS8607::HUM_ADDRESS, &cmd).map_err(Error::from)?;
448        
449        // wait 15ms
450        delay.delay_ms(15);
451        Ok(())
452    }
453}
454
455struct _MS8607 {}
456
457impl _MS8607 {
458    // I2C ADDRESS/BITS/SETTINGS. The MS8607 uses two different I2C addresses
459
460    /// The pressure and temperature I2C address for the sensor
461    pub const PT_ADDRESS: u8 = 0x76;
462    /// The default pressure and temperature I2C address for the sensor
463    pub const HUM_ADDRESS: u8 = 0x40;
464
465    // HSENSOR device commands
466    /// reset command
467    pub const HSENSOR_RESET_COMMAND: u8 = 0xFE;
468    /// read humidity w hold command
469    pub const HSENSOR_READ_HUMIDITY_W_HOLD_COMMAND: u8 = 0xE5;
470    /// read humidity w/o hold command
471    pub const HSENSOR_READ_HUMIDITY_WO_HOLD_COMMAND: u8 = 0xF5;
472    /// read serial first 8bytes command
473    pub const HSENSOR_READ_SERIAL_FIRST_8BYTES_COMMAND: u16 = 0xFA0F;
474    /// read serial last 6bytes command
475    pub const HSENSOR_READ_SERIAL_LAST_6BYTES_COMMAND: u16 = 0xFCC9;
476    /// write user reg command
477    pub const HSENSOR_WRITE_USER_REG_COMMAND: u8 = 0xE6;
478    /// read user reg command
479    pub const HSENSOR_READ_USER_REG_COMMAND: u8 = 0xE7;
480
481    // Processing constants
482    /// temperature coefficient
483    pub const HSENSOR_TEMPERATURE_COEFFICIENT: f32 = -0.15;
484    /// constant a
485    pub const HSENSOR_CONSTANT_A: f32 = 8.1332;
486    /// constant b
487    pub const HSENSOR_CONSTANT_B: f32 = 1762.39;
488    /// constant c
489    pub const HSENSOR_CONSTANT_C: f32 = 235.66;
490
491    // Coefficients for temperature computation
492    /// temperature coeff mul
493    pub const TEMPERATURE_COEFF_MUL: f32 = 175.72;
494    /// temperature coeff add
495    pub const TEMPERATURE_COEFF_ADD: f32 = -46.85;
496
497    // Coefficients for relative humidity computation
498    /// humidity coeff mul
499    pub const HUMIDITY_COEFF_MUL: f32 = 125.0;
500    /// humidity coeff add
501    pub const HUMIDITY_COEFF_ADD: f32 = -6.0;
502
503    // Conversion timings
504    /// conversion time 12b
505    pub const HSENSOR_CONVERSION_TIME_12B: u8 = 16;
506    /// conversion time 10b
507    pub const HSENSOR_CONVERSION_TIME_10B: u8 = 5;
508    /// conversion time 8b
509    pub const HSENSOR_CONVERSION_TIME_8B: u8 = 3;
510    /// conversion time 11b
511    pub const HSENSOR_CONVERSION_TIME_11B: u8 = 9;
512
513    // HSENSOR User Register masks and bit position
514    /// user reg resolution mask
515    pub const HSENSOR_USER_REG_RESOLUTION_MASK: u8 = 0x81;
516    /// user reg end of battery mask
517    pub const HSENSOR_USER_REG_END_OF_BATTERY_MASK: u8 = 0x40;
518    /// user reg enable onchip heater mask
519    pub const HSENSOR_USER_REG_ENABLE_ONCHIP_HEATER_MASK: u8 = 0x4;
520    /// user reg disable otp reload mask
521    pub const HSENSOR_USER_REG_DISABLE_OTP_RELOAD_MASK: u8 = 0x2;
522
523    /// Humidity I2C address for the sensor.
524    pub const RH_ADDRESS: u8 = 0x40;
525
526    /// value for each count coming from the humidity
527    /// register
528    pub const MS8607_RH_LSB: f32 = 0.001_907_348_6;
529
530    // PSENSOR commands
531    /// 16-bit registers through 0xAE
532    pub const PROM_ADDRESS_READ_ADDRESS_0: u8 = 0xA0;
533
534    // Pressure & Temperature commands
535    /// Pressure and temperature sensor reset
536    pub const P_T_RESET: u8 = 0x1E;
537    /// Sampling rate 256
538    pub const CONVERT_D1_OSR_256: u8 = 0x40;
539    /// Sampling rate 512
540    pub const CONVERT_D1_OSR_512: u8 = 0x42;
541    /// Sampling rate 1024
542    pub const CONVERT_D1_OSR_1024: u8 = 0x44;
543    /// Sampling rate 2048
544    pub const CONVERT_D1_OSR_2048: u8 = 0x46;
545    /// Sampling rate 4096
546    pub const CONVERT_D1_OSR_4096: u8 = 0x48;
547    /// Sampling rate 8192
548    pub const CONVERT_D1_OSR_8192: u8 = 0x4A;
549    /// Sampling rate 256
550    pub const CONVERT_D2_OSR_256: u8 = 0x50;
551    /// Sampling rate 512
552    pub const CONVERT_D2_OSR_512: u8 = 0x52;
553    /// Sampling rate 1024
554    pub const CONVERT_D2_OSR_1024: u8 = 0x54;
555    /// Sampling rate 2048
556    pub const CONVERT_D2_OSR_2048: u8 = 0x56;
557    /// Sampling rate 4096
558    pub const CONVERT_D2_OSR_4096: u8 = 0x58;
559    /// Sampling rate 8192
560    pub const CONVERT_D2_OSR_8192: u8 = 0x5A;
561    /// Command to read from ADC
562    pub const ADC_READ: u8 = 0x00;
563    // PROM READ P&T is from 0xA0 to 0xAE. Not sure whether or not to add
564
565    // Commands for relative humidity
566    /// Humidity sensor reset
567    pub const HUMIDITY_RESET: u8 = 0xFE;
568    /// Humidity sensor write register
569    pub const HUMIDITY_WRITE_REGISTER: u8 = 0xE6;
570    /// Humidity sensor read register
571    pub const HUMIDITY_READ_REGISTER: u8 = 0xE7;
572    /// Humidity sensor measure relative humidity hold master
573    pub const HUM_MEASURE_RH_HOLD: u8 = 0xE5;
574    /// Humidity sensor measure relative humidity no hold master
575    pub const HUM_MEASURE_RH_NO_HOLD: u8 = 0xF5;
576    // PROM READ RH is from 0xA0 to 0xAE. Not sure whether or not to add
577
578    /// Command to reset pressure sensor
579    pub const PSENSOR_RESET_COMMAND: u8 = 0x1E;
580    /// Command to start pressure ADC measurement
581    pub const PSENSOR_START_PRESSURE_ADC_CONVERSION: u8 = 0x40;
582    /// Command to start temperature ADC measurement
583    pub const PSENSOR_START_TEMPERATURE_ADC_CONVERSION: u8 = 0x50;
584    /// Temp and pressure ADC read command
585    pub const PSENSOR_READ_ADC: u8 = 0x00;
586}
587
588/// Pressure sensor resolution options
589#[derive(Clone, Copy)]
590pub enum Ms8607PressureResolution {
591    /// 0
592    Osr256,
593    /// 1
594    Osr512,
595    /// 2
596    Osr1024,
597    /// 3
598    Osr2048,
599    /// 4
600    Osr4096,
601    /// 5
602    Osr8192,
603}
604
605/// Options for setHumidityResolution
606pub enum Ms8607HumidityResolution {
607    Osr12b = 0x00,
608    Osr11b = 0x81,
609    Osr10b = 0x80,
610    Osr8b = 0x01,
611}
612
613/// Options for I2C clock stretch for humidity readings
614pub enum Ms8607HumidityClockStretch {
615    Ms8607I2cHold = 0xE5,
616    Ms8607I2cNoHold = 0xF5,
617}