Push button dimmer - how?

You need logic-level Mosfet with VGS(th) max 3.3V. IRLB8721 has full saturation on 2.35V. You probably know that. Just to be sure.

Thank you, @drdolitle1 - this works perfectly for my needs and improves my attempt no end!

I have it working on an ESP8266-01, using pin 2 for output to a MOSFET (through a opto-coupler) and pin 0 for a touch switch input.

Thanks again!

1 Like

Thanks for the code!

I added a few features I like:

  • Dim up and down constantly if max/min brightness is reached
  • Start with a default brightness of 70%
  • Always dim up after turning on (from off)
globals:
  - id: my_global_bool
    type: bool
  - id: my_global_float
    type: float
    
binary_sensor:
  - platform: gpio
    pin:
      number: 34
      mode: INPUT    
      inverted: True
    filters:
      - delayed_on: 20ms
    name: "light switch with a name"
    id: "kids1_tast"
      
    on_click:
      then:
        - if:
            condition:
              light.is_off: light1
            then:
              - lambda: |-
                  id(my_global_float) = 0.7;
                  ESP_LOGD("main", "Global value brightness is: %f", id(my_global_float));
                  id(my_global_bool) = (true);  // make sure always dim up after turn on
              - light.turn_on: 
                  id: light1
                  brightness: !lambda |-
                    return id(my_global_float);        
            else:
              - light.turn_off: light1
       
    on_press:
      then:
        - delay: 0.5s
        - if:
            condition: 
              binary_sensor.is_on: kids1_tast
              # don't do a thing if not pressed long enough
            then:
              - while:
                  condition:
                    binary_sensor.is_on: kids1_tast
                  then:
                    - if:
                        condition: 
                            lambda: |-
                              return id(my_global_bool);
                        then:
                                
                          - light.dim_relative:
                              id: light1
                              relative_brightness: 2%
                              transition_length: 0.1s
                          - delay: 0.1s
                          - lambda: |-
                              id(my_global_float) = id(light1).current_values.get_brightness();
                              ESP_LOGD("main", "+Global value is: %f", id(my_global_float));
                              // invert dim direction if full on
                              if (id(light1).current_values.get_brightness() >= 0.99) id(my_global_bool) = false;
                        else:
                          - light.dim_relative:
                              id: light1
                              relative_brightness: -2%
                              transition_length: 0.1s
                          - delay: 0.1s
                          - lambda: |-
                              id(my_global_float) = id(light1).current_values.get_brightness();
                              ESP_LOGD("main", "Global value brightness is: %f", id(my_global_float)); 
                              if (id(light1).current_values.get_brightness() <= 0.04) id(my_global_bool) = true;                 
              - lambda: |-
                  id(my_global_bool) = !id(my_global_bool) ; // invert bool at end of while

cheers

5 Likes

Hi. I’m sorry, what platform do you use? I read this thread twice: @drdolitle1 is using Wemos, @aceindy went with Moes, does it work with any ESP8266 switch or does need an actual dimmer? For example, will the code work with Sonoff mini R2 and Dual R3 after certain adaptation?

will work. works for me on sonoff basic

You can see my solution Here

1 Like

Thanks a bunch for the quick reply.
So , you need a PWM module anyway, you used a 5/12/36V LED, but what about regular 230V dimmable LED lamps?

There is such a component I bought it but haven’t been able to run it yet. Maybe it’s broken.

I thought so. Okay, thanks again, I’m off for testing.

These are all esp8266 based.

But is depends a bit on the dimmer used…

The trick is to figure out the IO used, meaning the IO pins might differ a bit between different models
So this applies to Moes:

uart:
  tx_pin: GPIO1
  rx_pin: GPIO3

- platform: duty_cycle
    pin: GPIO13
  - platform: esp8266_pwm
    pin: GPIO14
    frequency: 800 Hz

But other brands might use other pins.
I haven’t found a suitable device list for ESPHome, but I did find a good list for Tasmota, and since they both use the same pins it is a good reference :stuck_out_tongue:

1 Like

Yes, I realised I was missing the point of needing an MCU of some sort, was kinda hoping to achieve dimmer effect via basic light component :roll_eyes: Then I remembered I had some experience with Sonoff T4 coding where you can setup slow LED activation like this one:

# Setting up slow LED activation
output:  
  - platform: esp8266_pwm
    id: blue_led
    pin: GPIO13
    inverted: True

light:
  - platform: monochromatic
    name: "Sonoff ${device_name} Blue LED"
    internal: true
    output: blue_led
    id: led

and then it hit me - I WAS using software PWM for that purpose. Now I’m on the right track with coding, going to order some dimmers :smiley:

