sht4x-rs 0.1.0

Sensirion SHT4x temperature & humidity sensor driver (embedded-hal 1.0, no_std, blocking + async)
Documentation
//! Public types: precision, heater settings, and measurement results.

use crate::commands;

/// Measurement precision (repeatability) setting.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum Precision {
    /// Highest accuracy, longest conversion time (~8.3 ms max).
    High,
    /// Medium accuracy (~4.5 ms max).
    Medium,
    /// Lowest accuracy, fastest (~1.7 ms max).
    Low,
}

impl Precision {
    #[inline]
    pub(crate) const fn command(self) -> u8 {
        match self {
            Precision::High => commands::MEASURE_HIGH,
            Precision::Medium => commands::MEASURE_MEDIUM,
            Precision::Low => commands::MEASURE_LOW,
        }
    }

    #[inline]
    pub(crate) const fn duration_us(self) -> u32 {
        match self {
            Precision::High => commands::duration_us::HIGH,
            Precision::Medium => commands::duration_us::MEDIUM,
            Precision::Low => commands::duration_us::LOW,
        }
    }
}

/// Heater power level (at 3.3 V supply).
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HeaterPower {
    /// 200 mW (highest).
    High,
    /// 110 mW.
    Medium,
    /// 20 mW (lowest).
    Low,
}

/// Heater activation duration.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub enum HeaterDuration {
    /// 1 second.
    Long,
    /// 0.1 second.
    Short,
}

impl HeaterDuration {
    #[inline]
    pub(crate) const fn duration_us(self) -> u32 {
        match self {
            HeaterDuration::Long => commands::duration_us::HEATER_1S,
            HeaterDuration::Short => commands::duration_us::HEATER_100MS,
        }
    }
}

#[inline]
pub(crate) const fn heater_command(power: HeaterPower, duration: HeaterDuration) -> u8 {
    match (power, duration) {
        (HeaterPower::High, HeaterDuration::Long) => commands::HEATER_200MW_1S,
        (HeaterPower::High, HeaterDuration::Short) => commands::HEATER_200MW_100MS,
        (HeaterPower::Medium, HeaterDuration::Long) => commands::HEATER_110MW_1S,
        (HeaterPower::Medium, HeaterDuration::Short) => commands::HEATER_110MW_100MS,
        (HeaterPower::Low, HeaterDuration::Long) => commands::HEATER_20MW_1S,
        (HeaterPower::Low, HeaterDuration::Short) => commands::HEATER_20MW_100MS,
    }
}

/// A temperature + humidity measurement, holding the raw 16-bit ticks
/// reported by the sensor. Use the accessor methods to convert to
/// engineering units.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Measurement {
    raw_temperature: u16,
    raw_humidity: u16,
}

impl Measurement {
    #[inline]
    pub(crate) const fn from_raw(raw_temperature: u16, raw_humidity: u16) -> Self {
        Self {
            raw_temperature,
            raw_humidity,
        }
    }

    /// Raw 16-bit temperature ticks as received from the sensor.
    #[inline]
    pub const fn raw_temperature(&self) -> u16 {
        self.raw_temperature
    }

    /// Raw 16-bit humidity ticks as received from the sensor.
    #[inline]
    pub const fn raw_humidity(&self) -> u16 {
        self.raw_humidity
    }

    /// Temperature in degrees Celsius.
    ///
    /// `T = -45 + 175 * raw / 65535`
    #[inline]
    pub fn temperature_celsius(&self) -> f32 {
        -45.0 + 175.0 * (self.raw_temperature as f32 / 65535.0)
    }

    /// Relative humidity in percent, clamped to \[0, 100\].
    ///
    /// `RH = -6 + 125 * raw / 65535`
    #[inline]
    pub fn humidity_percent(&self) -> f32 {
        let rh = -6.0 + 125.0 * (self.raw_humidity as f32 / 65535.0);
        rh.clamp(0.0, 100.0)
    }

    /// Temperature in milli-degrees Celsius (e.g. 23456 = 23.456 °C),
    /// computed in fixed point from the raw ticks. Floating-point free.
    #[inline]
    pub const fn temperature_milli_celsius(&self) -> i32 {
        // -45000 + 175000 * raw / 65535
        let scaled = 175_000_i64 * self.raw_temperature as i64;
        let div = scaled / 65_535;
        (div as i32) - 45_000
    }

    /// Relative humidity in milli-percent (e.g. 50123 = 50.123 %RH),
    /// clamped to \[0, 100000\]. Floating-point free.
    #[inline]
    pub const fn humidity_milli_percent(&self) -> i32 {
        // -6000 + 125000 * raw / 65535
        let scaled = 125_000_i64 * self.raw_humidity as i64;
        let div = scaled / 65_535;
        let rh = (div as i32) - 6_000;
        if rh < 0 {
            0
        } else if rh > 100_000 {
            100_000
        } else {
            rh
        }
    }
}