I have some Martin Jerry / Tessan dimmer switches, which are Tuya based. I’ve successfully flashed Tasmota to it using tuya_convert, so all is good there.
I’d like to convert to ESPHome, which is brilliant stuff (hats off to OttoWinter!)
These switches use a ton of GPIOs: one for each button (power, up, and down), one for each of the LEDs that indicate the dimmer level, a relay (which controls the load), PWM for dimmer. Each of these needs to be managed independently. For instance, when you raise the dim level, you have to calculate and light the indicator lights yourself (e.g. all 4 lit for 100% dim, 2 lit for 50% dim level, etc).
I actually have it working, but am running into a few issues that maybe I get some guidance on:
-
There is a relay that turns the load (goes to the light) completely on and off. Dimming is handled separately through PWM. You have to turn the relay (switch) on to get light. This means there are two items in Home Assistant: the switch (relay) and the light (which HA shows is dimmable). At the moment, I have the “switch” turn on the “light” in ESPHome using the “on_turn_on” action, since the switch (relay) has to be on for the light to illuminate.
-
I’m keeping a global variable with the dim level (0-100), and using that to track the current dim level and to calculate how many LED indicator lights to light up. Right now the calcs are sloppy, as I copied the Tasmota “rule” setup for now. This works brilliantly when manually manipulating the switch (e.g. pushing the UP or DOWN buttons), but I can’t figure out how to update these when Home Assistant changes the dim level.
In essence, I’m trying to have the Home Assistant config be clean (one HA light that turns on and off and is dimmable) and have the LED indicator lights be accurate to the current dim level whether done manually at the switch or through Home Assistant. Would a template switch help? I’m not sure I fully understand them yet, frankly.
Here’s what I have, I know there are a ton of lambdas and I may be overthinking it… but I do love that I can drop into C code anytime.
Any help would be appreciated! Oh, and if you have similar switches, feel free to use this… it mostly works.
# Martin Jerry / Tessan In-Wall Dimmer
esphome:
name: dimmer_master_bedroom
platform: ESP8266
board: esp01_1m
wifi:
ssid: "#####"
password: "####"
# Enable logging
logger:
# Enable Home Assistant API
api:
ota:
web_server:
port: 80
# Lots of stuff to define
# Reference: https://github.com/arendst/Sonoff-Tasmota/wiki/Martin-Jerry-MJ-SD01
# GLOBAL to hold current dimmer value in percentage
# Will need to divide by 100 in lambda when setting power
globals:
- id: dimmerpct
type: float
restore_value: no
initial_value: '100.0'
#------------------------------------------------------------------------------
# Initial GPIO Outputs
#------------------------------------------------------------------------------
# Indiciator LEDs for dimmer value
# We go from 1 to 4, with 1 being the lowest LED and 4 being the highest
output:
- platform: gpio
pin: GPIO14
inverted: true
id: level_led1
- platform: gpio
pin: GPIO12
inverted: true
id: level_led2
- platform: gpio
pin: GPIO5
inverted: true
id: level_led3
- platform: gpio
pin: GPIO3
inverted: true
id: level_led4
# PWM for dimmer control, to attach to main light
- platform: esp8266_pwm
pin: GPIO13
frequency: 1000 Hz
id: dimmer_pwm
#------------------------------------------------------------------------------
# Main relay - internal switch to turn the light on and off
#------------------------------------------------------------------------------
switch:
- platform: gpio
pin:
number: GPIO16
inverted: true
id: light_relay
name: "Master Bedroom Lamp"
on_turn_on:
- light.turn_on:
id: main_light
brightness: !lambda 'return (id(dimmerpct) / 100.0);'
- lambda: !lambda |-
// Turn on indicators
if (id(dimmerpct) > 19.0) { id(level_led1).turn_on(); }
if (id(dimmerpct) < 20.0) { id(level_led1).turn_off(); }
if (id(dimmerpct) > 39.0) { id(level_led2).turn_on(); }
if (id(dimmerpct) < 40.0) { id(level_led2).turn_off(); }
if (id(dimmerpct) > 59.0) { id(level_led3).turn_on(); }
if (id(dimmerpct) < 60.0) { id(level_led3).turn_off(); }
if (id(dimmerpct) > 79.0) { id(level_led4).turn_on(); }
if (id(dimmerpct) < 80.0) { id(level_led4).turn_off(); }
on_turn_off:
- light.turn_off:
id: main_light
transition_length: 1000 ms
- output.turn_off: level_led1
- output.turn_off: level_led2
- output.turn_off: level_led3
- output.turn_off: level_led4
#------------------------------------------------------------------------------
# Main output light
#------------------------------------------------------------------------------
light:
- platform: monochromatic
name: "Master Bedroom Lamp - Light"
id: main_light
gamma_correct: '0.0'
default_transition_length: 0 ms
output: dimmer_pwm
#------------------------------------------------------------------------------
# Buttons - Up, Down, and the main power toggle
#------------------------------------------------------------------------------
binary_sensor:
# UP button
- platform: gpio
pin:
number: GPIO0
mode: INPUT_PULLUP
internal: true
id: button_up
filters:
- delayed_on: 10ms
on_press:
then:
- lambda: !lambda |-
if (id(light_relay).state) {
if (id(dimmerpct) <= 90.0) {
id(dimmerpct) += 10.0;
};
id(dimmer_pwm).set_level(id(dimmerpct)/100.0);
// Update Indicators
if (id(dimmerpct) > 19.0) { id(level_led1).turn_on(); }
if (id(dimmerpct) < 20.0) { id(level_led1).turn_off(); }
if (id(dimmerpct) > 39.0) { id(level_led2).turn_on(); }
if (id(dimmerpct) < 40.0) { id(level_led2).turn_off(); }
if (id(dimmerpct) > 59.0) { id(level_led3).turn_on(); }
if (id(dimmerpct) < 60.0) { id(level_led3).turn_off(); }
if (id(dimmerpct) > 79.0) { id(level_led4).turn_on(); }
if (id(dimmerpct) < 80.0) { id(level_led4).turn_off(); }
}
# DOWN button
- platform: gpio
pin:
number: GPIO1
mode: INPUT_PULLUP
internal: true
id: button_down
filters:
- delayed_on: 10ms
on_press:
then:
- lambda: !lambda |-
if (id(light_relay).state) {
if (id(dimmerpct) >= 11) {
id(dimmerpct) -= 10.0;
};
id(dimmer_pwm).set_level(id(dimmerpct)/100.0);
// Update Indicators
if (id(dimmerpct) > 19.0) { id(level_led1).turn_on(); }
if (id(dimmerpct) < 20.0) { id(level_led1).turn_off(); }
if (id(dimmerpct) > 39.0) { id(level_led2).turn_on(); }
if (id(dimmerpct) < 40.0) { id(level_led2).turn_off(); }
if (id(dimmerpct) > 59.0) { id(level_led3).turn_on(); }
if (id(dimmerpct) < 60.0) { id(level_led3).turn_off(); }
if (id(dimmerpct) > 79.0) { id(level_led4).turn_on(); }
if (id(dimmerpct) < 80.0) { id(level_led4).turn_off(); }
}
# Main Power Button
- platform: gpio
pin:
number: GPIO15
mode: INPUT_PULLUP
internal: true
id: button_main_power
filters:
- delayed_on: 10ms
on_press:
then:
- switch.toggle: light_relay