I still got to the 220v dimmer module. it works and I will continue to connect bulbs for testing

@RGN01 trying to do the same thing here.

The light I want to control is not directly attached to the esp board like most of the examples here seem to be. I do have that on another node and use a little while loop like this:

              - while:
                  condition:
                    binary_sensor.is_on: the_orange_button
                  then:
                  - light.dim_relative:
                      id: led
                      relative_brightness: -1%
                      transition_length: 0.01s
                  - delay: 0.01s

For another button I was setting up today - again, not connected directly to the light I want to control. I use this little while loop blurb:

  - timing:
    - ON for at least 0.75s
    then:
    - while:
        condition:
          binary_sensor.is_on: the_button
        then:
        - logger.log: "Hoooooolds it"
        - homeassistant.service:
            service: light.turn_on
            data:
              brightness_step_pct: "5"
              transition: "1"
              entity_id: light.office_lamp
        - delay: 3s

Still futzing with the values for step_pct, transition and delay but this does seem to work.

Figured I could make this a bit more awesome so I added a sensor to the esp config that gets the current brightness of the light from home assistant. Once I knew that I was able to make it so that if I hold the button and the light is below 50% it will increase the brightness, if it’s above 50% it will decrease it.

Brightness sensor:

sensor:
  - platform: homeassistant
    id: light_bright
    entity_id: light.office_lamp
    attribute: brightness

Then the binary_sensor - aka - the_button

binary_sensor:
- platform: gpio
  pin:
    number: D6
    mode: INPUT_PULLUP
    inverted: True
  name: "$name Button"
  id: the_button
  internal: true
  on_multi_click:
  - timing:
    - ON for at most 1s
    - OFF for at least 0.5s
    then:
    - logger.log: "Single Click"
    - homeassistant.service:
        service: light.toggle
        data:
          entity_id: light.office_lamp
  - timing:
    - ON for at least 0.75s
    then:
    - while:
        condition:
          binary_sensor.is_on: the_button
        then:
        - logger.log: "Hoooooolds it"
        - homeassistant.service:
            service: light.turn_on
            data:
              brightness_step_pct: "5"
              transition: "1"
              entity_id: light.office_lamp
        - delay: 3s
        - if:
            condition:
              - lambda: 'return id(light_bright).state < 127;'
            then:
              - while:
                  condition:
                    binary_sensor.is_on: the_button
                  then:
                    - logger.log: "Hoooooolds it up"
                    - homeassistant.service:
                        service: light.turn_on
                        data:
                          brightness_step_pct: "5"
                          transition: "1"
                          entity_id: light.office_lamp
                    - delay: 3s
            else:
              - while:
                  condition:
                    binary_sensor.is_on: the_button
                  then:
                    - logger.log: "Hoooooolds it down"
                    - homeassistant.service:
                        service: light.turn_on
                        data:
                          brightness_step_pct: "-5"
                          transition: "1"
                          entity_id: light.office_lamp
                    - delay: 3s

It works. I’m sure somebody could make it better but this works.

cheers! :beers:

This is great - thank you!

I have a setup on an ESP node where the button can dim or brighten the attached LEDS and will try to merge that code with yours so the same logic can be used on lights not directly attached to the ESP. I’m a bit short on time right now so it won’t be immediately.

Thanks again for sharing your code!

1 Like

I managed to merge the code as mentioned. This uses a touch switch module on a ESPHOME ESP-01 node to control a remote HASS light.

A click toggles the light while holding the switch brightens or dims it. To reverse operation (e.g. if it is dimming and you need it brighten) then release the hold down and go straight to hold down again.

I hope it is helpful.

esphome:
  name: $devicename
  platform: ESP8266
  board: esp01_1m

substitutions:
  devicename: light-remote-switch        # name of this node  
  upper_devicename: "Light and Switch"   # English Readable name for the node
  short_devicename: "LightSwitch"        # Short form English readable name
  hass_light: "light.study_ceiling"      # HASS entity name of the HASS light to be controlled
  address_ip: X.Y.Z.A
  address_subnet: Y.Y.Y.Y
  address_gateway: X.Y.Z.B

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  domain: !secret wifi_domain
  reboot_timeout: 5min

  manual_ip:
    static_ip: $address_ip
    gateway: $address_gateway
    subnet: $address_subnet

logger:
api:
ota:


globals:
  - id: bool_dim_or_bright #false = dim, true = brighten
    type: bool
    restore_value: no
    initial_value: 'false'

switch:
# This is to restart the ESPHome device remotely
  - platform: restart
    name: ${upper_devicename} - Restart

