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
|
substitutions:
device_name: toiletlight
friendly_name: "Toilet Light"
esphome:
name: ${device_name}
friendly_name: ${friendly_name}
area: Toilet
esp32:
variant: esp32c3
cpu_frequency: 80MHz
framework:
type: esp-idf
sdkconfig_options:
CONFIG_BOOTLOADER_SKIP_VALIDATE_ON_POWER_ON: y
CONFIG_BOOTLOADER_LOG_LEVEL_NONE: y
CONFIG_LOG_DEFAULT_LEVEL_NONE: y
preferences:
flash_write_interval: 30s
# Enable logging
logger:
# disable logging for much faster startup
level: NONE
# make RXD / TXD available
baud_rate: 0
# Enable Home Assistant API
api:
encryption:
key: !secret api_encryption_key
# OTA
ota:
- platform: esphome
password: !secret ota_password
# WiFi Credentials
wifi:
domain: .lan
ssid: !secret wifi_ssid
password: !secret wifi_password
# enabling power saves causes jitter!
power_save_mode: NONE
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${device_name} Fallback Hotspot"
password: !secret wifi_ap_password
captive_portal:
light:
- id: toilet
platform: color_temperature
name: "Toilet"
color_temperature: pwm_warm_cold
# we are using pwm_dim_mapped to transform between min+max-power
# otherwise one can use:
#brightness: pwm_dim
#gamma_correct: 1.0
brightness: pwm_dim_mapped
cold_white_color_temperature: 6500 K
warm_white_color_temperature: 3000 K
default_transition_length: 300ms
initial_state:
state: true
brightness: 100%
color_temperature: 4500 K
restore_mode: RESTORE_DEFAULT_ON
output:
- id: pwm_dim
platform: ledc
pin: GPIO1
frequency: 3900 Hz
channel: 0
min_power: 0.04
zero_means_zero: true
- id: pwm_warm
platform: ledc
pin: GPIO3
# original mcu uses 3900Hz
frequency: 24000 Hz
channel: 2
- id: pwm_cold
platform: ledc
pin: GPIO4
# original mcu uses 3900Hz
frequency: 24000 Hz
channel: 3
phase_angle: 180°
- platform: template
id: pwm_warm_cold
type: float
write_action:
- lambda: |-
auto warm = id(pwm_warm), cold = id(pwm_cold);
ESP_LOGD("cal", "warm: %f, cold: %f, phase: %f", state, 1-state, state*360.0);
warm->set_level(state);
cold->set_level(1 - state);
cold->set_phase_angle(state * 360.0);
# map output to range (min_power, max_power)
- platform: template
id: pwm_dim_mapped
type: float
write_action:
- lambda: |-
auto output = id(pwm_dim);
float min = output->get_min_power(), max = output->get_max_power();
float newlvl = (state) ? state * (max - min) + min : 0;
ESP_LOGD("cal", "dim: %f -> %f", state, newlvl);
output->set_level(newlvl);
if (newlvl == 0) {
id(pwm_warm).set_level(0);
id(pwm_cold).set_level(0);
}
# closed loop not implemented
#sensor:
# - id: adc_cs
# platform: adc
# pin: GPIO0
# accuracy_decimals: 2
# attenuation: auto
# update_interval: 1s
globals:
- id: saved_brightness
type: float
restore_value: yes
initial_value: '1.0'
- id: saved_color_temp
type: float
restore_value: yes
initial_value: '222.0' # 4500K
binary_sensor:
- platform: homeassistant
name: "Nightlight enabled from Home Assistant"
entity_id: input_boolean.toilet_light_nightlight
on_state_change:
then:
- if:
condition:
lambda: 'return x.has_value() && x.value();'
then:
- globals.set:
id: saved_brightness
value: !lambda 'return id(toilet).current_values.get_brightness();'
- globals.set:
id: saved_color_temp
value: !lambda 'return id(toilet).current_values.get_color_temperature();'
- light.turn_on:
id: toilet
brightness: 1%
color_temperature: 3000 K
else:
- light.turn_on:
id: toilet
brightness: !lambda 'return id(saved_brightness);'
color_temperature: !lambda 'return id(saved_color_temp);'
|