├── images
├── SEN5x.png
└── SEN5X_pinout.png
├── .github
└── workflows
│ ├── github_release.yml
│ └── arduino_quality_check.yml
├── library.properties
├── .clang-format
├── CHANGELOG.md
├── LICENSE
├── keywords.txt
├── .gitignore
├── README.md
├── examples
└── exampleUsage
│ └── exampleUsage.ino
└── src
├── SensirionI2CSen5x.cpp
└── SensirionI2CSen5x.h
/images/SEN5x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sensirion/arduino-i2c-sen5x/HEAD/images/SEN5x.png
--------------------------------------------------------------------------------
/images/SEN5X_pinout.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Sensirion/arduino-i2c-sen5x/HEAD/images/SEN5X_pinout.png
--------------------------------------------------------------------------------
/.github/workflows/github_release.yml:
--------------------------------------------------------------------------------
1 | name: Github Release
2 |
3 | on:
4 | push:
5 | tags:
6 | - '*'
7 |
8 | jobs:
9 | github-release:
10 | uses: sensirion/.github/.github/workflows/driver.common.github_release.yml@main
11 |
--------------------------------------------------------------------------------
/library.properties:
--------------------------------------------------------------------------------
1 | name=Sensirion I2C SEN5X
2 | version=0.3.0
3 | author=Sensirion
4 | maintainer=Sensirion
5 | sentence=Library for the SEN5X sensor family by Sensirion
6 | paragraph=Enables you to use the SEN50, SEN54 and SEN55 via I2C.
7 | url=https://github.com/Sensirion/arduino-i2c-sen5x
8 | category=Sensors
9 | depends=Sensirion Core
10 | includes=SensirionI2CSen5x.h
11 |
--------------------------------------------------------------------------------
/.github/workflows/arduino_quality_check.yml:
--------------------------------------------------------------------------------
1 | name: Quality check
2 |
3 | on:
4 | pull_request:
5 | branches:
6 | - master
7 | push:
8 | branches:
9 | - master
10 |
11 | jobs:
12 | arduino-quality:
13 | uses: sensirion/.github/.github/workflows/driver.arduino.check.yml@main
14 | with:
15 | expect-arduino-examples: true
16 | lint-lib-manager-check: update
17 |
--------------------------------------------------------------------------------
/.clang-format:
--------------------------------------------------------------------------------
1 | ---
2 | Language: Cpp
3 | BasedOnStyle: LLVM
4 | IndentWidth: 4
5 | AlignAfterOpenBracket: Align
6 | AllowShortBlocksOnASingleLine: false
7 | AllowShortCaseLabelsOnASingleLine: false
8 | AllowShortFunctionsOnASingleLine: false
9 | IndentCaseLabels: true
10 | SpacesBeforeTrailingComments: 2
11 | PointerAlignment: Left
12 | AlignEscapedNewlines: Left
13 | ForEachMacros: ['TEST_GROUP', 'TEST']
14 | ...
15 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 | All notable changes to this project will be documented in this file.
3 |
4 | The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
5 | and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6 |
7 | ## [Unreleased]
8 |
9 | ## [0.3.0] - 2023-01-19
10 |
11 | Fix scaling of typicalParticleSize for readMeasuredPmValues
12 | Fix comments for readMeasuredPmValuesAsIntegers
13 |
14 | ## [0.2.0] - 2022-03-30
15 |
16 | Add support for SEN50
17 |
18 | ## [0.1.0] - 2022-01-05
19 |
20 | Initial release
21 |
22 | [0.3.0]: https://github.com/Sensirion/embedded-i2c-sen5x/compare/0.2.0...0.3.0
23 | [0.2.0]: https://github.com/Sensirion/embedded-i2c-sen5x/compare/0.1.0...0.2.0
24 | [0.1.0]: https://github.com/Sensirion/arduino-i2c-sen5x/releases/tag/0.1.0
25 |
26 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2021, Sensirion AG
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | 1. Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | 2. Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | 3. Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/keywords.txt:
--------------------------------------------------------------------------------
1 | #######################################
2 | # Syntax Coloring Map
3 | #######################################
4 |
5 | #######################################
6 | # Datatypes (KEYWORD1)
7 | #######################################
8 |
9 | SensirionI2CSen5x KEYWORD1
10 |
11 | #######################################
12 | # Methods and Functions (KEYWORD2)
13 | #######################################
14 | startMeasurement KEYWORD2
15 | startMeasurementWithoutPm KEYWORD2
16 | stopMeasurement KEYWORD2
17 | readDataReady KEYWORD2
18 | readMeasuredValues KEYWORD2
19 | readMeasuredValuesAsIntegers KEYWORD2
20 | readMeasuredValuesSen50 KEYWORD2
21 | readMeasuredRawValues KEYWORD2
22 | readMeasuredPmValues KEYWORD2
23 | readMeasuredPmValuesAsIntegers KEYWORD2
24 | startFanCleaning KEYWORD2
25 | setTemperatureOffsetSimple KEYWORD2
26 | getTemperatureOffsetSimple KEYWORD2
27 | setTemperatureOffsetParameters KEYWORD2
28 | getTemperatureOffsetParameters KEYWORD2
29 | setWarmStartParameter KEYWORD2
30 | getWarmStartParameter KEYWORD2
31 | setVocAlgorithmTuningParameters KEYWORD2
32 | getVocAlgorithmTuningParameters KEYWORD2
33 | setNoxAlgorithmTuningParameters KEYWORD2
34 | getNoxAlgorithmTuningParameters KEYWORD2
35 | setRhtAccelerationMode KEYWORD2
36 | getRhtAccelerationMode KEYWORD2
37 | setVocAlgorithmState KEYWORD2
38 | getVocAlgorithmState KEYWORD2
39 | setFanAutoCleaningInterval KEYWORD2
40 | getFanAutoCleaningInterval KEYWORD2
41 | getProductName KEYWORD2
42 | getSerialNumber KEYWORD2
43 | getVersion KEYWORD2
44 | readDeviceStatus KEYWORD2
45 | readAndClearDeviceStatus KEYWORD2
46 | deviceReset KEYWORD2
47 | #######################################
48 | # Instances (KEYWORD2)
49 | #######################################
50 |
51 | sen5x KEYWORD2
52 |
53 | #######################################
54 | # Constants (LITERAL1)
55 | #######################################
56 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | app/bin/
2 | app/pde.jar
3 | build/macosx/work/
4 | arduino-core/bin/
5 | arduino-core/arduino-core.jar
6 | hardware/arduino/bootloaders/caterina_LUFA/Descriptors.o
7 | hardware/arduino/bootloaders/caterina_LUFA/Descriptors.lst
8 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.sym
9 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.o
10 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.map
11 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.lst
12 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.lss
13 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.elf
14 | hardware/arduino/bootloaders/caterina_LUFA/Caterina.eep
15 | hardware/arduino/bootloaders/caterina_LUFA/.dep/
16 | build/*.zip
17 | build/*.tar.bz2
18 | build/windows/work/
19 | build/windows/*.zip
20 | build/windows/*.tgz
21 | build/windows/*.tar.bz2
22 | build/windows/libastylej*
23 | build/windows/liblistSerials*
24 | build/windows/arduino-*.zip
25 | build/windows/dist/*.tar.gz
26 | build/windows/dist/*.tar.bz2
27 | build/windows/launch4j-*.tgz
28 | build/windows/launch4j-*.zip
29 | build/windows/launcher/launch4j
30 | build/windows/WinAVR-*.zip
31 | build/macosx/arduino-*.zip
32 | build/macosx/dist/*.tar.gz
33 | build/macosx/dist/*.tar.bz2
34 | build/macosx/*.tar.bz2
35 | build/macosx/libastylej*
36 | build/macosx/appbundler*.jar
37 | build/macosx/appbundler*.zip
38 | build/macosx/appbundler
39 | build/macosx/appbundler-1.0ea-arduino?
40 | build/macosx/appbundler-1.0ea-arduino*.zip
41 | build/macosx/appbundler-1.0ea-upstream*.zip
42 | build/linux/work/
43 | build/linux/dist/*.tar.gz
44 | build/linux/dist/*.tar.bz2
45 | build/linux/*.tgz
46 | build/linux/*.tar.xz
47 | build/linux/*.tar.bz2
48 | build/linux/*.zip
49 | build/linux/libastylej*
50 | build/linux/liblistSerials*
51 | build/shared/arduino-examples*
52 | build/shared/reference*.zip
53 | build/shared/Edison*.zip
54 | build/shared/Galileo*.zip
55 | build/shared/WiFi101-Updater-ArduinoIDE-Plugin*.zip
56 | test-bin
57 | *.iml
58 | .idea
59 | .DS_Store
60 | .directory
61 | hardware/arduino/avr/libraries/Bridge/examples/XivelyClient/passwords.h
62 | avr-toolchain-*.zip
63 | /app/nbproject/private/
64 | /arduino-core/nbproject/private/
65 | /app/build/
66 | /arduino-core/build/
67 |
68 | manifest.mf
69 | nbbuild.xml
70 | nbproject
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Sensirion I2C SEN5X Arduino Library
2 |
3 | This is the Sensirion SEN5X library for Arduino using the
4 | modules I2C interface.
5 |
6 |
7 |
8 | ## Supported sensors
9 |
10 | - SEN50 (only particulate matter signals available)
11 | - SEN54 (no NOx signal available)
12 | - SEN55 (full feature set)
13 |
14 | # Installation
15 |
16 | To install, download the latest release as .zip file and add it to your
17 | [Arduino IDE](http://www.arduino.cc/en/main/software) via
18 |
19 | Sketch => Include Library => Add .ZIP Library...
20 |
21 | Don't forget to **install the dependencies** listed below the same way via `Add
22 | .ZIP Library`
23 |
24 | Note: Installation via the Arduino Library Manager is coming soon.
25 |
26 | # Dependencies
27 |
28 | * [Sensirion Core](https://github.com/Sensirion/arduino-core)
29 |
30 |
31 | # Quick Start
32 |
33 | 1. Connect the SEN5X Sensor to your Arduino board's standard
34 | I2C bus. Check the pinout of your Arduino board to find the correct pins.
35 | The pinout of the SEN5X Sensor board can be found in the
36 | data sheet.
37 |
38 | | *SEN5X* | *Arduino* | *Jumper Wire* |
39 | | ------- | ----------- | ------------- |
40 | | VCC | 5V | Red |
41 | | GND | GND | Black |
42 | | SDA | SDA | Green |
43 | | SCL | SCL | Yellow |
44 | | SEL | GND for I2C | Blue |
45 |
46 |
47 |
48 | | *Pin* | *Name* | *Description* | *Comments* |
49 | | ----- | ------ | ------------------------------- | -------------------------------- |
50 | | 1 | VCC | Supply Voltage | 5V ±10% |
51 | | 2 | GND | Ground |
52 | | 3 | SDA | I2C: Serial data input / output | TTL 5V and LVTTL 3.3V compatible |
53 | | 4 | SCL | I2C: Serial clock input | TTL 5V and LVTTL 3.3V compatible |
54 | | 5 | SEL | Interface select | Pull to GND to select I2C |
55 | | 6 | NC | Do not connect |
56 |
57 | 2. Open the `exampleUsage` sample project within the Arduino IDE
58 |
59 | File => Examples => Sensirion I2C SEN5X => exampleUsage
60 |
61 | 3. Click the `Upload` button in the Arduino IDE or
62 |
63 | Sketch => Upload
64 |
65 | 4. When the upload process has finished, open the `Serial Monitor` or `Serial
66 | Plotter` via the `Tools` menu to observe the measurement values. Note that
67 | the `Baud Rate` in the corresponding window has to be set to `115200 baud`.
68 |
69 | # Contributing
70 |
71 | **Contributions are welcome!**
72 |
73 | We develop and test this driver using our company internal tools (version
74 | control, continuous integration, code review etc.) and automatically
75 | synchronize the master branch with GitHub. But this doesn't mean that we don't
76 | respond to issues or don't accept pull requests on GitHub. In fact, you're very
77 | welcome to open issues or create pull requests :)
78 |
79 | This Sensirion library uses
80 | [`clang-format`](https://releases.llvm.org/download.html) to standardize the
81 | formatting of all our `.cpp` and `.h` files. Make sure your contributions are
82 | formatted accordingly:
83 |
84 | The `-i` flag will apply the format changes to the files listed.
85 |
86 | ```bash
87 | clang-format -i src/*.cpp src/*.h
88 | ```
89 |
90 | Note that differences from this formatting will result in a failed build until
91 | they are fixed.
92 |
93 | # License
94 |
95 | See [LICENSE](LICENSE).
96 |
--------------------------------------------------------------------------------
/examples/exampleUsage/exampleUsage.ino:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * I2C-Generator: 0.3.0
4 | * Yaml Version: 2.1.3
5 | * Template Version: 0.7.0-112-g190ecaa
6 | */
7 | /*
8 | * Copyright (c) 2021, Sensirion AG
9 | * All rights reserved.
10 | *
11 | * Redistribution and use in source and binary forms, with or without
12 | * modification, are permitted provided that the following conditions are met:
13 | *
14 | * * Redistributions of source code must retain the above copyright notice, this
15 | * list of conditions and the following disclaimer.
16 | *
17 | * * Redistributions in binary form must reproduce the above copyright notice,
18 | * this list of conditions and the following disclaimer in the documentation
19 | * and/or other materials provided with the distribution.
20 | *
21 | * * Neither the name of Sensirion AG nor the names of its
22 | * contributors may be used to endorse or promote products derived from
23 | * this software without specific prior written permission.
24 | *
25 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
29 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 | * POSSIBILITY OF SUCH DAMAGE.
36 | */
37 |
38 | #include
39 | #include
40 | #include
41 |
42 | // The used commands use up to 48 bytes. On some Arduino's the default buffer
43 | // space is not large enough
44 | #define MAXBUF_REQUIREMENT 48
45 |
46 | #if (defined(I2C_BUFFER_LENGTH) && \
47 | (I2C_BUFFER_LENGTH >= MAXBUF_REQUIREMENT)) || \
48 | (defined(BUFFER_LENGTH) && BUFFER_LENGTH >= MAXBUF_REQUIREMENT)
49 | #define USE_PRODUCT_INFO
50 | #endif
51 |
52 | SensirionI2CSen5x sen5x;
53 |
54 | void printModuleVersions() {
55 | uint16_t error;
56 | char errorMessage[256];
57 |
58 | unsigned char productName[32];
59 | uint8_t productNameSize = 32;
60 |
61 | error = sen5x.getProductName(productName, productNameSize);
62 |
63 | if (error) {
64 | Serial.print("Error trying to execute getProductName(): ");
65 | errorToString(error, errorMessage, 256);
66 | Serial.println(errorMessage);
67 | } else {
68 | Serial.print("ProductName:");
69 | Serial.println((char*)productName);
70 | }
71 |
72 | uint8_t firmwareMajor;
73 | uint8_t firmwareMinor;
74 | bool firmwareDebug;
75 | uint8_t hardwareMajor;
76 | uint8_t hardwareMinor;
77 | uint8_t protocolMajor;
78 | uint8_t protocolMinor;
79 |
80 | error = sen5x.getVersion(firmwareMajor, firmwareMinor, firmwareDebug,
81 | hardwareMajor, hardwareMinor, protocolMajor,
82 | protocolMinor);
83 | if (error) {
84 | Serial.print("Error trying to execute getVersion(): ");
85 | errorToString(error, errorMessage, 256);
86 | Serial.println(errorMessage);
87 | } else {
88 | Serial.print("Firmware: ");
89 | Serial.print(firmwareMajor);
90 | Serial.print(".");
91 | Serial.print(firmwareMinor);
92 | Serial.print(", ");
93 |
94 | Serial.print("Hardware: ");
95 | Serial.print(hardwareMajor);
96 | Serial.print(".");
97 | Serial.println(hardwareMinor);
98 | }
99 | }
100 |
101 | void printSerialNumber() {
102 | uint16_t error;
103 | char errorMessage[256];
104 | unsigned char serialNumber[32];
105 | uint8_t serialNumberSize = 32;
106 |
107 | error = sen5x.getSerialNumber(serialNumber, serialNumberSize);
108 | if (error) {
109 | Serial.print("Error trying to execute getSerialNumber(): ");
110 | errorToString(error, errorMessage, 256);
111 | Serial.println(errorMessage);
112 | } else {
113 | Serial.print("SerialNumber:");
114 | Serial.println((char*)serialNumber);
115 | }
116 | }
117 |
118 | void setup() {
119 |
120 | Serial.begin(115200);
121 | while (!Serial) {
122 | delay(100);
123 | }
124 |
125 | Wire.begin();
126 |
127 | sen5x.begin(Wire);
128 |
129 | uint16_t error;
130 | char errorMessage[256];
131 | error = sen5x.deviceReset();
132 | if (error) {
133 | Serial.print("Error trying to execute deviceReset(): ");
134 | errorToString(error, errorMessage, 256);
135 | Serial.println(errorMessage);
136 | }
137 |
138 | // Print SEN55 module information if i2c buffers are large enough
139 | #ifdef USE_PRODUCT_INFO
140 | printSerialNumber();
141 | printModuleVersions();
142 | #endif
143 |
144 | // set a temperature offset in degrees celsius
145 | // Note: supported by SEN54 and SEN55 sensors
146 | // By default, the temperature and humidity outputs from the sensor
147 | // are compensated for the modules self-heating. If the module is
148 | // designed into a device, the temperature compensation might need
149 | // to be adapted to incorporate the change in thermal coupling and
150 | // self-heating of other device components.
151 | //
152 | // A guide to achieve optimal performance, including references
153 | // to mechanical design-in examples can be found in the app note
154 | // “SEN5x – Temperature Compensation Instruction” at www.sensirion.com.
155 | // Please refer to those application notes for further information
156 | // on the advanced compensation settings used
157 | // in `setTemperatureOffsetParameters`, `setWarmStartParameter` and
158 | // `setRhtAccelerationMode`.
159 | //
160 | // Adjust tempOffset to account for additional temperature offsets
161 | // exceeding the SEN module's self heating.
162 | float tempOffset = 0.0;
163 | error = sen5x.setTemperatureOffsetSimple(tempOffset);
164 | if (error) {
165 | Serial.print("Error trying to execute setTemperatureOffsetSimple(): ");
166 | errorToString(error, errorMessage, 256);
167 | Serial.println(errorMessage);
168 | } else {
169 | Serial.print("Temperature Offset set to ");
170 | Serial.print(tempOffset);
171 | Serial.println(" deg. Celsius (SEN54/SEN55 only");
172 | }
173 |
174 | // Start Measurement
175 | error = sen5x.startMeasurement();
176 | if (error) {
177 | Serial.print("Error trying to execute startMeasurement(): ");
178 | errorToString(error, errorMessage, 256);
179 | Serial.println(errorMessage);
180 | }
181 | }
182 |
183 | void loop() {
184 | uint16_t error;
185 | char errorMessage[256];
186 |
187 | delay(1000);
188 |
189 | // Read Measurement
190 | float massConcentrationPm1p0;
191 | float massConcentrationPm2p5;
192 | float massConcentrationPm4p0;
193 | float massConcentrationPm10p0;
194 | float ambientHumidity;
195 | float ambientTemperature;
196 | float vocIndex;
197 | float noxIndex;
198 |
199 | error = sen5x.readMeasuredValues(
200 | massConcentrationPm1p0, massConcentrationPm2p5, massConcentrationPm4p0,
201 | massConcentrationPm10p0, ambientHumidity, ambientTemperature, vocIndex,
202 | noxIndex);
203 |
204 | if (error) {
205 | Serial.print("Error trying to execute readMeasuredValues(): ");
206 | errorToString(error, errorMessage, 256);
207 | Serial.println(errorMessage);
208 | } else {
209 | Serial.print("MassConcentrationPm1p0:");
210 | Serial.print(massConcentrationPm1p0);
211 | Serial.print("\t");
212 | Serial.print("MassConcentrationPm2p5:");
213 | Serial.print(massConcentrationPm2p5);
214 | Serial.print("\t");
215 | Serial.print("MassConcentrationPm4p0:");
216 | Serial.print(massConcentrationPm4p0);
217 | Serial.print("\t");
218 | Serial.print("MassConcentrationPm10p0:");
219 | Serial.print(massConcentrationPm10p0);
220 | Serial.print("\t");
221 | Serial.print("AmbientHumidity:");
222 | if (isnan(ambientHumidity)) {
223 | Serial.print("n/a");
224 | } else {
225 | Serial.print(ambientHumidity);
226 | }
227 | Serial.print("\t");
228 | Serial.print("AmbientTemperature:");
229 | if (isnan(ambientTemperature)) {
230 | Serial.print("n/a");
231 | } else {
232 | Serial.print(ambientTemperature);
233 | }
234 | Serial.print("\t");
235 | Serial.print("VocIndex:");
236 | if (isnan(vocIndex)) {
237 | Serial.print("n/a");
238 | } else {
239 | Serial.print(vocIndex);
240 | }
241 | Serial.print("\t");
242 | Serial.print("NoxIndex:");
243 | if (isnan(noxIndex)) {
244 | Serial.println("n/a");
245 | } else {
246 | Serial.println(noxIndex);
247 | }
248 | }
249 | }
250 |
--------------------------------------------------------------------------------
/src/SensirionI2CSen5x.cpp:
--------------------------------------------------------------------------------
1 | /*
2 | * THIS FILE IS AUTOMATICALLY GENERATED
3 | *
4 | * I2C-Generator: 0.3.0
5 | * Yaml Version: 2.1.3
6 | * Template Version: 0.7.0-112-g190ecaa
7 | */
8 | /*
9 | * Copyright (c) 2021, Sensirion AG
10 | * All rights reserved.
11 | *
12 | * Redistribution and use in source and binary forms, with or without
13 | * modification, are permitted provided that the following conditions are met:
14 | *
15 | * * Redistributions of source code must retain the above copyright notice, this
16 | * list of conditions and the following disclaimer.
17 | *
18 | * * Redistributions in binary form must reproduce the above copyright notice,
19 | * this list of conditions and the following disclaimer in the documentation
20 | * and/or other materials provided with the distribution.
21 | *
22 | * * Neither the name of Sensirion AG nor the names of its
23 | * contributors may be used to endorse or promote products derived from
24 | * this software without specific prior written permission.
25 | *
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 | * POSSIBILITY OF SUCH DAMAGE.
37 | */
38 |
39 | #include "SensirionI2CSen5x.h"
40 | #include "Arduino.h"
41 | #include "SensirionCore.h"
42 | #include
43 | #include
44 |
45 | #define SEN5X_I2C_ADDRESS 0x69
46 | #define UINT_INVALID 0xFFFF
47 | #define INT_INVALID 0x7FFF
48 |
49 | SensirionI2CSen5x::SensirionI2CSen5x() {
50 | }
51 |
52 | void SensirionI2CSen5x::begin(TwoWire& i2cBus) {
53 | _i2cBus = &i2cBus;
54 | }
55 |
56 | uint16_t SensirionI2CSen5x::startMeasurement() {
57 | uint16_t error = 0;
58 | uint8_t buffer[2];
59 | SensirionI2CTxFrame txFrame =
60 | SensirionI2CTxFrame::createWithUInt16Command(0x21, buffer, 2);
61 |
62 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
63 | *_i2cBus);
64 | delay(50);
65 | return error;
66 | }
67 |
68 | uint16_t SensirionI2CSen5x::startMeasurementWithoutPm() {
69 | uint16_t error = 0;
70 | uint8_t buffer[2];
71 | SensirionI2CTxFrame txFrame =
72 | SensirionI2CTxFrame::createWithUInt16Command(0x37, buffer, 2);
73 |
74 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
75 | *_i2cBus);
76 | delay(50);
77 | return error;
78 | }
79 |
80 | uint16_t SensirionI2CSen5x::stopMeasurement() {
81 | uint16_t error = 0;
82 | uint8_t buffer[2];
83 | SensirionI2CTxFrame txFrame =
84 | SensirionI2CTxFrame::createWithUInt16Command(0x104, buffer, 2);
85 |
86 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
87 | *_i2cBus);
88 | delay(200);
89 | return error;
90 | }
91 |
92 | uint16_t SensirionI2CSen5x::readDataReady(bool& dataReady) {
93 | uint16_t error = 0;
94 | uint8_t buffer[3];
95 | SensirionI2CTxFrame txFrame =
96 | SensirionI2CTxFrame::createWithUInt16Command(0x202, buffer, 3);
97 |
98 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
99 | *_i2cBus);
100 | if (error) {
101 | return error;
102 | }
103 |
104 | delay(20);
105 |
106 | SensirionI2CRxFrame rxFrame(buffer, 3);
107 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 3,
108 | rxFrame, *_i2cBus);
109 | if (error) {
110 | return error;
111 | }
112 |
113 | uint8_t padding;
114 | error |= rxFrame.getUInt8(padding); // remove padding
115 | error |= rxFrame.getBool(dataReady);
116 | return error;
117 | }
118 |
119 | uint16_t SensirionI2CSen5x::readMeasuredValues(
120 | float& massConcentrationPm1p0, float& massConcentrationPm2p5,
121 | float& massConcentrationPm4p0, float& massConcentrationPm10p0,
122 | float& ambientHumidity, float& ambientTemperature, float& vocIndex,
123 | float& noxIndex) {
124 |
125 | uint16_t error = 0;
126 | uint16_t massConcentrationPm1p0Int;
127 | uint16_t massConcentrationPm2p5Int;
128 | uint16_t massConcentrationPm4p0Int;
129 | uint16_t massConcentrationPm10p0Int;
130 | int16_t ambientHumidityInt;
131 | int16_t ambientTemperatureInt;
132 | int16_t vocIndexInt;
133 | int16_t noxIndexInt;
134 |
135 | error = readMeasuredValuesAsIntegers(
136 | massConcentrationPm1p0Int, massConcentrationPm2p5Int,
137 | massConcentrationPm4p0Int, massConcentrationPm10p0Int,
138 | ambientHumidityInt, ambientTemperatureInt, vocIndexInt, noxIndexInt);
139 |
140 | if (error) {
141 | return error;
142 | }
143 |
144 | massConcentrationPm1p0 = massConcentrationPm1p0Int == UINT_INVALID
145 | ? NAN
146 | : massConcentrationPm1p0Int / 10.0f;
147 | massConcentrationPm2p5 = massConcentrationPm2p5Int == UINT_INVALID
148 | ? NAN
149 | : massConcentrationPm2p5Int / 10.0f;
150 | massConcentrationPm4p0 = massConcentrationPm4p0Int == UINT_INVALID
151 | ? NAN
152 | : massConcentrationPm4p0Int / 10.0f;
153 | massConcentrationPm10p0 = massConcentrationPm10p0Int == UINT_INVALID
154 | ? NAN
155 | : massConcentrationPm10p0Int / 10.0f;
156 | ambientHumidity =
157 | ambientHumidityInt == INT_INVALID ? NAN : ambientHumidityInt / 100.0f;
158 | ambientTemperature = ambientTemperatureInt == INT_INVALID
159 | ? NAN
160 | : ambientTemperatureInt / 200.0f;
161 | vocIndex = vocIndexInt == INT_INVALID ? NAN : vocIndexInt / 10.0f;
162 | noxIndex = noxIndexInt == INT_INVALID ? NAN : noxIndexInt / 10.0f;
163 |
164 | return NoError;
165 | }
166 |
167 | uint16_t SensirionI2CSen5x::readMeasuredValuesAsIntegers(
168 | uint16_t& massConcentrationPm1p0, uint16_t& massConcentrationPm2p5,
169 | uint16_t& massConcentrationPm4p0, uint16_t& massConcentrationPm10p0,
170 | int16_t& ambientHumidity, int16_t& ambientTemperature, int16_t& vocIndex,
171 | int16_t& noxIndex) {
172 | uint16_t error = 0;
173 | uint8_t buffer[24];
174 | SensirionI2CTxFrame txFrame =
175 | SensirionI2CTxFrame::createWithUInt16Command(0x3C4, buffer, 24);
176 |
177 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
178 | *_i2cBus);
179 | if (error) {
180 | return error;
181 | }
182 |
183 | delay(20);
184 |
185 | SensirionI2CRxFrame rxFrame(buffer, 24);
186 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 24,
187 | rxFrame, *_i2cBus);
188 | if (error) {
189 | return error;
190 | }
191 |
192 | error |= rxFrame.getUInt16(massConcentrationPm1p0);
193 | error |= rxFrame.getUInt16(massConcentrationPm2p5);
194 | error |= rxFrame.getUInt16(massConcentrationPm4p0);
195 | error |= rxFrame.getUInt16(massConcentrationPm10p0);
196 | error |= rxFrame.getInt16(ambientHumidity);
197 | error |= rxFrame.getInt16(ambientTemperature);
198 | error |= rxFrame.getInt16(vocIndex);
199 | error |= rxFrame.getInt16(noxIndex);
200 | return error;
201 | }
202 |
203 | uint16_t SensirionI2CSen5x::readMeasuredRawValues(int16_t& rawHumidity,
204 | int16_t& rawTemperature,
205 | uint16_t& rawVoc,
206 | uint16_t& rawNox) {
207 | uint16_t error = 0;
208 | uint8_t buffer[12];
209 | SensirionI2CTxFrame txFrame =
210 | SensirionI2CTxFrame::createWithUInt16Command(0x3D2, buffer, 12);
211 |
212 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
213 | *_i2cBus);
214 | if (error) {
215 | return error;
216 | }
217 |
218 | delay(20);
219 |
220 | SensirionI2CRxFrame rxFrame(buffer, 12);
221 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 12,
222 | rxFrame, *_i2cBus);
223 | if (error) {
224 | return error;
225 | }
226 |
227 | error |= rxFrame.getInt16(rawHumidity);
228 | error |= rxFrame.getInt16(rawTemperature);
229 | error |= rxFrame.getUInt16(rawVoc);
230 | error |= rxFrame.getUInt16(rawNox);
231 | return error;
232 | }
233 |
234 | uint16_t SensirionI2CSen5x::readMeasuredValuesSen50(
235 | float& massConcentrationPm1p0, float& massConcentrationPm2p5,
236 | float& massConcentrationPm4p0, float& massConcentrationPm10p0) {
237 |
238 | uint16_t error = 0;
239 | float ambientHumidityDummy;
240 | float ambientTemperatureDummy;
241 | float vocIndexDummy;
242 | float noxIndexDummy;
243 | error = readMeasuredValues(massConcentrationPm1p0, massConcentrationPm2p5,
244 | massConcentrationPm4p0, massConcentrationPm10p0,
245 | ambientHumidityDummy, ambientTemperatureDummy,
246 | vocIndexDummy, noxIndexDummy);
247 | return error;
248 | }
249 |
250 | uint16_t SensirionI2CSen5x::readMeasuredPmValues(
251 | float& massConcentrationPm1p0, float& massConcentrationPm2p5,
252 | float& massConcentrationPm4p0, float& massConcentrationPm10p0,
253 | float& numberConcentrationPm0p5, float& numberConcentrationPm1p0,
254 | float& numberConcentrationPm2p5, float& numberConcentrationPm4p0,
255 | float& numberConcentrationPm10p0, float& typicalParticleSize) {
256 |
257 | uint16_t error = 0;
258 | uint16_t massConcentrationPm1p0Int;
259 | uint16_t massConcentrationPm2p5Int;
260 | uint16_t massConcentrationPm4p0Int;
261 | uint16_t massConcentrationPm10p0Int;
262 | uint16_t numberConcentrationPm0p5Int;
263 | uint16_t numberConcentrationPm1p0Int;
264 | uint16_t numberConcentrationPm2p5Int;
265 | uint16_t numberConcentrationPm4p0Int;
266 | uint16_t numberConcentrationPm10p0Int;
267 | uint16_t typicalParticleSizeInt;
268 |
269 | error = readMeasuredPmValuesAsIntegers(
270 | massConcentrationPm1p0Int, massConcentrationPm2p5Int,
271 | massConcentrationPm4p0Int, massConcentrationPm10p0Int,
272 | numberConcentrationPm0p5Int, numberConcentrationPm1p0Int,
273 | numberConcentrationPm2p5Int, numberConcentrationPm4p0Int,
274 | numberConcentrationPm10p0Int, typicalParticleSizeInt);
275 |
276 | if (error) {
277 | return error;
278 | }
279 |
280 | massConcentrationPm1p0 = massConcentrationPm1p0Int == UINT_INVALID
281 | ? NAN
282 | : massConcentrationPm1p0Int / 10.0f;
283 | massConcentrationPm2p5 = massConcentrationPm2p5Int == UINT_INVALID
284 | ? NAN
285 | : massConcentrationPm2p5Int / 10.0f;
286 | massConcentrationPm4p0 = massConcentrationPm4p0Int == UINT_INVALID
287 | ? NAN
288 | : massConcentrationPm4p0Int / 10.0f;
289 | massConcentrationPm10p0 = massConcentrationPm10p0Int == UINT_INVALID
290 | ? NAN
291 | : massConcentrationPm10p0Int / 10.0f;
292 | numberConcentrationPm0p5 = numberConcentrationPm0p5Int == UINT_INVALID
293 | ? NAN
294 | : numberConcentrationPm0p5Int / 10.0f;
295 | numberConcentrationPm1p0 = numberConcentrationPm1p0Int == UINT_INVALID
296 | ? NAN
297 | : numberConcentrationPm1p0Int / 10.0f;
298 | numberConcentrationPm2p5 = numberConcentrationPm2p5Int == UINT_INVALID
299 | ? NAN
300 | : numberConcentrationPm2p5Int / 10.0f;
301 | numberConcentrationPm4p0 = numberConcentrationPm4p0Int == UINT_INVALID
302 | ? NAN
303 | : numberConcentrationPm4p0Int / 10.0f;
304 | numberConcentrationPm10p0 = numberConcentrationPm10p0Int == UINT_INVALID
305 | ? NAN
306 | : numberConcentrationPm10p0Int / 10.0f;
307 | typicalParticleSize = typicalParticleSizeInt == UINT_INVALID
308 | ? NAN
309 | : typicalParticleSizeInt / 1000.0f;
310 |
311 | return NoError;
312 | }
313 |
314 | uint16_t SensirionI2CSen5x::readMeasuredPmValuesAsIntegers(
315 | uint16_t& massConcentrationPm1p0, uint16_t& massConcentrationPm2p5,
316 | uint16_t& massConcentrationPm4p0, uint16_t& massConcentrationPm10p0,
317 | uint16_t& numberConcentrationPm0p5, uint16_t& numberConcentrationPm1p0,
318 | uint16_t& numberConcentrationPm2p5, uint16_t& numberConcentrationPm4p0,
319 | uint16_t& numberConcentrationPm10p0, uint16_t& typicalParticleSize) {
320 | uint16_t error = 0;
321 | uint8_t buffer[30];
322 | SensirionI2CTxFrame txFrame =
323 | SensirionI2CTxFrame::createWithUInt16Command(0x413, buffer, 30);
324 |
325 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
326 | *_i2cBus);
327 | if (error) {
328 | return error;
329 | }
330 |
331 | delay(20);
332 |
333 | SensirionI2CRxFrame rxFrame(buffer, 30);
334 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 30,
335 | rxFrame, *_i2cBus);
336 | if (error) {
337 | return error;
338 | }
339 |
340 | error |= rxFrame.getUInt16(massConcentrationPm1p0);
341 | error |= rxFrame.getUInt16(massConcentrationPm2p5);
342 | error |= rxFrame.getUInt16(massConcentrationPm4p0);
343 | error |= rxFrame.getUInt16(massConcentrationPm10p0);
344 | error |= rxFrame.getUInt16(numberConcentrationPm0p5);
345 | error |= rxFrame.getUInt16(numberConcentrationPm1p0);
346 | error |= rxFrame.getUInt16(numberConcentrationPm2p5);
347 | error |= rxFrame.getUInt16(numberConcentrationPm4p0);
348 | error |= rxFrame.getUInt16(numberConcentrationPm10p0);
349 | error |= rxFrame.getUInt16(typicalParticleSize);
350 | return error;
351 | }
352 |
353 | uint16_t SensirionI2CSen5x::startFanCleaning() {
354 | uint16_t error = 0;
355 | uint8_t buffer[2];
356 | SensirionI2CTxFrame txFrame =
357 | SensirionI2CTxFrame::createWithUInt16Command(0x5607, buffer, 2);
358 |
359 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
360 | *_i2cBus);
361 | delay(20);
362 | return error;
363 | }
364 |
365 | uint16_t SensirionI2CSen5x::setTemperatureOffsetSimple(float tempOffset) {
366 | int16_t defaultSlope = 0;
367 | uint16_t defaultTimeConstant = 0;
368 | int16_t tempOffsetTicks = static_cast(tempOffset * 200);
369 | return setTemperatureOffsetParameters(tempOffsetTicks, defaultSlope,
370 | defaultTimeConstant);
371 | }
372 |
373 | uint16_t SensirionI2CSen5x::getTemperatureOffsetSimple(float& tempOffset) {
374 | int16_t tempOffsetTicks;
375 | int16_t slope;
376 | uint16_t timeConstant;
377 | uint16_t error = 0;
378 |
379 | error =
380 | getTemperatureOffsetParameters(tempOffsetTicks, slope, timeConstant);
381 | if (error) {
382 | return error;
383 | }
384 |
385 | tempOffset = static_cast(tempOffsetTicks) / 200.0f;
386 |
387 | return NoError;
388 | }
389 |
390 | uint16_t SensirionI2CSen5x::setTemperatureOffsetParameters(
391 | int16_t tempOffset, int16_t slope, uint16_t timeConstant) {
392 | uint16_t error = 0;
393 | uint8_t buffer[11];
394 | SensirionI2CTxFrame txFrame =
395 | SensirionI2CTxFrame::createWithUInt16Command(0x60B2, buffer, 11);
396 |
397 | error |= txFrame.addInt16(tempOffset);
398 | error |= txFrame.addInt16(slope);
399 | error |= txFrame.addUInt16(timeConstant);
400 |
401 | if (error) {
402 | return error;
403 | }
404 |
405 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
406 | *_i2cBus);
407 | delay(20);
408 | return error;
409 | }
410 |
411 | uint16_t SensirionI2CSen5x::getTemperatureOffsetParameters(
412 | int16_t& tempOffset, int16_t& slope, uint16_t& timeConstant) {
413 | uint16_t error = 0;
414 | uint8_t buffer[9];
415 | SensirionI2CTxFrame txFrame =
416 | SensirionI2CTxFrame::createWithUInt16Command(0x60B2, buffer, 9);
417 |
418 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
419 | *_i2cBus);
420 | if (error) {
421 | return error;
422 | }
423 |
424 | delay(20);
425 |
426 | SensirionI2CRxFrame rxFrame(buffer, 9);
427 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 9,
428 | rxFrame, *_i2cBus);
429 | if (error) {
430 | return error;
431 | }
432 |
433 | error |= rxFrame.getInt16(tempOffset);
434 | error |= rxFrame.getInt16(slope);
435 | error |= rxFrame.getUInt16(timeConstant);
436 | return error;
437 | }
438 |
439 | uint16_t SensirionI2CSen5x::setWarmStartParameter(uint16_t warmStart) {
440 | uint16_t error = 0;
441 | uint8_t buffer[5];
442 | SensirionI2CTxFrame txFrame =
443 | SensirionI2CTxFrame::createWithUInt16Command(0x60C6, buffer, 5);
444 |
445 | error |= txFrame.addUInt16(warmStart);
446 |
447 | if (error) {
448 | return error;
449 | }
450 |
451 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
452 | *_i2cBus);
453 | delay(20);
454 | return error;
455 | }
456 |
457 | uint16_t SensirionI2CSen5x::getWarmStartParameter(uint16_t& warmStart) {
458 | uint16_t error = 0;
459 | uint8_t buffer[3];
460 | SensirionI2CTxFrame txFrame =
461 | SensirionI2CTxFrame::createWithUInt16Command(0x60C6, buffer, 3);
462 |
463 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
464 | *_i2cBus);
465 | if (error) {
466 | return error;
467 | }
468 |
469 | delay(20);
470 |
471 | SensirionI2CRxFrame rxFrame(buffer, 3);
472 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 3,
473 | rxFrame, *_i2cBus);
474 | if (error) {
475 | return error;
476 | }
477 |
478 | error |= rxFrame.getUInt16(warmStart);
479 | return error;
480 | }
481 |
482 | uint16_t SensirionI2CSen5x::setVocAlgorithmTuningParameters(
483 | int16_t indexOffset, int16_t learningTimeOffsetHours,
484 | int16_t learningTimeGainHours, int16_t gatingMaxDurationMinutes,
485 | int16_t stdInitial, int16_t gainFactor) {
486 | uint16_t error = 0;
487 | uint8_t buffer[20];
488 | SensirionI2CTxFrame txFrame =
489 | SensirionI2CTxFrame::createWithUInt16Command(0x60D0, buffer, 20);
490 |
491 | error |= txFrame.addInt16(indexOffset);
492 | error |= txFrame.addInt16(learningTimeOffsetHours);
493 | error |= txFrame.addInt16(learningTimeGainHours);
494 | error |= txFrame.addInt16(gatingMaxDurationMinutes);
495 | error |= txFrame.addInt16(stdInitial);
496 | error |= txFrame.addInt16(gainFactor);
497 |
498 | if (error) {
499 | return error;
500 | }
501 |
502 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
503 | *_i2cBus);
504 | delay(20);
505 | return error;
506 | }
507 |
508 | uint16_t SensirionI2CSen5x::getVocAlgorithmTuningParameters(
509 | int16_t& indexOffset, int16_t& learningTimeOffsetHours,
510 | int16_t& learningTimeGainHours, int16_t& gatingMaxDurationMinutes,
511 | int16_t& stdInitial, int16_t& gainFactor) {
512 | uint16_t error = 0;
513 | uint8_t buffer[18];
514 | SensirionI2CTxFrame txFrame =
515 | SensirionI2CTxFrame::createWithUInt16Command(0x60D0, buffer, 18);
516 |
517 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
518 | *_i2cBus);
519 | if (error) {
520 | return error;
521 | }
522 |
523 | delay(20);
524 |
525 | SensirionI2CRxFrame rxFrame(buffer, 18);
526 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 18,
527 | rxFrame, *_i2cBus);
528 | if (error) {
529 | return error;
530 | }
531 |
532 | error |= rxFrame.getInt16(indexOffset);
533 | error |= rxFrame.getInt16(learningTimeOffsetHours);
534 | error |= rxFrame.getInt16(learningTimeGainHours);
535 | error |= rxFrame.getInt16(gatingMaxDurationMinutes);
536 | error |= rxFrame.getInt16(stdInitial);
537 | error |= rxFrame.getInt16(gainFactor);
538 | return error;
539 | }
540 |
541 | uint16_t SensirionI2CSen5x::setNoxAlgorithmTuningParameters(
542 | int16_t indexOffset, int16_t learningTimeOffsetHours,
543 | int16_t learningTimeGainHours, int16_t gatingMaxDurationMinutes,
544 | int16_t stdInitial, int16_t gainFactor) {
545 | uint16_t error = 0;
546 | uint8_t buffer[20];
547 | SensirionI2CTxFrame txFrame =
548 | SensirionI2CTxFrame::createWithUInt16Command(0x60E1, buffer, 20);
549 |
550 | error |= txFrame.addInt16(indexOffset);
551 | error |= txFrame.addInt16(learningTimeOffsetHours);
552 | error |= txFrame.addInt16(learningTimeGainHours);
553 | error |= txFrame.addInt16(gatingMaxDurationMinutes);
554 | error |= txFrame.addInt16(stdInitial);
555 | error |= txFrame.addInt16(gainFactor);
556 |
557 | if (error) {
558 | return error;
559 | }
560 |
561 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
562 | *_i2cBus);
563 | delay(20);
564 | return error;
565 | }
566 |
567 | uint16_t SensirionI2CSen5x::getNoxAlgorithmTuningParameters(
568 | int16_t& indexOffset, int16_t& learningTimeOffsetHours,
569 | int16_t& learningTimeGainHours, int16_t& gatingMaxDurationMinutes,
570 | int16_t& stdInitial, int16_t& gainFactor) {
571 | uint16_t error = 0;
572 | uint8_t buffer[18];
573 | SensirionI2CTxFrame txFrame =
574 | SensirionI2CTxFrame::createWithUInt16Command(0x60E1, buffer, 18);
575 |
576 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
577 | *_i2cBus);
578 | if (error) {
579 | return error;
580 | }
581 |
582 | delay(20);
583 |
584 | SensirionI2CRxFrame rxFrame(buffer, 18);
585 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 18,
586 | rxFrame, *_i2cBus);
587 | if (error) {
588 | return error;
589 | }
590 |
591 | error |= rxFrame.getInt16(indexOffset);
592 | error |= rxFrame.getInt16(learningTimeOffsetHours);
593 | error |= rxFrame.getInt16(learningTimeGainHours);
594 | error |= rxFrame.getInt16(gatingMaxDurationMinutes);
595 | error |= rxFrame.getInt16(stdInitial);
596 | error |= rxFrame.getInt16(gainFactor);
597 | return error;
598 | }
599 |
600 | uint16_t SensirionI2CSen5x::setRhtAccelerationMode(uint16_t mode) {
601 | uint16_t error = 0;
602 | uint8_t buffer[5];
603 | SensirionI2CTxFrame txFrame =
604 | SensirionI2CTxFrame::createWithUInt16Command(0x60F7, buffer, 5);
605 |
606 | error |= txFrame.addUInt16(mode);
607 |
608 | if (error) {
609 | return error;
610 | }
611 |
612 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
613 | *_i2cBus);
614 | delay(20);
615 | return error;
616 | }
617 |
618 | uint16_t SensirionI2CSen5x::getRhtAccelerationMode(uint16_t& mode) {
619 | uint16_t error = 0;
620 | uint8_t buffer[3];
621 | SensirionI2CTxFrame txFrame =
622 | SensirionI2CTxFrame::createWithUInt16Command(0x60F7, buffer, 3);
623 |
624 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
625 | *_i2cBus);
626 | if (error) {
627 | return error;
628 | }
629 |
630 | delay(20);
631 |
632 | SensirionI2CRxFrame rxFrame(buffer, 3);
633 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 3,
634 | rxFrame, *_i2cBus);
635 | if (error) {
636 | return error;
637 | }
638 |
639 | error |= rxFrame.getUInt16(mode);
640 | return error;
641 | }
642 |
643 | uint16_t SensirionI2CSen5x::setVocAlgorithmState(const uint8_t state[],
644 | uint8_t stateSize) {
645 | uint16_t error = 0;
646 | uint8_t buffer[14];
647 | SensirionI2CTxFrame txFrame =
648 | SensirionI2CTxFrame::createWithUInt16Command(0x6181, buffer, 14);
649 |
650 | error |= txFrame.addBytes(state, stateSize);
651 |
652 | if (error) {
653 | return error;
654 | }
655 |
656 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
657 | *_i2cBus);
658 | delay(20);
659 | return error;
660 | }
661 |
662 | uint16_t SensirionI2CSen5x::getVocAlgorithmState(uint8_t state[],
663 | uint8_t stateSize) {
664 | uint16_t error = 0;
665 | uint8_t buffer[12];
666 | SensirionI2CTxFrame txFrame =
667 | SensirionI2CTxFrame::createWithUInt16Command(0x6181, buffer, 12);
668 |
669 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
670 | *_i2cBus);
671 | if (error) {
672 | return error;
673 | }
674 |
675 | delay(20);
676 |
677 | SensirionI2CRxFrame rxFrame(buffer, 12);
678 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 12,
679 | rxFrame, *_i2cBus);
680 | if (error) {
681 | return error;
682 | }
683 |
684 | error |= rxFrame.getBytes(state, stateSize);
685 | return error;
686 | }
687 |
688 | uint16_t SensirionI2CSen5x::setFanAutoCleaningInterval(uint32_t interval) {
689 | uint16_t error = 0;
690 | uint8_t buffer[8];
691 | SensirionI2CTxFrame txFrame =
692 | SensirionI2CTxFrame::createWithUInt16Command(0x8004, buffer, 8);
693 |
694 | error |= txFrame.addUInt32(interval);
695 |
696 | if (error) {
697 | return error;
698 | }
699 |
700 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
701 | *_i2cBus);
702 | delay(20);
703 | return error;
704 | }
705 |
706 | uint16_t SensirionI2CSen5x::getFanAutoCleaningInterval(uint32_t& interval) {
707 | uint16_t error = 0;
708 | uint8_t buffer[6];
709 | SensirionI2CTxFrame txFrame =
710 | SensirionI2CTxFrame::createWithUInt16Command(0x8004, buffer, 6);
711 |
712 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
713 | *_i2cBus);
714 | if (error) {
715 | return error;
716 | }
717 |
718 | delay(20);
719 |
720 | SensirionI2CRxFrame rxFrame(buffer, 6);
721 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 6,
722 | rxFrame, *_i2cBus);
723 | if (error) {
724 | return error;
725 | }
726 |
727 | error |= rxFrame.getUInt32(interval);
728 | return error;
729 | }
730 |
731 | uint16_t SensirionI2CSen5x::getProductName(unsigned char productName[],
732 | uint8_t productNameSize) {
733 | uint16_t error = 0;
734 | uint8_t buffer[48];
735 | SensirionI2CTxFrame txFrame =
736 | SensirionI2CTxFrame::createWithUInt16Command(0xD014, buffer, 48);
737 |
738 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
739 | *_i2cBus);
740 | if (error) {
741 | return error;
742 | }
743 |
744 | delay(50);
745 |
746 | SensirionI2CRxFrame rxFrame(buffer, 48);
747 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 48,
748 | rxFrame, *_i2cBus);
749 | if (error) {
750 | return error;
751 | }
752 |
753 | error |= rxFrame.getBytes(productName, productNameSize);
754 | return error;
755 | }
756 |
757 | uint16_t SensirionI2CSen5x::getSerialNumber(unsigned char serialNumber[],
758 | uint8_t serialNumberSize) {
759 | uint16_t error = 0;
760 | uint8_t buffer[48];
761 | SensirionI2CTxFrame txFrame =
762 | SensirionI2CTxFrame::createWithUInt16Command(0xD033, buffer, 48);
763 |
764 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
765 | *_i2cBus);
766 | if (error) {
767 | return error;
768 | }
769 |
770 | delay(50);
771 |
772 | SensirionI2CRxFrame rxFrame(buffer, 48);
773 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 48,
774 | rxFrame, *_i2cBus);
775 | if (error) {
776 | return error;
777 | }
778 |
779 | error |= rxFrame.getBytes(serialNumber, serialNumberSize);
780 | return error;
781 | }
782 |
783 | uint16_t
784 | SensirionI2CSen5x::getVersion(uint8_t& firmwareMajor, uint8_t& firmwareMinor,
785 | bool& firmwareDebug, uint8_t& hardwareMajor,
786 | uint8_t& hardwareMinor, uint8_t& protocolMajor,
787 | uint8_t& protocolMinor) {
788 | uint16_t error = 0;
789 | uint8_t buffer[12];
790 | SensirionI2CTxFrame txFrame =
791 | SensirionI2CTxFrame::createWithUInt16Command(0xD100, buffer, 12);
792 |
793 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
794 | *_i2cBus);
795 | if (error) {
796 | return error;
797 | }
798 |
799 | delay(20);
800 |
801 | SensirionI2CRxFrame rxFrame(buffer, 12);
802 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 12,
803 | rxFrame, *_i2cBus);
804 | if (error) {
805 | return error;
806 | }
807 |
808 | error |= rxFrame.getUInt8(firmwareMajor);
809 | error |= rxFrame.getUInt8(firmwareMinor);
810 | error |= rxFrame.getBool(firmwareDebug);
811 | error |= rxFrame.getUInt8(hardwareMajor);
812 | error |= rxFrame.getUInt8(hardwareMinor);
813 | error |= rxFrame.getUInt8(protocolMajor);
814 | error |= rxFrame.getUInt8(protocolMinor);
815 | uint8_t padding;
816 | error |= rxFrame.getUInt8(padding); // remove padding
817 | return error;
818 | }
819 |
820 | uint16_t SensirionI2CSen5x::readDeviceStatus(uint32_t& deviceStatus) {
821 | uint16_t error = 0;
822 | uint8_t buffer[6];
823 | SensirionI2CTxFrame txFrame =
824 | SensirionI2CTxFrame::createWithUInt16Command(0xD206, buffer, 6);
825 |
826 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
827 | *_i2cBus);
828 | if (error) {
829 | return error;
830 | }
831 |
832 | delay(20);
833 |
834 | SensirionI2CRxFrame rxFrame(buffer, 6);
835 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 6,
836 | rxFrame, *_i2cBus);
837 | if (error) {
838 | return error;
839 | }
840 |
841 | error |= rxFrame.getUInt32(deviceStatus);
842 | return error;
843 | }
844 |
845 | uint16_t SensirionI2CSen5x::readAndClearDeviceStatus(uint32_t& deviceStatus) {
846 | uint16_t error = 0;
847 | uint8_t buffer[6];
848 | SensirionI2CTxFrame txFrame =
849 | SensirionI2CTxFrame::createWithUInt16Command(0xD210, buffer, 6);
850 |
851 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
852 | *_i2cBus);
853 | if (error) {
854 | return error;
855 | }
856 |
857 | delay(20);
858 |
859 | SensirionI2CRxFrame rxFrame(buffer, 6);
860 | error = SensirionI2CCommunication::receiveFrame(SEN5X_I2C_ADDRESS, 6,
861 | rxFrame, *_i2cBus);
862 | if (error) {
863 | return error;
864 | }
865 |
866 | error |= rxFrame.getUInt32(deviceStatus);
867 | return error;
868 | }
869 |
870 | uint16_t SensirionI2CSen5x::deviceReset() {
871 | uint16_t error = 0;
872 | uint8_t buffer[2];
873 | SensirionI2CTxFrame txFrame =
874 | SensirionI2CTxFrame::createWithUInt16Command(0xD304, buffer, 2);
875 |
876 | error = SensirionI2CCommunication::sendFrame(SEN5X_I2C_ADDRESS, txFrame,
877 | *_i2cBus);
878 | delay(200);
879 | return error;
880 | }
881 |
--------------------------------------------------------------------------------
/src/SensirionI2CSen5x.h:
--------------------------------------------------------------------------------
1 | /*
2 | * THIS FILE IS AUTOMATICALLY GENERATED
3 | *
4 | * I2C-Generator: 0.3.0
5 | * Yaml Version: 2.1.3
6 | * Template Version: 0.7.0-112-g190ecaa
7 | */
8 | /*
9 | * Copyright (c) 2021, Sensirion AG
10 | * All rights reserved.
11 | *
12 | * Redistribution and use in source and binary forms, with or without
13 | * modification, are permitted provided that the following conditions are met:
14 | *
15 | * * Redistributions of source code must retain the above copyright notice, this
16 | * list of conditions and the following disclaimer.
17 | *
18 | * * Redistributions in binary form must reproduce the above copyright notice,
19 | * this list of conditions and the following disclaimer in the documentation
20 | * and/or other materials provided with the distribution.
21 | *
22 | * * Neither the name of Sensirion AG nor the names of its
23 | * contributors may be used to endorse or promote products derived from
24 | * this software without specific prior written permission.
25 | *
26 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
27 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
30 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 | * POSSIBILITY OF SUCH DAMAGE.
37 | */
38 |
39 | #ifndef SENSIRIONI2CSEN5X_H
40 | #define SENSIRIONI2CSEN5X_H
41 |
42 | #include
43 |
44 | #include
45 |
46 | class SensirionI2CSen5x {
47 |
48 | public:
49 | SensirionI2CSen5x();
50 | /**
51 | * begin() - Initializes the SensirionI2CSen5x class.
52 | *
53 | * @param i2cBus Arduino stream object to use for communication.
54 | *
55 | */
56 | void begin(TwoWire& i2cBus);
57 |
58 | /**
59 | * startMeasurement() - Starts a continuous measurement.
60 |
61 | * After starting the measurement, it takes some time (~1s) until the first
62 | * measurement results are available. You could poll with the command
63 | * 0x0202 \"Read Data Ready\" to check when the results are ready to read.
64 | *
65 | * If the device is in measure mode without particulate matter (low-power)
66 | * and the firmware version is at least 2.0, this command enables PM
67 | * measurement without affecting the already running RH/T/VOC/NOx
68 | * measurements (except that the \"data ready\"-flag will be cleared). In
69 | * previous firmware versions, this command is supported only in idle mode.
70 | *
71 | * @return 0 on success, an error code otherwise
72 | */
73 | uint16_t startMeasurement(void);
74 |
75 | /**
76 | * startMeasurementWithoutPm() - Starts a continuous measurement without PM.
77 | * Only humidity, temperature, VOC and NOx are available in this mode. Laser
78 | * and fan are switched off to keep power consumption low.
79 | *
80 | * After starting the measurement, it takes some time (~1s) until the first
81 | * measurement results are available. You could poll with the command
82 | * 0x0202 \"Read Data Ready\" to check when the results are ready to read.
83 | *
84 | * If the device is in measure mode with particulate matter (normal measure
85 | * mode) and the firmware version is at least 2.0, this command disables PM
86 | * measurement without affecting the already running RH/T/VOC/NOx
87 | * measurements (except that the \"data ready\"-flag will be cleared). In
88 | * previous firmware versions, this command is supported only in idle mode.
89 | *
90 | * Supported sensors: SEN54, SEN55
91 | *
92 | * @return 0 on success, an error code otherwise
93 | */
94 | uint16_t startMeasurementWithoutPm(void);
95 |
96 | /**
97 | * stopMeasurement() - Stops the measurement and returns to idle mode.
98 | *
99 | * If the device is already in idle mode, this command has no effect.
100 | *
101 | * @return 0 on success, an error code otherwise
102 | */
103 | uint16_t stopMeasurement(void);
104 |
105 | /**
106 | * readDataReady() - This command can be used to check if new measurement
107 | * results are ready to read. The data ready flag is automatically reset
108 | * after reading the measurement values with the 0x03.. \"Read Measured
109 | * Values\" commands.
110 | *
111 | * @note During fan (auto-)cleaning, no measurement data is available for
112 | * several seconds and thus this flag will not be set until cleaning has
113 | * finished. So please expect gaps of several seconds at any time if fan
114 | * auto-cleaning is enabled.
115 | *
116 | * @param padding Padding byte, always 0x00.
117 | *
118 | * @param dataReady True (0x01) if data is ready, False (0x00) if not. When
119 | * no measurement is running, False will be returned.
120 | *
121 | * @return 0 on success, an error code otherwise
122 | */
123 | uint16_t readDataReady(bool& dataReady);
124 |
125 | /**
126 | * readMeasuredValues() - Returns the measured values.
127 | *
128 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
129 | * data is available since the last read operation. If no new data is
130 | * available, the previous values will be returned again. If no data is
131 | * available at all (e.g. measurement not running for at least one
132 | * second), all values will be NAN.
133 | *
134 | * @param massConcentrationPm1p0 PM1.0 [µg/m³]
135 | * Note: If this value is unknown, NAN is returned.*
136 | *
137 | * @param massConcentrationPm2p5 PM2.5 [µg/m³]
138 | * Note: If this value is unknown, NAN is returned.*
139 | *
140 | * @param massConcentrationPm4p0 PM4.0 [µg/m³]
141 | * Note: If this value is unknown, NAN is returned.*
142 | *
143 | * @param massConcentrationPm10p0 PM10.0 [µg/m³]
144 | * Note: If this value is unknown, NAN is returned.*
145 | *
146 | * @param ambientHumidity RH [%]
147 | * Note: If this value is unknown, NAN is returned.*
148 | *
149 | * @param ambientTemperature T [°C]
150 | * Note: If this value is unknown, NAN is returned.*
151 | *
152 | * @param vocIndex VOC Index
153 | * Note: If this value is unknown, NAN is returned.*
154 | *
155 | * @param noxIndex NOx Index
156 | * Note: If this value is unknown, which is true for SEN54,
157 | * NAN is returned. During the first 10..11 seconds after
158 | * power-on or device reset, this value will be NAN as well.*
159 | *
160 | * @return 0 on success, an error code otherwise
161 | */
162 | uint16_t readMeasuredValues(float& massConcentrationPm1p0,
163 | float& massConcentrationPm2p5,
164 | float& massConcentrationPm4p0,
165 | float& massConcentrationPm10p0,
166 | float& ambientHumidity,
167 | float& ambientTemperature, float& vocIndex,
168 | float& noxIndex);
169 |
170 | /**
171 | * readMeasuredValuesAsIntegers() - Returns the measured values
172 | * without scaling factors applied.
173 | *
174 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
175 | * data is available since the last read operation. If no new data is
176 | * available, the previous values will be returned again. If no data is
177 | * available at all (e.g. measurement not running for at least one
178 | * second), all values will be at their upper limit (0xFFFF for `uint16`,
179 | * 0x7FFF for `int16`).
180 | *
181 | * @param massConcentrationPm1p0 Value is scaled with factor 10:
182 | * PM1.0 [µg/m³] = value / 10
183 | * Note: If this value is unknown, 0xFFFF is returned.*
184 | *
185 | * @param massConcentrationPm2p5 Value is scaled with factor 10:
186 | * PM2.5 [µg/m³] = value / 10
187 | * Note: If this value is unknown, 0xFFFF is returned.*
188 | *
189 | * @param massConcentrationPm4p0 Value is scaled with factor 10:
190 | * PM4.0 [µg/m³] = value / 10
191 | * Note: If this value is unknown, 0xFFFF is returned.*
192 | *
193 | * @param massConcentrationPm10p0 Value is scaled with factor 10:
194 | * PM10.0 [µg/m³] = value / 10
195 | * Note: If this value is unknown, 0xFFFF is returned.*
196 | *
197 | * @param ambientHumidity Value is scaled with factor 100:
198 | * RH [%] = value /100
199 | * Note: If this value is unknown, 0x7FFF is returned.*
200 | *
201 | * @param ambientTemperature Value is scaled with factor 200:
202 | * T [°C] = value / 200
203 | * Note: If this value is unknown, 0x7FFF is returned.*
204 | *
205 | * @param vocIndex Value is scaled with factor 10: VOC Index = value / 10
206 | * Note: If this value is unknown, 0x7FFF is returned.*
207 | *
208 | * @param noxIndex Value is scaled with factor 10: NOx Index = value / 10
209 | * Note: If this value is unknown, which is the case for SEN54,
210 | * 0x7FFF is returned. During the first 10..11 seconds after power-on
211 | * or device reset, this value will be 0x7FFF as well.*
212 | *
213 | * @return 0 on success, an error code otherwise
214 | */
215 | uint16_t readMeasuredValuesAsIntegers(uint16_t& massConcentrationPm1p0,
216 | uint16_t& massConcentrationPm2p5,
217 | uint16_t& massConcentrationPm4p0,
218 | uint16_t& massConcentrationPm10p0,
219 | int16_t& ambientHumidity,
220 | int16_t& ambientTemperature,
221 | int16_t& vocIndex, int16_t& noxIndex);
222 |
223 | /**
224 | * readMeasuredRawValues() - Returns the measured raw values.
225 | *
226 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
227 | * data is available since the last read operation. If no new data is
228 | * available, the previous values will be returned again. If no data
229 | * is available at all (e.g. measurement not running for at least one
230 | * second), all values will be at their upper limit (0xFFFF for `uint16`,
231 | * 0x7FFF for `int16`).
232 | *
233 | * Supported sensors: SEN54 (no NOx), SEN55
234 | *
235 | * @param rawHumidity Value is scaled with factor 100: RH [%] = value / 100
236 | * Note: If this value is unknown, 0x7FFF is returned.*
237 | *
238 | * @param rawTemperature Value is scaled with factor 200:
239 | * T [°C] = value / 200
240 | * Note: If this value is unknown, 0x7FFF is returned.*
241 | *
242 | * @param rawVoc Raw measured VOC ticks without scale factor.
243 | * Note: If this value is unknown, 0xFFFF is returned.*
244 | *
245 | * @param rawNox Raw measured NOx ticks without scale factor.
246 | * Note: If this value is unknown, which is the case for SEN54,
247 | * 0xFFFF is returned. During the first 10..11 seconds after power-on
248 | * or device reset, this value will be 0xFFFF as well.*
249 | *
250 | * @return 0 on success, an error code otherwise
251 | */
252 | uint16_t readMeasuredRawValues(int16_t& rawHumidity,
253 | int16_t& rawTemperature, uint16_t& rawVoc,
254 | uint16_t& rawNox);
255 |
256 | /**
257 | * readMeasuredValuesSen50() - Returns the measured values for SEN50.
258 | *
259 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
260 | * data is available since the last read operation. If no new data is
261 | * available, the previous values will be returned again. If no data is
262 | * available at all (e.g. measurement not running for at least one
263 | * second), all values will be NAN.
264 | *
265 | * @param massConcentrationPm1p0 PM1.0 [µg/m³]
266 | * Note: If this value is unknown, NAN is returned.*
267 | *
268 | * @param massConcentrationPm2p5 PM2.5 [µg/m³]
269 | * Note: If this value is unknown, NAN is returned.*
270 | *
271 | * @param massConcentrationPm4p0 PM4.0 [µg/m³]
272 | * Note: If this value is unknown, NAN is returned.*
273 | *
274 | * @param massConcentrationPm10p0 PM10.0 [µg/m³]
275 | * Note: If this value is unknown, NAN is returned.*
276 | *
277 | * @return 0 on success, an error code otherwise
278 | */
279 | uint16_t readMeasuredValuesSen50(float& massConcentrationPm1p0,
280 | float& massConcentrationPm2p5,
281 | float& massConcentrationPm4p0,
282 | float& massConcentrationPm10p0);
283 |
284 | /**
285 | * readMeasuredPmValues() - Returns the measured particulate matter values.
286 | *
287 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
288 | * data is available since the last read operation. If no new data is
289 | * available, the previous values will be returned again. If no data
290 | * is available at all (e.g. measurement not running for at least one
291 | * second), all values will be NAN.
292 | *
293 | * @param massConcentrationPm1p0 PM1.0 [µg/m³]
294 | * Note: If this value is unknown, NAN is returned.*
295 | *
296 | * @param massConcentrationPm2p5 PM2.5 [µg/m³]
297 | * Note: If this value is unknown, NAN is returned.*
298 | *
299 | * @param massConcentrationPm4p0 PM4.0 [µg/m³]
300 | * Note: If this value is unknown, NAN is returned.*
301 | *
302 | * @param massConcentrationPm10p0 PM10.0 [µg/m³]
303 | * Note: If this value is unknown, NAN is returned.*
304 | *
305 | * @param numberConcentrationPm0p5 PM0.5 [#/cm³]
306 | * Note: If this value is unknown, NAN is returned.*
307 | *
308 | * @param numberConcentrationPm1p0 PM1.0 [#/cm³]
309 | * Note: If this value is unknown, NAN is returned.*
310 | *
311 | * @param numberConcentrationPm2p5 PM2.5 [#/cm³]
312 | * Note: If this value is unknown, NAN is returned.*
313 | *
314 | * @param numberConcentrationPm4p0 PM4.0 [#/cm³]
315 | * Note: If this value is unknown, NAN is returned.*
316 | *
317 | * @param numberConcentrationPm10p0 PM10.0 [#/cm³]
318 | * Note: If this value is unknown, NAN is returned.*
319 | *
320 | * @param typicalParticleSize Size [µm]
321 | * Note: If this value is unknown, NAN is returned.*
322 | *
323 | * @return 0 on success, an error code otherwise
324 | */
325 | uint16_t readMeasuredPmValues(
326 | float& massConcentrationPm1p0, float& massConcentrationPm2p5,
327 | float& massConcentrationPm4p0, float& massConcentrationPm10p0,
328 | float& numberConcentrationPm0p5, float& numberConcentrationPm1p0,
329 | float& numberConcentrationPm2p5, float& numberConcentrationPm4p0,
330 | float& numberConcentrationPm10p0, float& typicalParticleSize);
331 |
332 | /**
333 | * readMeasuredPmValuesAsIntegers() - Returns the measured particulate
334 | * matter values.
335 | *
336 | * The command 0x0202 \"Read Data Ready\" can be used to check if new
337 | * data is available since the last read operation. If no new data is
338 | * available, the previous values will be returned again. If no data
339 | * is available at all (e.g. measurement not running for at least one
340 | * second), all values will be 0xFFFF.
341 | *
342 | * @param massConcentrationPm1p0 Value is scaled with factor 10:
343 | * PM1.0 [µg/m³] = value / 10
344 | * Note: If this value is unknown, 0xFFFF is returned.*
345 | *
346 | * @param massConcentrationPm2p5 Value is scaled with factor 10:
347 | * PM2.5 [µg/m³] = value / 10
348 | * Note: If this value is unknown, 0xFFFF is returned.*
349 | *
350 | * @param massConcentrationPm4p0 Value is scaled with factor 10:
351 | * PM4.0 [µg/m³] = value / 10
352 | * Note: If this value is unknown, 0xFFFF is returned.*
353 | *
354 | * @param massConcentrationPm10p0 Value is scaled with factor 10:
355 | * PM10.0 [µg/m³] = value / 10
356 | * Note: If this value is unknown, 0xFFFF is returned.*
357 | *
358 | * @param numberConcentrationPm0p5 Value is scaled with factor 10:
359 | * PM0.5 [#/cm³] = value / 10
360 | * Note: If this value is unknown, 0xFFFF is returned.*
361 | *
362 | * @param numberConcentrationPm1p0 Value is scaled with factor 10:
363 | * PM1.0 [#/cm³] = value / 10
364 | * Note: If this value is unknown, 0xFFFF is returned.*
365 | *
366 | * @param numberConcentrationPm2p5 Value is scaled with factor 10:
367 | * PM2.5 [#/cm³] = value / 10
368 | * Note: If this value is unknown, 0xFFFF is returned.*
369 | *
370 | * @param numberConcentrationPm4p0 Value is scaled with factor 10:
371 | * PM4.0 [#/cm³] = value / 10
372 | * Note: If this value is unknown, 0xFFFF is returned.*
373 | *
374 | * @param numberConcentrationPm10p0 Value is scaled with factor 10:
375 | * PM10.0 [#/cm³] = value / 10
376 | * Note: If this value is unknown, 0xFFFF is returned.*
377 | *
378 | * @param typicalParticleSize Value is scaled with factor 1000:
379 | * Size [µm] = value / 1000
380 | * Note: If this value is unknown, 0xFFFF is returned.*
381 | *
382 | * @return 0 on success, an error code otherwise
383 | */
384 | uint16_t readMeasuredPmValuesAsIntegers(
385 | uint16_t& massConcentrationPm1p0, uint16_t& massConcentrationPm2p5,
386 | uint16_t& massConcentrationPm4p0, uint16_t& massConcentrationPm10p0,
387 | uint16_t& numberConcentrationPm0p5, uint16_t& numberConcentrationPm1p0,
388 | uint16_t& numberConcentrationPm2p5, uint16_t& numberConcentrationPm4p0,
389 | uint16_t& numberConcentrationPm10p0, uint16_t& typicalParticleSize);
390 |
391 | /**
392 | * startFanCleaning() - Starts the fan cleaning manually. The \"data
393 | * ready\"-flag will be cleared immediately and during the next few seconds,
394 | * no new measurement results will be available (old values will be
395 | * returned). Once the cleaning is finished, the \"data ready\"-flag will be
396 | * set and new measurement results will be available.
397 | *
398 | * When executing this command while cleaning is already active, the
399 | * command does nothing.
400 | *
401 | * If you stop the measurement while fan cleaning is active, the cleaning
402 | * will be aborted immediately.
403 | *
404 | * @note This command is only available in measure mode with PM measurement
405 | * enabled, i.e. only if the fan is already running. In any other state,
406 | * this command does nothing.
407 | *
408 | * @return 0 on success, an error code otherwise
409 | */
410 | uint16_t startFanCleaning(void);
411 |
412 | /**
413 | * setTemperatureOffsetSimple() - Sets the temperature offset parameter
414 | * in degrees celsius for the device, while leaving the other parameters at
415 | * their default setting.
416 | *
417 | * Supported sensors: SEN54, SEN55
418 | *
419 | * @param tempOffset Constant temperature offset in degrees celsius.
420 | * The default value is 0.
421 | *
422 | * @return 0 on success, an error code otherwise
423 | */
424 | uint16_t setTemperatureOffsetSimple(float tempOffset);
425 |
426 | /**
427 | * getTemperatureOffsetSimple() - Gets the temperature offset parameter
428 | * in degrees celsius from the device.
429 | * @note The other parameters, such as slope and time constant may differ
430 | * from the default values, if they were previously set using
431 | * `setTemperatureOffsetParameters`.
432 | *
433 | * Supported sensors: SEN54, SEN55
434 | *
435 | * @param tempOffset Constant temperature offset in degrees celsius.
436 | *
437 | * @return 0 on success, an error code otherwise
438 | */
439 | uint16_t getTemperatureOffsetSimple(float& tempOffset);
440 |
441 | /**
442 | * setTemperatureOffsetParameters() - Sets the temperature offset parameters
443 | * for the device.
444 | *
445 | * Supported sensors: SEN54, SEN55
446 | *
447 | * @param tempOffset Constant temperature offset scaled with factor 200 (T
448 | * [°C] = value / 200). The default value is 0.
449 | *
450 | * @param slope Normalized temperature offset slope scaled with factor 10000
451 | * (applied factor = value / 10000). The default value is 0.
452 | *
453 | * @param timeConstant Time constant [s] how fast the new slope and offset
454 | * will be applied. After the specified value in seconds, 63% of the new
455 | * slope and offset are applied. A time constant of zero means the new
456 | * values will be applied immediately (within the next measure interval of 1
457 | * second).
458 | *
459 | * @return 0 on success, an error code otherwise
460 | */
461 | uint16_t setTemperatureOffsetParameters(int16_t tempOffset, int16_t slope,
462 | uint16_t timeConstant);
463 |
464 | /**
465 | * getTemperatureOffsetParameters() - Gets the temperature offset parameters
466 | * from the device.
467 | *
468 | * Supported sensors: SEN54, SEN55
469 | *
470 | * @param tempOffset Constant temperature offset scaled with factor 200 (T
471 | * [°C] = value / 200).
472 | *
473 | * @param slope Normalized temperature offset slope scaled with factor 10000
474 | * (applied factor = value / 10000).
475 | *
476 | * @param timeConstant Time constant [s] how fast the slope and offset are
477 | * applied. After the specified value in seconds, 63% of the new slope and
478 | * offset are applied.
479 | *
480 | * @return 0 on success, an error code otherwise
481 | */
482 | uint16_t getTemperatureOffsetParameters(int16_t& tempOffset, int16_t& slope,
483 | uint16_t& timeConstant);
484 |
485 | /**
486 | * setWarmStartParameter() - Sets the warm start parameter for the device.
487 | *
488 | * Supported sensors: SEN54, SEN55
489 | *
490 | * @note This parameter can be changed in any state of the device (and the
491 | * getter immediately returns the new value), but it is applied only the
492 | * next time starting a measurement, i.e. when sending a \"Start
493 | * Measurement\" command! So the parameter needs to be set *before* a
494 | * warm-start measurement is started.
495 | *
496 | * @param warmStart Warm start behavior as a value in the range from 0 (cold
497 | * start) to 65535 (warm start). The default value is 0.
498 | *
499 | * @return 0 on success, an error code otherwise
500 | */
501 | uint16_t setWarmStartParameter(uint16_t warmStart);
502 |
503 | /**
504 | * getWarmStartParameter() - Gets the warm start parameter from the device.
505 | *
506 | * Supported sensors: SEN54, SEN55
507 | *
508 | * @param warmStart Warm start behavior as a value in the range from 0 (cold
509 | * start) to 65535 (warm start).
510 | *
511 | * @return 0 on success, an error code otherwise
512 | */
513 | uint16_t getWarmStartParameter(uint16_t& warmStart);
514 |
515 | /**
516 | * setVocAlgorithmTuningParameters() - Sets the tuning parameters of the VOC
517 | * algorithm.
518 | *
519 | * Supported sensors: SEN54, SEN55
520 | *
521 | * @note This command is available only in idle mode. In measure mode, this
522 | * command has no effect. In addition, it has no effect if at least one
523 | * parameter is outside the specified range.
524 | *
525 | * @param indexOffset VOC index representing typical (average) conditions.
526 | * Allowed values are in range 1..250. The default value is 100.
527 | *
528 | * @param learningTimeOffsetHours Time constant to estimate the VOC
529 | * algorithm offset from the history in hours. Past events will be forgotten
530 | * after about twice the learning time. Allowed values are in range 1..1000.
531 | * The default value is 12 hours.
532 | *
533 | * @param learningTimeGainHours Time constant to estimate the VOC algorithm
534 | * gain from the history in hours. Past events will be forgotten after about
535 | * twice the learning time. Allowed values are in range 1..1000. The default
536 | * value is 12 hours.
537 | *
538 | * @param gatingMaxDurationMinutes Maximum duration of gating in minutes
539 | * (freeze of estimator during high VOC index signal). Set to zero to
540 | * disable the gating. Allowed values are in range 0..3000. The default
541 | * value is 180 minutes.
542 | *
543 | * @param stdInitial Initial estimate for standard deviation. Lower value
544 | * boosts events during initial learning period, but may result in larger
545 | * device-to-device variations. Allowed values are in range 10..5000. The
546 | * default value is 50.
547 | *
548 | * @param gainFactor Gain factor to amplify or to attenuate the VOC index
549 | * output. Allowed values are in range 1..1000. The default value is 230.
550 | *
551 | * @return 0 on success, an error code otherwise
552 | */
553 | uint16_t setVocAlgorithmTuningParameters(int16_t indexOffset,
554 | int16_t learningTimeOffsetHours,
555 | int16_t learningTimeGainHours,
556 | int16_t gatingMaxDurationMinutes,
557 | int16_t stdInitial,
558 | int16_t gainFactor);
559 |
560 | /**
561 | * getVocAlgorithmTuningParameters() - Gets the currently set tuning
562 | * parameters of the VOC algorithm.
563 | *
564 | * Supported sensors: SEN54, SEN55
565 | *
566 | * @param indexOffset VOC index representing typical (average) conditions.
567 | *
568 | * @param learningTimeOffsetHours Time constant to estimate the VOC
569 | * algorithm offset from the history in hours. Past events will be forgotten
570 | * after about twice the learning time.
571 | *
572 | * @param learningTimeGainHours Time constant to estimate the VOC algorithm
573 | * gain from the history in hours. Past events will be forgotten after about
574 | * twice the learning time.
575 | *
576 | * @param gatingMaxDurationMinutes Maximum duration of gating in minutes
577 | * (freeze of estimator during high VOC index signal). Zero disables the
578 | * gating.
579 | *
580 | * @param stdInitial Initial estimate for standard deviation. Lower value
581 | * boosts events during initial learning period, but may result in larger
582 | * device-to-device variations.
583 | *
584 | * @param gainFactor Gain factor to amplify or to attenuate the VOC index
585 | * output.
586 | *
587 | * @return 0 on success, an error code otherwise
588 | */
589 | uint16_t getVocAlgorithmTuningParameters(int16_t& indexOffset,
590 | int16_t& learningTimeOffsetHours,
591 | int16_t& learningTimeGainHours,
592 | int16_t& gatingMaxDurationMinutes,
593 | int16_t& stdInitial,
594 | int16_t& gainFactor);
595 |
596 | /**
597 | * setNoxAlgorithmTuningParameters() - Sets the tuning parameters of the NOx
598 | * algorithm.
599 | *
600 | * Supported sensors: SEN55
601 | *
602 | * @note This command is available only in idle mode. In measure mode, this
603 | * command has no effect. In addition, it has no effect if at least one
604 | * parameter is outside the specified range.
605 | *
606 | * @param indexOffset NOx index representing typical (average) conditions.
607 | * Allowed values are in range 1..250. The default value is 1.
608 | *
609 | * @param learningTimeOffsetHours Time constant to estimate the NOx
610 | * algorithm offset from the history in hours. Past events will be forgotten
611 | * after about twice the learning time. Allowed values are in range 1..1000.
612 | * The default value is 12 hours.
613 | *
614 | * @param learningTimeGainHours The time constant to estimate the NOx
615 | * algorithm gain from the history has no impact for NOx. This parameter is
616 | * still in place for consistency reasons with the VOC tuning parameters
617 | * command. This parameter must always be set to 12 hours.
618 | *
619 | * @param gatingMaxDurationMinutes Maximum duration of gating in minutes
620 | * (freeze of estimator during high NOx index signal). Set to zero to
621 | * disable the gating. Allowed values are in range 0..3000. The default
622 | * value is 720 minutes.
623 | *
624 | * @param stdInitial The initial estimate for standard deviation parameter
625 | * has no impact for NOx. This parameter is still in place for consistency
626 | * reasons with the VOC tuning parameters command. This parameter must
627 | * always be set to 50.
628 | *
629 | * @param gainFactor Gain factor to amplify or to attenuate the NOx index
630 | * output. Allowed values are in range 1..1000. The default value is 230.
631 | *
632 | * @return 0 on success, an error code otherwise
633 | */
634 | uint16_t setNoxAlgorithmTuningParameters(int16_t indexOffset,
635 | int16_t learningTimeOffsetHours,
636 | int16_t learningTimeGainHours,
637 | int16_t gatingMaxDurationMinutes,
638 | int16_t stdInitial,
639 | int16_t gainFactor);
640 |
641 | /**
642 | * getNoxAlgorithmTuningParameters() - Gets the currently set tuning
643 | * parameters of the NOx algorithm.
644 | *
645 | * Supported sensors: SEN55
646 | *
647 | * @param indexOffset NOx index representing typical (average) conditions.
648 | *
649 | * @param learningTimeOffsetHours Time constant to estimate the NOx
650 | * algorithm offset from the history in hours. Past events will be forgotten
651 | * after about twice the learning time.
652 | *
653 | * @param learningTimeGainHours The time constant to estimate the NOx
654 | * algorithm gain from the history has no impact for NOx. This parameter is
655 | * still in place for consistency reasons with the VOC tuning parameters
656 | * command.
657 | *
658 | * @param gatingMaxDurationMinutes Maximum duration of gating in minutes
659 | * (freeze of estimator during high NOx index signal). Zero disables the
660 | * gating.
661 | *
662 | * @param stdInitial The initial estimate for standard deviation has no
663 | * impact for NOx. This parameter is still in place for consistency reasons
664 | * with the VOC tuning parameters command.
665 | *
666 | * @param gainFactor Gain factor to amplify or to attenuate the NOx index
667 | * output.
668 | *
669 | * @return 0 on success, an error code otherwise
670 | */
671 | uint16_t getNoxAlgorithmTuningParameters(int16_t& indexOffset,
672 | int16_t& learningTimeOffsetHours,
673 | int16_t& learningTimeGainHours,
674 | int16_t& gatingMaxDurationMinutes,
675 | int16_t& stdInitial,
676 | int16_t& gainFactor);
677 |
678 | /**
679 | * setRhtAccelerationMode() - Sets the RH/T acceleration mode.
680 | *
681 | * Supported sensors: SEN54, SEN55
682 | *
683 | * @note This parameter can be changed in any state of the device (and the
684 | * getter immediately returns the new value), but it is applied only the
685 | * next time starting a measurement, i.e. when sending a \"Start
686 | * Measurement\" command. So the parameter needs to be set *before* a new
687 | * measurement is started.
688 | *
689 | * @param mode The new RH/T acceleration mode.
690 | *
691 | * @return 0 on success, an error code otherwise
692 | */
693 | uint16_t setRhtAccelerationMode(uint16_t mode);
694 |
695 | /**
696 | * getRhtAccelerationMode() - Gets the RH/T acceleration mode.
697 | *
698 | * Supported sensors: SEN54, SEN55
699 | *
700 | * @param mode The current RH/T acceleration mode.
701 | *
702 | * @return 0 on success, an error code otherwise
703 | */
704 | uint16_t getRhtAccelerationMode(uint16_t& mode);
705 |
706 | /**
707 | * setVocAlgorithmState() - Sets the VOC algorithm state previously received
708 | * with the \"Get VOC Algorithm State\" command.
709 | *
710 | * Supported sensors: SEN54, SEN55
711 | *
712 | * @note This command is only available in idle mode and the state will be
713 | * applied only once when starting the next measurement. Any further
714 | * measurements (i.e. when stopping and restarting the measure mode) will
715 | * reset the state to initial values. In measure mode, this command has no
716 | * effect.
717 | *
718 | * @param state VOC algorithm state to restore.
719 | *
720 | * @return 0 on success, an error code otherwise
721 | */
722 | uint16_t setVocAlgorithmState(const uint8_t state[], uint8_t stateSize);
723 |
724 | /**
725 | * getVocAlgorithmState() - Gets the current VOC algorithm state. This data
726 | * can be used to restore the state with the \"Set VOC Algorithm State\"
727 | * command after a short power cycle or device reset.
728 | *
729 | * This command can be used either in measure mode or in idle mode
730 | * (which will then return the state at the time when the measurement
731 | * was stopped). In measure mode, the state can be read each measure
732 | * interval to always have the latest state available, even in case of
733 | * a sudden power loss.
734 | *
735 | * Supported sensors: SEN54, SEN55
736 | *
737 | * @param state Current VOC algorithm state.
738 | *
739 | * @return 0 on success, an error code otherwise
740 | */
741 | uint16_t getVocAlgorithmState(uint8_t state[], uint8_t stateSize);
742 |
743 | /**
744 | * setFanAutoCleaningInterval() - Sets the fan auto cleaning interval for
745 | * the device.
746 | *
747 | * @param interval Fan auto cleaning interval [s]. Set to zero to disable
748 | * auto cleaning.
749 | *
750 | * @return 0 on success, an error code otherwise
751 | */
752 | uint16_t setFanAutoCleaningInterval(uint32_t interval);
753 |
754 | /**
755 | * getFanAutoCleaningInterval() - Gets the fan auto cleaning interval from
756 | * the device.
757 | *
758 | * @param interval Fan auto cleaning interval [s]. Zero means auto cleaning
759 | * is disabled.
760 | *
761 | * @return 0 on success, an error code otherwise
762 | */
763 | uint16_t getFanAutoCleaningInterval(uint32_t& interval);
764 |
765 | /**
766 | * getProductName() - Gets the product name from the device.
767 | *
768 | * @param productName Null-terminated ASCII string containing the product
769 | * name. Up to 32 characters can be read from the device.
770 | *
771 | * @return 0 on success, an error code otherwise
772 | */
773 | uint16_t getProductName(unsigned char productName[],
774 | uint8_t productNameSize);
775 |
776 | /**
777 | * getSerialNumber() - Gets the serial number from the device.
778 | *
779 | * @param serialNumber Null-terminated ASCII string containing the serial
780 | * number. Up to 32 characters can be read from the device.
781 | *
782 | * @return 0 on success, an error code otherwise
783 | */
784 | uint16_t getSerialNumber(unsigned char serialNumber[],
785 | uint8_t serialNumberSize);
786 |
787 | /**
788 | * getVersion() - Gets the version information for the hardware, firmware
789 | * and communication protocol.
790 | *
791 | * @param firmwareMajor Firmware major version number.
792 | *
793 | * @param firmwareMinor Firmware minor version number.
794 | *
795 | * @param firmwareDebug Firmware debug state. If the debug state is set, the
796 | * firmware is in development.
797 | *
798 | * @param hardwareMajor Hardware major version number.
799 | *
800 | * @param hardwareMinor Hardware minor version number.
801 | *
802 | * @param protocolMajor Protocol major version number.
803 | *
804 | * @param protocolMinor Protocol minor version number.
805 | *
806 | * @param padding Padding byte, ignore this.
807 | *
808 | * @return 0 on success, an error code otherwise
809 | */
810 | uint16_t getVersion(uint8_t& firmwareMajor, uint8_t& firmwareMinor,
811 | bool& firmwareDebug, uint8_t& hardwareMajor,
812 | uint8_t& hardwareMinor, uint8_t& protocolMajor,
813 | uint8_t& protocolMinor);
814 |
815 | /**
816 | * readDeviceStatus() - Reads the current device status.
817 | *
818 | * Use this command to get detailed information about the device status.
819 | * The device status is encoded in flags. Each device status flag
820 | * represents a single bit in a 32-bit integer value. If more than one
821 | * error is present, the device status register value is the sum of the
822 | * corresponding flag values. For details about the available flags,
823 | * refer to the device status flags documentation.
824 | *
825 | * @note The status flags of type \"Error\" are sticky, i.e. they are not
826 | * cleared automatically even if the error condition no longer exists. So
827 | * they can only be cleared manually with the command 0xD210 \"Read And
828 | * Clear Device Status\" or with a device reset. All other flags are not
829 | * sticky, i.e. they are cleared automatically if the trigger condition
830 | * disappears.
831 | *
832 | * @param deviceStatus Device status (32 flags as an integer value). For
833 | * details, please refer to the device status flags documentation.
834 | *
835 | * @return 0 on success, an error code otherwise
836 | */
837 | uint16_t readDeviceStatus(uint32_t& deviceStatus);
838 |
839 | /**
840 | * readAndClearDeviceStatus() - Reads the current device status (like
841 | * command 0xD206 \"Read Device Status\") and afterwards clears all flags.
842 | *
843 | * @param deviceStatus Device status (32 flags as an integer value)
844 | * **before** clearing it. For details, please refer to the device status
845 | * flags documentation.
846 | *
847 | * @return 0 on success, an error code otherwise
848 | */
849 | uint16_t readAndClearDeviceStatus(uint32_t& deviceStatus);
850 |
851 | /**
852 | * deviceReset() - Executes a reset on the device. This has the same effect
853 | * as a power cycle.
854 | *
855 | * @return 0 on success, an error code otherwise
856 | */
857 | uint16_t deviceReset(void);
858 |
859 | private:
860 | TwoWire* _i2cBus = nullptr;
861 | };
862 |
863 | #endif /* SENSIRIONI2CSEN5X_H */
864 |
--------------------------------------------------------------------------------