sensor:
  - platform: wifi_signal
    name: ${upper_devicename} - WiFi
    update_interval: 60s

  - platform: homeassistant #a local sensor to hold the HASS light brightness
    id: light_brightness_from_hass
    entity_id: $hass_light 
    attribute: brightness    

binary_sensor:
  - platform: homeassistant # a local binary sensor to hold the HASS light on / off status
    id: controlled_light_on_hass
    entity_id: $hass_light 

  - platform: gpio
    pin: # Note: This must be true or the ESP-01 will not boot is using a touch switch module (which must be set to be active low)
      number: 0
      inverted: TRUE 
      mode: INPUT_PULLUP
    id: touch_switch
    filters:
      - delayed_on: 50ms  
      - delayed_off: 50ms 
    on_click:
      then:
        - if:
            condition:
              binary_sensor.is_off: controlled_light_on_hass # if light is off, turn it on
            then:
              - homeassistant.service:
                  service: light.turn_on
                  data:
                    entity_id: $hass_light 
            else: # else it is on so turn it off
              - homeassistant.service:
                  service: light.turn_off
                  data:
                    entity_id: $hass_light 
    on_press:
      then:
      - if:
          condition: 
              lambda: |-
                return id(bool_dim_or_bright);
# When above condition evaluates to true - brighter function else dimmer
          then:
          - delay: 0.5s
          - while:
              condition:
                binary_sensor.is_on: touch_switch
              then:
                - homeassistant.service:
                    service: light.turn_on
                    data:
                      brightness_step: "5"
#                      transition: "1" 
                      entity_id: $hass_light 
                - delay: 0.05s
          - lambda: |-
              id(bool_dim_or_bright) = (false);
          else:
          - delay: 0.5s
          - while:
              condition:
                and:
                  - binary_sensor.is_on: touch_switch
# This is to set the minimum value so that touch sensor only allows pre-set minimum
                  - sensor.in_range:
                      id: light_brightness_from_hass
                      above: 10
              then:
                - homeassistant.service:
                    service: light.turn_on
                    data:
                      brightness_step: "-5"
#                      transition: "1"
                      entity_id: $hass_light 
                - delay: 0.05s
          - lambda: |-
              id(bool_dim_or_bright) = (true);
3 Likes

Is this the solution or still work in progress?

I am using it but everything on my HASS installation is permanently a WIP! :joy:

I tested it and it works great for me. I immediately flashed it on a sonoff mini which controls an esp led dimmer in my ceiling lamp. I couldn’t figure out how to do it otherwise, while still using my conventional wall switches. Before I had to adjust the dimming through home assistant and the wall switch was used for powering on/off. However, this was not making the wife happy.
Now, she is happy again. Also because now we can controll all led lighting through the momentary wall switches.

Hi, thanks for the dimming yaml.

globals:
  - id: bool_dim_or_bright #false = dim, true = brighten
    type: bool
    restore_value: no
    initial_value: 'false'

  - id: bool_warm_or_cold #false = warm, true = cold
    type: bool
    restore_value: no
    initial_value: 'false'


binary_sensor:
  - platform: gpio
    pin:
      number: GPIO5
    name: ${device_name} button
    id: ${device_name} button
    # config for multi click actions
    on_multi_click:
      # double click
      - timing:
          - ON for at most 1s
          - OFF for at most 1s
          - ON for at most 1s
          - OFF for at least 0.2s
        then:
          - if:
              condition:
                and:
                  - wifi.connected:
                  - api.connected:
              # double click to toggle between cold and warm light
              then:
              - if:
                  condition: 
                      lambda: |-
                        return id(bool_dim_or_bright);
        # When above condition evaluates to true - cold else warm
                  then:
                  - delay: 0.5s
                  - while:
                      condition:
                        binary_sensor.is_on: ${device_name} button
                      then:
                        - light.turn_on:
                            id: light_1
                            brightness: 40%
                            color_temperature: 2000 K
                  - lambda: |-
                      id(bool_dim_or_bright) = (false);
                  else:
                  - delay: 0.5s
                  - while:
                      condition:
                        and:
                          - binary_sensor.is_on: ${device_name} button
                      then:
                        - light.turn_on:
                            id: light_1
                            brightness: 100%
                            color_temperature: 6530 K
                  - lambda: |-
                      id(bool_dim_or_bright) = (true);
              # toggle relay in case either wifi or api are not connected
              else:
                - switch.toggle: shelly_relay

I’m trying to figure out how to toggle cold or warm light with double click using lambda.
But I’m not sure how to configure the condition so double click would just toggle bool_warm_or_cold true or false.