-
Notifications
You must be signed in to change notification settings - Fork 0
/
product_iaq_monitor.yaml
145 lines (135 loc) · 5.06 KB
/
product_iaq_monitor.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
---
i2c:
- id: i2c_bus_0
sda: 21
scl: 22
frequency: 100kHz
- id: i2c_bus_1
sda: 17
scl: 13
frequency: 100kHz
uart:
- id: uart_bus_0
rx_pin: 26
tx_pin: 27
baud_rate: 9600
data_bits: 8
parity: NONE
stop_bits: 1
sensor:
- platform: scd30
i2c_id: i2c_bus_0
co2:
name: "${friendly_shortname} SCD30 CO₂ Concentration"
id: iaq_scd30_co2
filters:
- filter_out: 0 # Sometimes reports zero right after power cycle
- &scd30-smoothing-filter
exponential_moving_average:
alpha: 0.4
send_every: 5
# Do not publish temperature and humidity that are biased by the NDIR heater
update_interval: 2s
# SVM30-J module contains both SGP30 and SHTC1
- platform: sgp30
i2c_id: &svm30-i2c-bus i2c_bus_1
eco2:
name: "${friendly_shortname} SVM30 eCO₂ Concentration"
id: iaq_svm30_eco2
filters:
&svm30-common-filters
- exponential_moving_average:
alpha: 0.2
send_every: 10
# Do not publish estimated CO₂ because a real NDIR reading is available
internal: true
tvoc:
name: "${friendly_shortname} SVM30 TVOC Concentration"
id: iaq_svm30_tvoc
filters: *svm30-common-filters
compensation:
temperature_source: iaq_svm30_temperature
humidity_source: iaq_svm30_humidity
update_interval: &svm30-update-interval 1s
- platform: shtcx
i2c_id: *svm30-i2c-bus
temperature:
name: "${friendly_shortname} Temperature"
id: iaq_svm30_temperature
filters: *svm30-common-filters
humidity:
name: "${friendly_shortname} Humidity"
id: iaq_svm30_humidity
filters: *svm30-common-filters
update_interval: *svm30-update-interval
- platform: pmsx003
type: PMSX003
uart_id: uart_bus_0
pm_1_0:
name: "${friendly_shortname} PM <1.0µm Concentration"
id: iaq_pm_1_0
filters:
&pmsx003-common-filters
- exponential_moving_average:
alpha: 0.2
send_every: 10
pm_2_5:
name: "${friendly_shortname} PM 1.0–2.5µm Concentration"
id: iaq_pm_2_5
filters: *pmsx003-common-filters
pm_10_0:
name: "${friendly_shortname} PM 2.5–10.0µm Concentration"
id: iaq_pm_10_0
filters: *pmsx003-common-filters
- platform: tsl2561
i2c_id: i2c_bus_0
name: "${friendly_shortname} Ambient Light"
update_interval: 1s
on_value:
then:
- light.turn_on:
id: light_display_backlight
# From "Integrating Ambient Light Sensors with Computers Running
# Windows 10" whose example curve takes illuminance (lux) and
# outputs into linear backlight luminance space (nits) and also
# perceptual brightness (%) for a display peaking at 435 nits.
# https://learn.microsoft.com/en-us/windows-hardware/design/whitepapers/integrating-ambient-light-sensors-with-computers-running-windows-10-creators-update
# The TTGO T-Display is rated for 400 nits and ESPHome applies gamma
# correction to make this output in units of perceptual brightness,
# different from the Windows 10 perceptual brightness slider. So,
# the "(Nits)" column in Fig. 10 is used to produce a brightness
# setting using the formula
# brightness = (nits / 435) ** (1 / gamma)
# where gamma is defined as 2.8 for `light_display_backlight`.
brightness: !lambda |-
// sensor illuminance (lux) to perceptual brightness map (%)
// must be sorted by lux and start at the sensor's min reading
constexpr std::pair<float, float> kBrightnesses[] = {
{0.f, .146f},
{10.f, .355f},
{20.f, .441f},
{40.f, .563f},
{100.f, .660f},
{200.f, .706f},
{400.f, .766f},
{1200.f, .888f},
{2000.f, 1.f},
};
// Search for first point with lux strictly greater than `x`.
const auto next_brightness_iter = std::partition_point(
std::begin(kBrightnesses), std::end(kBrightnesses),
[x](auto p) { return p.first <= x; });
// `x` is NaN when the sensor is saturated
if (std::isnan(x) ||
(next_brightness_iter == std::end(kBrightnesses))) {
// return max brightness setting in map
return std::rbegin(kBrightnesses)->second;
}
// linearly interpolate to the next lowest curve point
const auto prev_brightness_iter = std::prev(next_brightness_iter);
const float lux_0 = prev_brightness_iter->first;
const float lux_1 = next_brightness_iter->first;
const float bright_0 = prev_brightness_iter->second;
const float bright_1 = next_brightness_iter->second;
return bright_0 +
(x - lux_0) * (bright_1 - bright_0) / (lux_1 - lux_0);