Skip to content

Commit 8051016

Browse files
committed
Add LED for TVOC
1 parent 91240f0 commit 8051016

File tree

5 files changed

+168
-6
lines changed

5 files changed

+168
-6
lines changed

packages.md

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,21 @@ substitutions:
142142
pm_2_5_purple: '201'
143143
```
144144
145+
## led_tvoc.yaml
146+
147+
LED bar in AG ONE reflects VOC levels.
148+
149+
Mixes colors from blue>green>purple based on numbers provided by AirGradient. The values for each color can be modified by adding a substitution section to your config.
150+
151+
```yaml
152+
substitutions:
153+
voc_green: '100'
154+
voc_yellow: '150'
155+
voc_red: '250'
156+
voc_purple: '400'
157+
voc_blue: '50'
158+
```
159+
145160
## led.yaml
146161
147162
Configures the 11 segment LED bar in AG ONE models.
@@ -166,7 +181,7 @@ Configures the Plantower PMS5003 sensor.
166181
167182
By default collects readings every second. Since this device has a limited lifespan, it is possible to extend the life by collecting readings less frequently. Could introduce a new failure mode as the fan shuts down, allowing insects to get inside past the fan that is no longer spinning after 30 seconds.
168183
169-
Collects readings every 2 minutes by default, but can be modifed by adding an entry under substitutions, ensuring the value is surrounded by double quotes
184+
Collects readings every 2 minutes by default, but can be modified by adding an entry under substitutions, ensuring the value is surrounded by double quotes
170185
`pm_update_interval: "2min"`
171186

172187
## sensor_pms5003t_2_extended_life.yaml
@@ -179,7 +194,7 @@ In addition to enabling sensors from the second device, also creates sensors tha
179194

180195
By default collects readings every second. Since this device has a limited lifespan, it is possible to extend the life by collecting readings less frequently. Could introduce a new failure mode as the fan shuts down, allowing insects to get inside past the fan that is no longer spinning after 30 seconds.
181196

182-
Collects readings every 2 minutes by default, but can be modifed by adding an entry under substitutions, ensuring the value is surrounded by double quotes
197+
Collects readings every 2 minutes by default, but can be modified by adding an entry under substitutions, ensuring the value is surrounded by double quotes
183198
`pm_update_interval: "2min"`
184199
185200
## sensor_pms5003t_2.yaml
@@ -198,7 +213,7 @@ Also applies a compensation algorithm from AirGradient to correct temperature an
198213
199214
By default collects readings every second. Since this device has a limited lifespan, it is possible to extend the life by collecting readings less frequently. Could introduce a new failure mode as the fan shuts down, allowing insects to get inside past the fan that is no longer spinning after 30 seconds.
200215
201-
Collects readings every 2 minutes by default, but can be modifed by adding an entry under substitutions, ensuring the value is surrounded by double quotes
216+
Collects readings every 2 minutes by default, but can be modified by adding an entry under substitutions, ensuring the value is surrounded by double quotes
202217
`pm_update_interval: "2min"`
203218

204219
## sensor_pms5003t_uncorrected.yaml

packages/airgradient_d1_mini_board.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
substitutions:
2-
config_version: 5.0.0
2+
config_version: 5.1.0
33

44
esphome:
55
name: "${name}"

packages/airgradient_esp32-c3_board-arduino.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
substitutions:
2-
config_version: 5.0.0
2+
config_version: 5.1.0
33

44
esphome:
55
name: "${name}"

packages/airgradient_esp32-c3_board.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
substitutions:
2-
config_version: 5.0.0
2+
config_version: 5.1.0
33

44
esphome:
55
name: "${name}"

packages/led_tvoc.yaml

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
# Sets the full LED bar to a color relative to VOC levels
2+
# https://app.airgradient.com/dashboard/about
3+
4+
substitutions:
5+
voc_green: '100'
6+
voc_yellow: '150'
7+
voc_red: '250'
8+
voc_purple: '400'
9+
voc_blue: '50'
10+
11+
interval:
12+
- interval: 5s
13+
then:
14+
- if:
15+
condition:
16+
light.is_on: led_strip
17+
then:
18+
- if:
19+
condition:
20+
# Fade to purple as Index goes above 100
21+
lambda: 'return id(voc).state >= 100;'
22+
then:
23+
- light.addressable_set:
24+
id: led_strip
25+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 5)) / 100.0);'
26+
range_from: 0
27+
range_to: 10
28+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
29+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
30+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
31+
- light.addressable_set:
32+
id: led_strip
33+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 4)) / 100.0);'
34+
range_from: 1
35+
range_to: 9
36+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
37+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
38+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
39+
- light.addressable_set:
40+
id: led_strip
41+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 3)) / 100.0);'
42+
range_from: 2
43+
range_to: 8
44+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
45+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
46+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
47+
- light.addressable_set:
48+
id: led_strip
49+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 2)) / 100.0);'
50+
range_from: 3
51+
range_to: 7
52+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
53+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
54+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
55+
- light.addressable_set:
56+
id: led_strip
57+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 1)) / 100.0);'
58+
range_from: 4
59+
range_to: 6
60+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
61+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
62+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
63+
- light.addressable_set:
64+
id: led_strip
65+
color_brightness: !lambda 'return id(led_brightness).state / 100.0;'
66+
range_from: 5
67+
range_to: 5
68+
red: !lambda 'return (id(voc).state < $voc_green) ? 0 : (id(voc).state <= $voc_yellow) ? (id(voc).state - $voc_green) / ($voc_yellow - $voc_green) : 1;'
69+
green: !lambda 'return (id(voc).state < $voc_yellow) ? 1 : (id(voc).state <= $voc_red) ? 1 - (id(voc).state - $voc_yellow) / ($voc_red - $voc_yellow) : 0;'
70+
blue: !lambda 'return (id(voc).state < $voc_red) ? 0 : (id(voc).state <= $voc_purple) ? (id(voc).state - $voc_red) / ($voc_purple - $voc_red) : 1;'
71+
- if:
72+
condition:
73+
# Fade to blue as Index goes below 100
74+
lambda: 'return id(voc).state < 100;'
75+
then:
76+
- light.addressable_set:
77+
id: led_strip
78+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
79+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
80+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 5)) / 100.0);'
81+
range_from: 0
82+
range_to: 10
83+
red: 0%
84+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
85+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
86+
- light.addressable_set:
87+
id: led_strip
88+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
89+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
90+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 4)) / 100.0);'
91+
range_from: 1
92+
range_to: 9
93+
red: 0%
94+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
95+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
96+
- light.addressable_set:
97+
id: led_strip
98+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
99+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
100+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 3)) / 100.0);'
101+
range_from: 2
102+
range_to: 8
103+
red: 0%
104+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
105+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
106+
- light.addressable_set:
107+
id: led_strip
108+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
109+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
110+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 2)) / 100.0);'
111+
range_from: 3
112+
range_to: 7
113+
red: 0%
114+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
115+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
116+
- light.addressable_set:
117+
id: led_strip
118+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
119+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
120+
color_brightness: !lambda 'return ((id(led_brightness).state - (id(led_fade).state * 1)) / 100.0);'
121+
range_from: 4
122+
range_to: 6
123+
red: 0%
124+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
125+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
126+
- light.addressable_set:
127+
id: led_strip
128+
# Green prompt: If x is between 50 and 100 then gradually increase from 1 to 0 in a single line of C++
129+
# Blue prompt: If x is 50 or less assign 1, if between 50 and 100 then gradually decrease from 1 to 0, 100 or higher assign 0 in a single line of C++
130+
color_brightness: !lambda 'return id(led_brightness).state / 100.0;'
131+
range_from: 5
132+
range_to: 5
133+
red: 0%
134+
green: !lambda 'return (id(voc).state < $voc_blue) ? 0 : (id(voc).state <= $voc_green) ? (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 1;'
135+
blue: !lambda 'return (id(voc).state < $voc_blue) ? 1 : (id(voc).state >= $voc_blue) ? 1 - (id(voc).state - $voc_blue) / ($voc_green - $voc_blue) : 0;'
136+
- if:
137+
condition:
138+
lambda: 'return (isnan(id(voc).state));' # No data from sensor yet
139+
then:
140+
- light.addressable_set:
141+
id: led_strip
142+
color_brightness: !lambda 'return id(led_brightness).state / 100.0;'
143+
range_from: 0
144+
range_to: 10
145+
red: 0%
146+
green: 0%
147+
blue: 0%

0 commit comments

Comments
 (0)