Add complete SPS30 library
@@ -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
|
||||
@@ -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.
|
||||
@@ -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();
|
||||
}
|
||||
|
After Width: | Height: | Size: 405 KiB |
|
After Width: | Height: | Size: 322 KiB |
|
After Width: | Height: | Size: 297 KiB |
|
After Width: | Height: | Size: 315 KiB |
|
After Width: | Height: | Size: 526 KiB |
|
After Width: | Height: | Size: 487 KiB |
|
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
|
||||