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