ESPHome configuration for PWM to 0..10V output, sensor and control

Hey community,
I want to control a heating element through a PWM to voltage converter (0 to 10V). The electronics part is working but I’m struggling with the integration in Home Assistant.

My config so far:

esphome:
  name: heizung_test
  platform: ESP8266
  board: d1_mini

wifi:
  ...

output:
  - platform: esp8266_pwm
    pin: D1
    frequency: 1000 Hz
    id: pwm_output

How do I now properly link this to Home Assistant? I would like

  1. the current level from the ESP as an entity value
  2. the ability to change the value (e.g. through Home Assistant automation)

Maybe I’m missing something obvious here… I could hack a light entity to do the job but that can’t be it. There has to be a cleaner way. Grateful for any hints!

Thanks!


Btw. For testing purposes I added this quick proof of concept:

switch:
  - platform: gpio
    name: "test"
    pin: D2  # there is actually nothing connected here
    on_turn_on:
      then:
        - output.set_level:
            id: pwm_output
            level: 50%

This works and produces the expected 5V out upon switching from HA.

I would probably start by using a Template Switch instead of the GPIO platform if you want to do control from HA rather than locally on the ESP. Actually two template switches maybe - one to turn up frequency and one to lower it?

As for outputting to HA the current value, again templates, the Template Sensor.

Do all the range checking for low and high values in the template switches. Store the current value of the output in a Global Variable.

Have a read of Automations and Templates - it’s full of lots of good stuff.

Hey @zoogara,
thanks for your response. I followed your input and hacked the following together.

sensor:
  - platform: template
    name: "Test Template Sensor"
    id: heat_set_value_sensor
    lambda: 'return id(heat_set_percent);'
    update_interval: 10s

globals:
   - id: heat_set_percent
     type: float
     initial_value: '0'  # 0..100

switch:
  - platform: template
    name: "Test Template Switch +10%"
    lambda: 'return false;'
    turn_on_action:
      - lambda: |-
          id(heat_set_percent) += 10;
          if (id(heat_set_percent) > 100) id(heat_set_percent) = 100;
          id(pwm_output).set_level(id(heat_set_percent)/100);
          id(heat_set_value_sensor).publish_state(id(heat_set_percent));

  - platform: template
    name: "Test Template Switch -10%"
    ...

It is ridiculously complicated for such a simple task - but it does the trick.

Now here is the issue. Buttons to increase or decrease by 10% won’t cut it :upside_down_face: In order to control the heating system I need to send an absolute value (e.g. 55%) from a Home Assistant automation. I don’t see the ESPHome integration providing an HA service. I also thought about the ESPHome REST API but it doesn’t seem to allow writing directly to a global variable.

This little project is my first contact with ESPHome and so far it does not compete well :sweat_smile: But I’m here to learn. Any further help would be hugely appreciated :slight_smile:

OK - so to read a value from HA into ESPHome - use a HA Text Sensor:

You can use that sensor value to update your variable or apply it direct to the PWM - whatever…

In HA you need an entity for the text sensor to reference - use the Input Number integration:

You can have a slider or an input box. Or both.

There are probably other ways - maybe Tom or one of the other moderators may pop in with a suggestion.

EDIT: Or maybe you already have the value in HA - just thought of that. :slight_smile: You get the drift.

1 Like

There is a home assistant sensor! I didn’t expect that.

Strange circular dependency and cognitive overhead this adds to the control system :thinking: What do you think? Do you by any chance know whether a HA service to send a command to ESPHome is planned?


It is now fully working. Leaving the solution for others.

Home Assistant config:

input_number:
  sollwert:
    name: Sollwert
    unit_of_measurement: "%"
    min: 0
    max: 100
    step: 1

ESPHome config:

globals:
  - id: heat_set_percent
    type: float
    # restore_value: yes
    initial_value: '0'  # 0..100

sensor:
  - platform: homeassistant
    entity_id: input_number.sollwert
    id: ha_heat_set_input
    internal: true
    accuracy_decimals: 0
    on_value:
      then:
        - lambda: |-
            id(heat_set_percent) = x;
            id(heat_set_value_sensor).publish_state(x);

  - platform: template
    name: "Test Template Sensor"
    id: heat_set_value_sensor
    lambda: 'return id(heat_set_percent);'
    update_interval: 60s
    unit_of_measurement: "%"
    accuracy_decimals: 0
    icon: "mdi:pulse"
    on_value:
      then:
        - lambda: |-
            id(pwm_output).set_level(x/100);

I left the ±10% switches from above and the global variable in for now. If I decided to remove them at a later point, the logic could be a simplified. After all I am very happy with the result.

Thanks @zoogara! Please leave another comment so I can mark it as the solution.

Glad it’s working ok. ESPHome sort of already gets commands from HA, in the form of MQTT or API messages to perform switching etc. There is a component in ESPHome to go the other way - i.e. directly perform HA service calls from ESPHome, but nothing to do things like pass values or commands to ESPHome other than the things you are already using.

Good luck with the project.

You can already do that. You can define a service in your ESPHome yaml that you can that call as service in HA automations. See: https://esphome.io/components/api.html#user-defined-services

2 Likes

@danielw :star_struck: I’ll have a look later this week.

I have to be honest, I totally underestimated how tightly integrated ESPHome is with Home Assistant. I didn’t even think about the possibility that you might be able to access HA entities, let alone, expose a service to it.

Thanks both, I now have exactly the solution I wanted

  • A sensor reporting the current setting
  • A HA service to change the setting
  • Memory restore across reboots of my ESP

For others following along, the service definition:

api:
  services:
    - service: set_heating_pwm_level
      variables:
        percentage: int
      then:
        - lambda: |-
            id(heat_set_percent) = percentage;
            id(heat_set_value_sensor).publish_state(percentage);

Great :slight_smile:

How did you do that?

No big tricks :slight_smile:

esphome:
  name: test
  platform: ESP8266
  board: d1_mini
  esp8266_restore_from_flash: yes  # <--

globals:
  - id: heat_set_percent
    type: int
    restore_value: yes  # <--

OK keep in mind if the value is changing a lot it will kill your flash sooner or later.

Hi, I’m also busy with a valve from Honeywell to control 0-10v For underfloor heating.

First 0-10v, then in HA PID regulator programming…

Can you please show us you complete ESP yaml…
Because I saw a difference in globals… from float to int…

Thanks allot