sen66_interface/
command.rs

1//! SEN66 I2C Commands.
2
3/// I2C Commands for the SEN66 according to its [interface
4/// description](https://sensirion.com/media/documents/FAFC548D/6731FFFA/Sensirion_Datasheet_SEN6x.pdf).
5#[derive(Clone, Copy)]
6pub enum Command {
7    /// Starts a continuous measurement and moves chip to measuring state. After the sending the command
8    /// it might take some time until the first measurement is ready.
9    /// Exec. Time: 50ms
10    /// <div class="warning">Only available in idle state</div>
11    StartContinuousMeasurement = 0x0021,
12    /// Stops measurements and returns to idle state. Wait at least 1000ms until starting a new
13    /// measurement.
14    /// Exec. Time: 1000ms
15    /// <div class="warning">Only available in measuring state</div>
16    StopMeasurement = 0x0104,
17    /// Queries whether a measurement can be read from the sensor's buffer. The answer is `1` if a
18    /// measurement is available `0` otherwise.
19    /// Exec. Time: 20ms
20    /// <div class="warning">Only available in measuring state</div>
21    GetDataReady = 0x0202,
22    /// If a measurement is available reads out the measurement. If no new data is available the
23    /// previous measurement is returned. If no data is available all data is set to the maximum
24    /// value (`0xFFFF` for `u16`, `0x7FFF` for `i16`). The measurement contains the mass
25    /// concentration for PM1.0, PM2.5, PM4.0 and PM10.0 in ug/m³, the relative humidity in %, the temperature
26    /// in °C, the [volatile organic compounds (VOC)
27    /// index](https://sensirion.com/media/documents/02232963/6294E043/Info_Note_VOC_Index.pdf),
28    /// the [NOx
29    /// index](https://sensirion.com/media/documents/9F289B95/6294DFFC/Info_Note_NOx_Index.pdf) and
30    /// CO2 concentration in ppm.
31    /// Exec. Time: 20ms
32    /// <div class="warning">Only available in measuring state</div>
33    ReadMeasurement = 0x0300,
34    /// If a measurement is available reads out the measured raw values. If no new data is available
35    /// the previous measurement is returned. If no data is available all data is set to the maximum
36    /// value (`0xFFFF` for `u16`, `0x7FFF` for `i16`). The measurement contains the raw relative
37    /// humidity in %, the raw temperature in °C, the VOC ticks, the NOx ticks and the CO2
38    /// concentration in ppm. For the first 10-11s after power-on or device reset the CO2 value will
39    /// be `0xFFFF`.
40    /// Exec. Time: 20ms
41    /// <div class="warning">Only available in measuring state</div>
42    ReadRawMeasurement = 0x0405,
43    /// If a measurement is available reads out the measured number concentration values. If no
44    /// new data is available the previous values will be returned. If no data is available at all,
45    /// the data is set to the maximum value (`0xFFFF` for `u16`). The values contain the mass
46    /// concentration for PM0.5, PM1.0, PM2.5, PM4.0 and PM10.0 in p/cm³
47    /// Exec. Time: 20ms
48    /// <div class="warning">Only available in measuring state</div>
49    ReadNumberConcentrationValues = 0x0316,
50    /// Configures the temperature compensation via a slope and one of five offsets in °C.
51    /// Exec. Time: 20ms
52    SetTemperatureOffsetParameters = 0x60B2,
53    /// Configures the temperature acceleration parameters for the RH/T engine. Thes parameters are
54    /// volatile and reverted after a device reset.
55    /// Exec. Time: 20ms
56    /// <div class="warning">Only available in idle state</div>
57    SetTemperatureAccelerationParameters = 0x6100,
58    /// Reads out the product name as a null-terminated ASCII string with up to 32 characters.
59    /// Exec. Time: 20ms
60    GetProductName = 0xD014,
61    /// Reads out the device's serial number as a null-terminated ASCII string with up to 32
62    /// characters.
63    /// Exec. Time: 20ms
64    GetSerialNumber = 0xD033,
65    /// Read out the device's status register as a 32-bit bitfield.
66    /// Exec. Time: 20ms
67    GetDeviceStatus = 0xD206,
68    /// Read the current device status as a 32-bit bitfield and clear all flags.
69    /// Exec. Time: 20ms
70    ReadAndClearDeviceStatus = 0xD210,
71    /// Executes a device reset, the same as a power cycle.
72    /// Exec. Time: 1200ms
73    ResetDevice = 0xD304,
74    /// Starts fan cleaning, where fan speed is set to a maximum for 10s. Wait at least 10s after
75    /// this command until the next measurement.
76    /// Exec. Time: 1ms
77    /// <div class="warning">Only available in idle state</div>
78    StartFanCleaning = 0x5607,
79    /// Start the SHT's inbuilt heater for 1s with 200mW. Wait at least 20s after this command
80    /// until the next measurement.
81    /// Exec. Time: 1300ms
82    /// <div class="warning">Only available in idle state</div>
83    ActivateShtHeater = 0x3730,
84    /// Sets or reads the parameters that customize the VOC algorithm. Contains the index offset,
85    /// the learning time offset hours, the learning time gain hours, the max duration minutes, the
86    /// initial standard deviation and the gain factor (all `i16`).
87    /// Exec. Time: 20ms
88    /// <div class="warning">Only available in idle state</div>
89    SetReadVocTuningParameters = 0x60D0,
90    /// Sets or reads the state of the VOC algorithm to skip the initial learning phase. The state
91    /// is encoded in a byte array of length 8.
92    /// Exec. Time: 20ms
93    /// <div class="warning">Writing only available in idle state</div>
94    SetReadVocAlgorithmState = 0x6181,
95    /// Sets or reads the parameters that customize the VOC algorithm. Contains the index offset,
96    /// the learning time offset hours, the learning time gain hours, the max duration minutes, the
97    /// initial standard deviation and the gain factor (all `i16`).
98    /// Exec. Time: 20ms
99    /// <div class="warning">Only available in idle state</div>
100    SetReadNoxTuningParameters = 0x60E1,
101    /// Executes a forced recalibration (FRC) of the CO2 signal. Send the target CO2 concentation
102    /// (as `u16`) and receive the correction factor as FRC - 0x8000 (as `u16`). Wait at least 1000ms after power-on
103    /// and 600ms after stopping measurement to send this command.
104    /// # Errors
105    /// If recalibration failes 0xFFFF is returned.
106    /// Exec. Time: 500ms
107    /// <div class="warning">Only available in idle state</div>
108    ForcedRecalibration = 0x6707,
109    /// Enables/Disables or reads the status of the automatic self calibration (ASC) for the CO2
110    /// sensor via a `bool` value. Sending a `0x01` activates ASC, sending a `0x00` disables ASC.
111    /// Receiving a `0x01` indicates that ASC is enabled, a `0x00` indicates that ASC is disabled.
112    /// Exec. Time: 20ms
113    /// <div class="warning">Only available in idle state</div>
114    SetReadCo2AutomaticSelfCalibration = 0x6711,
115    /// Sets or reads the ambient pressure value in hPA (as `u16`) which is used for the CO2
116    /// sensor's pressure compensation.
117    /// Exec. Time: 20ms
118    SetReadAmbientPreassure = 0x6720,
119    /// Sets or reads the sensors current altitude in m (as `u16`) which is used for the CO2
120    /// sensor's pressure compensation.
121    /// Exec. Time: 20ms
122    /// <div class="warning">Only available in idle state</div>
123    SetReadSensorAltitude = 0x6736,
124}
125
126impl Command {
127    /// Returns a big endian byte representation of the command.
128    pub const fn to_be_bytes(&self) -> [u8; 2] {
129        (*self as u16).to_be_bytes()
130    }
131
132    /// Returns the execution_time of the command in ms.
133    pub(crate) const fn execution_time_ms(&self) -> u32 {
134        match self {
135            Command::StartContinuousMeasurement => 50,
136            Command::StopMeasurement => 1000,
137            Command::GetDataReady => 20,
138            Command::ReadMeasurement => 20,
139            Command::ReadRawMeasurement => 20,
140            Command::ReadNumberConcentrationValues => 20,
141            Command::SetTemperatureOffsetParameters => 20,
142            Command::SetTemperatureAccelerationParameters => 20,
143            Command::GetProductName => 20,
144            Command::GetSerialNumber => 20,
145            Command::GetDeviceStatus => 20,
146            Command::ReadAndClearDeviceStatus => 20,
147            Command::ResetDevice => 20,
148            Command::StartFanCleaning => 20,
149            Command::ActivateShtHeater => 1300,
150            Command::SetReadVocTuningParameters => 20,
151            Command::SetReadVocAlgorithmState => 20,
152            Command::SetReadNoxTuningParameters => 20,
153            Command::ForcedRecalibration => 500,
154            Command::SetReadCo2AutomaticSelfCalibration => 20,
155            Command::SetReadAmbientPreassure => 20,
156            Command::SetReadSensorAltitude => 20,
157        }
158    }
159}
160
161#[cfg(test)]
162mod tests {
163    use super::*;
164
165    #[test]
166    fn serialize_to_bytes_works() {
167        use Command::*;
168        let data = [
169            (StartContinuousMeasurement, [0x00, 0x21]),
170            (StopMeasurement, [0x01, 0x04]),
171            (GetDataReady, [0x02, 0x02]),
172            (ReadMeasurement, [0x03, 0x00]),
173            (ReadRawMeasurement, [0x04, 0x05]),
174            (ReadNumberConcentrationValues, [0x03, 0x16]),
175            (SetTemperatureOffsetParameters, [0x60, 0xB2]),
176            (SetTemperatureAccelerationParameters, [0x61, 0x00]),
177            (GetProductName, [0xD0, 0x14]),
178            (GetSerialNumber, [0xD0, 0x33]),
179            (GetDeviceStatus, [0xD2, 0x06]),
180            (ReadAndClearDeviceStatus, [0xD2, 0x10]),
181            (ResetDevice, [0xD3, 0x04]),
182            (StartFanCleaning, [0x56, 0x07]),
183            (ActivateShtHeater, [0x37, 0x30]),
184            (SetReadVocTuningParameters, [0x60, 0xD0]),
185            (SetReadVocAlgorithmState, [0x61, 0x81]),
186            (SetReadNoxTuningParameters, [0x60, 0xE1]),
187            (ForcedRecalibration, [0x67, 0x07]),
188            (SetReadCo2AutomaticSelfCalibration, [0x67, 0x11]),
189            (SetReadAmbientPreassure, [0x67, 0x20]),
190            (SetReadSensorAltitude, [0x67, 0x36]),
191        ];
192        for (command, result) in data {
193            assert_eq!(command.to_be_bytes(), result);
194        }
195    }
196}