Skip to content
This repository has been archived by the owner on Sep 27, 2023. It is now read-only.

Ppd42 x #577

Open
wants to merge 77 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 74 commits
Commits
Show all changes
77 commits
Select commit Hold shift + click to select a range
eb4ee37
test
pi4homez Mar 30, 2019
49ed1e3
tests.yaml
pi4homez Mar 31, 2019
9b8a2da
us_to_pm fix
pi4homez Mar 31, 2019
f001306
us_to_pm fix 2
pi4homez Mar 31, 2019
c5b0579
pm_02_5_pin_ fix
pi4homez Mar 31, 2019
92055b2
pm_02_5_pin_ fix 2
pi4homez Mar 31, 2019
da62e60
uper case fix
pi4homez Mar 31, 2019
d330b25
ident fix
pi4homez Mar 31, 2019
93a4742
spaces fix
pi4homez Mar 31, 2019
eea52c8
spaces fix 2
pi4homez Mar 31, 2019
ff5ccdd
spaces fix 3
pi4homez Mar 31, 2019
6c4d904
spaces fix 4
pi4homez Mar 31, 2019
9d89b61
test
pi4homez Mar 30, 2019
a52c2a6
tests.yaml
pi4homez Mar 31, 2019
96f38d5
us_to_pm fix
pi4homez Mar 31, 2019
f6d1f44
us_to_pm fix 2
pi4homez Mar 31, 2019
abf3fc8
pm_02_5_pin_ fix
pi4homez Mar 31, 2019
5c81c0e
pm_02_5_pin_ fix 2
pi4homez Mar 31, 2019
c4de101
uper case fix
pi4homez Mar 31, 2019
f9fbfc3
ident fix
pi4homez Mar 31, 2019
823f72b
spaces fix
pi4homez Mar 31, 2019
1cb9e49
spaces fix 2
pi4homez Mar 31, 2019
40f1fa8
spaces fix 3
pi4homez Mar 31, 2019
cfefff8
spaces fix 4
pi4homez Mar 31, 2019
2110a3c
Merge branch 'PPD42X' of https://github.com/pi4homez/esphome-core int…
pi4homez Mar 31, 2019
09196ff
ppd42x txt 5
pi4homez Mar 31, 2019
a88d08a
Refactore ppd42x.py
pi4homez Apr 5, 2019
a35e654
Refactore ppd42x.py
pi4homez Apr 5, 2019
879c8a0
Refactore ppd42x.py
pi4homez Apr 5, 2019
8aa1b78
Refactore ppd42x.py
pi4homez Apr 6, 2019
5dde068
Refactore ppd42x.py
pi4homez Apr 6, 2019
994face
Refactore ppd42x.py
pi4homez Apr 6, 2019
0d2d43f
Refactore ppd42x.py
pi4homez Apr 6, 2019
263b835
Refactore ppd42x.py
pi4homez Apr 6, 2019
f3363d4
Refactore ppd42x.py
pi4homez Apr 6, 2019
86b9d92
Refactore ppd42x.py
pi4homez Apr 6, 2019
cb4e98c
Refactore ppd42x.py
pi4homez Apr 6, 2019
21330b4
Refactore ppd42x.py
pi4homez Apr 6, 2019
5b62b37
Refactore ppd42x.py
pi4homez Apr 6, 2019
84f147c
Refactore ppd42x.py
pi4homez Apr 6, 2019
2161981
Refactore ppd42x.py
pi4homez Apr 6, 2019
c554d90
from scrach
pi4homez Apr 7, 2019
c640774
from scrach
pi4homez Apr 7, 2019
48865e5
from scrach
pi4homez Apr 7, 2019
4d3e524
from scrach
pi4homez Apr 7, 2019
eceeec2
from scrach
pi4homez Apr 7, 2019
f851b06
from scrach
pi4homez Apr 7, 2019
9ccc6aa
from scrach
pi4homez Apr 7, 2019
dc09017
syntax error-
pi4homez Apr 7, 2019
9131ad9
syntax error--
pi4homez Apr 7, 2019
8fb6901
adapt +
pi4homez Apr 7, 2019
bc5c738
adapt ++
pi4homez Apr 7, 2019
4e56ff3
adapt +++
pi4homez Apr 7, 2019
0a4b26c
adapt ++++
pi4homez Apr 7, 2019
920c14d
adapt +++++
pi4homez Apr 7, 2019
9796be0
adapt +++++!
pi4homez Apr 7, 2019
c588de9
adapt +++++git add .
pi4homez Apr 7, 2019
ea5b175
adapt ++++git add .git add .git add .
pi4homez Apr 7, 2019
491fb94
adapt ++++++
pi4homez Apr 7, 2019
d65557c
adapt +++++++
pi4homez Apr 7, 2019
52058f3
includ otto remarks
pi4homez Apr 7, 2019
a7b16b1
includ otto remarks
pi4homez Apr 7, 2019
38dff4d
includ otto remarks
pi4homez Apr 7, 2019
6420022
includ otto remarks
pi4homez Apr 7, 2019
5b80aa8
includ otto remarks
pi4homez Apr 7, 2019
9aab896
includ otto remarks
pi4homez Apr 7, 2019
b9fdb4e
includ otto remarks
pi4homez Apr 7, 2019
c6075cd
includ otto remarks
pi4homez Apr 7, 2019
f582d7a
includ otto remarks
pi4homez Apr 7, 2019
5dea20f
includ otto remarks
pi4homez Apr 7, 2019
5b92680
includ otto remarks
pi4homez Apr 7, 2019
20c8739
include otto remarks
pi4homez Apr 7, 2019
6eebc5b
include otto remarks
pi4homez Apr 10, 2019
d1fdc67
Update defines.h
pi4homez Apr 14, 2019
0146dd5
res conflict
pi4homez Apr 14, 2019
3f7d1d6
res conflict
pi4homez Apr 14, 2019
feef5e2
conflict
pi4homez Apr 14, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ lib_deps =
ESP Async [email protected]
[email protected]
[email protected]
ESPAsyncTCP@1.2.0
ESPAsyncTCP@1.1.3
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove this.

