Sensor for PWM output duty cycle

Hello,

I have recently started playing Home Assistant + ESPHome and I decided to use it to automate my fish tank. I quite easily managed to created a controller with an ESP8266 that works quite well to control the tank’s lights, filter, heater, temperature sensor etc.

The lights are controller through the ESP8266 Software PWM Output component. I have setup Home Assistant to retrieve the sunrise, sunset and twilight times for some given coordinates. And automation then turns on the lights a the sunrise time with a transition equal to the twilight time. The same way another automation turns off the light at the sunset time again with a transition equal to the twilight time. Another set of automation does the same with the moonlight based on the moonrise and moonset times.

All this works quite well, but there is one more thing I would like to do and I’m struggling with…

In the Home Assistant dashboard I have created for the fish tank I would like to add a Sensor card that shows the brightness of the fish tank light through the day. For this I have created a Template sensor on the ESP8266 controller that is supposed to feedback the current brightness setting of the light:

  - platform: template
    name: "Freshwater Tank - Light 1 Brightness"
    id: freshwater_tank_light1_brightness
    update_interval: 20s
    accuracy_decimals: 0
    unit_of_measurement: "%"
    icon: "mdi:weather-sunny"
    lambda: |-
      if (id(freshwater_tank_light1).remote_values.is_on()) {
        return (int(id(freshwater_tank_light1).remote_values.get_brightness() * 100));
      } else {
        return 0;
      }

The problem is that even if I use a long transition time (e.g. 30min) the brightness read by this sensor goes immediately to the max as soon as the light is turn on and immediately to 0 as soon as the light is turn off. I believe this is because the brightness attribute of the light component does not change during the transition.

Is there any way to set up in ESPHome a virtual sensor to feedback the current duty cycle of the PWM output so that the actual brightness of the light can be plotted in Home Assistant?

1 Like

Does it make a difference when you access “current_values” instead of “remote_values”?

I just tried changing the code to .current_values and made no difference. The sensor value went straight to the maximum value when I started the transition to turn on the light.

oh :frowning:

Current Values is definitely correct. See comment in source:

 /** The current values of the light as outputted to the light.
   *
   * These values represent the "real" state of the light - During transitions this
   * property will be changed continuously (in contrast to .remote_values, where they
   * are constant during transitions).
   *
   * This property is read-only for users. Any changes to it will be ignored.
   */

and remote_values:

/** The remote color values reported to the frontend.
   *
   * These are different from the "current" values: For example transitions will
   * continuously change the "current" values. But the remote values will immediately
   * switch to the target value for a transition, reducing the number of packets sent.
   *
   * This property is read-only for users. Any changes to it will be ignored.
   */

I now looked into the code again. I think the issue is, that the transition is not chaning the brightness but the light state. That is because you have transition from off to on. that does not change the brightness but the “on-ness”. State is a float.

Please try this:

      if (id(freshwater_tank_light1).remote_values.is_on()) {
        float brightness;
        id(freshwater_tank_light1).current_values_as_brightness(&brightness);
        return (int(brightness * 100));
      } else {
        return 0;
      }

Let’s hope that does it. If not I am afraid I am out of ideas. From the source I see that is how it works.

1 Like

Hi Danielw,

I tried the code you suggested but did not work. However, you pointed me in the right direction and I found a solution that might not be elegant but works for what I’m trying to do. :slight_smile:

As you mentioned remote_values returns the value set up in HA, while current_values returns the actual value during the transition. However, as you mentioned if the light is turn on and off the brightness attribute is not changed: it stays to the value that was setup when the light was on.

The work around I found for my case is instead of turning off the light to dim it down to the minimum value with a transition, wait the end of the transition and then turn it off.
Below is how I have setup the automation. Worth mentioning that I had to use brightness: ‘{{ 1 }}’ because brightness: ‘{{ 0 }}’ just toggles the light off without changing the brightness value.

- id: '1618083836630'
  alias: Freshwater Tank - Sunset
  description: ''
  trigger:
  - platform: time
    at: input_datetime.freshwater_tank_sunset
  condition: []
  action:
  - service: light.turn_on
    target:
      entity_id: light.freshwater_tank_light_1
    data_template:
      transition: '{{ (states(''input_number.freshwater_tank_twilight'') | int) *
        60 }}

        '
      brightness: '{{ 1 }}'
  - delay: '{{ states(''input_number.freshwater_tank_twilight'') | multiply(60) |
      int }}'
  - service: light.turn_off
    target:
      entity_id: light.freshwater_tank_light_1
  mode: single

In ESPHome I have setup a sensor that just returns current_values.get_brightness():

  - platform: template
    name: "Freshwater Tank - Light 1 Brightness"
    id: freshwater_tank_light1_brightness
    update_interval: 20s
    accuracy_decimals: 0
    unit_of_measurement: "%"
    icon: "mdi:weather-sunny"
    lambda: |-
      return (int(id(freshwater_tank_light1).current_values.get_brightness() * 100));

This does the trick!
dashboard

1 Like

OK, great that you figured it out.

I am a little confused though I thoug that I finally understood the logic :frowning: (a on → off or off->on transistion should change the “on” state from 0 to 1 oder 1 to 0. And current_values_as_brightness should return the brightness * state (* gamma correction).

1 Like