Add complete SPS30 library

This commit is contained in:
Theo Arends
2026-06-01 17:46:57 +02:00
parent 696255995a
commit e077f6a34d
18 changed files with 1360 additions and 0 deletions
@@ -0,0 +1,14 @@
---
Language: Cpp
BasedOnStyle: LLVM
IndentWidth: 4
AlignAfterOpenBracket: Align
AllowShortBlocksOnASingleLine: false
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
IndentCaseLabels: true
SpacesBeforeTrailingComments: 2
PointerAlignment: Left
AlignEscapedNewlines: Left
ForEachMacros: ['TEST_GROUP', 'TEST']
...
@@ -0,0 +1,23 @@
# CHANGELOG
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [1.0.1] - 2025-8-28
### Added
- Changed start_measurement example-value to enum
- Added float example
- Added warning for the use with AVR boards
## [1.0.0] - 2025-8-25
### Added
- Inital release of SPS30 driver
[Unreleased]: https://github.com/Sensirion/arduino-i2c-sps30/compare/1.0.1...HEAD
[1.0.1]: https://github.com/Sensirion/arduino-i2c-sps30/compare/1.0.0...1.0.1
[1.0.0]: https://github.com/Sensirion/arduino-i2c-sps30/releases/tag/1.0.0
+29
View File
@@ -0,0 +1,29 @@
BSD 3-Clause License
Copyright (c) 2025, Sensirion AG
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+210
View File
@@ -0,0 +1,210 @@
# Sensirion I²C SPS30 Arduino Library
This is the Sensirion SPS30 library for Arduino allowing you to
communicate with a SPS30 sensor
over I²C.
<img src="images/product-image-sps30.png" width="300px">
Click [here](https://sensirion.com/products/catalog/SPS30) to learn more about the Sensirion SPS30 sensor.
Not all sensors of this driver family support all measurements.
In case a measurement is not supported by all sensors, the products that
support it are listed in the API description.
The default I²C address of [SPS30](https://sensirion.com/products/catalog/SPS30) is **0x69**.
## Installation of the library
This library can be installed using the Arduino Library manager:
Start the [Arduino IDE](http://www.arduino.cc/en/main/software) and open
the Library Manager via
`Sketch``Include Library``Manage Libraries...`
Search for the `Sensirion I2C SPS30` library in the `Filter
your search...` field and install it by clicking the `install` button.
If you cannot find it in the library manager, download the latest release as .zip file
and add it to your [Arduino IDE](http://www.arduino.cc/en/main/software) via
`Sketch``Include Library``Add .ZIP Library...`
Don't forget to **install the dependencies** listed below the same way via library
manager or `Add .ZIP Library`
#### Dependencies
* [Sensirion Core](https://github.com/Sensirion/arduino-core)
## Connect the sensor
Use the following pin description to connect your SPS30 to the standard I²C bus of your Arduino board:
<img src="images/product-pinout-sps30.jpg" width="300px">
| *Pin* | *Cable Color* | *Name* | *Description* | *Comments* |
|-------|---------------|:------:|----------------|------------|
| 1 | red | VDD | Supply Voltage | 5V
| 2 | green | SDA | I2C: Serial data input / output |
| 3 | yellow | SCL | I2C: Serial clock input |
| 4 | blue | SEL | Interface select | Pull to GND to select I2C
| 5 | black | GND | Ground |
The recommended voltage is 5V.
### Board specific wiring
You will find pinout schematics for recommended board models below:
<details><summary>Arduino Uno</summary>
<p>
| *SPS30* | *SPS30 Pin* | *Cable Color* | *Board Pin* |
| :---: | --- | --- | --- |
| VDD | 1 | red | 5V |
| SDA | 2 | green | D18/SDA |
| SCL | 3 | yellow | D19/SCL |
| SEL | 4 | blue | GND |
| GND | 5 | black | GND |
<img src="images/Arduino-Uno-Rev3-i2c-pinout-5V-SEL.png" width="600px">
</p>
</details>
<details><summary>Arduino Nano</summary>
<p>
| *SPS30* | *SPS30 Pin* | *Cable Color* | *Board Pin* |
| :---: | --- | --- | --- |
| VDD | 1 | red | 5V |
| SDA | 2 | green | A4 |
| SCL | 3 | yellow | A5 |
| SEL | 4 | blue | GND |
| GND | 5 | black | GND |
<img src="images/Arduino-Nano-i2c-pinout-5V-SEL.png" width="600px">
</p>
</details>
<details><summary>Arduino Micro</summary>
<p>
| *SPS30* | *SPS30 Pin* | *Cable Color* | *Board Pin* |
| :---: | --- | --- | --- |
| VDD | 1 | red | 5V |
| SDA | 2 | green | D2/SDA |
| SCL | 3 | yellow | ~D3/SCL |
| SEL | 4 | blue | GND |
| GND | 5 | black | GND |
<img src="images/Arduino-Micro-i2c-pinout-5V-SEL.png" width="600px">
</p>
</details>
<details><summary>Arduino Mega 2560</summary>
<p>
| *SPS30* | *SPS30 Pin* | *Cable Color* | *Board Pin* |
| :---: | --- | --- | --- |
| VDD | 1 | red | 5V |
| SDA | 2 | green | D20/SDA |
| SCL | 3 | yellow | D21/SCL |
| SEL | 4 | blue | GND |
| GND | 5 | black | GND |
<img src="images/Arduino-Mega-2560-Rev3-i2c-pinout-5V-SEL.png" width="600px">
</p>
</details>
<details><summary>ESP32 DevKitC</summary>
<p>
| *SPS30* | *SPS30 Pin* | *Cable Color* | *Board Pin* |
| :---: | --- | --- | --- |
| VDD | 1 | red | 5V |
| SDA | 2 | green | GPIO 21 |
| SCL | 3 | yellow | GPIO 22 |
| SEL | 4 | blue | GND |
| GND | 5 | black | GND |
<img src="images/esp32-devkitc-i2c-pinout-5V-SEL.png" width="600px">
</p>
</details>
## Quick Start
1. Install the libraries and dependencies according to [Installation of the library](#installation-of-the-library)
2. Connect the SPS30 sensor to your Arduino as explained in [Connect the sensor](#connect-the-sensor)
3. Open the `exampleUsage` sample project within the Arduino IDE:
`File``Examples``Sensirion I2C SPS30``exampleUsage`
5. Click the `Upload` button in the Arduino IDE or `Sketch``Upload`
4. When the upload process has finished, open the `Serial Monitor` or `Serial
Plotter` via the `Tools` menu to observe the measurement values. Note that
the `Baud Rate` in the used tool has to be set to `115200 baud`.
> **AVR Boards are not fully compatible with SPS30 firmware-version > 1.0:**
> - readSerialNumber is limited to 20 Bytes which is enouth for probably every sensor.
> - Float measurement mode will not work, due to limitations of the Wire library. Use Uint16 measurement mode instead.
## Contributing
**Contributions are welcome!**
This Sensirion library uses
[`clang-format`](https://releases.llvm.org/download.html) to standardize the
formatting of all our `.cpp` and `.h` files. Make sure your contributions are
formatted accordingly:
The `-i` flag will apply the format changes to the files listed.
```bash
clang-format -i src/*.cpp src/*.h
```
Note that differences from this formatting will result in a failed build until
they are fixed.
:
## License
See [LICENSE](LICENSE).
@@ -0,0 +1,141 @@
/*
* THIS FILE IS AUTOMATICALLY GENERATED
*
* Generator: sensirion-driver-generator 1.3.4
* Product: sps30
* Model-Version: 1.0.2
*/
/*
* Copyright (c) 2025, Sensirion AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sensirion AG nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <Arduino.h>
#include <SensirionI2cSps30.h>
#include <Wire.h>
// macro definitions
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0
SensirionI2cSps30 sensor;
static char errorMessage[64];
static int16_t error;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Wire.begin();
sensor.begin(Wire, SPS30_I2C_ADDR_69);
sensor.stopMeasurement();
int8_t serialNumber[32] = {0};
int8_t productType[8] = {0};
sensor.readSerialNumber(serialNumber, 32);
Serial.print("serialNumber: ");
Serial.print((const char*)serialNumber);
Serial.println();
sensor.readProductType(productType, 8);
Serial.print("productType: ");
Serial.print((const char*)productType);
Serial.println();
sensor.startMeasurement(SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_UINT16);
delay(100);
}
void loop() {
uint16_t dataReadyFlag = 0;
uint16_t mc1p0 = 0;
uint16_t mc2p5 = 0;
uint16_t mc4p0 = 0;
uint16_t mc10p0 = 0;
uint16_t nc0p5 = 0;
uint16_t nc1p0 = 0;
uint16_t nc2p5 = 0;
uint16_t nc4p0 = 0;
uint16_t nc10p0 = 0;
uint16_t typicalParticleSize = 0;
delay(1000);
error = sensor.readDataReadyFlag(dataReadyFlag);
if (error != NO_ERROR) {
Serial.print("Error trying to execute readDataReadyFlag(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
Serial.print("dataReadyFlag: ");
Serial.print(dataReadyFlag);
Serial.println();
error = sensor.readMeasurementValuesUint16(mc1p0, mc2p5, mc4p0, mc10p0,
nc0p5, nc1p0, nc2p5, nc4p0,
nc10p0, typicalParticleSize);
if (error != NO_ERROR) {
Serial.print("Error trying to execute readMeasurementValuesUint16(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
Serial.print("mc1p0: ");
Serial.print(mc1p0);
Serial.print("\t");
Serial.print("mc2p5: ");
Serial.print(mc2p5);
Serial.print("\t");
Serial.print("mc4p0: ");
Serial.print(mc4p0);
Serial.print("\t");
Serial.print("mc10p0: ");
Serial.print(mc10p0);
Serial.print("\t");
Serial.print("nc0p5: ");
Serial.print(nc0p5);
Serial.print("\t");
Serial.print("nc1p0: ");
Serial.print(nc1p0);
Serial.print("\t");
Serial.print("nc2p5: ");
Serial.print(nc2p5);
Serial.print("\t");
Serial.print("nc4p0: ");
Serial.print(nc4p0);
Serial.print("\t");
Serial.print("nc10p0: ");
Serial.print(nc10p0);
Serial.print("\t");
Serial.print("typicalParticleSize: ");
Serial.print(typicalParticleSize);
Serial.println();
}
@@ -0,0 +1,134 @@
/*
* Copyright (c) 2025, Sensirion AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sensirion AG nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include <Arduino.h>
#include <SensirionI2cSps30.h>
#include <Wire.h>
// macro definitions
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0
SensirionI2cSps30 sensor;
static char errorMessage[64];
static int16_t error;
void setup() {
Serial.begin(115200);
while (!Serial) {
delay(100);
}
Wire.begin();
sensor.begin(Wire, SPS30_I2C_ADDR_69);
sensor.stopMeasurement();
int8_t serialNumber[32] = {0};
int8_t productType[8] = {0};
sensor.readSerialNumber(serialNumber, 32);
Serial.print("serialNumber: ");
Serial.print((const char*)serialNumber);
Serial.println();
sensor.readProductType(productType, 8);
Serial.print("productType: ");
Serial.print((const char*)productType);
Serial.println();
sensor.startMeasurement(SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_FLOAT);
delay(100);
}
void loop() {
uint16_t dataReadyFlag = 0;
float mc1p0 = 0;
float mc2p5 = 0;
float mc4p0 = 0;
float mc10p0 = 0;
float nc0p5 = 0;
float nc1p0 = 0;
float nc2p5 = 0;
float nc4p0 = 0;
float nc10p0 = 0;
float typicalParticleSize = 0;
delay(1000);
error = sensor.readDataReadyFlag(dataReadyFlag);
if (error != NO_ERROR) {
Serial.print("Error trying to execute readDataReadyFlag(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
Serial.print("dataReadyFlag: ");
Serial.print(dataReadyFlag);
Serial.println();
error = sensor.readMeasurementValuesFloat(mc1p0, mc2p5, mc4p0, mc10p0,
nc0p5, nc1p0, nc2p5, nc4p0,
nc10p0, typicalParticleSize);
if (error != NO_ERROR) {
Serial.print("Error trying to execute readMeasurementValuesFloat(): ");
errorToString(error, errorMessage, sizeof errorMessage);
Serial.println(errorMessage);
return;
}
Serial.print("mc1p0: ");
Serial.print(mc1p0);
Serial.print("\t");
Serial.print("mc2p5: ");
Serial.print(mc2p5);
Serial.print("\t");
Serial.print("mc4p0: ");
Serial.print(mc4p0);
Serial.print("\t");
Serial.print("mc10p0: ");
Serial.print(mc10p0);
Serial.print("\t");
Serial.print("nc0p5: ");
Serial.print(nc0p5);
Serial.print("\t");
Serial.print("nc1p0: ");
Serial.print(nc1p0);
Serial.print("\t");
Serial.print("nc2p5: ");
Serial.print(nc2p5);
Serial.print("\t");
Serial.print("nc4p0: ");
Serial.print(nc4p0);
Serial.print("\t");
Serial.print("nc10p0: ");
Serial.print(nc10p0);
Serial.print("\t");
Serial.print("typicalParticleSize: ");
Serial.print(typicalParticleSize);
Serial.println();
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 405 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 315 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 526 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 487 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

@@ -0,0 +1,41 @@
#######################################
# Syntax Coloring Map
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
SensirionI2cSps30 KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
wakeUpSequence KEYWORD2
startMeasurement KEYWORD2
stopMeasurement KEYWORD2
readDataReadyFlag KEYWORD2
readMeasurementValuesUint16 KEYWORD2
readMeasurementValuesFloat KEYWORD2
sleep KEYWORD2
wakeUp KEYWORD2
startFanCleaning KEYWORD2
readAutoCleaningInterval KEYWORD2
writeAutoCleaningInterval KEYWORD2
readProductType KEYWORD2
readSerialNumber KEYWORD2
readFirmwareVersion KEYWORD2
readDeviceStatusRegister KEYWORD2
clearDeviceStatusRegister KEYWORD2
deviceReset KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
sensor KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
@@ -0,0 +1,11 @@
name=Sensirion I2C SPS30
version=1.0.1
author=Sensirion
maintainer=Sensirion
sentence=Library for the SPS30 sensor by Sensirion
paragraph=Enables you to use the SPS30 sensor via I2C.
url=https://github.com/Sensirion/arduino-i2c-sps30
category=Sensors
architectures=*
depends=Sensirion Core
includes=SensirionI2cSps30.h
@@ -0,0 +1,7 @@
# driver generation metadata
generator_version: 1.3.4
model_version: 1.0.2
dg_status: released
is_manually_modified: true
first_generated: '2025-08-15 14:56'
last_generated: '2025-08-28 11:37'
@@ -0,0 +1,390 @@
/*
* THIS FILE IS AUTOMATICALLY GENERATED
*
* Generator: sensirion-driver-generator 1.3.4
* Product: sps30
* Model-Version: 1.0.2
*/
/*
* Copyright (c) 2025, Sensirion AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sensirion AG nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "SensirionI2cSps30.h"
#include <Arduino.h>
#include <assert.h>
// make sure that we use the proper definition of NO_ERROR
#ifdef NO_ERROR
#undef NO_ERROR
#endif
#define NO_ERROR 0
static uint8_t communication_buffer[60] = {0};
SensirionI2cSps30::SensirionI2cSps30() {
}
int16_t SensirionI2cSps30::wakeUpSequence() {
int16_t localError = 0;
localError = wakeUp();
if (localError != NO_ERROR) {
return localError;
}
localError = wakeUp();
if (localError != NO_ERROR) {
return localError;
}
return localError;
}
int16_t
SensirionI2cSps30::startMeasurement(SPS30OutputFormat measurementOutputFormat) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
#ifdef __AVR__
if (measurementOutputFormat == SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_FLOAT) {
Serial.println();
Serial.println(
"WARNING: AVR Boards are not fully compatible with SPS30 "
"firmware-version > 1.0:");
Serial.println(" - Float measurement mode will not work");
Serial.println();
delay(2000);
assert(false);
}
#endif
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x10, buffer_ptr, 5);
localError |= txFrame.addUInt16(measurementOutputFormat);
if (localError != NO_ERROR) {
return localError;
}
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(20);
return localError;
}
int16_t SensirionI2cSps30::stopMeasurement() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x104, buffer_ptr, 2);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(20);
return localError;
}
int16_t SensirionI2cSps30::readDataReadyFlag(uint16_t& dataReadyFlag) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x202, buffer_ptr, 3);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 3);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 3,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getUInt16(dataReadyFlag);
return localError;
}
int16_t SensirionI2cSps30::readMeasurementValuesUint16(
uint16_t& mc1p0, uint16_t& mc2p5, uint16_t& mc4p0, uint16_t& mc10p0,
uint16_t& nc0p5, uint16_t& nc1p0, uint16_t& nc2p5, uint16_t& nc4p0,
uint16_t& nc10p0, uint16_t& typicalParticleSize) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x300, buffer_ptr, 30);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 30);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 30,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getUInt16(mc1p0);
localError |= rxFrame.getUInt16(mc2p5);
localError |= rxFrame.getUInt16(mc4p0);
localError |= rxFrame.getUInt16(mc10p0);
localError |= rxFrame.getUInt16(nc0p5);
localError |= rxFrame.getUInt16(nc1p0);
localError |= rxFrame.getUInt16(nc2p5);
localError |= rxFrame.getUInt16(nc4p0);
localError |= rxFrame.getUInt16(nc10p0);
localError |= rxFrame.getUInt16(typicalParticleSize);
return localError;
}
int16_t SensirionI2cSps30::readMeasurementValuesFloat(
float& mc1p0, float& mc2p5, float& mc4p0, float& mc10p0, float& nc0p5,
float& nc1p0, float& nc2p5, float& nc4p0, float& nc10p0,
float& typicalParticleSize) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x300, buffer_ptr, 60);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 60);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 60,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getFloat(mc1p0);
localError |= rxFrame.getFloat(mc2p5);
localError |= rxFrame.getFloat(mc4p0);
localError |= rxFrame.getFloat(mc10p0);
localError |= rxFrame.getFloat(nc0p5);
localError |= rxFrame.getFloat(nc1p0);
localError |= rxFrame.getFloat(nc2p5);
localError |= rxFrame.getFloat(nc4p0);
localError |= rxFrame.getFloat(nc10p0);
localError |= rxFrame.getFloat(typicalParticleSize);
return localError;
}
int16_t SensirionI2cSps30::sleep() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x1001, buffer_ptr, 2);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(5);
return localError;
}
int16_t SensirionI2cSps30::wakeUp() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x1103, buffer_ptr, 2);
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
delay(5);
return localError;
}
int16_t SensirionI2cSps30::startFanCleaning() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x5607, buffer_ptr, 2);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(5);
return localError;
}
int16_t
SensirionI2cSps30::readAutoCleaningInterval(uint32_t& autoCleaningInterval) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x8004, buffer_ptr, 6);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(5);
SensirionI2CRxFrame rxFrame(buffer_ptr, 6);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 6,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getUInt32(autoCleaningInterval);
return localError;
}
int16_t
SensirionI2cSps30::writeAutoCleaningInterval(uint32_t autoCleaningInterval) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0x8004, buffer_ptr, 8);
localError |= txFrame.addUInt32(autoCleaningInterval);
if (localError != NO_ERROR) {
return localError;
}
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(20);
return localError;
}
int16_t SensirionI2cSps30::readProductType(int8_t productType[],
uint16_t productTypeSize) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd002, buffer_ptr, 12);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 12);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 12,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getBytes((uint8_t*)productType, productTypeSize);
return localError;
}
int16_t SensirionI2cSps30::readSerialNumber(int8_t serialNumber[],
uint16_t serialNumberSize) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd033, buffer_ptr, 48);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 48);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 48,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getBytes((uint8_t*)serialNumber, serialNumberSize);
return localError;
}
int16_t SensirionI2cSps30::readFirmwareVersion(uint8_t& majorVersion,
uint8_t& minorVersion) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd100, buffer_ptr, 3);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 3);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 3,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getUInt8(majorVersion);
localError |= rxFrame.getUInt8(minorVersion);
return localError;
}
int16_t SensirionI2cSps30::readDeviceStatusRegister(uint32_t& deviceStatus) {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd206, buffer_ptr, 6);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
SensirionI2CRxFrame rxFrame(buffer_ptr, 6);
localError = SensirionI2CCommunication::receiveFrame(_i2cAddress, 6,
rxFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
localError |= rxFrame.getUInt32(deviceStatus);
return localError;
}
int16_t SensirionI2cSps30::clearDeviceStatusRegister() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd210, buffer_ptr, 2);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(5);
return localError;
}
int16_t SensirionI2cSps30::deviceReset() {
int16_t localError = NO_ERROR;
uint8_t* buffer_ptr = communication_buffer;
SensirionI2CTxFrame txFrame =
SensirionI2CTxFrame::createWithUInt16Command(0xd304, buffer_ptr, 2);
localError =
SensirionI2CCommunication::sendFrame(_i2cAddress, txFrame, *_i2cBus);
if (localError != NO_ERROR) {
return localError;
}
delay(100);
return localError;
}
void SensirionI2cSps30::begin(TwoWire& i2cBus, uint8_t i2cAddress) {
_i2cBus = &i2cBus;
_i2cAddress = i2cAddress;
}
@@ -0,0 +1,360 @@
/*
* THIS FILE IS AUTOMATICALLY GENERATED
*
* Generator: sensirion-driver-generator 1.3.4
* Product: sps30
* Model-Version: 1.0.2
*/
/*
* Copyright (c) 2025, Sensirion AG
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* * Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* * Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* * Neither the name of Sensirion AG nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SENSIRIONI2CSPS30_H
#define SENSIRIONI2CSPS30_H
#include <SensirionCore.h>
#include <Wire.h>
#define SPS30_I2C_ADDR_69 0x69
typedef enum {
SPS30_START_MEASUREMENT_CMD_ID = 0x10,
SPS30_STOP_MEASUREMENT_CMD_ID = 0x104,
SPS30_READ_DATA_READY_FLAG_CMD_ID = 0x202,
SPS30_READ_MEASUREMENT_VALUES_UINT16_CMD_ID = 0x300,
SPS30_READ_MEASUREMENT_VALUES_FLOAT_CMD_ID = 0x300,
SPS30_SLEEP_CMD_ID = 0x1001,
SPS30_WAKE_UP_CMD_ID = 0x1103,
SPS30_START_FAN_CLEANING_CMD_ID = 0x5607,
SPS30_READ_AUTO_CLEANING_INTERVAL_CMD_ID = 0x8004,
SPS30_WRITE_AUTO_CLEANING_INTERVAL_CMD_ID = 0x8004,
SPS30_READ_PRODUCT_TYPE_CMD_ID = 0xd002,
SPS30_READ_SERIAL_NUMBER_CMD_ID = 0xd033,
SPS30_READ_FIRMWARE_VERSION_CMD_ID = 0xd100,
SPS30_READ_DEVICE_STATUS_REGISTER_CMD_ID = 0xd206,
SPS30_CLEAR_DEVICE_STATUS_REGISTER_CMD_ID = 0xd210,
SPS30_DEVICE_RESET_CMD_ID = 0xd304,
} SPS30CmdId;
typedef enum {
SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_FLOAT = 768,
SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_UINT16 = 1280,
} SPS30OutputFormat;
class SensirionI2cSps30 {
public:
SensirionI2cSps30();
/**
* @brief Initializes the SPS30 class.
*
* @param i2cBus Arduino stream object to be used for communication.
*/
void begin(TwoWire& i2cBus, uint8_t i2cAddress);
/**
* @brief Fully wake up the device
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t wakeUpSequence();
/**
* @brief Start measurement
*
* Starts the measurement. After power up, the module is in Idle-Mode.
* Before any measurement values can be read, the Measurement-Mode needs to
* be started using this command.
*
* @param[in] measurementOutputFormat Possible enum values:
* output_format_float, output_format_uint16
*
* @note This command can only be executed in Idle-Mode.
*
* @return error_code 0 on success, an error code otherwise.
*
* Example:
* --------
*
* @code{.cpp}
*
* int16_t localError = 0;
* localError =
* sensor.startMeasurement(SPS30_OUTPUT_FORMAT_OUTPUT_FORMAT_UINT16); if
* (localError != NO_ERROR) { return;
* }
*
* @endcode
*
*/
int16_t startMeasurement(SPS30OutputFormat measurementOutputFormat);
/**
* @brief Stop measurement
*
* Use this command to return to the Idle-Mode.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t stopMeasurement();
/**
* @brief Read data ready flag
*
* This command can be used for polling to find out when new measurements
* are available. The pointer address only has to be set once. Repeated read
* requests get the status of the Data-Ready Flag.
*
* @param[out] dataReadyFlag 0x0000: no new measurements available 0x0001:
* new measurements ready to read
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readDataReadyFlag(uint16_t& dataReadyFlag);
/**
* @brief Read measurement values
*
* Reads the measured values from the sensor module and resets the
* “Data-Ready Flag”. If the sensor module is in Measurement-Mode, an
* updated measurement value is provided every second and the “Data-Ready
* Flag” is set. If no synchronized readout is desired, the “Data-Ready
* Flag” can be ignored. The command “Read Measured Values” always returns
* the latest measured values.
*
* @param[out] mc1p0 Mass Concentration PM1.0 [µg/m³]
* @param[out] mc2p5 Mass Concentration PM2.5 [µg/m³]
* @param[out] mc4p0 Mass Concentration PM4.0 [µg/m³]
* @param[out] mc10p0 Mass Concentration PM10.0 [µg/m³]
* @param[out] nc0p5 Number Concentration PM0.5 [#/cm³]
* @param[out] nc1p0 Number Concentration PM1.0 [#/cm³]
* @param[out] nc2p5 Number Concentration PM2.5 [#/cm³]
* @param[out] nc4p0 Number Concentration PM4.0 [#/cm³]
* @param[out] nc10p0 Number Concentration PM10.0 [#/cm³]
* @param[out] typicalParticleSize Typical Particle Size [µm]
*
* @note Use this function when the measurement output format is configured
* to: "Big-endian unsigned 16-bit integer values"
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readMeasurementValuesUint16(uint16_t& mc1p0, uint16_t& mc2p5,
uint16_t& mc4p0, uint16_t& mc10p0,
uint16_t& nc0p5, uint16_t& nc1p0,
uint16_t& nc2p5, uint16_t& nc4p0,
uint16_t& nc10p0,
uint16_t& typicalParticleSize);
/**
* @brief Read measurement values
*
* Reads the measured values from the sensor module and resets the
* “Data-Ready Flag”. If the sensor module is in Measurement-Mode, an
* updated measurement value is provided every second and the “Data-Ready
* Flag” is set. If no synchronized readout is desired, the “Data-Ready
* Flag” can be ignored. The command “Read Measured Values” always returns
* the latest measured values.
*
* @param[out] mc1p0 Mass Concentration PM1.0 [µg/m³]
* @param[out] mc2p5 Mass Concentration PM2.5 [µg/m³]
* @param[out] mc4p0 Mass Concentration PM4.0 [µg/m³]
* @param[out] mc10p0 Mass Concentration PM10.0 [µg/m³]
* @param[out] nc0p5 Number Concentration PM0.5 [#/cm³]
* @param[out] nc1p0 Number Concentration PM1.0 [#/cm³]
* @param[out] nc2p5 Number Concentration PM2.5 [#/cm³]
* @param[out] nc4p0 Number Concentration PM4.0 [#/cm³]
* @param[out] nc10p0 Number Concentration PM10.0 [#/cm³]
* @param[out] typicalParticleSize Typical Particle Size [µm]
*
* @note Use this function when the measurement output format is configured
* to: "Big-endian IEEE754 float values"
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readMeasurementValuesFloat(float& mc1p0, float& mc2p5, float& mc4p0,
float& mc10p0, float& nc0p5,
float& nc1p0, float& nc2p5, float& nc4p0,
float& nc10p0,
float& typicalParticleSize);
/**
* @brief Enter Sleep-Mode
*
* Enters the Sleep-Mode with minimum power consumption. This will also
* deactivate the I2C interface.
*
* @note This command can only be executed in Idle-Mode.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t sleep();
/**
* @brief Switch from Sleep-Mode to Idle-Mode
*
* In Sleep-Mode the I2C interface is disabled and must first be activated
* by sending a low pulse on the SDA line. A low pulse can be generated by
* sending a I2C-Start-Condition followed by a Stop-Condition. If then a
* Wake-up command follows within 100ms, the module will switch on again and
* is ready for further commands in the Idle-Mode. If the low pulse is not
* followed by the Wake-up command, the microcontroller returns after 100ms
* to Sleep-Mode and the interface is deactivated again.
*
* Alternatively, if the software implementation does not allow to send a
* I2C-Start-Condition followed by a Stop-Condition, the Wake-up command can
* be sent twice in succession. In this case the first Wake-up command is
* ignored, but causes the interface to be activated.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t wakeUp();
/**
* @brief Starts fan cleaning manually
*
* @note This command can only be executed in Measurement-Mode.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t startFanCleaning();
/**
* @brief Reads auto cleaning interval of the periodic fan-cleaning
*
* @param[out] autoCleaningInterval Interval in seconds
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readAutoCleaningInterval(uint32_t& autoCleaningInterval);
/**
* @brief Writes auto cleaning interval of the periodic fan-cleaning
*
* @param[in] autoCleaningInterval Interval in seconds
*
* @note For FW Version < 2.2: After writing a new interval, this will be
* activated immediately. However, if the interval register is read out
* after setting the new value, the previous value is returned until the
* next start/reset of the sensor module.
*
* @return error_code 0 on success, an error code otherwise.
*
* Example:
* --------
*
* @code{.cpp}
*
* int16_t localError = 0;
* localError = sensor.writeAutoCleaningInterval(604800);
* if (localError != NO_ERROR) {
* return;
* }
*
* @endcode
*
*/
int16_t writeAutoCleaningInterval(uint32_t autoCleaningInterval);
/**
* @brief Read product type
*
* This command returns the product type. It is defined as a string value
* with a length of 8 ASCII characters (excluding terminating
* null-character)
*
* @param[out] productType 8-byte ASCII string
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readProductType(int8_t productType[], uint16_t productTypeSize);
/**
* @brief Read serial number
*
* This command returns the serial number. It is defined as a string value
* with a maximum length of 32 ASCII characters (including terminating
* null-character)
*
* @param[out] serialNumber 32-byte ASCII string
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readSerialNumber(int8_t serialNumber[], uint16_t serialNumberSize);
/**
* @brief Gets firmware major.minor firmware version.
*
* @param[out] majorVersion
* @param[out] minorVersion
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readFirmwareVersion(uint8_t& majorVersion, uint8_t& minorVersion);
/**
* @brief Reads device status register
*
* Use this command to read the device status register. For more details,
* check explanations given in chapter 4.4 of the datasheet.
*
* @param[out] deviceStatus
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t readDeviceStatusRegister(uint32_t& deviceStatus);
/**
* @brief Clears the device status register.
*
* Use this command to clear the device status register. For more details,
* check explanations given in chapter 4.4 of the datasheet.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t clearDeviceStatusRegister();
/**
* @brief Device software reset
*
* Device software reset command. After calling this command, the module is
* in the same state as after a power reset.
*
* @note To perform a reset when the sensor is in sleep mode, it is required
* to send first a wake-up sequence to activate the interface.
*
* @return error_code 0 on success, an error code otherwise.
*/
int16_t deviceReset();
private:
TwoWire* _i2cBus = nullptr;
uint8_t _i2cAddress = 0;
};
#endif // SENSIRIONI2CSPS30_H