Skip to main content

sht4x/
types.rs

1//! Public types: precision, heater settings, and measurement results.
2
3use crate::commands;
4
5/// Measurement precision (repeatability) setting.
6#[derive(Debug, Clone, Copy, PartialEq, Eq)]
7#[cfg_attr(feature = "defmt", derive(defmt::Format))]
8pub enum Precision {
9    /// Highest accuracy, longest conversion time (~8.3 ms max).
10    High,
11    /// Medium accuracy (~4.5 ms max).
12    Medium,
13    /// Lowest accuracy, fastest (~1.7 ms max).
14    Low,
15}
16
17impl Precision {
18    #[inline]
19    pub(crate) const fn command(self) -> u8 {
20        match self {
21            Precision::High => commands::MEASURE_HIGH,
22            Precision::Medium => commands::MEASURE_MEDIUM,
23            Precision::Low => commands::MEASURE_LOW,
24        }
25    }
26
27    #[inline]
28    pub(crate) const fn duration_us(self) -> u32 {
29        match self {
30            Precision::High => commands::duration_us::HIGH,
31            Precision::Medium => commands::duration_us::MEDIUM,
32            Precision::Low => commands::duration_us::LOW,
33        }
34    }
35}
36
37/// Heater power level (at 3.3 V supply).
38#[derive(Debug, Clone, Copy, PartialEq, Eq)]
39#[cfg_attr(feature = "defmt", derive(defmt::Format))]
40pub enum HeaterPower {
41    /// 200 mW (highest).
42    High,
43    /// 110 mW.
44    Medium,
45    /// 20 mW (lowest).
46    Low,
47}
48
49/// Heater activation duration.
50#[derive(Debug, Clone, Copy, PartialEq, Eq)]
51#[cfg_attr(feature = "defmt", derive(defmt::Format))]
52pub enum HeaterDuration {
53    /// 1 second.
54    Long,
55    /// 0.1 second.
56    Short,
57}
58
59impl HeaterDuration {
60    #[inline]
61    pub(crate) const fn duration_us(self) -> u32 {
62        match self {
63            HeaterDuration::Long => commands::duration_us::HEATER_1S,
64            HeaterDuration::Short => commands::duration_us::HEATER_100MS,
65        }
66    }
67}
68
69#[inline]
70pub(crate) const fn heater_command(power: HeaterPower, duration: HeaterDuration) -> u8 {
71    match (power, duration) {
72        (HeaterPower::High, HeaterDuration::Long) => commands::HEATER_200MW_1S,
73        (HeaterPower::High, HeaterDuration::Short) => commands::HEATER_200MW_100MS,
74        (HeaterPower::Medium, HeaterDuration::Long) => commands::HEATER_110MW_1S,
75        (HeaterPower::Medium, HeaterDuration::Short) => commands::HEATER_110MW_100MS,
76        (HeaterPower::Low, HeaterDuration::Long) => commands::HEATER_20MW_1S,
77        (HeaterPower::Low, HeaterDuration::Short) => commands::HEATER_20MW_100MS,
78    }
79}
80
81/// A temperature + humidity measurement, holding the raw 16-bit ticks
82/// reported by the sensor. Use the accessor methods to convert to
83/// engineering units.
84#[derive(Debug, Clone, Copy, PartialEq, Eq)]
85#[cfg_attr(feature = "defmt", derive(defmt::Format))]
86pub struct Measurement {
87    raw_temperature: u16,
88    raw_humidity: u16,
89}
90
91impl Measurement {
92    #[inline]
93    pub(crate) const fn from_raw(raw_temperature: u16, raw_humidity: u16) -> Self {
94        Self {
95            raw_temperature,
96            raw_humidity,
97        }
98    }
99
100    /// Raw 16-bit temperature ticks as received from the sensor.
101    #[inline]
102    pub const fn raw_temperature(&self) -> u16 {
103        self.raw_temperature
104    }
105
106    /// Raw 16-bit humidity ticks as received from the sensor.
107    #[inline]
108    pub const fn raw_humidity(&self) -> u16 {
109        self.raw_humidity
110    }
111
112    /// Temperature in degrees Celsius.
113    ///
114    /// `T = -45 + 175 * raw / 65535`
115    #[inline]
116    pub fn temperature_celsius(&self) -> f32 {
117        -45.0 + 175.0 * (self.raw_temperature as f32 / 65535.0)
118    }
119
120    /// Relative humidity in percent, clamped to \[0, 100\].
121    ///
122    /// `RH = -6 + 125 * raw / 65535`
123    #[inline]
124    pub fn humidity_percent(&self) -> f32 {
125        let rh = -6.0 + 125.0 * (self.raw_humidity as f32 / 65535.0);
126        rh.clamp(0.0, 100.0)
127    }
128
129    /// Temperature in milli-degrees Celsius (e.g. 23456 = 23.456 °C),
130    /// computed in fixed point from the raw ticks. Floating-point free.
131    #[inline]
132    pub const fn temperature_milli_celsius(&self) -> i32 {
133        // -45000 + 175000 * raw / 65535
134        let scaled = 175_000_i64 * self.raw_temperature as i64;
135        let div = scaled / 65_535;
136        (div as i32) - 45_000
137    }
138
139    /// Relative humidity in milli-percent (e.g. 50123 = 50.123 %RH),
140    /// clamped to \[0, 100000\]. Floating-point free.
141    #[inline]
142    pub const fn humidity_milli_percent(&self) -> i32 {
143        // -6000 + 125000 * raw / 65535
144        let scaled = 125_000_i64 * self.raw_humidity as i64;
145        let div = scaled / 65_535;
146        let rh = (div as i32) - 6_000;
147        if rh < 0 {
148            0
149        } else if rh > 100_000 {
150            100_000
151        } else {
152            rh
153        }
154    }
155}