-
Notifications
You must be signed in to change notification settings - Fork 115
Ppd42 x #577
base: dev
Are you sure you want to change the base?
Ppd42 x #577
Changes from 74 commits
eb4ee37
49ed1e3
9b8a2da
f001306
c5b0579
92055b2
da62e60
d330b25
93a4742
eea52c8
ff5ccdd
6c4d904
9d89b61
a52c2a6
96f38d5
f6d1f44
abf3fc8
5c81c0e
c4de101
f9fbfc3
823f72b
1cb9e49
40f1fa8
cfefff8
2110a3c
09196ff
a88d08a
a35e654
879c8a0
8aa1b78
5dde068
994face
0d2d43f
263b835
f3363d4
86b9d92
cb4e98c
21330b4
5b62b37
84f147c
2161981
c554d90
c640774
48865e5
4d3e524
eceeec2
f851b06
9ccc6aa
dc09017
9131ad9
8fb6901
bc5c738
4e56ff3
0a4b26c
920c14d
9796be0
c588de9
ea5b175
491fb94
d65557c
52058f3
a7b16b1
38dff4d
6420022
5b80aa8
9aab896
b9fdb4e
c6075cd
f582d7a
5dea20f
5b92680
20c8739
6eebc5b
d1fdc67
0146dd5
3f7d1d6
feef5e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ lib_deps = | |
ESP Async [email protected] | ||
[email protected] | ||
[email protected] | ||
ESPAsyncTCP@1.2.0 | ||
ESPAsyncTCP@1.1.3 | ||
build_flags = | ||
-Wno-reorder | ||
-DUSE_WEB_SERVER | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
#include "esphome/defines.h" | ||
|
||
#ifdef USE_PPD42X | ||
|
||
#include "esphome/sensor/ppd42x.h" | ||
#include "esphome/log.h" | ||
|
||
ESPHOME_NAMESPACE_BEGIN | ||
|
||
namespace sensor { | ||
|
||
static const char *TAG = "sensor.ppd42x"; | ||
|
||
PPD42XComponent::PPD42XComponent(PPD42XType type, uint32_t update_interval, uint32_t time_out) | ||
: ctype_(type), ui_(update_interval), timeout_ms_(time_out) {} | ||
|
||
void PPD42XComponent::loop() { | ||
const uint32_t now = millis(); | ||
if ((now - this->starttime_) > this->ui_) { | ||
uint32_t duration_pl_02_5 = pulseIn(this->pl_02_5_sensor_->pl_pin_->get_pin(), | ||
uint8_t(!this->pl_02_5_sensor_->pl_pin_->is_inverted()), this->timeout_ms_); | ||
uint32_t duration_pl_10_0 = pulseIn(this->pl_10_0_sensor_->pl_pin_->get_pin(), | ||
uint8_t(!this->pl_10_0_sensor_->pl_pin_->is_inverted()), this->timeout_ms_); | ||
this->lowpulseoccupancy_02_5_ = this->lowpulseoccupancy_02_5_ + duration_pl_02_5; | ||
this->lowpulseoccupancy_10_0_ = this->lowpulseoccupancy_10_0_ + duration_pl_10_0; | ||
|
||
if ((now - this->starttime_) > this->timeout_ms_) { | ||
// last transmission too long ago | ||
this->starttime_ = now; | ||
parse_data_(); | ||
} | ||
} | ||
} | ||
|
||
float PPD42XComponent::get_setup_priority() const { return setup_priority::HARDWARE_LATE; } | ||
|
||
void PPD42XComponent::parse_data_() { | ||
switch (this->ctype_) { | ||
case PPD42X_TYPE: { | ||
float pl_02_5_concentration = us_to_pl(this->lowpulseoccupancy_02_5_, this->timeout_ms_); | ||
float pl_10_0_concentration = us_to_pl(this->lowpulseoccupancy_10_0_, this->timeout_ms_); | ||
ESP_LOGD(TAG, "Got PM2.5 Concentration %.0f pcs/L, PM10.0 Concentration: %f pcs/L", pl_02_5_concentration, | ||
pl_10_0_concentration); | ||
if (this->pl_02_5_sensor_ != nullptr) | ||
this->pl_02_5_sensor_->publish_state(pl_02_5_concentration); | ||
if (this->pl_10_0_sensor_ != nullptr) | ||
this->pl_10_0_sensor_->publish_state(pl_10_0_concentration); | ||
break; | ||
} | ||
case PPD42X_TYPE_NS: { | ||
float pl_02_5_concentration = us_to_pl(this->lowpulseoccupancy_02_5_, this->timeout_ms_); | ||
float pl_10_0_concentration = us_to_pl(this->lowpulseoccupancy_10_0_, this->timeout_ms_); | ||
ESP_LOGD(TAG, "Got PM2.5 Concentration %.0f pcs/L, PM10.0 Concentration: %f pcs/L", pl_02_5_concentration, | ||
pl_10_0_concentration); | ||
if (this->pl_02_5_sensor_ != nullptr) | ||
this->pl_02_5_sensor_->publish_state(pl_02_5_concentration); | ||
if (this->pl_10_0_sensor_ != nullptr) | ||
this->pl_10_0_sensor_->publish_state(pl_10_0_concentration); | ||
break; | ||
} | ||
case PPD42X_TYPE_NJ: { | ||
float pl_02_5_concentration = us_to_pl(this->lowpulseoccupancy_02_5_, this->timeout_ms_); | ||
float pl_10_0_concentration = us_to_pl(this->lowpulseoccupancy_10_0_, this->timeout_ms_); | ||
ESP_LOGD(TAG, "Got PM2.5 Concentration %.0f pcs/L, PM10.0 Concentration: %f pcs/L", pl_02_5_concentration, | ||
pl_10_0_concentration); | ||
if (this->pl_02_5_sensor_ != nullptr) | ||
this->pl_02_5_sensor_->publish_state(pl_02_5_concentration); | ||
if (this->pl_10_0_sensor_ != nullptr) | ||
this->pl_10_0_sensor_->publish_state(pl_10_0_concentration); | ||
break; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the difference between these switch cases? They all look the same to me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. we may have only one sensor ? PM2.5 or PM10.0 or both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, I mean why do you differentiate between |
||
} | ||
} | ||
} | ||
|
||
float PPD42XComponent::us_to_pl(uint32_t sample_length, uint32_t time_pm) { | ||
float ratio = time_pm / (sample_length * 10.0f); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why does this depend on the timeout value? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. this is the recommended max value to listen to ! There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I mean why does this calculation depend on the timeout? The sensor doesn't know which timeout we chose, so how can this calculation depend on the timeout value There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nop, the sensor send continuously data. |
||
return 1.1f * powf(ratio, 3) - 3.8f * powf(ratio, 2) + 520.0f * ratio + 0.62f; | ||
} | ||
|
||
PPD42XSensor *PPD42XComponent::make_pl_02_5_sensor(const std::string &name, GPIOInputPin *pl) { | ||
return this->pl_02_5_sensor_ = new PPD42XSensor(name, pl, PPD42X_SENSOR_TYPE_PM_02_5); | ||
} | ||
|
||
PPD42XSensor *PPD42XComponent::make_pl_10_0_sensor(const std::string &name, GPIOInputPin *pl) { | ||
return this->pl_10_0_sensor_ = new PPD42XSensor(name, pl, PPD42X_SENSOR_TYPE_PM_10_0); | ||
} | ||
|
||
void PPD42XComponent::dump_config() { | ||
ESP_LOGCONFIG(TAG, "PPD42X:"); | ||
LOG_SENSOR(" ", "PM2.5", this->pl_02_5_sensor_); | ||
LOG_SENSOR(" ", "PM10.0", this->pl_10_0_sensor_); | ||
} | ||
|
||
std::string PPD42XSensor::unit_of_measurement() { | ||
switch (this->stype_) { | ||
case PPD42X_SENSOR_TYPE_PM_02_5: | ||
case PPD42X_SENSOR_TYPE_PM_10_0: | ||
return UNIT_PARTICLES_PER_LITER; | ||
} | ||
return ""; | ||
} | ||
|
||
std::string PPD42XSensor::icon() { | ||
switch (this->stype_) { | ||
case PPD42X_SENSOR_TYPE_PM_02_5: | ||
case PPD42X_SENSOR_TYPE_PM_10_0: | ||
// Not the ideal icon, but Otto can't find a better one ;) | ||
return ICON_CHEMICAL_WEAPON; | ||
} | ||
return ""; | ||
} | ||
|
||
int8_t PPD42XSensor::accuracy_decimals() { | ||
switch (this->stype_) { | ||
case PPD42X_SENSOR_TYPE_PM_02_5: | ||
case PPD42X_SENSOR_TYPE_PM_10_0: | ||
return 0; | ||
} | ||
return 0; | ||
} | ||
// void PPD42XComponent::set_timeout_us(uint32_t timeout_us) { this->timeout_ms_ = timeout_us; } | ||
|
||
PPD42XSensor::PPD42XSensor(const std::string &name, GPIOInputPin *pl, PPD42XSensorType type) | ||
: Sensor(name), pl_pin_(pl), stype_(type) {} | ||
} // namespace sensor | ||
|
||
ESPHOME_NAMESPACE_END | ||
|
||
#endif // USE_PPD42X |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#ifndef ESPHOME_SENSOR_PPD42X_H | ||
#define ESPHOME_SENSOR_PPD42X_H | ||
|
||
#include "esphome/defines.h" | ||
|
||
#ifdef USE_PPD42X | ||
|
||
#include "esphome/component.h" | ||
#include "esphome/sensor/sensor.h" | ||
#include "esphome/helpers.h" | ||
|
||
ESPHOME_NAMESPACE_BEGIN | ||
|
||
namespace sensor { | ||
|
||
enum PPD42XType { | ||
PPD42X_TYPE = 0, | ||
PPD42X_TYPE_NJ, | ||
PPD42X_TYPE_NS, | ||
}; | ||
|
||
enum PPD42XSensorType { | ||
/// PM2.5 concentration in pcs/L, PPD42, PPD42NJ, PPD42NS | ||
PPD42X_SENSOR_TYPE_PM_02_5, | ||
/// PM10.0 concentration in pcs/L, PPD42X | ||
PPD42X_SENSOR_TYPE_PM_10_0, | ||
}; | ||
|
||
class PPD42XSensor : public sensor::Sensor { | ||
public: | ||
PPD42XSensor(const std::string &name, GPIOInputPin *pl, PPD42XSensorType type); | ||
|
||
std::string unit_of_measurement() override; | ||
std::string icon() override; | ||
int8_t accuracy_decimals() override; | ||
GPIOInputPin *pl_pin_; | ||
|
||
protected: | ||
const PPD42XSensorType stype_; | ||
|
||
}; // class PPD42XSensor | ||
|
||
class PPD42XComponent : public Component { | ||
public: | ||
PPD42XComponent(PPD42XType type, uint32_t update_interval, uint32_t time_out); | ||
void set_timeout_us(uint32_t timeout_us); | ||
void loop() override; | ||
float get_setup_priority() const override; | ||
void dump_config() override; | ||
|
||
PPD42XSensor *make_pl_02_5_sensor(const std::string &name, GPIOInputPin *pl); | ||
PPD42XSensor *make_pl_10_0_sensor(const std::string &name, GPIOInputPin *pl); | ||
|
||
protected: | ||
void parse_data_(); | ||
static float us_to_pl(uint32_t sample_length, uint32_t time_pm); | ||
|
||
uint32_t timeout_ms_{30}; | ||
uint32_t starttime_{0}; | ||
uint32_t lowpulseoccupancy_02_5_{0}; | ||
uint32_t lowpulseoccupancy_10_0_{0}; | ||
|
||
uint32_t last_transmission_{0}; | ||
uint32_t ui_{0}; | ||
const PPD42XType ctype_; | ||
PPD42XSensor *pl_02_5_sensor_{nullptr}; | ||
PPD42XSensor *pl_10_0_sensor_{nullptr}; | ||
}; // class PPD42XComponent | ||
|
||
} // namespace sensor | ||
|
||
ESPHOME_NAMESPACE_END | ||
|
||
#endif // USE_PPD42X | ||
|
||
#endif // ESPHOME_SENSOR_PPD42X_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove this.