embedded_devices/devices/sensirion/sen6x/commands.rs
1use crate::devices::sensirion::commands::define_sensirion_commands;
2use embedded_interfaces::codegen::interface_objects;
3use uom::si::{
4 f64::{Length, Pressure, Ratio, ThermodynamicTemperature, Time, VolumetricNumberDensity},
5 length::meter,
6 pressure::hectopascal,
7 ratio::part_per_million,
8 thermodynamic_temperature::degree_celsius,
9 time::second,
10 volumetric_number_density::per_cubic_centimeter,
11};
12
13interface_objects! {
14 /// Whether data is ready to be read out
15 enum DataReadyStatus: u8{1} {
16 0 NotReady,
17 1 Ready,
18 }
19
20 struct DataReady(size=2) {
21 _: u16{15},
22 /// When no measurement is running, [`DataReadyStatus::NotReady`] will be returned.
23 data_ready: DataReadyStatus = DataReadyStatus::NotReady,
24 }
25
26 struct NumberConcentrationValues(size=10) {
27 /// PM0.5 volumetric number density, LSB = 0.1 particles/cm³
28 raw_number_concentration_pm0_5: u16 = u16::MAX => {
29 quantity: VolumetricNumberDensity,
30 unit: per_cubic_centimeter,
31 lsb: 1f64 / 10f64,
32 },
33 /// PM1 volumetric number density, LSB = 0.1 particles/cm³
34 raw_number_concentration_pm1: u16 = u16::MAX => {
35 quantity: VolumetricNumberDensity,
36 unit: per_cubic_centimeter,
37 lsb: 1f64 / 10f64,
38 },
39 /// PM2.5 volumetric number density, LSB = 0.1 particles/cm³
40 raw_number_concentration_pm2_5: u16 = u16::MAX => {
41 quantity: VolumetricNumberDensity,
42 unit: per_cubic_centimeter,
43 lsb: 1f64 / 10f64,
44 },
45 /// PM4 volumetric number density, LSB = 0.1 particles/cm³
46 raw_number_concentration_pm4: u16 = u16::MAX => {
47 quantity: VolumetricNumberDensity,
48 unit: per_cubic_centimeter,
49 lsb: 1f64 / 10f64,
50 },
51 /// PM10 volumetric number density, LSB = 0.1 particles/cm³
52 raw_number_concentration_pm10: u16 = u16::MAX => {
53 quantity: VolumetricNumberDensity,
54 unit: per_cubic_centimeter,
55 lsb: 1f64 / 10f64,
56 },
57 }
58
59 struct TemperatureOffsetParameters(size=8) {
60 /// Temperature offset, LSB = 0.005°C
61 raw_offset: i16 = 0 => {
62 quantity: ThermodynamicTemperature,
63 unit: degree_celsius,
64 lsb: 1f64 / 200f64,
65 },
66 /// Normalized temperature offset slope factor, LSB = 0.0001
67 slope: i16 = 0,
68 /// The time constant determines how fast the new slope and offset will be applied. After the
69 /// specified value in seconds, 63% of the new slope and offset are applied. A time constant of
70 /// zero means the new values will be applied immediately (within the next measure interval of
71 /// 1 second). LSB = 1 second.
72 raw_time_constant: u16 = 0 => {
73 quantity: Time,
74 unit: second,
75 lsb: 1f64 / 1f64,
76 },
77 /// The temperature offset slot to be modified. Valid values are 0 to 4. If the value is
78 /// outside this range, the parameters will not be applied.
79 slot: u16 = 0,
80 }
81
82 struct TemperatureAccelerationParameters(size=8) {
83 /// Filter constant K, LSB = 0.1
84 k: u16,
85 /// Filter constant P, LSB = 0.1
86 p: u16,
87 /// Filter constant T1, LSB = 0.1 second
88 raw_t1: u16 = 0 => {
89 quantity: Time,
90 unit: second,
91 lsb: 1f64 / 10f64,
92 },
93 /// Filter constant T2, LSB = 0.1 second
94 raw_t2: u16 = 0 => {
95 quantity: Time,
96 unit: second,
97 lsb: 1f64 / 10f64,
98 },
99 }
100
101 struct ProductName(size=32) {
102 /// Null-terminated ASCII string containing the product name.
103 name: [u8; 32],
104 }
105
106 struct SerialNumber(size=32) {
107 /// Null-terminated ASCII string containing the serial number.
108 serial_number: [u8; 32],
109 }
110
111 struct VOCAlgorithmTuningParameters(size=12) {
112 /// VOC index representing typical (average) conditions. Allowed values are in range 1-250.
113 /// The default value is 100.
114 index_offset: i16 = 100,
115 /// Time constant to estimate the VOC algorithm offset from the history in hours. Past events
116 /// will be forgotten after about twice the learning time. Allowed values are in range 1-1000.
117 /// The default value is 12 hours.
118 learning_time_offset_hours: i16 = 12,
119 /// Time constant to estimate the VOC algorithm gain from the history in hours. Past events
120 /// will be forgotten after about twice the learning time. Allowed values are in range 1-1000.
121 /// The default value is 12 hours.
122 learning_time_gain_hours: i16 = 12,
123 /// Maximum duration of gating in minutes (freeze of estimator during high VOC index signal).
124 /// Set to zero to disable the gating. Allowed values are in range 0-3000. The default value
125 /// is 180 minutes.
126 gating_max_duration_minutes: i16 = 180,
127 /// Initial estimate for standard deviation. Lower value boosts events during initial learning
128 /// period but may result in larger device-to-device variations. Allowed values are in range
129 /// 10-5000. The default value is 50.
130 std_initial: i16 = 50,
131 /// Gain factor to amplify or to attenuate the VOC index output. Allowed values are in range
132 /// 1-1000. The default value is 230.
133 gain_factor: i16 = 230,
134 }
135
136 struct VOCAlgorithmState(size=8) {
137 /// The opaque internal state.
138 state: [u8; 8],
139 }
140
141 struct NOxAlgorithmTuningParameters(size=12) {
142 /// NOx index representing typical (average) conditions. Allowed values are in range 1-250.
143 /// The default value is 1.
144 index_offset: i16 = 1,
145 /// Time constant to estimate the NOx algorithm offset from the history in hours. Past events
146 /// will be forgotten after about twice the learning time. Allowed values are in range 1-1000.
147 /// The default value is 12 hours.
148 learning_time_offset_hours: i16 = 12,
149 /// The time constant to estimate the NOx algorithm gain from the history has no impact for
150 /// NOx. This parameter is still in place for consistency reasons with the VOC tuning
151 /// parameters command. This parameter must always be set to 12 hours.
152 learning_time_gain_hours: i16 = 12,
153 /// Maximum duration of gating in minutes (freeze of estimator during high NOx index signal).
154 /// Set to zero to disable the gating. Allowed values are in range 0-3000. The default value
155 /// is 720 minutes.
156 gating_max_duration_minutes: i16 = 720,
157 /// The initial estimate for standard deviation parameter has no impact for NOx. This parameter
158 /// is still in place for consistency reasons with the VOC tuning parameters command. This
159 /// parameter must always be set to 50.
160 std_initial: i16 = 50,
161 /// Gain factor to amplify or to attenuate the NOx index output. Allowed values are in range
162 /// 1-1000. The default value is 230.
163 gain_factor: i16 = 230,
164 }
165
166 struct TargetCo2Concentration(size=2) {
167 /// Target co2 concentration of the test setup. LSB = 1 ppm.
168 raw_target_co2_concentration: u16 = 0 => {
169 quantity: Ratio,
170 unit: part_per_million,
171 lsb: 1f64 / 1f64,
172 },
173 }
174
175 struct Co2Correction(size=2) {
176 /// Correction value as received from the SCD in ppm. To get the FRC correction in ppm,
177 /// subtract `0x8000` from this value.
178 ///
179 /// If the recalibration has failed this value is 0xFFFF.
180 raw_correction: u16 = u16::MAX => {
181 quantity: Ratio,
182 unit: part_per_million,
183 from_raw: |x| (x - 0x8000) as f64,
184 into_raw: |x| x as u16 + 0x8000,
185 },
186 }
187
188 struct Co2SensorAutomaticSelfCalibration(size=2) {
189 _: u16{15},
190 /// Set to true to enable or false to disable the automatic CO2 measurement self-calibration
191 /// feature.
192 enable: bool,
193 }
194
195 struct AmbientPressure(size=2) {
196 /// Ambient pressure in hPa to be used for pressure compensation. LSB = 1 hPa.
197 raw_pressure: u16 = 1013 => {
198 quantity: Pressure,
199 unit: hectopascal,
200 lsb: 1f64 / 1f64,
201 },
202 }
203
204 struct SensorAltitude(size=2) {
205 /// Sensor altitude, valid input between 0 and 3000m. LSB = 1 meter.
206 raw_altitude: u16 = 0 => {
207 quantity: Length,
208 unit: meter,
209 lsb: 1f64 / 1f64,
210 },
211 }
212}
213
214define_sensirion_commands! {
215 id_len 2;
216 marker [
217 ("sensirion-sen63c", crate::devices::sensirion::sen63c::SEN63CCommand),
218 ("sensirion-sen65", crate::devices::sensirion::sen65::SEN65Command),
219 ("sensirion-sen66", crate::devices::sensirion::sen66::SEN66Command),
220 ("sensirion-sen68", crate::devices::sensirion::sen68::SEN68Command),
221 ];
222
223 /// Starts a continuous measurement. After starting the measurement, it takes some time (~1.1s)
224 /// until the first measurement results are available. You could poll with the command
225 /// [`GetDataReady`] to check when the results are ready to be read.
226 ///
227 /// Cannot be executed during measurement.
228 send 0x0021 time_ms=50 StartContinuousMeasurement();
229
230 /// Stops the measurement and returns to idle mode.
231 ///
232 /// May be executed during measurement.
233 send 0x0104 time_ms=1000 StopMeasurement();
234
235 /// This command can be used to check if new measurement results are ready to read. The data ready
236 /// flag is automatically reset after reading the measurement values
237 ///
238 /// May be executed during measurement.
239 read 0x0202 time_ms=20 GetDataReady() -> DataReady;
240
241 /// Returns the measured number concentration values. The command [`GetDataReady`] can be used to
242 /// check if new data is available since the last read operation. If no new data is available, the
243 /// previous values will be returned. If no data is available at all (e.g. measurement not running
244 /// for at least one second), all values will be at their upper limit (0xFFFF for u16, 0x7FFF for
245 /// i16).
246 ///
247 /// May be executed during measurement.
248 read 0x0316 time_ms=20 ReadNumberConcentrationValues() -> NumberConcentrationValues;
249
250 /// This command allows to compensate temperature effects of the design-in at customer side by
251 /// applying custom temperature offsets to the ambient temperature. The compensated ambient
252 /// temperature is calculated as follows:
253 ///
254 /// ```text
255 /// T_Ambient_Compensated = T_Ambient + (slope * T_Ambient) + offset
256 /// ```
257 ///
258 /// Where slope and offset are the values set with this command, smoothed with the specified time
259 /// constant. All temperatures (`T_Ambient_Compensated`, `T_Ambient` and `offset`) are represented
260 /// in °C. There are 5 temperature offset slots available that all contribute additively to
261 /// `T_Ambient_Compensated`. The default values for the temperature offset parameters are all zero,
262 /// meaning that `T_Ambient_Compensated` is equal to `T_Ambient` by default.
263 ///
264 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
265 /// value of zero after a device reset.
266 ///
267 /// May be executed during measurement.
268 write 0x60b2 time_ms=20 SetTemperatureOffsetParameters(TemperatureOffsetParameters);
269
270 /// This command allows to set custom temperature acceleration parameters of the RH/T engine. It
271 /// overwrites the default temperature acceleration parameters of the RH/T engine with custom
272 /// values.
273 ///
274 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
275 /// values after a device reset.
276 ///
277 /// Cannot be executed during measurement.
278 write 0x6100 time_ms=20 SetTemperatureAccelerationParameters(TemperatureAccelerationParameters);
279
280 /// Gets the product name from the device.
281 ///
282 /// May be executed during measurement.
283 read 0xd014 time_ms=20 GetProductName() -> ProductName;
284
285 /// Gets the serial number from the device.
286 ///
287 /// May be executed during measurement.
288 read 0xd033 time_ms=20 GetSerialNumber() -> SerialNumber;
289
290 /// Executes a reset on the device. This has the same effect as a power cycle.
291 ///
292 /// Cannot be executed during measurement.
293 send 0xd304 time_ms=20 DeviceReset();
294
295 /// This command triggers fan cleaning. The fan is set to the maximum speed for 10 seconds and then
296 /// automatically stopped. Wait at least 10s after this command before starting a measurement.
297 ///
298 /// Cannot be executed during measurement.
299 send 0x5607 time_ms=20 StartFanCleaning();
300
301 /// This command allows you to use the inbuilt heater in SHT sensor to reverse creep at high
302 /// humidity. This command activates the SHT sensor heater with 200mW for 1s. The heater is then
303 /// automatically deactivated again.
304 ///
305 /// Note: Wait at least 20s after this command before starting a measurement to get coherent
306 /// temperature values (heating consequence to disappear).
307 ///
308 /// Cannot be executed during measurement.
309 send 0x6765 time_ms=1300 ActivateSHTHeater();
310}
311
312define_sensirion_commands! {
313 id_len 2;
314 marker [
315 ("sensirion-sen65", crate::devices::sensirion::sen65::SEN65Command),
316 ("sensirion-sen66", crate::devices::sensirion::sen66::SEN66Command),
317 ("sensirion-sen68", crate::devices::sensirion::sen68::SEN68Command),
318 ];
319
320 /// Gets the parameters to customize the VOC algorithm.
321 ///
322 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
323 /// values after a device reset.
324 ///
325 /// Cannot be executed during measurement.
326 read 0x60d0 time_ms=20 GetVOCAlgorithmTuningParameters() -> VOCAlgorithmTuningParameters;
327
328 /// Sets the parameters to customize the VOC algorithm. Writing has no effect if at least one
329 /// parameter is outside the specified range.
330 ///
331 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
332 /// values after a device reset.
333 ///
334 /// Cannot be executed during measurement.
335 write 0x60d0 time_ms=20 SetVOCAlgorithmTuningParameters(VOCAlgorithmTuningParameters);
336
337 /// Allows backup/restore of the VOC algorithm state to resume operation after a power cycle or
338 /// device reset, skipping initial learning phase.
339 ///
340 /// By default, the VOC Engine is reset, and the algorithm state is retained if a measurement is
341 /// stopped and started again. If the VOC algorithm state shall be reset, a device reset, or a
342 /// power cycle can be executed.
343 ///
344 /// Reads the current VOC algorithm state. This data can be used to restore the state
345 /// with [`SetVOCAlgorithmState`] command after a short power cycle or device reset.
346 ///
347 /// This can be read either in measure mode or in idle mode (which will then return the state at
348 /// the time when the measurement was stopped). In measure mode, the state can be read each measure
349 /// interval to always have the latest state available, even in case of a sudden power loss.
350 ///
351 /// May be executed during measurement.
352 read 0x6181 time_ms=20 GetVOCAlgorithmState() -> VOCAlgorithmState;
353
354 /// Allows backup/restore of the VOC algorithm state to resume operation after a power cycle or
355 /// device reset, skipping initial learning phase.
356 ///
357 /// Writing is only possible in idle mode and the state will be applied only once when starting the
358 /// next measurement.
359 ///
360 /// Cannot be executed during measurement.
361 write 0x6181 time_ms=20 SetVOCAlgorithmState(VOCAlgorithmState);
362
363 /// Gets the parameters to customize the NOx algorithm.
364 ///
365 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
366 /// values after a device reset.
367 ///
368 /// Cannot be executed during measurement.
369 read 0x60e1 time_ms=20 GetNOxAlgorithmTuningParameters() -> NOxAlgorithmTuningParameters;
370
371 /// Sets the parameters to customize the NOx algorithm. Writing has no effect if at least one
372 /// parameter is outside the specified range.
373 ///
374 /// Note: This configuration is volatile, i.e. the parameters will be reverted to their default
375 /// values after a device reset.
376 ///
377 /// Cannot be executed during measurement.
378 write 0x60e1 time_ms=20 SetNOxAlgorithmTuningParameters(NOxAlgorithmTuningParameters);
379}
380
381define_sensirion_commands! {
382 id_len 2;
383 marker [
384 ("sensirion-sen63c", crate::devices::sensirion::sen63c::SEN63CCommand),
385 ("sensirion-sen66", crate::devices::sensirion::sen66::SEN66Command),
386 ];
387
388 /// Execute the forced recalibration (FRC) of the CO2 signal. Refer to the datasheet for additional
389 /// information on how this is to be used.
390 ///
391 /// Note: After power-on wait at least 1000 ms and after stopping a measurement 600 ms before
392 /// sending this command. The recalibration procedure will take about 500 ms to complete, during
393 /// which time no other functions can be executed.
394 ///
395 /// Cannot be executed during measurement.
396 write_read 0x6707 time_ms=500 PerformForcedCo2Recalibration(TargetCo2Concentration) -> Co2Correction;
397
398 /// Gets the status of the CO2 sensor automatic self-calibration (ASC). The CO2 sensor
399 /// supports automatic self-calibration (ASC) for long-term stability of the CO2 output. This
400 /// feature can be enabled or disabled. By default, it is enabled.
401 ///
402 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
403 /// after a device reset.
404 ///
405 /// Cannot be executed during measurement.
406 read 0x6711 time_ms=20 GetCo2SensorAutomaticSelfCalibration() -> Co2SensorAutomaticSelfCalibration;
407
408 /// Sets the status of the CO2 sensor automatic self-calibration (ASC). The CO2 sensor
409 /// supports automatic self-calibration (ASC) for long-term stability of the CO2 output. This
410 /// feature can be enabled or disabled. By default, it is enabled.
411 ///
412 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
413 /// after a device reset.
414 ///
415 /// Cannot be executed during measurement.
416 write 0x6711 time_ms=20 SetCo2SensorAutomaticSelfCalibration(Co2SensorAutomaticSelfCalibration);
417
418 /// Gets the ambient pressure value. The ambient pressure can be used for pressure
419 /// compensation in the CO2 sensor. Setting an ambient pressure overrides any pressure compensation
420 /// based on a previously set sensor altitude. Use of this command is recommended for applications
421 /// experiencing significant ambient pressure changes to ensure CO2 sensor accuracy. Valid input
422 /// values are between 700 to 1200 hPa. The default value is 1013 hPa.
423 ///
424 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
425 /// after a device reset.
426 ///
427 /// May be executed during measurement.
428 read 0x6720 time_ms=20 GetAmbientPressure() -> AmbientPressure;
429
430 /// Sets the ambient pressure value. The ambient pressure can be used for pressure
431 /// compensation in the CO2 sensor. Setting an ambient pressure overrides any pressure compensation
432 /// based on a previously set sensor altitude. Use of this command is recommended for applications
433 /// experiencing significant ambient pressure changes to ensure CO2 sensor accuracy. Valid input
434 /// values are between 700 to 1200 hPa. The default value is 1013 hPa.
435 ///
436 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
437 /// after a device reset.
438 ///
439 /// May be executed during measurement.
440 write 0x6720 time_ms=20 SetAmbientPressure(AmbientPressure);
441
442 /// Gets the current sensor altitude. The sensor altitude can be used for pressure
443 /// compensation in the CO2 sensor. The default sensor altitude value is set to 0 meters above sea
444 /// level. Valid input values are between 0 and 3000m.
445 ///
446 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
447 /// after a device reset.
448 ///
449 /// Cannot be executed during measurement.
450 read 0x6736 time_ms=20 GetSensorAltitude() -> SensorAltitude;
451
452 /// Sets the current sensor altitude. The sensor altitude can be used for pressure
453 /// compensation in the CO2 sensor. The default sensor altitude value is set to 0 meters above sea
454 /// level. Valid input values are between 0 and 3000m.
455 ///
456 /// Note: This configuration is volatile, i.e. the parameter will be reverted to its default values
457 /// after a device reset.
458 ///
459 /// Cannot be executed during measurement.
460 write 0x6736 time_ms=20 SetSensorAltitude(SensorAltitude);
461}