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.

1 Like

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

Good point and I would have accepted that. However thinking about it: The application will be static (no regular reboots) and when it does I’d rather have a safe state to recover via HA from. I’ve removed the option.

@mupsje you need to find your own configuration that serves your needs. Mine includes other sensors and settings. Hence the following is not the complete yaml and beware that I have changed a few things.

globals:
  - id: heiz_sollwert_percent_pwm
    type: int
    #restore_value: yes
    initial_value: '30'  # 0..100

api:
  services:
    - service: set_heiz_sollwert_percent_pwm
      variables:
        percentage: int
      then:
        - lambda: |-
            id(heiz_sollwert_percent_pwm) = percentage;
            id(heiz_sollwert_sensor).publish_state(percentage);

output:
  - platform: esp8266_pwm
    pin: D1
    frequency: 1000 Hz
    id: heiz_sollwert_pwm_output
    inverted: False
    min_power: 0.00
    max_power: 1.00

# output:
#   - platform: ledc
#     pin: GPIO16
#     frequency: 1220 Hz
#     id: heiz_sollwert_pwm_output
#     inverted: False
#     min_power: 0.00
#     max_power: 1.00

sensor:
  - platform: template
    name: "Heizung Sollwert Sensor (PWM level)"
    id: heiz_sollwert_sensor
    lambda: 'return id(heiz_sollwert_percent_pwm);'
    update_interval: 60s
    unit_of_measurement: "%"
    accuracy_decimals: 0
    icon: "mdi:pulse"
    on_value:
      then:
        - lambda: |-
            id(heiz_sollwert_pwm_output).set_level(x/100);

Additionally, In Home Assistant I’ve defined a couple of input_number entities to get from my wanted set temperature to voltage to PWM level. In testing that looks like this:

grafik

5 Likes

Hello ThomDietrich,

i think i have the same plan as you already solved :slight_smile:

I have a lot of temperature sensors on my heating system. One of my pumps has an integrated heat meter function, but requires an analog input 0-10V from the return.

I have already integrated some DS18B20 and read them out via an ESP32. Now I am looking for a solution how I can generate a 0-10v output sensor via the ESP.

I still don’t understand in your solution how you generate the percentage output from another temperature sensor in Hassio and return it to the ESP? If I overwrite the 30% in hassio, will it be set back to 30% after 60 seconds and not the value in the ESP changed? What am i forgetting?

thank you

Hey!
Above I only showed the code for ESPHome. This device exposes a service (through the code in the api section), which can be called by a Home Assistant automation. The sliders that I showed in the screenshot have this automation behind:

automation:
  - id: "1618577571740"
    alias: Regel Heizungsregelung Sollwert über Prozent Schieberegler
    trigger:
      - platform: state
        entity_id: input_number.heizungsregelung_sollwert_prozent
    action:
      - service: esphome.heizungsregelung_eigenbau_set_heiz_sollwert_percent_pwm
        data:
          percentage: "{{ trigger.to_state.state | int }}"

Hope this helps!

1 Like

Dear @ThomDietrich,

I know it’s been a while, but I hope I can ping you still. I’d like to solve a very similar issue: control my Wolf CWL400 ventillation system with 0-10V input based on various existing HA sensors data (presence, humidity, temperature, etc).

Would you be willing to share with me/us your complete config - both ESP yaml, and HA automation setup - and your electronic setup as well (what devices did you use as ESP and as PWM), so I can have it as a guide to build my own setup?

What I’d like to achieve:

  • be able to read from ESP what is the current level of ventillation
  • be able to instruct my ESP to set PWM to certain level based on HA sensor changes (eg. humidity drops below certain value, then drop ventillantion to X%, overrule this based on time of day, eg- have a constant low PWM during the night, and completely shut down ventillation when outside air quality sensor reports bad aur quality near air intake to avoid spreading bad smells in the house).

Many thanks in advance!

Hey! Sorry I didn’t answer. Reason being, that we postponed the implementation of this new heating control. I wanted to get it finished for this winter but we decided to hold off and install, test and take online for the winter to come.

Everything I can provide to learn from is posted above. Hope it helped

1 Like

Hi @ThomDietrich

Could you tell me what kind of hardware you’re using? I plan on doing something similar as you, I want to control my heat pump via a 0-10V Input when I have excess power from my solar panels.

Cheers
Dani

Hey Daniel,
I used something like this: 1-3KHZ 0-10V PWM Signal to Voltage Converter Module

Hope this helps.

When I finally got around finishing this project I HAVE to post the full project here :slight_smile: