diff --git a/docs/local-server.md b/docs/local-server.md index 307ad8c..d65aee1 100644 --- a/docs/local-server.md +++ b/docs/local-server.md @@ -50,12 +50,18 @@ You get the following response: |-----------------------------------|---------|----------------------------------------------------------------------------------------| | `serialno` | String | Serial Number of the monitor | | `wifi` | Number | WiFi signal strength | -| `pm01` | Number | PM1 in ug/m3 | -| `pm02` | Number | PM2.5 in ug/m3 | -| `pm10` | Number | PM10 in ug/m3 | +| `pm01` | Number | PM1.0 in ug/m3 (atmospheric environment) | +| `pm02` | Number | PM2.5 in ug/m3 (atmospheric environment) | +| `pm10` | Number | PM10 in ug/m3 (atmospheric environment) | | `pm02Compensated` | Number | PM2.5 in ug/m3 with correction applied (from fw version 3.1.4 onwards) | +| `pm01Standard` | Number | PM1.0 in ug/m3 (standard particle) | +| `pm02Standard` | Number | PM2.5 in ug/m3 (standard particle) | +| `pm10Standard` | Number | PM10 in ug/m3 (standard particle) | | `rco2` | Number | CO2 in ppm | -| `pm003Count` | Number | Particle count per dL | +| `pm003Count` | Number | Particle count 0.3um per dL | +| `pm01Count` | Number | Particle count 1.0um per dL | +| `pm25Count` | Number | Particle count 2.5um per dL | +| `pm10Count` | Number | Particle count 10um per dL (only for indoor monitor) | | `atmp` | Number | Temperature in Degrees Celsius | | `atmpCompensated` | Number | Temperature in Degrees Celsius with correction applied | | `rhum` | Number | Relative Humidity | diff --git a/examples/OneOpenAir/OneOpenAir.ino b/examples/OneOpenAir/OneOpenAir.ino index b202929..8627583 100644 --- a/examples/OneOpenAir/OneOpenAir.ino +++ b/examples/OneOpenAir/OneOpenAir.ino @@ -1001,12 +1001,24 @@ static void updatePMS5003() { measurements.update(Measurements::PM01, ag->pms5003.getPm01Ae()); measurements.update(Measurements::PM25, ag->pms5003.getPm25Ae()); measurements.update(Measurements::PM10, ag->pms5003.getPm10Ae()); + measurements.update(Measurements::PM01_SP, ag->pms5003.getPm01Sp()); + measurements.update(Measurements::PM25_SP, ag->pms5003.getPm25Sp()); + measurements.update(Measurements::PM10_SP, ag->pms5003.getPm10Sp()); measurements.update(Measurements::PM03_PC, ag->pms5003.getPm03ParticleCount()); + measurements.update(Measurements::PM01_PC, ag->pms5003.getPm01ParticleCount()); + measurements.update(Measurements::PM25_PC, ag->pms5003.getPm25ParticleCount()); + measurements.update(Measurements::PM10_PC, ag->pms5003.getPm10ParticleCount()); } else { measurements.update(Measurements::PM01, utils::getInvalidPmValue()); measurements.update(Measurements::PM25, utils::getInvalidPmValue()); measurements.update(Measurements::PM10, utils::getInvalidPmValue()); + measurements.update(Measurements::PM01_SP, utils::getInvalidPmValue()); + measurements.update(Measurements::PM25_SP, utils::getInvalidPmValue()); + measurements.update(Measurements::PM10_SP, utils::getInvalidPmValue()); measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue()); + measurements.update(Measurements::PM01_PC, utils::getInvalidPmValue()); + measurements.update(Measurements::PM25_PC, utils::getInvalidPmValue()); + measurements.update(Measurements::PM10_PC, utils::getInvalidPmValue()); } } @@ -1027,18 +1039,28 @@ static void updatePm(void) { measurements.update(Measurements::PM01, ag->pms5003t_1.getPm01Ae(), channel); measurements.update(Measurements::PM25, ag->pms5003t_1.getPm25Ae(), channel); measurements.update(Measurements::PM10, ag->pms5003t_1.getPm10Ae(), channel); + measurements.update(Measurements::PM01_SP, ag->pms5003t_1.getPm01Sp(), channel); + measurements.update(Measurements::PM25_SP, ag->pms5003t_1.getPm25Sp(), channel); + measurements.update(Measurements::PM10_SP, ag->pms5003t_1.getPm10Sp(), channel); measurements.update(Measurements::PM03_PC, ag->pms5003t_1.getPm03ParticleCount(), channel); + measurements.update(Measurements::PM01_PC, ag->pms5003t_1.getPm01ParticleCount(), channel); + measurements.update(Measurements::PM25_PC, ag->pms5003t_1.getPm25ParticleCount(), channel); measurements.update(Measurements::Temperature, ag->pms5003t_1.getTemperature(), channel); measurements.update(Measurements::Humidity, ag->pms5003t_1.getRelativeHumidity(), channel); // flag that new valid PMS value exists - newPMS2Value = true; + newPMS1Value = true; } else { // PMS channel 1 now is not connected, update using invalid value measurements.update(Measurements::PM01, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM25, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM10, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM01_SP, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM25_SP, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM10_SP, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM01_PC, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM25_PC, utils::getInvalidPmValue(), channel); measurements.update(Measurements::Temperature, utils::getInvalidTemperature(), channel); measurements.update(Measurements::Humidity, utils::getInvalidHumidity(), channel); } @@ -1051,18 +1073,28 @@ static void updatePm(void) { measurements.update(Measurements::PM01, ag->pms5003t_2.getPm01Ae(), channel); measurements.update(Measurements::PM25, ag->pms5003t_2.getPm25Ae(), channel); measurements.update(Measurements::PM10, ag->pms5003t_2.getPm10Ae(), channel); + measurements.update(Measurements::PM01_SP, ag->pms5003t_2.getPm01Sp(), channel); + measurements.update(Measurements::PM25_SP, ag->pms5003t_2.getPm25Sp(), channel); + measurements.update(Measurements::PM10_SP, ag->pms5003t_2.getPm10Sp(), channel); measurements.update(Measurements::PM03_PC, ag->pms5003t_2.getPm03ParticleCount(), channel); + measurements.update(Measurements::PM01_PC, ag->pms5003t_2.getPm01ParticleCount(), channel); + measurements.update(Measurements::PM25_PC, ag->pms5003t_2.getPm25ParticleCount(), channel); measurements.update(Measurements::Temperature, ag->pms5003t_2.getTemperature(), channel); measurements.update(Measurements::Humidity, ag->pms5003t_2.getRelativeHumidity(), channel); // flag that new valid PMS value exists newPMS2Value = true; } else { - // PMS channel channel now is not connected, update using invalid value + // PMS channel 2 now is not connected, update using invalid value measurements.update(Measurements::PM01, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM25, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM10, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM01_SP, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM25_SP, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM10_SP, utils::getInvalidPmValue(), channel); measurements.update(Measurements::PM03_PC, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM01_PC, utils::getInvalidPmValue(), channel); + measurements.update(Measurements::PM25_PC, utils::getInvalidPmValue(), channel); measurements.update(Measurements::Temperature, utils::getInvalidTemperature(), channel); measurements.update(Measurements::Humidity, utils::getInvalidHumidity(), channel); } @@ -1133,18 +1165,31 @@ static void tempHumUpdate(void) { /* Set max period for each measurement type based on sensor update interval*/ void setMeasurementMaxPeriod() { + int max; + /// Max period for S8 sensors measurements measurements.maxPeriod(Measurements::CO2, calculateMaxPeriod(SENSOR_CO2_UPDATE_INTERVAL)); + /// Max period for SGP sensors measurements - measurements.maxPeriod(Measurements::TVOC, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::TVOCRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::NOx, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::NOxRaw, calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL)); + max = calculateMaxPeriod(SENSOR_TVOC_UPDATE_INTERVAL); + measurements.maxPeriod(Measurements::TVOC, max); + measurements.maxPeriod(Measurements::TVOCRaw, max); + measurements.maxPeriod(Measurements::NOx, max); + measurements.maxPeriod(Measurements::NOxRaw, max); + /// Max period for PMS sensors measurements - measurements.maxPeriod(Measurements::PM25, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::PM01, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::PM10, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); - measurements.maxPeriod(Measurements::PM03_PC, calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL)); + max = calculateMaxPeriod(SENSOR_PM_UPDATE_INTERVAL); + measurements.maxPeriod(Measurements::PM25, max); + measurements.maxPeriod(Measurements::PM01, max); + measurements.maxPeriod(Measurements::PM10, max); + measurements.maxPeriod(Measurements::PM25_SP, max); + measurements.maxPeriod(Measurements::PM01_SP, max); + measurements.maxPeriod(Measurements::PM10_SP, max); + measurements.maxPeriod(Measurements::PM03_PC, max); + measurements.maxPeriod(Measurements::PM01_PC, max); + measurements.maxPeriod(Measurements::PM25_PC, max); + measurements.maxPeriod(Measurements::PM10_PC, max); + // Temperature and Humidity if (configuration.hasSensorSHT) { /// Max period for SHT sensors measurements diff --git a/src/AgValue.cpp b/src/AgValue.cpp index 7965b68..00343cc 100644 --- a/src/AgValue.cpp +++ b/src/AgValue.cpp @@ -41,10 +41,34 @@ void Measurements::maxPeriod(MeasurementType type, int max) { _pm_10[0].update.max = max; _pm_10[1].update.max = max; break; + case PM01_SP: + _pm_01_sp[0].update.max = max; + _pm_01_sp[1].update.max = max; + break; + case PM25_SP: + _pm_25_sp[0].update.max = max; + _pm_25_sp[1].update.max = max; + break; + case PM10_SP: + _pm_10_sp[0].update.max = max; + _pm_10_sp[1].update.max = max; + break; case PM03_PC: _pm_03_pc[0].update.max = max; _pm_03_pc[1].update.max = max; break; + case PM01_PC: + _pm_01_pc[0].update.max = max; + _pm_01_pc[1].update.max = max; + break; + case PM25_PC: + _pm_25_pc[0].update.max = max; + _pm_25_pc[1].update.max = max; + break; + case PM10_PC: + _pm_10_pc[0].update.max = max; + _pm_10_pc[1].update.max = max; + break; }; } @@ -57,6 +81,7 @@ bool Measurements::update(MeasurementType type, int val, int ch) { // Define data point source IntegerValue *temporary = nullptr; + // Act as reference invalid value respective to target measurements int invalidValue = 0; switch (type) { case CO2: @@ -91,10 +116,34 @@ bool Measurements::update(MeasurementType type, int val, int ch) { temporary = &_pm_10[ch]; invalidValue = utils::getInvalidPmValue(); break; + case PM01_SP: + temporary = &_pm_01_sp[ch]; + invalidValue = utils::getInvalidPmValue(); + break; + case PM25_SP: + temporary = &_pm_25_sp[ch]; + invalidValue = utils::getInvalidPmValue(); + break; + case PM10_SP: + temporary = &_pm_10_sp[ch]; + invalidValue = utils::getInvalidPmValue(); + break; case PM03_PC: temporary = &_pm_03_pc[ch]; invalidValue = utils::getInvalidPmValue(); break; + case PM01_PC: + temporary = &_pm_01_pc[ch]; + invalidValue = utils::getInvalidPmValue(); + break; + case PM25_PC: + temporary = &_pm_25_pc[ch]; + invalidValue = utils::getInvalidPmValue(); + break; + case PM10_PC: + temporary = &_pm_10_pc[ch]; + invalidValue = utils::getInvalidPmValue(); + break; default: break; }; @@ -155,6 +204,7 @@ bool Measurements::update(MeasurementType type, float val, int ch) { // Define data point source FloatValue *temporary = nullptr; + // Act as reference invalid value respective to target measurements float invalidValue = 0; switch (type) { case Temperature: @@ -344,16 +394,34 @@ String Measurements::measurementTypeStr(MeasurementType type) { str = "NOxRaw"; break; case PM25: - str = "PM25"; + str = "PM25_AE"; break; case PM01: - str = "PM01"; + str = "PM1_AE"; break; case PM10: - str = "PM10"; + str = "PM10_AE"; + break; + case PM25_SP: + str = "PM25_SP"; + break; + case PM01_SP: + str = "PM1_SP"; + break; + case PM10_SP: + str = "PM10_SP"; break; case PM03_PC: - str = "PM03"; + str = "PM003_PC"; + break; + case PM01_PC: + str = "PM01_PC"; + break; + case PM25_PC: + str = "PM25_PC"; + break; + case PM10_PC: + str = "PM10_PC"; break; default: break; @@ -524,9 +592,31 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem if (utils::isValidPm(_pm_10[ch].update.avg)) { pms["pm10"] = ag.round2(_pm_10[ch].update.avg); } + if (utils::isValidPm(_pm_01_sp[ch].update.avg)) { + pms["pm01Standard"] = ag.round2(_pm_01_sp[ch].update.avg); + } + if (utils::isValidPm(_pm_25_sp[ch].update.avg)) { + pms["pm02Standard"] = ag.round2(_pm_25_sp[ch].update.avg); + } + if (utils::isValidPm(_pm_10_sp[ch].update.avg)) { + pms["pm10Standard"] = ag.round2(_pm_10_sp[ch].update.avg); + } if (utils::isValidPm03Count(_pm_03_pc[ch].update.avg)) { pms["pm003Count"] = ag.round2(_pm_03_pc[ch].update.avg); } + if (utils::isValidPm03Count(_pm_01_pc[ch].update.avg)) { + pms["pm01Count"] = ag.round2(_pm_01_pc[ch].update.avg); + } + if (utils::isValidPm03Count(_pm_25_pc[ch].update.avg)) { + pms["pm02Count"] = ag.round2(_pm_25_pc[ch].update.avg); + } + if (_pm_10_pc[ch].listValues.empty() == false) { + // Only include pm10 count when values available on its list + // If not, means no pm10_pc available from the sensor + if (utils::isValidPm03Count(_pm_10_pc[ch].update.avg)) { + pms["pm10Count"] = ag.round2(_pm_10_pc[ch].update.avg); + } + } if (withTempHum) { float _vc; @@ -571,8 +661,10 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem return pms; }; - // Handle both channel with average, if one of the channel not valid, use another one - /// PM01 + /** Handle both channels by averaging their values; if one channel's value is not valid, skip + * averaging and use the valid value from the other channel */ + + /// PM1.0 atmospheric environment if (utils::isValidPm(_pm_01[0].update.avg) && utils::isValidPm(_pm_01[1].update.avg)) { float avg = (_pm_01[0].update.avg + _pm_01[1].update.avg) / 2.0f; pms["pm01"] = ag.round2(avg); @@ -586,7 +678,7 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem pms["channels"]["2"]["pm01"] = ag.round2(_pm_01[1].update.avg); } - /// PM2.5 + /// PM2.5 atmospheric environment if (utils::isValidPm(_pm_25[0].update.avg) && utils::isValidPm(_pm_25[1].update.avg)) { float avg = (_pm_25[0].update.avg + _pm_25[1].update.avg) / 2.0f; pms["pm02"] = ag.round2(avg); @@ -600,7 +692,7 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem pms["channels"]["2"]["pm02"] = ag.round2(_pm_25[1].update.avg); } - /// PM10 + /// PM10 atmospheric environment if (utils::isValidPm(_pm_10[0].update.avg) && utils::isValidPm(_pm_10[1].update.avg)) { float avg = (_pm_10[0].update.avg + _pm_10[1].update.avg) / 2.0f; pms["pm10"] = ag.round2(avg); @@ -614,7 +706,49 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem pms["channels"]["2"]["pm10"] = ag.round2(_pm_10[1].update.avg); } - /// PM03 particle count + /// PM1.0 standard particle + if (utils::isValidPm(_pm_01_sp[0].update.avg) && utils::isValidPm(_pm_01_sp[1].update.avg)) { + float avg = (_pm_01_sp[0].update.avg + _pm_01_sp[1].update.avg) / 2.0f; + pms["pm01Standard"] = ag.round2(avg); + pms["channels"]["1"]["pm01Standard"] = ag.round2(_pm_01_sp[0].update.avg); + pms["channels"]["2"]["pm01Standard"] = ag.round2(_pm_01_sp[1].update.avg); + } else if (utils::isValidPm(_pm_01_sp[0].update.avg)) { + pms["pm01Standard"] = ag.round2(_pm_01_sp[0].update.avg); + pms["channels"]["1"]["pm01Standard"] = ag.round2(_pm_01_sp[0].update.avg); + } else if (utils::isValidPm(_pm_01_sp[1].update.avg)) { + pms["pm01Standard"] = ag.round2(_pm_01_sp[1].update.avg); + pms["channels"]["2"]["pm01Standard"] = ag.round2(_pm_01_sp[1].update.avg); + } + + /// PM2.5 standard particle + if (utils::isValidPm(_pm_25_sp[0].update.avg) && utils::isValidPm(_pm_25_sp[1].update.avg)) { + float avg = (_pm_25_sp[0].update.avg + _pm_25_sp[1].update.avg) / 2.0f; + pms["pm02Standard"] = ag.round2(avg); + pms["channels"]["1"]["pm02Standard"] = ag.round2(_pm_25_sp[0].update.avg); + pms["channels"]["2"]["pm02Standard"] = ag.round2(_pm_25_sp[1].update.avg); + } else if (utils::isValidPm(_pm_25_sp[0].update.avg)) { + pms["pm02Standard"] = ag.round2(_pm_25_sp[0].update.avg); + pms["channels"]["1"]["pm02Standard"] = ag.round2(_pm_25_sp[0].update.avg); + } else if (utils::isValidPm(_pm_25_sp[1].update.avg)) { + pms["pm02Standard"] = ag.round2(_pm_25_sp[1].update.avg); + pms["channels"]["2"]["pm02Standard"] = ag.round2(_pm_25_sp[1].update.avg); + } + + /// PM10 standard particle + if (utils::isValidPm(_pm_10_sp[0].update.avg) && utils::isValidPm(_pm_10_sp[1].update.avg)) { + float avg = (_pm_10_sp[0].update.avg + _pm_10_sp[1].update.avg) / 2.0f; + pms["pm10Standard"] = ag.round2(avg); + pms["channels"]["1"]["pm10Standard"] = ag.round2(_pm_10_sp[0].update.avg); + pms["channels"]["2"]["pm10Standard"] = ag.round2(_pm_10_sp[1].update.avg); + } else if (utils::isValidPm(_pm_10_sp[0].update.avg)) { + pms["pm10Standard"] = ag.round2(_pm_10_sp[0].update.avg); + pms["channels"]["1"]["pm10Standard"] = ag.round2(_pm_10_sp[0].update.avg); + } else if (utils::isValidPm(_pm_10_sp[1].update.avg)) { + pms["pm10Standard"] = ag.round2(_pm_10_sp[1].update.avg); + pms["channels"]["2"]["pm10Standard"] = ag.round2(_pm_10_sp[1].update.avg); + } + + /// PM003 particle count if (utils::isValidPm03Count(_pm_03_pc[0].update.avg) && utils::isValidPm03Count(_pm_03_pc[1].update.avg)) { float avg = (_pm_03_pc[0].update.avg + _pm_03_pc[1].update.avg) / 2.0f; @@ -629,6 +763,53 @@ JSONVar Measurements::buildPMS(AirGradient &ag, int ch, bool allCh, bool withTem pms["channels"]["2"]["pm003Count"] = ag.round2(_pm_03_pc[1].update.avg); } + /// PM1.0 particle count + if (utils::isValidPm03Count(_pm_01_pc[0].update.avg) && + utils::isValidPm03Count(_pm_01_pc[1].update.avg)) { + float avg = (_pm_01_pc[0].update.avg + _pm_01_pc[1].update.avg) / 2.0f; + pms["pm01Count"] = ag.round2(avg); + pms["channels"]["1"]["pm01Count"] = ag.round2(_pm_01_pc[0].update.avg); + pms["channels"]["2"]["pm01Count"] = ag.round2(_pm_01_pc[1].update.avg); + } else if (utils::isValidPm(_pm_01_pc[0].update.avg)) { + pms["pm01Count"] = ag.round2(_pm_01_pc[0].update.avg); + pms["channels"]["1"]["pm01Count"] = ag.round2(_pm_01_pc[0].update.avg); + } else if (utils::isValidPm(_pm_01_pc[1].update.avg)) { + pms["pm01Count"] = ag.round2(_pm_01_pc[1].update.avg); + pms["channels"]["2"]["pm01Count"] = ag.round2(_pm_01_pc[1].update.avg); + } + + /// PM2.5 particle count + if (utils::isValidPm03Count(_pm_25_pc[0].update.avg) && + utils::isValidPm03Count(_pm_25_pc[1].update.avg)) { + float avg = (_pm_25_pc[0].update.avg + _pm_25_pc[1].update.avg) / 2.0f; + pms["pm25Count"] = ag.round2(avg); + pms["channels"]["1"]["pm25Count"] = ag.round2(_pm_25_pc[0].update.avg); + pms["channels"]["2"]["pm25Count"] = ag.round2(_pm_25_pc[1].update.avg); + } else if (utils::isValidPm(_pm_25_pc[0].update.avg)) { + pms["pm25Count"] = ag.round2(_pm_25_pc[0].update.avg); + pms["channels"]["1"]["pm25Count"] = ag.round2(_pm_25_pc[0].update.avg); + } else if (utils::isValidPm(_pm_25_pc[1].update.avg)) { + pms["pm25Count"] = ag.round2(_pm_25_pc[1].update.avg); + pms["channels"]["2"]["pm25Count"] = ag.round2(_pm_25_pc[1].update.avg); + } + + // NOTE: No need for particle count 10. When allCh is true, basically monitor using PM5003T, which + // don't have PC 10 + // /// PM10 particle count + // if (utils::isValidPm03Count(_pm_10_pc[0].update.avg) && + // utils::isValidPm03Count(_pm_10_pc[1].update.avg)) { + // float avg = (_pm_10_pc[0].update.avg + _pm_10_pc[1].update.avg) / 2.0f; + // pms["pm10Count"] = ag.round2(avg); + // pms["channels"]["1"]["pm10Count"] = ag.round2(_pm_10_pc[0].update.avg); + // pms["channels"]["2"]["pm10Count"] = ag.round2(_pm_10_pc[1].update.avg); + // } else if (utils::isValidPm(_pm_10_pc[0].update.avg)) { + // pms["pm10Count"] = ag.round2(_pm_10_pc[0].update.avg); + // pms["channels"]["1"]["pm10Count"] = ag.round2(_pm_10_pc[0].update.avg); + // } else if (utils::isValidPm(_pm_10_pc[1].update.avg)) { + // pms["pm10Count"] = ag.round2(_pm_10_pc[1].update.avg); + // pms["channels"]["2"]["pm10Count"] = ag.round2(_pm_10_pc[1].update.avg); + // } + if (withTempHum) { /// Temperature if (utils::isValidTemperature(_temperature[0].update.avg) && diff --git a/src/AgValue.h b/src/AgValue.h index 8c26bf2..cb723a0 100644 --- a/src/AgValue.h +++ b/src/AgValue.h @@ -46,10 +46,16 @@ public: TVOCRaw, NOx, // index value NOxRaw, - PM25, - PM01, - PM10, - PM03_PC, // Particle count + PM01, // PM1.0 under atmospheric environment + PM25, // PM2.5 under athompheric environment + PM10, // PM10 under atmospheric environment + PM01_SP, // PM1.0 standard particle + PM25_SP, // PM2.5 standard particle + PM10_SP, // PM10 standard particle + PM03_PC, // Particle 0.3 count + PM01_PC, // Particle 1.0 count + PM25_PC, // Particle 2.5 count + PM10_PC, // Particle 10 count }; /** @@ -129,10 +135,16 @@ private: IntegerValue _tvoc_raw; IntegerValue _nox; // Index value IntegerValue _nox_raw; - IntegerValue _pm_25[2]; - IntegerValue _pm_01[2]; - IntegerValue _pm_10[2]; + IntegerValue _pm_01[2]; // pm 1.0 atmospheric environment + IntegerValue _pm_25[2]; // pm 2.5 atmospheric environment + IntegerValue _pm_10[2]; // pm 10 atmospheric environment + IntegerValue _pm_01_sp[2]; // pm 1.0 standard particle + IntegerValue _pm_25_sp[2]; // pm 2.5 standard particle + IntegerValue _pm_10_sp[2]; // pm 10 standard particle IntegerValue _pm_03_pc[2]; // particle count 0.3 + IntegerValue _pm_01_pc[2]; // particle count 1.0 + IntegerValue _pm_25_pc[2]; // particle count 2.5 + IntegerValue _pm_10_pc[2]; // particle count 10 bool _debug = false; diff --git a/src/PMS/PMS.cpp b/src/PMS/PMS.cpp index 45c16c0..68df585 100644 --- a/src/PMS/PMS.cpp +++ b/src/PMS/PMS.cpp @@ -399,20 +399,26 @@ bool PMSBase::validate(const uint8_t *buf) { } void PMSBase::parse(const uint8_t *buf) { + // Standard particle pms_raw0_1 = toU16(&buf[4]); pms_raw2_5 = toU16(&buf[6]); pms_raw10 = toU16(&buf[8]); + // atmospheric pms_pm0_1 = toU16(&buf[10]); pms_pm2_5 = toU16(&buf[12]); pms_pm10 = toU16(&buf[14]); + + // particle count pms_count0_3 = toU16(&buf[16]); pms_count0_5 = toU16(&buf[18]); pms_count1_0 = toU16(&buf[20]); pms_count2_5 = toU16(&buf[22]); - pms_count5_0 = toU16(&buf[24]); - pms_count10 = toU16(&buf[26]); - pms_temp = toU16(&buf[24]); - pms_hum = toU16(&buf[26]); + pms_count5_0 = toU16(&buf[24]); // PMS5003 only + pms_count10 = toU16(&buf[26]); // PMS5003 only + + // Others + pms_temp = toU16(&buf[24]); // PMS5003T only + pms_hum = toU16(&buf[26]); // PMS5003T only pms_firmwareVersion = buf[28]; pms_errorCode = buf[29]; } diff --git a/src/PMS/PMS5003.cpp b/src/PMS/PMS5003.cpp index 7b021bf..5b8cdfd 100644 --- a/src/PMS/PMS5003.cpp +++ b/src/PMS/PMS5003.cpp @@ -79,28 +79,49 @@ bool PMS5003::begin(void) { } /** - * @brief Read PM1.0 must call this function after @ref readData success + * @brief Read PM1.0 * - * @return int PM1.0 index + * @return int PM1.0 index (atmospheric environment) */ int PMS5003::getPm01Ae(void) { return pms.getPM0_1(); } /** - * @brief Read PM2.5 must call this function after @ref readData success + * @brief Read PM2.5 * - * @return int PM2.5 index + * @return int PM2.5 index (atmospheric environment) */ int PMS5003::getPm25Ae(void) { return pms.getPM2_5(); } /** - * @brief Read PM10.0 must call this function after @ref readData success + * @brief Read PM10.0 * - * @return int PM10.0 index + * @return int PM10.0 index (atmospheric environment) */ int PMS5003::getPm10Ae(void) { return pms.getPM10(); } /** - * @brief Read PM0.3 must call this function after @ref readData success + * @brief Read PM1.0 + * + * @return int PM1.0 index (standard particle) + */ +int PMS5003::getPm01Sp(void) { return pms.getRaw0_1(); } + +/** + * @brief Read PM2.5 + * + * @return int PM2.5 index (standard particle) + */ +int PMS5003::getPm25Sp(void) { return pms.getRaw2_5(); } + +/** + * @brief Read PM10 + * + * @return int PM10 index (standard particle) + */ +int PMS5003::getPm10Sp(void) { return pms.getRaw10(); } + +/** + * @brief Read particle 0.3 count * * @return int PM0.3 index */ @@ -108,6 +129,27 @@ int PMS5003::getPm03ParticleCount(void) { return pms.getCount0_3(); } +/** + * @brief Read particle 1.0 count + * + * @return int particle 1.0 count index + */ +int PMS5003::getPm01ParticleCount(void) { return pms.getCount1_0(); } + +/** + * @brief Read particle 2.5 count + * + * @return int particle 2.5 count index + */ +int PMS5003::getPm25ParticleCount(void) { return pms.getCount2_5(); } + +/** + * @brief Read particle 10 count + * + * @return int particle 10 count index + */ +int PMS5003::getPm10ParticleCount(void) { return pms.getCount10(); } + /** * @brief Convert PM2.5 to US AQI * diff --git a/src/PMS/PMS5003.h b/src/PMS/PMS5003.h index d8fc862..0e3ca13 100644 --- a/src/PMS/PMS5003.h +++ b/src/PMS/PMS5003.h @@ -25,10 +25,20 @@ public: void resetFailCount(void); int getFailCount(void); int getFailCountMax(void); + // Atmospheric environment int getPm01Ae(void); int getPm25Ae(void); int getPm10Ae(void); + // Standard particle + int getPm01Sp(void); + int getPm25Sp(void); + int getPm10Sp(void); + // Particle count int getPm03ParticleCount(void); + int getPm01ParticleCount(void); + int getPm25ParticleCount(void); + int getPm10ParticleCount(void); + int convertPm25ToUsAqi(int pm25); float compensate(float pm25, float humidity); int getFirmwareVersion(void); diff --git a/src/PMS/PMS5003T.cpp b/src/PMS/PMS5003T.cpp index 38ce259..e43ea91 100644 --- a/src/PMS/PMS5003T.cpp +++ b/src/PMS/PMS5003T.cpp @@ -108,35 +108,70 @@ bool PMS5003T::begin(void) { } /** - * @brief Read PM1.0 must call this function after @ref readData success + * @brief Read PM1.0 * - * @return int PM1.0 index + * @return int PM1.0 index (atmospheric environment) */ int PMS5003T::getPm01Ae(void) { return pms.getPM0_1(); } /** - * @brief Read PM2.5 must call this function after @ref readData success + * @brief Read PM2.5 * - * @return int PM2.5 index + * @return int PM2.5 index (atmospheric environment) */ int PMS5003T::getPm25Ae(void) { return pms.getPM2_5(); } /** - * @brief Read PM10.0 must call this function after @ref readData success + * @brief Read PM10.0 * - * @return int PM10.0 index + * @return int PM10.0 index (atmospheric environment) */ int PMS5003T::getPm10Ae(void) { return pms.getPM10(); } /** - * @brief Read PM 0.3 Count must call this function after @ref readData success + * @brief Read PM1.0 * - * @return int PM 0.3 Count index + * @return int PM1.0 index (standard particle) + */ +int PMS5003T::getPm01Sp(void) { return pms.getRaw0_1(); } + +/** + * @brief Read PM2.5 + * + * @return int PM2.5 index (standard particle) + */ +int PMS5003T::getPm25Sp(void) { return pms.getRaw2_5(); } + +/** + * @brief Read PM10 + * + * @return int PM10 index (standard particle) + */ +int PMS5003T::getPm10Sp(void) { return pms.getRaw10(); } + +/** + * @brief Read particle 0.3 count + * + * @return int particle 0.3 count index */ int PMS5003T::getPm03ParticleCount(void) { return pms.getCount0_3(); } +/** + * @brief Read particle 1.0 count + * + * @return int particle 1.0 count index + */ +int PMS5003T::getPm01ParticleCount(void) { return pms.getCount1_0(); } + +/** + * @brief Read particle 2.5 count + * + * @return int particle 2.5 count index + */ +int PMS5003T::getPm25ParticleCount(void) { return pms.getCount2_5(); } + /** * @brief Convert PM2.5 to US AQI * diff --git a/src/PMS/PMS5003T.h b/src/PMS/PMS5003T.h index eac4a8d..695439b 100644 --- a/src/PMS/PMS5003T.h +++ b/src/PMS/PMS5003T.h @@ -28,10 +28,19 @@ public: void resetFailCount(void); int getFailCount(void); int getFailCountMax(void); + // Atmospheric environment int getPm01Ae(void); int getPm25Ae(void); int getPm10Ae(void); + // Standard particle + int getPm01Sp(void); + int getPm25Sp(void); + int getPm10Sp(void); + // Particle count int getPm03ParticleCount(void); + int getPm01ParticleCount(void); + int getPm25ParticleCount(void); + int convertPm25ToUsAqi(int pm25); float getTemperature(void); float getRelativeHumidity(void);