-
Notifications
You must be signed in to change notification settings - Fork 0
/
h801_dimmer.yaml
520 lines (490 loc) · 21.5 KB
/
h801_dimmer.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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
# H801 ESP8266 dimmer sketch with 2 dimmer outputs, one switched output (to turn on/off 12V power to a device) and one switched output to which an active buzzer is connected
# 2 button inmputs to control the dimmer outputs, one button input to control the switch
# version: 0.3 - first stable version
# version: 0.4 - added gamma reverse compensation for brightness in relative_brightness lambda function to get better step values (previously relied on gamma set to 1.0 in light definition to stay leneair)
# - Avoid dimming up if current brightness is already at maximum value (no point trying to dim up and only leads to unnecesary buzzer beep)
# - Avoid dimming down if current brightness is already at minimum value (no point trying to dim down and only leads to unnecesary buzzer beep)
# - Changed default values for Dimmer step to 0.02, transition_length to 0.05s and delay to 0.04s
# - Changed default values for wifi RSSI reporting to 900s
# - Changed gamma_correct for lights to 2.0
#
# H801 pinout for quick reference:
# redPIN 15 - defined as PWM output and as light but not used
# greenPIN 13 - used for buzzer
# bluePIN 12 - used as switch 1
# w1PIN 14 - used as PWM and as light monochromatic 1
# w2PIN 4 - - used as PWM and as light monochromatic 2
# // onboard red LED D1
# LEDPIN 5 - used as status led
# // onboard green LED D2
# LED2PIN 1 - used as output gpio and as binary light
# TX GPIO2 @Serial1 (Serial ONE) - used as input button for switch 1
# RX GPIO3 @Serial - used as input button for light monochromatic 2
# GPIO0 - - used as input button for light monochromatic 1
esphome:
name: h801_1
comment: Kitchen lights
platform: ESP8266
board: esp01_1m
on_boot:
- light.turn_on:
id: light_buzzer
effect: beeptwice
wifi:
ssid: "MySSID"
password: "SomePassword"
manual_ip: # I am using manual/static IP just during testing as in mu setup mDNS does not work and then you cannot do OTA. I recommend to remove this in production (avoids having to OTA a new config if you ever change your LAN setup or want to use the device in another network)
static_ip: 192.168.100.164
gateway: 192.168.100.254
subnet: 255.255.255.0
dns1: 192.168.100.254
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "h801_1"
password: "SomePassword2"
ap_timeout: 5min
# time: #not using this at present, may consider this in the future
# - platform: sntp
# id: sntp_time
captive_portal:
mqtt:
broker: mqtt.someserver.com
discovery: True
web_server:
port: 80
# included the css/js URLs explicitly these can be changed easily later on; these are the defaults
css_url: https://esphome.io/_static/webserver-v1.min.css
js_url: https://esphome.io/_static/webserver-v1.min.js
# pin 5 = red, pin 1 = green
status_led:
pin:
number: 5
inverted: True
# Enable logging
debug:
logger:
level: VERBOSE #Change the log level as required; during testing verbose is helpful.
# disable serial logging as we ar eusing the pins as button inputs
baud_rate: 0
#hardware_uart: UART1
# Enable Home Assistant API (Not using this so enable this if needed)
#api:
# password: "SomePassword3"
ota:
password: "SomePassword4"
globals:
# for light 1, "PV"
- id: light_pv_min_brightness #set the minimum allowed brightness for light 'pv'
type: float
restore_value: no
initial_value: '0.05'
- id: light_pv_max_brightness #set the maximum allowed brightness for light 'pv'
type: float
restore_value: no
initial_value: '1.0'
- id: dim_direction_pv #remember the current dim direction for light 'pv'
type: int
restore_value: no
initial_value: '1'
- id: PV_loop_stop # stop the while loop upon min/max brightness
type: bool
restore_value: no
initial_value: 'false'
# for light 2, "KV"
- id: light_kv_min_brightness #set the minimum allowed brightness for light 'kv'
type: float
restore_value: no
initial_value: '0.1'
- id: light_kv_max_brightness #set the maximum allowed brightness for light 'kv'
type: float
restore_value: no
initial_value: '1.0'
- id: dim_direction_kv #remember the current dim direction for light 'kv'
type: int
restore_value: no
initial_value: '0'
- id: KV_loop_stop # stop the while loop upon min/max brightness
type: bool
restore_value: no
initial_value: 'false'
# Common setting dimmer steps
- id: step #dimmer steps
type: float
restore_value: no
initial_value: '0.02'
# sensor to report wifi RSSI
sensor:
- platform: wifi_signal
name: "RSSI"
update_interval: 60s
binary_sensor:
# Button 1: push button to control the light "PV" connected to GPIO 14 / pwm_w1
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
inverted: True
name: "Button 1"
id: light_pv_button
# we use multi_click to get both single and double click
# single click to turn on and off (toggle)
# double click to set either max or min brightness: if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "on_multi_click: Double Clicked"
- if:
condition:
light.is_off: light_PV
then:
- light.turn_on:
id: light_PV
brightness: !lambda |-
return id(light_pv_max_brightness);
- if:
condition:
light.is_on: light_PV
then:
- light.turn_on:
id: light_PV
# if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max:
brightness: !lambda |-
float brightness;
id(light_PV).current_values_as_brightness(&brightness);
if (brightness >= id(light_pv_max_brightness)) {
return id(light_pv_min_brightness);
}
else {
return id(light_pv_max_brightness);
}
# single click to turn on and off (toggle):
- timing:
- ON for at most 350ms
- OFF for at least 350ms
then:
- logger.log: "on_multi_click: single click"
- light.toggle: light_PV
# Long press to dim up and down:
on_press:
then:
- logger.log: "on_press"
# we need this delay (and then to look for binary_sensor.is_on) to ensure it's not a multi-click
- delay: 0.75s
- if:
condition:
and:
- light.is_off: light_PV
- binary_sensor.is_on: light_pv_button
then:
# if the light was off we also want the long press to turn it on and then start dimming
- light.toggle: light_PV
#- delay: 0.75s
#
# this sets the globales variable that will stop the while loop from needlessly running if the buttons keeps being pressed but ar are already at max or min value
# it's also needed to ensure the buzzer only buzzes once and doesn't keep buzzing when the max/min is reached
- lambda: |-
id(PV_loop_stop) = false;
- while:
# keep on going as long as the button is pressed and when the max/min threshold is not exceeded yet (indicated by the global var of type bool)
condition:
and:
- binary_sensor.is_on: light_pv_button
- lambda: |-
return(!id(PV_loop_stop));
then:
- light.dim_relative:
id: light_PV
# This lambda will dim up or down depending on the dim direction
# if dim = up, it will keep increasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until max_brightness would be exceed
# in the case it will set it to max brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
# if dim = down, it will keep decreasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until min_brightness would be exceed
# in the case it will set it to min brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
relative_brightness: !lambda |-
float brightness;
float gamma;
id(light_PV).current_values_as_brightness(&brightness);
// this is the gamma corrected value - we need to 'un'compensate for gamma to get a lineair %value
gamma = id(light_PV).get_gamma_correct();
brightness = powf(brightness,1/gamma);
//id(light_PV).dump_config();
ESP_LOGD("main", "while loop, dim=%d, brightness=%6.4lf, step=%6.4lf, max=%6.4lf, gamma=%6.4lf", id(dim_direction_pv), brightness,id(step),id(light_pv_max_brightness),gamma);
if (brightness >= id(light_pv_max_brightness)) {
// if we are at max already, no point in dimming up - this will ever happen at loop start because of the loopstop break, so no issues with the loop
id(dim_direction_pv) = '0';
}
else if (brightness <= id(light_pv_min_brightness)) {
// if we are at min already, no point in dimming down - this will ever happen at loop start because of the loopstop break, so no issues with the loop
id(dim_direction_pv) = '1';
}
if (id(dim_direction_pv) == '1') {
if ((id(step) + brightness) <= id(light_pv_max_brightness)) {
return(id(step));
}
else {
auto call = id(light_buzzer).turn_on();
call.set_effect("beeponce");
call.perform();
id(PV_loop_stop) = true;
return(id(light_pv_max_brightness)- brightness);
}
}
else if (id(dim_direction_pv) != '1') {
if ((brightness - id(step)) >= id(light_pv_min_brightness)) {
return(-id(step));
}
else {
auto call = id(light_buzzer).turn_on();
call.set_effect("beeponce");
call.perform();
id(PV_loop_stop) = true;
return(id(light_pv_min_brightness)- brightness);
}
}
// the else is strictly speaking not needed as the loop should break before this condition is true but if for whatever reason that would not happen at least we are returning something
else {
return(0);
}
transition_length: 0.05s
- delay: 0.04s
# now toggle the dim up/down direction so next time we do the opposite action
- globals.set:
id: dim_direction_pv
value: !lambda |-
if (id(dim_direction_pv) == '1') {
return('0');
} else {
return('1');
}
#on_release:
# - logger.log: "on_release"
# Button 2: push button to control the light "KV" connected to GPIO 3 / pwm_w2
- platform: gpio
# GPIO3 is Rx pin (but is marked on H801 as Tx!)
pin:
number: GPIO3
mode: INPUT_PULLUP
inverted: True
name: "Button 2"
id: light_kv_button
# we use multi_click to get both single and double click
# single click to turn on and off (toggle)
# double click to set either max or min brightness: if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max
on_multi_click:
- timing:
- ON for at most 1s
- OFF for at most 1s
- ON for at most 1s
- OFF for at least 0.2s
then:
- logger.log: "on_multi_click: Double Clicked"
- if:
condition:
light.is_off: light_KV
then:
- light.turn_on:
id: light_KV
brightness: !lambda |-
return id(light_kv_max_brightness);
- if:
condition:
light.is_on: light_KV
then:
- light.turn_on:
id: light_KV
# if currently off then turn on with brightness=max. If currently on, then if currently brigthness equals max then set to min, else set to max:
brightness: !lambda |-
float brightness;
id(light_KV).current_values_as_brightness(&brightness);
if (brightness >= id(light_kv_max_brightness)) {
return id(light_kv_min_brightness);
}
else {
return id(light_kv_max_brightness);
}
# single click to turn on and off (toggle):
- timing:
- ON for at most 350ms
- OFF for at least 350ms
then:
- logger.log: "on_multi_click: single click"
- light.toggle: light_KV
# Long press to dim up and down:
on_press:
then:
- logger.log: "on_press"
# we need this delay (and then to look for binary_sensor.is_on) to ensure it's not a multi-click
- delay: 0.75s
- if:
condition:
and:
- light.is_off: light_KV
- binary_sensor.is_on: light_kv_button
then:
# if the light was off we also want the long press to turn it on and then start dimming
- light.toggle: light_KV
#- delay: 0.75s
#
# this sets the globales variable that will stop the while loop from needlessly running if the buttons keeps being pressed but ar are already at max or min value
# it's also needed to ensure the buzzer only buzzes once and doesn't keep buzzing when the max/min is reached
- lambda: |-
id(KV_loop_stop) = false;
- while:
# keep on going as long as the button is pressed and when the max/min threshold is not exceeded yet (indicated by the global var of type bool)
condition:
and:
- binary_sensor.is_on: light_kv_button
- lambda: |-
return(!id(KV_loop_stop));
then:
- light.dim_relative:
id: light_KV
# This lambda will dim up or down depending on the dim direction
# if dim = up, it will keep increasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until max_brightness would be exceed
# in the case it will set it to max brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
# if dim = down, it will keep decreasing brightness with global var 'step' (so we can easily change this in a central place) as long as the button keeps being pressed until min_brightness would be exceed
# in the case it will set it to min brightness, beep the buzzer once (the buzzer is defined as a light with effect "beeponce") and then stop the loop - this both prevent further needless loops as well as ensures the buzzer only buzzes once
relative_brightness: !lambda |-
float brightness;
float gamma;
id(light_KV).current_values_as_brightness(&brightness);
// this is the gamma corrected value - we need to 'un'compensate for gamma to get a lineair %value
gamma = id(light_KV).get_gamma_correct();
brightness = powf(brightness,1/gamma);
//id(light_KV).dump_config();
brightness = powf(brightness,1/id(light_KV).get_gamma_correct());
ESP_LOGD("main", "while loop, dim=%d, brightness=%6.4lf, step=%6.4lf, max=%6.4lf", id(dim_direction_kv), brightness,id(step),id(light_kv_max_brightness));
if (brightness >= id(light_kv_max_brightness)) {
// if we are at max already, no point in dimming up - this will ever happen at loop start because of the loopstop break
id(dim_direction_kv) = '0';
}
else if (brightness <= id(light_kv_min_brightness)) {
// if we are at min already, no point in dimming down - this will ever happen at loop start because of the loopstop break
id(dim_direction_kv) = '1';
}
if (id(dim_direction_kv) == '1') {
if ((id(step) + brightness) <= id(light_kv_max_brightness)) {
return(id(step));
}
else {
auto call = id(light_buzzer).turn_on();
call.set_effect("beeponce");
call.perform();
id(KV_loop_stop) = true;
return(id(light_kv_max_brightness)- brightness);
}
}
else if (id(dim_direction_kv) != '1') {
if ((brightness - id(step)) >= id(light_kv_min_brightness)) {
return(-id(step));
}
else {
auto call = id(light_buzzer).turn_on();
call.set_effect("beeponce");
call.perform();
id(KV_loop_stop) = true;
return(id(light_kv_min_brightness)- brightness);
}
}
// the else is strictly speaking not needed as the loop should break before this condition is true but if for whatever reason that would not happen at least we are returning something
else {
return(0);
}
transition_length: 0.05s
- delay: 0.04s
# now toggle the dim up/down direction so next time we do the opposite action
- globals.set:
id: dim_direction_kv
value: !lambda |-
if (id(dim_direction_kv) == '1') {
return('0');
} else {
return('1');
}
# button to control (toggle) the switch connected to GPIO2
- platform: gpio
pin:
number: GPIO2
mode: INPUT_PULLUP
inverted: True
name: "Button 3"
id: Switch_1_button
on_click:
then:
- switch.toggle: switch_1
#
switch:
# - platform: gpio
pin: 12
name: "Switch 1"
id: "switch_1"
# this provides fr a possibility to rstart from the web console or Home automation should we ever need it
- platform: restart
name: "Restart"
output:
- platform: esp8266_pwm
pin: 15
frequency: 2000 Hz
id: pwm_r
- platform: esp8266_pwm
pin: 14
frequency: 2000 Hz
id: pwm_w1
#min_power: 0.01
#max_power: 0.95
- platform: esp8266_pwm
pin: 4
frequency: 2000 Hz
id: pwm_w2
#min_power: 0.01
#max_power: 0.95
- platform: gpio
pin: 1
id: green_led
inverted: True
- platform: gpio
pin: 13
id: buzzer
light:
- platform: monochromatic
name: "Kitchen cabinets"
id: light_KV
output: pwm_w2
gamma_correct: 2.0
- platform: monochromatic
name: "Kitchen ceiling"
output: pwm_w1
gamma_correct: 2.0
id: light_PV
- platform: monochromatic
name: "pwm_r"
output: pwm_r
id: light_pwm_r
- platform: binary
name: "light_green_led"
output: green_led
id: light_green_led
- platform: binary
#name: "buzzer"
output: buzzer
id: light_buzzer
effects:
- automation:
name: beeponce
sequence:
- light.turn_on: light_buzzer
- delay: 0.1s
- light.turn_off: light_buzzer
- automation:
name: beeptwice
sequence:
- light.turn_on: light_buzzer
- delay: 0.1s
- light.turn_off: light_buzzer
- delay: 0.075s
- light.turn_on: light_buzzer
- delay: 0.1s
- light.turn_off: light_buzzer