embedded_devices/devices/sensirion/sen66/
commands.rs

1use crate::devices::sensirion::commands::define_sensirion_commands;
2use embedded_interfaces::codegen::interface_objects;
3use uom::si::{
4    f64::{MassConcentration, Ratio, ThermodynamicTemperature},
5    mass_concentration::microgram_per_cubic_meter,
6    ratio::{part_per_million, percent},
7    thermodynamic_temperature::degree_celsius,
8};
9
10pub use crate::devices::sensirion::sen6x::commands::{
11    ActivateSHTHeater, AmbientPressure, DeviceReset, GetCo2SensorAutomaticSelfCalibration, GetDataReady,
12    GetNOxAlgorithmTuningParameters, GetProductName, GetSensorAltitude, GetSerialNumber, GetVOCAlgorithmState,
13    GetVOCAlgorithmTuningParameters, PerformForcedCo2Recalibration, ReadNumberConcentrationValues,
14    SetCo2SensorAutomaticSelfCalibration, SetNOxAlgorithmTuningParameters, SetSensorAltitude,
15    SetTemperatureAccelerationParameters, SetTemperatureOffsetParameters, SetVOCAlgorithmState,
16    SetVOCAlgorithmTuningParameters, StartContinuousMeasurement, StartFanCleaning, StopMeasurement,
17};
18
19interface_objects! {
20    struct MeasuredValues(size=18) {
21        /// PM1 mass concentration, LSB = 0.1 µg/m³
22        raw_mass_concentration_pm1: u16 = u16::MAX => {
23            quantity: MassConcentration,
24            unit: microgram_per_cubic_meter,
25            lsb: 1f64 / 10f64,
26        },
27        /// PM2.5 mass concentration, LSB = 0.1 µg/m³
28        raw_mass_concentration_pm2_5: u16 = u16::MAX => {
29            quantity: MassConcentration,
30            unit: microgram_per_cubic_meter,
31            lsb: 1f64 / 10f64,
32        },
33        /// PM4 mass concentration, LSB = 0.1 µg/m³
34        raw_mass_concentration_pm4: u16 = u16::MAX => {
35            quantity: MassConcentration,
36            unit: microgram_per_cubic_meter,
37            lsb: 1f64 / 10f64,
38        },
39        /// PM10 mass concentration, LSB = 0.1 µg/m³
40        raw_mass_concentration_pm10: u16 = u16::MAX => {
41            quantity: MassConcentration,
42            unit: microgram_per_cubic_meter,
43            lsb: 1f64 / 10f64,
44        },
45        /// Ambient relative humidity, LSB = 0.01%
46        raw_relative_humidity: i16 = i16::MAX => {
47            quantity: Ratio,
48            unit: percent,
49            lsb: 1f64 / 100f64,
50        },
51        /// Ambient temperature, LSB = 0.005°C
52        raw_temperature: i16 = i16::MAX => {
53            quantity: ThermodynamicTemperature,
54            unit: degree_celsius,
55            lsb: 1f64 / 200f64,
56        },
57        /// VOC index, LSB = 0.1
58        raw_voc_index: i16 = i16::MAX => {
59            quantity: Ratio,
60            unit: percent,
61            lsb: 1f64 / 10f64,
62        },
63        /// NOx index, LSB = 0.1
64        /// Will be i16::MAX for the first 10-11 seconds after startup or reset.
65        raw_nox_index: i16 = i16::MAX => {
66            quantity: Ratio,
67            unit: percent,
68            lsb: 1f64 / 10f64,
69        },
70        /// CO2 concentration, LSB = 1 ppm
71        /// Will be u16::MAX for the first 5-6 seconds after startup or reset.
72        raw_co2_concentration: u16 = u16::MAX => {
73            quantity: Ratio,
74            unit: part_per_million,
75            lsb: 1f64 / 1f64,
76        },
77    }
78
79    struct MeasuredRawValues(size=10) {
80        /// Raw relative humidity, LSB = 0.01%
81        raw_relative_humidity: i16 = i16::MAX => {
82            quantity: Ratio,
83            unit: percent,
84            lsb: 1f64 / 100f64,
85        },
86        /// Raw temperature, LSB = 0.005°C
87        raw_temperature: i16 = i16::MAX => {
88            quantity: ThermodynamicTemperature,
89            unit: degree_celsius,
90            lsb: 1f64 / 200f64,
91        },
92        /// VOC ticks, LSB = 1
93        voc_ticks: u16 = u16::MAX,
94        /// NOx ticks, LSB = 1
95        /// Will be i16::MAX for the first 10-11 seconds after startup or reset.
96        nox_ticks: u16 = u16::MAX,
97        /// CO2 concentration, not interpolated, LSB = 1 ppm
98        /// Will be u16::MAX for the first 5-6 seconds after startup or reset.
99        raw_co2_concentration: u16 = u16::MAX => {
100            quantity: Ratio,
101            unit: part_per_million,
102            lsb: 1f64 / 1f64,
103        },
104    }
105
106    struct DeviceStatus(size=4) {
107        _: u16{10},
108        /// Fan is switched on, but its speed is more than 10% off the target speed for multiple
109        /// consecutive measurement intervals. During the first 10 seconds after starting the
110        /// measurement, the fan speed is not checked (settling time). Very low or very high ambient
111        /// temperature could trigger this warning during startup. If this flag is set constantly, it
112        /// might indicate a problem with the power supply or with the fan, and the measured PM values
113        /// might be wrong. This flag is automatically cleared as soon as the measured speed is within
114        /// 10% of the target speed or when leaving the measure mode.
115        ///
116        /// Can occur only in measurement mode.
117        fan_speed_warning: bool = false,
118        _: u8, // reserved1
119        _: bool, // reserved_co2_error1
120        /// Error related to the PM sensor. The particulate matter values might be unknown or wrong if
121        /// this flag is set, relative humidity and temperature values might be out of specs due to
122        /// compensation algorithms depending on PM sensor state.
123        ///
124        /// Can occur only in measurement mode.
125        pm_error: bool = false,
126        _: bool, // reserved_hcho_error
127        /// Error related to the CO2 sensor. The CO2 values might be unknown or wrong if this flag is
128        /// set, relative humidity and temperature values might be out of specs due to compensation
129        /// algorithms depending on CO2 sensor state.
130        ///
131        /// Can occur only in measurement mode.
132        co2_error: bool = false,
133        _: bool, // reserved2
134        /// Error related to the gas sensor. The VOC index and NOx index might be unknown or wrong if
135        /// this flag is set, relative humidity and temperature values might be out of specs due to
136        /// compensation algorithms depending on gas sensor state.
137        ///
138        /// Can occur only in measurement mode.
139        gas_error: bool = false,
140        /// Error related to the RH&T sensor. The temperature and humidity values might be unknown or
141        /// wrong if this flag is set, and other measured values might be out of specs due compensation
142        /// algorithms depending on RH&T sensor values.
143        ///
144        /// Can occur only in measurement mode.
145        rh_t_error: bool = false,
146        _: bool, // reserved3
147        /// Fan is switched on, but 0 RPM is measured for multiple consecutive measurement intervals.
148        /// This can occur if the fan is mechanically blocked or broken. Note that the measured values
149        /// are most likely wrong if this error is reported.
150        ///
151        /// Can occur only in measurement mode.
152        fan_error: bool = false,
153        _: u8{4}, // reserved4
154    }
155}
156
157define_sensirion_commands! {
158    id_len 2;
159    marker [
160        ("sensirion-sen66", crate::devices::sensirion::sen66::SEN66Command),
161    ];
162
163    /// Returns the measured values. The command [`GetDataReady`] can be used to check if new data is
164    /// available since the last read operation. If no new data is available, the previous values will
165    /// be returned. If no data is available at all (e.g. measurement not running for at least one
166    /// second), all values will be at their upper limit (0xFFFF for u16, 0x7FFF for i16).
167    ///
168    /// May be executed during measurement.
169    read 0x0300 time_ms=20 ReadMeasuredValues() -> MeasuredValues;
170
171    /// Returns the measured raw values. The command [`GetDataReady`] can be used to check if new data
172    /// is available since the last read operation. If no new data is available, the previous values
173    /// will be returned. If no data is available at all (e.g. measurement not running for at least one
174    /// second), all values will be at their upper limit (0xFFFF for u16, 0x7FFF for i16).
175    ///
176    /// May be executed during measurement.
177    read 0x0405 time_ms=20 ReadMeasuredRawValues() -> MeasuredRawValues;
178
179    /// Reads the current device status.
180    ///
181    /// Note: The status flags of type `Error` are sticky, i.e. they are not cleared automatically even
182    /// if the error condition no longer exists. So, they can only be cleared manually with
183    /// [`ReadAndClearDeviceStatus`] or through a reset, either by calling [`DeviceReset`] or through a
184    /// power cycle. All other flags are not sticky, i.e. they are cleared automatically if the trigger
185    /// condition disappears.
186    ///
187    /// May be executed during measurement.
188    read 0xd206 time_ms=20 ReadDeviceStatus() -> DeviceStatus;
189
190    /// Reads the current device status (like command [`ReadDeviceStatus`]) and clears all
191    /// flags afterwards.
192    ///
193    /// May be executed during measurement.
194    read 0xd210 time_ms=20 ReadAndClearDeviceStatus() -> DeviceStatus;
195}