devices.esphome.io

Moes QS-WIFI-DS02

Moes QS-WIFI-DS02

Device Type: dimmer
Electrical Standard: eu
Board: esp8266

Dual gang wifi dimmer

substitutions:
node_name: qs-wifi-ds02
node_id: IP_name
friendly_node_name: "Dual Channel Dimmer"
esphome:
name: ${node_name}
comment: ${friendly_node_name}
platform: ESP8266
board: esp01_1m
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_pw
power_save_mode: none
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: ${node_name} FB
password: "fallback"
captive_portal:
# Enable Home Assistant API
api:
encryption:
key: !secret api_encryption
# Enable Over The Air updates
ota:
# Disable logging
logger:
baud_rate: 0
logs:
sensor: ERROR
duty_cycle: ERROR
binary_sensor: ERROR
light: ERROR
# Enable Web server.
web_server:
port: 80
# Sync time with Home Assistant.
time:
- platform: homeassistant
id: ${node_id}_homeassistant_time
# Binary Sensors.
binary_sensor:
- platform: status
name: ${friendly_node_name} Connection Status
id: ${node_id}_connection_status
#Binary sensor (on/off) which reads duty_cyle sensor readings. CH1
- platform: template
id: switch1
internal: true
name: "${node_id} Switch Binary Sensor 1"
# read duty_cycle, convert to on/off
lambda: |-
if (id(sensor_push_switch_1).state < 95.0) {
return true;
} else {
return false;
}
# Short Click - toggle light only
on_click:
max_length: 300ms
then:
light.toggle: light_main_1
# Generic On_Press - log press, toggle DIM Direction and reset press interval counter
on_press:
then:
- logger.log: "Switch 1 Press"
- lambda: |-
if (id(g_direction_1) == 0) {
id(g_direction_1) = 1;
} else {
id(g_direction_1) = 0;
}
id(g_counter_1) = 0;
#Binary sensor (on/off) which reads duty_cyle sensor readings. CH2
- platform: template
id: switch2
internal: true
name: "${node_id} Switch Binary Sensor 2"
# read duty_cycle, convert to on/off
lambda: |-
if (id(sensor_push_switch_2).state < 95.0) {
return true;
} else {
return false;
}
# Short Click - toggle light only
on_click:
max_length: 300ms
then:
light.toggle: light_main_2
# Generic On_Press - log press, toggle DIM Direction and reset press interval counter
on_press:
then:
- logger.log: "Switch 2 Press"
- lambda: |-
if (id(g_direction_2) == 0) {
id(g_direction_2) = 1;
} else {
id(g_direction_2) = 0;
}
id(g_counter_2) = 0;
# Sensors.
sensor:
- platform: uptime
name: Uptime Sensor
id: uptime_sensor
update_interval: 600s
on_raw_value:
then:
- text_sensor.template.publish:
id: uptime_human
state: !lambda |-
int seconds = round(id(uptime_sensor).raw_state);
int days = seconds / (24 * 3600);
seconds = seconds % (24 * 3600);
int hours = seconds / 3600;
seconds = seconds % 3600;
int minutes = seconds / 60;
seconds = seconds % 60;
return (
(days ? to_string(days) + "d " : "") +
(hours ? to_string(hours) + "h " : "") +
(minutes ? to_string(minutes) + "m " : "") +
(to_string(seconds) + "s")
).c_str();
- platform: wifi_signal
name: ${friendly_node_name} WiFi Signal
id: ${node_id}_wifi_signal
update_interval: 60s
# Primary template sensor to track Brightness of light object for "on_value" sending to MCU dimmer
# CH1
- platform: template
name: "${node_id} Brightness Sensor CH1"
id: sensor_g_bright_1
internal: true
update_interval: 20ms
# Ensure on_value only triggered when brightness (0-255) changes
filters:
delta: 0.8
# Read brightness (0 - 1) from light , convert to (0-255) for MCU
lambda: |-
if (id(light_main_1).remote_values.is_on()) {
return (int(id(light_main_1).remote_values.get_brightness() * 255));
}
else {
return 0;
}
# On Change send to MCU via UART
on_value:
then:
- uart.write: !lambda |-
return {0xFF, 0x55, 0x01, (char) id(sensor_g_bright_1).state, 0x00, 0x00, 0x00, 0x0A};
- logger.log:
level: INFO
format: "CH1 Sensor Value Change sent to UART %3.1f"
args: ["id(sensor_g_bright_1).state"]
# Sensor to detect button push (via duty_cycle of 50hz mains signal)
- platform: template
name: "${node_id} Brightness Sensor CH2"
id: sensor_g_bright_2
internal: true
update_interval: 20ms
# Ensure on_value only triggered when brightness (0-255) changes
filters:
delta: 0.8
# Read brightness (0 - 1) from light , convert to (0-255) for MCU
lambda: |-
if (id(light_main_2).remote_values.is_on()) {
return (int(id(light_main_2).remote_values.get_brightness() * 255));
}
else {
return 0;
}
# On Change send to MCU via UART
on_value:
then:
- uart.write: !lambda |-
return {0xFF, 0x55, 0x02, 0x00, (char) id(sensor_g_bright_2).state, 0x00, 0x00, 0x0A};
- logger.log:
level: INFO
format: "CH2 Sensor Value Change sent to UART %3.1f"
args: ["id(sensor_g_bright_2).state"]
# Sensor to detect button push (via duty_cycle of 50hz mains signal)
- platform: duty_cycle
pin: GPIO13
internal: true
id: sensor_push_switch_1
name: "${node_id} Sensor Push Switch 1"
update_interval: 20ms
- platform: duty_cycle
pin: GPIO5
internal: true
id: sensor_push_switch_2
name: "${node_id} Sensor Push Switch 2"
update_interval: 20ms
# Text Sensors.
text_sensor:
- platform: template
name: Uptime Human Readable
id: uptime_human
icon: mdi:clock-start
- platform: version
name: ${friendly_node_name} ESPHome Version
id: ${node_id}_esphome_version
- platform: wifi_info
ip_address:
name: ${friendly_node_name} IP Address
id: ${node_id}_ip_address
icon: mdi:ip-network
# Switches.
switch:
- platform: restart
name: ${friendly_node_name} Restart
id: ${node_id}_restart
icon: "mdi:restart"
- platform: shutdown
name: ${friendly_node_name} Shutdown
id: ${node_id}_shutdown
- platform: safe_mode
name: ${friendly_node_name} Restart (Safe Mode)"
id: ${node_id}_safe_mode
globals:
# Dim direction for Switch 1: 0=Up (brighten) 1=down (dim)
- id: g_direction_1
type: int
restore_value: no
initial_value: "1"
# Counter for time pressed for switch 1
- id: g_counter_1
type: int
restore_value: no
initial_value: "0"
# initial brightness
# Dim direction for Switch 2: 0=Up (brighten) 1=down (dim)
- id: g_direction_2
type: int
restore_value: no
initial_value: "1"
# Counter for time pressed for switch 2
- id: g_counter_2
type: int
restore_value: no
initial_value: "0"
# initial brightness
# Uart definition to talk to MCU dimmer
uart:
tx_pin: GPIO1
rx_pin: GPIO3
stop_bits: 1
baud_rate: 9600
# Dummy light output to allow creation of light object
output:
- platform: esp8266_pwm
pin: GPIO14
frequency: 800 Hz
id: dummy_pwm1
- platform: esp8266_pwm
pin: GPIO16
frequency: 800 Hz
id: dummy_pwm2
# Primary Light object exposed to HA
light:
- platform: monochromatic
default_transition_length: 20ms
restore_mode: RESTORE_DEFAULT_OFF
name: "${node_id} Light 1"
output: dummy_pwm1
id: light_main_1
- platform: monochromatic
default_transition_length: 20ms
restore_mode: RESTORE_DEFAULT_OFF
name: "${node_id} Light 2"
output: dummy_pwm2
id: light_main_2
# Polling object for long press handling of switch for dim/brighten cycle
interval:
- interval: 20ms
then:
- if:
condition:
binary_sensor.is_on: switch1
then:
# Ramp rate for dim is product of interval (20ms) * number of intervals
# Every 20ms Dimmer is increased/decreased by 2/255
# Lower limit = 10%
# Upper limit = 100%
# 100% - 10% = 90% = 230/255. Therefore 230/2 * 20ms = 2.3 seconds for full range
# At full/min brightness - further 16x20ms = 0.32 Seconds "dwell" by resetting counter to 0
# Initial pause for 16x20ms = 0.32s to allow "on_click" to be discounted 1st
# g_direction_1 = 0 (Increasing brightness)
# g_direction_1 = 1 (decreasing brightness)
# g_counter_1 = Interval pulse counter
lambda: |-
float curr_bright = id(light_main_1).remote_values.get_brightness();
id(g_counter_1) += 1;
// If max bright, change direction
if (curr_bright >= 0.999 && id(g_direction_1) == 0) {
id(g_direction_1) = 1;
id(g_counter_1) = 0;
}
// If below min_bright, change direction
if (curr_bright < 0.1 && id(g_direction_1) == 1) {
id(g_direction_1) = 0;
id(g_counter_1) = 0;
}
if (id(g_direction_1) == 0 && id(g_counter_1) > 15) {
// Increase Bright
auto call = id(light_main_1).turn_on();
call.set_brightness(curr_bright + (2.0/255.0));
call.perform();
}
else if(id(g_direction_1) == 1 && id(g_counter_1) > 15) {
// Decrease Bright
auto call = id(light_main_1).turn_on();
call.set_brightness(curr_bright - (2.0/255.0));
call.perform();
}
- if:
condition:
binary_sensor.is_on: switch2
then:
# Ramp rate for dim is product of interval (20ms) * number of intervals
# Every 20ms Dimmer is increased/decreased by 2/255
# Lower limit = 10%
# Upper limit = 100%
# 100% - 10% = 90% = 230/255. Therefore 230/2 * 20ms = 2.3 seconds for full range
# At full/min brightness - further 16x20ms = 0.32 Seconds "dwell" by resetting counter to 0
# Initial pause for 16x20ms = 0.32s to allow "on_click" to be discounted 1st
# g_direction_1 = 0 (Increasing brightness)
# g_direction_1 = 1 (decreasing brightness)
# g_counter_1 = Interval pulse counter
lambda: |-
float curr_bright = id(light_main_2).remote_values.get_brightness();
id(g_counter_2) += 1;
// If max bright, change direction
if (curr_bright >= 0.999 && id(g_direction_2) == 0) {
id(g_direction_2) = 1;
id(g_counter_2) = 0;
}
// If below min_bright, change direction
if (curr_bright < 0.1 && id(g_direction_2) == 1) {
id(g_direction_2) = 0;
id(g_counter_2) = 0;
}
if (id(g_direction_2) == 0 && id(g_counter_2) > 15) {
// Increase Bright
auto call = id(light_main_2).turn_on();
call.set_brightness(curr_bright + (2.0/255.0));
call.perform();
}
else if(id(g_direction_2) == 1 && id(g_counter_2) > 15) {
// Decrease Bright
auto call = id(light_main_2).turn_on();
call.set_brightness(curr_bright - (2.0/255.0));
call.perform();
}
Edit this page on GitHub