build_flags =
-Wno-reorder
-DUSE_WEB_SERVER
Expand Down
8 changes: 7 additions & 1 deletion src/esphome/application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,7 +432,6 @@ sensor::UltrasonicSensorComponent *Application::make_ultrasonic_sensor(const std
return ultrasonic;
}
#endif

#ifdef USE_WIFI_SIGNAL_SENSOR
sensor::WiFiSignalSensor *Application::make_wifi_signal_sensor(const std::string &name, uint32_t update_interval) {
auto *wifi = this->register_component(new WiFiSignalSensor(name, update_interval));
Expand Down Expand Up @@ -1090,6 +1089,13 @@ sensor::PMSX003Component *Application::make_pmsx003(UARTComponent *parent, senso
}
#endif

#ifdef USE_PPD42X
sensor::PPD42XComponent *Application::make_ppd42x(sensor::PPD42XType type, uint32_t update_interval,
uint32_t time_out) {
return this->register_component(new PPD42XComponent(type, time_out, update_interval));
}
#endif

#ifdef USE_A4988
stepper::A4988 *Application::make_a4988(const GPIOOutputPin &step_pin, const GPIOOutputPin &dir_pin) {
return this->register_component(new A4988(step_pin.copy(), dir_pin.copy()));
Expand Down
5 changes: 5 additions & 0 deletions src/esphome/application.h
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,7 @@
#include "esphome/sensor/mqtt_subscribe_sensor.h"
#include "esphome/sensor/ms5611.h"
#include "esphome/sensor/pmsx003.h"
#include "esphome/sensor/ppd42x.h"
#include "esphome/sensor/pulse_counter.h"
#include "esphome/sensor/rotary_encoder.h"
#include "esphome/sensor/sensor.h"
Expand Down Expand Up @@ -810,6 +811,10 @@ class Application {
#ifdef USE_PMSX003
sensor::PMSX003Component *make_pmsx003(UARTComponent *parent, sensor::PMSX003Type type);
#endif
#ifdef USE_PPD42X
sensor::PPD42XComponent *make_ppd42x(sensor::PPD42XType type, uint32_t update_interval = 60000,
uint32_t time_out = 30000);
#endif

#ifdef USE_TOTAL_DAILY_ENERGY_SENSOR
sensor::TotalDailyEnergy *make_total_daily_energy_sensor(const std::string &name, time::RealTimeClockComponent *time,
Expand Down
3 changes: 3 additions & 0 deletions src/esphome/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,9 @@
#define USE_MQTT_SUBSCRIBE_SENSOR
#define USE_CSE7766
#define USE_PMSX003
#define USE_PPD42X
#define USE_ENDSTOP_COVER
#define USE_TIME_BASED_COVER
#define USE_STEPPER
#define USE_A4988
#define USE_ULN2003
Expand Down
129 changes: 129 additions & 0 deletions src/esphome/sensor/ppd42x.cpp
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;
Copy link
Member

Choose a reason for hiding this comment

The 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.

Copy link
Author

Choose a reason for hiding this comment

The 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

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I mean why do you differentiate between this->ctype_ ? All the switch cases look the same to me.

}
}
}

float PPD42XComponent::us_to_pl(uint32_t sample_length, uint32_t time_pm) {
float ratio = time_pm / (sample_length * 10.0f);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does this depend on the timeout value?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is the recommended max value to listen to !

Copy link
Member

Choose a reason for hiding this comment

The 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 this->timeout_us_ we chose?

Copy link
Author

@pi4homez pi4homez Apr 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nop, the sensor send continuously data.
we cannot stay stuck too long to lisning the end of the signal, so we timeout...

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
76 changes: 76 additions & 0 deletions src/esphome/sensor/ppd42x.h
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
1 change: 1 addition & 0 deletions src/esphome/sensor/sensor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ const char UNIT_K[] = "K";
const char UNIT_MICROSIEMENS_PER_CENTIMETER[] = "µS/cm";
const char UNIT_MICROGRAMS_PER_CUBIC_METER[] = "µg/m³";
const char ICON_CHEMICAL_WEAPON[] = "mdi:chemical-weapon";
const char UNIT_PARTICLES_PER_LITER[] = "pcs/l";

SensorStateTrigger::SensorStateTrigger(Sensor *parent) {
parent->add_on_state_callback([this](float value) { this->trigger(value); });
Expand Down
1 change: 1 addition & 0 deletions src/esphome/sensor/sensor.h
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ extern const char UNIT_DEGREES[];
extern const char UNIT_K[];
extern const char UNIT_MICROSIEMENS_PER_CENTIMETER[];
extern const char UNIT_MICROGRAMS_PER_CUBIC_METER[];
extern const char UNIT_PARTICLES_PER_LITER[];

template<typename... Ts> SensorInRangeCondition<Ts...> *Sensor::make_sensor_in_range_condition() {
return new SensorInRangeCondition<Ts...>(this);
Expand Down