From 745ad6786badd96117407234671e2c4b51892b01 Mon Sep 17 00:00:00 2001 From: Driver Generator 2 Date: Tue, 3 Dec 2024 09:56:29 +0000 Subject: [PATCH] Generate SEN66 driver from SEN66 model version 1.3.1 --- .github/workflows/arduino_quality_check.yml | 2 +- .gitlab-ci.yml | 103 +++++++++++++++++ CHANGELOG.md | 8 +- README.md | 16 ++- examples/exampleUsage/exampleUsage.ino | 2 +- keywords.txt | 6 +- library.properties | 2 +- metadata.yml | 6 +- src/SensirionI2cSen66.cpp | 97 ++++++++++------ src/SensirionI2cSen66.h | 121 ++++++++++++++------ 10 files changed, 282 insertions(+), 81 deletions(-) create mode 100644 .gitlab-ci.yml diff --git a/.github/workflows/arduino_quality_check.yml b/.github/workflows/arduino_quality_check.yml index a8b92d4..a2dc17c 100644 --- a/.github/workflows/arduino_quality_check.yml +++ b/.github/workflows/arduino_quality_check.yml @@ -13,7 +13,7 @@ jobs: uses: sensirion/.github/.github/workflows/driver.arduino.check.yml@main with: expect-arduino-examples: true - lint-lib-manager-check: submit + lint-lib-manager-check: update todo-check: if: github.event_name == 'push' && github.ref != 'refs/head/main' diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..1610d88 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,103 @@ +stages: + - validate + - test + +variables: + YQ_URL: https://github.com/mikefarah/yq/releases/download/v4.33.3/yq_linux_amd64 + +compile_test: + stage: test + image: + name: registry.gitlab.sensirion.lokal/sensirion/docker/docker-arduino:0.4.0 + tags: [docker, linux] + before_script: + - rm -rf ../sensirion-core-arduino-library + script: + - git clone --depth 1 --branch 0.7.0 https://github.com/Sensirion/arduino-core.git ../sensirion-core-arduino-library + - arduino-cli compile --libraries=".." --warnings all --fqbn arduino:samd:mkrzero ./examples/exampleUsage/exampleUsage.ino + - arduino-cli compile --libraries=".." --warnings all --fqbn arduino:avr:mega ./examples/exampleUsage/exampleUsage.ino + - arduino-cli compile --libraries=".." --warnings all --fqbn arduino:avr:nano ./examples/exampleUsage/exampleUsage.ino + - arduino-cli compile --libraries=".." --warnings all --fqbn arduino:avr:uno ./examples/exampleUsage/exampleUsage.ino + - arduino-cli compile --libraries=".." --warnings all --fqbn esp32:esp32:esp32 ./examples/exampleUsage/exampleUsage.ino + - arduino-cli compile --libraries=".." --warnings all --fqbn esp8266:esp8266:generic ./examples/exampleUsage/exampleUsage.ino + +arduino_lint: + stage: validate + image: + name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.2.0 + tags: [linux, docker] + script: + - mkdir ~/arlint + - PATH=~/arlint:$PATH + - curl -fsSL https://raw.githubusercontent.com/arduino/arduino-lint/main/etc/install.sh | BINDIR=~/arlint sh + - arduino-lint --library-manager false + +syntax_check: + stage: validate + image: + name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.2.0 + tags: [linux, docker] + script: + - find . -type f -iregex ".*\.\(c\|h\|cpp\|ino\)" -exec clang-format-6.0 -i -style=file {} \; && git diff --exit-code + + +cppcheck: + stage: validate + image: + name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.2.0 + tags: [linux, docker] + script: + - cppcheck --std=c++11 --language=c++ --error-exitcode=1 --enable=warning,style,performance,portability --suppress=unreadVariable --suppress=unusedStructMember src/* + +TODO_check: + stage: validate + image: + name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.2.0 + tags: [linux, docker] + script: + - '! grep -rnw --exclude=.gitlab-ci.yml --exclude-dir=.git . -e "TODO"' + +metadata_check: + stage: validate + image: + name: registry.gitlab.sensirion.lokal/mso-sw/drivers/docker-driver-generator:0.2.0 + tags: [linux, docker] + before_script: + - apt-get -qq update && apt-get -qq install -y wget + - if ! [ -d downloads/ ]; then mkdir downloads; fi + - if ! [ -e downloads/yq ]; then wget --no-verbose $YQ_URL -O downloads/yq; fi + - cp downloads/yq /usr/local/bin/yq && chmod +x /usr/local/bin/yq + script: + # check if metadata.yml exists + - > + if ! [ -f "metadata.yml" ]; then + echo "metadata.yml file not found" + exit 1 + fi + # check that dg_status is 'released' + - export DG_STATUS=$(yq ".dg_status.[]" ./metadata.yml) + - > + if [ $DG_STATUS != "released" ]; then + echo "dg_status in metadata.yml has to be 'released', not '$DG_STATUS'" + exit 1 + fi + # check that last_generated is not older than timestamp of last non-merge commit (+ 3 minutes) + - export IS_MANUALLY_MODIFIED=$(yq ".is_manually_modified" ./metadata.yml) + - > + if [ $IS_MANUALLY_MODIFIED = false ]; then + export LAST_GENERATED_TS=$(yq ".last_generated" ./metadata.yml) + export LAST_GENERATED_TS_EPOCH=$(date -d "$LAST_GENERATED_TS" +%s) + export LAST_NON_MERGE_COMMIT_TS=$(git log --format=%ad --date=iso-strict --no-merges -1) + export COMMIT_TS_EPOCH=$(date -d "$LAST_NON_MERGE_COMMIT_TS" +%s) + if [ $(($LAST_GENERATED_TS_EPOCH + 180)) -lt $COMMIT_TS_EPOCH ]; then + echo "'last_generated' timestamp in metadata.yml is older than commit timestamp ($LAST_GENERATED_TS vs $LAST_NON_MERGE_COMMIT_TS)" + exit 1 + fi + fi + # check that 'is_manually_modified' is set to true if commit is not from driver generator + - export LAST_NON_MERGE_COMMIT_AUTHOR=$(git log --format=%an --no-merges -1) + - > + if ! [ "$LAST_NON_MERGE_COMMIT_AUTHOR" = "Driver Generator 2" ] && [ "$IS_MANUALLY_MODIFIED" = false ]; then + echo "Last commit is not from Driver Generator. Please update 'is_manually_modified' in metadata.yml" + exit 1 + fi \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index b0a15ca..c621661 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [1.0.1] - 2024-12-1 + +### Fixed + +- Fix naming from mass concentration to number concentration for read number concentration method (returned values were correct). ## [1.0.0] - 2024-11-25 ### Added @@ -21,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add interfaces to start, stop and read measurements. - Add interfaces to read product name, serial number and version -[Unreleased]: https://github.com/Sensirion/arduino-i2c-sen66/compare/1.0.0...HEAD +[Unreleased]: https://github.com/Sensirion/arduino-i2c-sen66/compare/1.0.1...HEAD +[1.0.1]: https://github.com/Sensirion/arduino-i2c-sen66/compare/1.0.0...1.0.1 [1.0.0]: https://github.com/Sensirion/arduino-i2c-sen66/compare/0.1.0...1.0.0 [0.1.0]: https://github.com/Sensirion/arduino-i2c-sen66/releases/tag/0.1.0 \ No newline at end of file diff --git a/README.md b/README.md index a63f38c..2be985e 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,12 @@ Use the following pin description to connect your SEN66 to the standard I²C bus | *Pin* | *Cable Color* | *Name* | *Description* | *Comments* | |-------|---------------|:------:|----------------|------------| -| 1 | red | VDD | Supply Voltage | 3.3V ±10% +| 1 | red | VDD | Supply Voltage | 3.3V ±5% | 2 | black | GND | Ground | | 3 | green | SDA | I2C: Serial data input / output | TTL 5V compatible | 4 | yellow | SCL | I2C: Serial clock input | TTL 5V compatible -| 5 | | NC | Do not connect | -| 6 | | NC | Do not connect | +| 5 | | GND | Ground | Do not connect (Pins 2 and 5 are connected internally) +| 6 | | VDD | Supply Voltage | Do not connect (Pins 1 and 6 are connected internally) @@ -69,6 +69,8 @@ You will find pinout schematics for recommended board models below: | GND | 2 | black | GND | | SDA | 3 | green | D18/SDA | | SCL | 4 | yellow | D19/SCL | +| GND | 5 | | GND | +| VDD | 6 | | 3.3V | @@ -88,6 +90,8 @@ You will find pinout schematics for recommended board models below: | GND | 2 | black | GND | | SDA | 3 | green | A4 | | SCL | 4 | yellow | A5 | +| GND | 5 | | GND | +| VDD | 6 | | 3.3V | @@ -107,6 +111,8 @@ You will find pinout schematics for recommended board models below: | GND | 2 | black | GND | | SDA | 3 | green | D2/SDA | | SCL | 4 | yellow | ~D3/SCL | +| GND | 5 | | GND | +| VDD | 6 | | 3.3V | @@ -126,6 +132,8 @@ You will find pinout schematics for recommended board models below: | GND | 2 | black | GND | | SDA | 3 | green | D20/SDA | | SCL | 4 | yellow | D21/SCL | +| GND | 5 | | GND | +| VDD | 6 | | 3.3V | @@ -145,6 +153,8 @@ You will find pinout schematics for recommended board models below: | GND | 2 | black | GND | | SDA | 3 | green | GPIO 21 | | SCL | 4 | yellow | GPIO 22 | +| GND | 5 | | GND | +| VDD | 6 | | 3V3 | diff --git a/examples/exampleUsage/exampleUsage.ino b/examples/exampleUsage/exampleUsage.ino index 1220390..24fa33c 100644 --- a/examples/exampleUsage/exampleUsage.ino +++ b/examples/exampleUsage/exampleUsage.ino @@ -3,7 +3,7 @@ * * Generator: sensirion-driver-generator 1.0.1 * Product: sen66 - * Model-Version: 1.3.0 + * Model-Version: 1.3.1 */ /* * Copyright (c) 2024, Sensirion AG diff --git a/keywords.txt b/keywords.txt index a89e74d..5b28fe4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -42,11 +42,15 @@ getSerialNumber KEYWORD2 readDeviceStatus KEYWORD2 readAndClearDeviceStatus KEYWORD2 deviceReset KEYWORD2 -signalMassConcentrationPm0p5 KEYWORD2 signalMassConcentrationPm1p0 KEYWORD2 signalMassConcentrationPm2p5 KEYWORD2 signalMassConcentrationPm4p0 KEYWORD2 signalMassConcentrationPm10p0 KEYWORD2 +signalNumberConcentrationPm0p5 KEYWORD2 +signalNumberConcentrationPm1p0 KEYWORD2 +signalNumberConcentrationPm2p5 KEYWORD2 +signalNumberConcentrationPm4p0 KEYWORD2 +signalNumberConcentrationPm10p0 KEYWORD2 signalTemperature KEYWORD2 signalHumidity KEYWORD2 signalVocIndex KEYWORD2 diff --git a/library.properties b/library.properties index 8c18059..4c065b6 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=Sensirion I2C SEN66 -version=1.0.0 +version=1.0.1 author=Sensirion maintainer=Sensirion sentence=Library for the SEN66 sensor by Sensirion diff --git a/metadata.yml b/metadata.yml index 5baaa84..505283c 100644 --- a/metadata.yml +++ b/metadata.yml @@ -1,7 +1,7 @@ # driver generation metadata generator_version: 1.0.1 -model_version: 1.3.0 +model_version: 1.3.1 dg_status: released -is_manually_modified: true +is_manually_modified: false first_generated: '2024-10-30 08:14' -last_generated: '2024-11-27 07:57' +last_generated: '2024-12-03 09:56' diff --git a/src/SensirionI2cSen66.cpp b/src/SensirionI2cSen66.cpp index dcd18fc..90b9446 100644 --- a/src/SensirionI2cSen66.cpp +++ b/src/SensirionI2cSen66.cpp @@ -3,7 +3,7 @@ * * Generator: sensirion-driver-generator 1.0.1 * Product: sen66 - * Model-Version: 1.3.0 + * Model-Version: 1.3.1 */ /* * Copyright (c) 2024, Sensirion AG @@ -50,13 +50,6 @@ static uint8_t communication_buffer[48] = {0}; SensirionI2cSen66::SensirionI2cSen66() { } -float SensirionI2cSen66::signalMassConcentrationPm0p5( - uint16_t massConcentrationPm0p5Raw) { - float massConcentrationPm0p5 = 0.0; - massConcentrationPm0p5 = massConcentrationPm0p5Raw / 10.0; - return massConcentrationPm0p5; -} - float SensirionI2cSen66::signalMassConcentrationPm1p0( uint16_t massConcentrationPm1p0Raw) { float massConcentrationPm1p0 = 0.0; @@ -85,6 +78,41 @@ float SensirionI2cSen66::signalMassConcentrationPm10p0( return massConcentrationPm10p0; } +float SensirionI2cSen66::signalNumberConcentrationPm0p5( + uint16_t numberConcentrationPm0p5Raw) { + float numberConcentrationPm0p5 = 0.0; + numberConcentrationPm0p5 = numberConcentrationPm0p5Raw / 10.0; + return numberConcentrationPm0p5; +} + +float SensirionI2cSen66::signalNumberConcentrationPm1p0( + uint16_t numberConcentrationPm1p0Raw) { + float numberConcentrationPm1p0 = 0.0; + numberConcentrationPm1p0 = numberConcentrationPm1p0Raw / 10.0; + return numberConcentrationPm1p0; +} + +float SensirionI2cSen66::signalNumberConcentrationPm2p5( + uint16_t numberConcentrationPm2p5Raw) { + float numberConcentrationPm2p5 = 0.0; + numberConcentrationPm2p5 = numberConcentrationPm2p5Raw / 10.0; + return numberConcentrationPm2p5; +} + +float SensirionI2cSen66::signalNumberConcentrationPm4p0( + uint16_t numberConcentrationPm4p0Raw) { + float numberConcentrationPm4p0 = 0.0; + numberConcentrationPm4p0 = numberConcentrationPm4p0Raw / 10.0; + return numberConcentrationPm4p0; +} + +float SensirionI2cSen66::signalNumberConcentrationPm10p0( + uint16_t numberConcentrationPm10p0Raw) { + float numberConcentrationPm10p0 = 0.0; + numberConcentrationPm10p0 = numberConcentrationPm10p0Raw / 10.0; + return numberConcentrationPm10p0; +} + float SensirionI2cSen66::signalTemperature(int16_t temperatureRaw) { float temperature = 0.0; temperature = temperatureRaw / 200.0; @@ -154,32 +182,37 @@ int16_t SensirionI2cSen66::readMeasuredValues( } int16_t SensirionI2cSen66::readNumberConcentrationValues( - float& massConcentrationPm0p5, float& massConcentrationPm1p0, - float& massConcentrationPm2p5, float& massConcentrationPm4p0, - float& massConcentrationPm10p0) { - uint16_t massConcentrationPm0p5Raw = 0; - uint16_t massConcentrationPm1p0Raw = 0; - uint16_t massConcentrationPm2p5Raw = 0; - uint16_t massConcentrationPm4p0Raw = 0; - uint16_t massConcentrationPm10p0Raw = 0; + float& numberConcentrationPm0p5, float& numberConcentrationPm1p0, + float& numberConcentrationPm2p5, float& numberConcentrationPm4p0, + float& numberConcentrationPm10p0) { + uint16_t numberConcentrationPm0p5Raw = 0; + uint16_t numberConcentrationPm1p0Raw = 0; + uint16_t numberConcentrationPm2p5Raw = 0; + uint16_t numberConcentrationPm4p0Raw = 0; + uint16_t numberConcentrationPm10p0Raw = 0; int16_t localError = 0; localError = readNumberConcentrationValuesAsIntegers( - massConcentrationPm0p5Raw, massConcentrationPm1p0Raw, - massConcentrationPm2p5Raw, massConcentrationPm4p0Raw, - massConcentrationPm10p0Raw); - if (localError != NO_ERROR) { - return localError; - } - massConcentrationPm0p5 = SensirionI2cSen66::signalMassConcentrationPm0p5( - massConcentrationPm0p5Raw); - massConcentrationPm1p0 = SensirionI2cSen66::signalMassConcentrationPm1p0( - massConcentrationPm1p0Raw); - massConcentrationPm2p5 = SensirionI2cSen66::signalMassConcentrationPm2p5( - massConcentrationPm2p5Raw); - massConcentrationPm4p0 = SensirionI2cSen66::signalMassConcentrationPm4p0( - massConcentrationPm4p0Raw); - massConcentrationPm10p0 = SensirionI2cSen66::signalMassConcentrationPm10p0( - massConcentrationPm10p0Raw); + numberConcentrationPm0p5Raw, numberConcentrationPm1p0Raw, + numberConcentrationPm2p5Raw, numberConcentrationPm4p0Raw, + numberConcentrationPm10p0Raw); + if (localError != NO_ERROR) { + return localError; + } + numberConcentrationPm0p5 = + SensirionI2cSen66::signalNumberConcentrationPm0p5( + numberConcentrationPm0p5Raw); + numberConcentrationPm1p0 = + SensirionI2cSen66::signalNumberConcentrationPm1p0( + numberConcentrationPm1p0Raw); + numberConcentrationPm2p5 = + SensirionI2cSen66::signalNumberConcentrationPm2p5( + numberConcentrationPm2p5Raw); + numberConcentrationPm4p0 = + SensirionI2cSen66::signalNumberConcentrationPm4p0( + numberConcentrationPm4p0Raw); + numberConcentrationPm10p0 = + SensirionI2cSen66::signalNumberConcentrationPm10p0( + numberConcentrationPm10p0Raw); return localError; } diff --git a/src/SensirionI2cSen66.h b/src/SensirionI2cSen66.h index 1dbce96..a1c3d7e 100644 --- a/src/SensirionI2cSen66.h +++ b/src/SensirionI2cSen66.h @@ -3,7 +3,7 @@ * * Generator: sensirion-driver-generator 1.0.1 * Product: sen66 - * Model-Version: 1.3.0 + * Model-Version: 1.3.1 */ /* * Copyright (c) 2024, Sensirion AG @@ -106,14 +106,14 @@ class SensirionI2cSen66 { /** * @brief Read measured values and apply scaling as defined in datasheet. * - * @param[out] massConcentrationPm1p0 Mass concentration for particles - * smaller than 1.0 μm. - * @param[out] massConcentrationPm2p5 Mass concentration for particles - * smaller than 2.5 μm. - * @param[out] massConcentrationPm4p0 Mass concentration for particles - * smaller than 4.0 μm. - * @param[out] massConcentrationPm10p0 Mass concentration for particles - * smaller than 10.0 μm. + * @param[out] massConcentrationPm1p0 Mass concentration in μg/m³ for + * particles smaller than 1.0 μm. + * @param[out] massConcentrationPm2p5 Mass concentration in μg/m³ for + * particles smaller than 2.5 μm. + * @param[out] massConcentrationPm4p0 Mass concentration in μg/m³ for + * particles smaller than 4.0 μm. + * @param[out] massConcentrationPm10p0 Mass concentration in μg/m³ for + * particles smaller than 10.0 μm. * @param[out] humidity Measured humidity in %RH. * @param[out] temperature Measured temperature in degrees celsius. * @param[out] vocIndex Measured VOC Index between 0 and 500. @@ -133,24 +133,24 @@ class SensirionI2cSen66 { * @brief Read measured number concentration values and apply scaling as * defined in datasheet. * - * @param[out] massConcentrationPm0p5 Mass concentration for particles - * smaller than 1.0 μm. - * @param[out] massConcentrationPm1p0 Mass concentration for particles - * smaller than 1.0 μm. - * @param[out] massConcentrationPm2p5 Mass concentration for particles - * smaller than 2.5 μm. - * @param[out] massConcentrationPm4p0 Mass concentration for particles - * smaller than 4.0 μm. - * @param[out] massConcentrationPm10p0 Mass concentration for particles - * smaller than 10.0 μm. + * @param[out] numberConcentrationPm0p5 Number concentration in + * particles/cm³ for particles smaller than 0.5 μm. + * @param[out] numberConcentrationPm1p0 Number concentration in + * particles/cm³ for particles smaller than 1.0 μm. + * @param[out] numberConcentrationPm2p5 Number concentration in + * particles/cm³ for particles smaller than 2.5 μm. + * @param[out] numberConcentrationPm4p0 Number concentration in + * particles/cm³ for particles smaller than 4.0 μm. + * @param[out] numberConcentrationPm10p0 Number concentration in + * particles/cm³ for particles smaller than 10.0 μm. * * @return error_code 0 on success, an error code otherwise. */ - int16_t readNumberConcentrationValues(float& massConcentrationPm0p5, - float& massConcentrationPm1p0, - float& massConcentrationPm2p5, - float& massConcentrationPm4p0, - float& massConcentrationPm10p0); + int16_t readNumberConcentrationValues(float& numberConcentrationPm0p5, + float& numberConcentrationPm1p0, + float& numberConcentrationPm2p5, + float& numberConcentrationPm4p0, + float& numberConcentrationPm10p0); /** * @brief Start a continuous measurement (interval 1s) @@ -880,22 +880,12 @@ class SensirionI2cSen66 { */ int16_t deviceReset(); - /** - * @brief signalMassConcentrationPm0p5 - * - * @param[in] massConcentrationPm0p5Raw - * - * @return Mass concentration for particles smaller than 0.5 μm - */ - static float - signalMassConcentrationPm0p5(uint16_t massConcentrationPm0p5Raw); - /** * @brief signalMassConcentrationPm1p0 * * @param[in] massConcentrationPm1p0Raw * - * @return Mass concentration for particles smaller than 1.0 μm + * @return Mass concentration in μg/m³ for particles smaller than 1.0 μm */ static float signalMassConcentrationPm1p0(uint16_t massConcentrationPm1p0Raw); @@ -905,7 +895,7 @@ class SensirionI2cSen66 { * * @param[in] massConcentrationPm2p5Raw * - * @return Mass concentration for particles smaller than 2.5 μm + * @return Mass concentration in μg/m³ for particles smaller than 2.5 μm */ static float signalMassConcentrationPm2p5(uint16_t massConcentrationPm2p5Raw); @@ -915,7 +905,7 @@ class SensirionI2cSen66 { * * @param[in] massConcentrationPm4p0Raw * - * @return Mass concentration for particles smaller than 4.0 μm + * @return Mass concentration in μg/m³ for particles smaller than 4.0 μm */ static float signalMassConcentrationPm4p0(uint16_t massConcentrationPm4p0Raw); @@ -925,11 +915,66 @@ class SensirionI2cSen66 { * * @param[in] massConcentrationPm10p0Raw * - * @return Mass concentration for particles smaller than 10.0 μm + * @return Mass concentration in μg/m³ for particles smaller than 10.0 μm */ static float signalMassConcentrationPm10p0(uint16_t massConcentrationPm10p0Raw); + /** + * @brief signalNumberConcentrationPm0p5 + * + * @param[in] numberConcentrationPm0p5Raw + * + * @return Number concentration in particles/cm³ for particles smaller than + * 0.5 μm + */ + static float + signalNumberConcentrationPm0p5(uint16_t numberConcentrationPm0p5Raw); + + /** + * @brief signalNumberConcentrationPm1p0 + * + * @param[in] numberConcentrationPm1p0Raw + * + * @return Number concentration in particles/cm³ for particles smaller + * than 1.0 μm + */ + static float + signalNumberConcentrationPm1p0(uint16_t numberConcentrationPm1p0Raw); + + /** + * @brief signalNumberConcentrationPm2p5 + * + * @param[in] numberConcentrationPm2p5Raw + * + * @return Number concentration in particles/cm³ for particles smaller + * than 2.5 μm + */ + static float + signalNumberConcentrationPm2p5(uint16_t numberConcentrationPm2p5Raw); + + /** + * @brief signalNumberConcentrationPm4p0 + * + * @param[in] numberConcentrationPm4p0Raw + * + * @return Number concentration in particles/cm³ for particles smaller + * than 4.0 μm + */ + static float + signalNumberConcentrationPm4p0(uint16_t numberConcentrationPm4p0Raw); + + /** + * @brief signalNumberConcentrationPm10p0 + * + * @param[in] numberConcentrationPm10p0Raw + * + * @return Number concentration in particles/cm³ for particles smaller + * than 10.0 μm + */ + static float + signalNumberConcentrationPm10p0(uint16_t numberConcentrationPm10p0Raw); + /** * @brief signalTemperature *