Opentherm Multi Room brainstorming / ideas

Just curious, did you ever find a solution for this? And I’m not sure why the solution you refer to wouldn’t work for you. I have the same situation you describe and the solution in your link sounds very similar to what I am working on. The only difference is that I have separate window sensors to determine if a room should be considered for heating.

The exact issue was that i’m using an OpenTherm module that requires me to input the setpoint temperature and actual temperature which this does not do. At the end its just switching based upon if a room needs heating.

I realized i could just create generic thermostats for the rooms and use their switch to open or close the valve in that room.
After that i created 2 custom sensors:

  1. Virtual Setpoint
    Here i compared the setpoint of each room and the temperature of that room, which ever had the biggest difference i would send to the OpenTherm module
  2. Virtual Temperature
    Like above i looked at the biggest difference and send that temperature

I did it this way to prevent it delivering to little heat. (The closer the temperature is to the setpoint the lower the CV will output)
And i switch off the pump if no room had any heating requirement.
This has been a real gas saver as no heat is being dumped in rooms that dont need it.

If you could share your code that would be great! Especially the ‘switch off the pump’ part since I read in some other forums posts that is not a standard part of the code that the diyless guys provide.

Also wondering if you have a backup system in case anything happens with the diyless components or home assistant? I was thinking about leaving my old thermostat hanging and using a simple switch to connect either the diyless or old thermostat to the boiler. If anything happens, I can just flip the switch and the old thermostat will start doing his thing.

On the other hand, I was also considering getting a regular smart thermostat and using this as you are using the diyless thermostat. It would just be a passthrough for the virtual thermostats set up in HA. But with the added benefit of not having a non-functional thermostat hanging on my living room wall which would be the case when using the diyless thermostat.

So here is my code, first of all i use a template sensor to calculate what i am going to send to the diyless thermostat. I do a basic comparison of all the rooms and send whatever room has the biggest delta temperature. So if 1 rooms reaches it temp and another room is still colder it wont start to throttle back the output temperature. I do this by using the index method.
By default it will use the living room as reference, so there is always a valid value send.

- platform: template
  sensors:
    setpoint_cv_virtual:
      friendly_name: "CV Virtual Setpoint"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = (state_attr('climate.alex','temperature') - states('sensor.alex_sensor_temperature') | float) %}
        {% set esther_td = (state_attr('climate.esther','temperature') - states('sensor.esther_sensor_temperature') | float)%}
        {% set woonkamer_td = (state_attr('climate.woonkamer','temperature') - states('sensor.woonkamer_sensor_temperature') | float) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ state_attr('climate.alex','temperature') }}
        {% elif index_td == 2 %}
          {{ state_attr('climate.esther','temperature') }}
        {% else %}
          {{ state_attr('climate.woonkamer','temperature') }}
        {% endif %}
    temperature_cv_virtual:
      friendly_name: "CV Virtual Temperature"
      unit_of_measurement: "°C"
      value_template: >
        {% set alex_td = (state_attr('climate.alex','temperature') - states('sensor.alex_sensor_temperature') | float) %}
        {% set esther_td = (state_attr('climate.esther','temperature') - states('sensor.esther_sensor_temperature') | float)%}
        {% set woonkamer_td = (state_attr('climate.woonkamer','temperature') - states('sensor.woonkamer_sensor_temperature') | float) %}
        {% set max_td = ([woonkamer_td,alex_td,esther_td] | max) %}
        {% set list_room_td = [woonkamer_td,alex_td,esther_td] %}
        {% set index_td = list_room_td.index(max_td) %}
        {% if index_td == 1 %}
          {{ states('sensor.alex_sensor_temperature') | float }}
        {% elif index_td == 2 %}
          {{ states('sensor.esther_sensor_temperature') | float }}
        {% else %}
          {{ states('sensor.woonkamer_sensor_temperature') | float }}
        {% endif %}

I send these 2 values to the shield using Node Red with the resend module in 20 seconds interval.
Found this easier then using an automation in the beginning, but there may be a better way.

For switching off the heating i use an automation to set the HVAC mode.

alias: CV Aan/Uit
description: ''
trigger:
  - platform: template
    value_template: >-
      {{ states('sensor.setpoint_cv_virtual') >
      states('sensor.temperature_cv_virtual') and states('climate.heating') ==
      "off" }}
    id: StartWarmteVraag
  - platform: template
    value_template: >-
      {{ states('sensor.setpoint_cv_virtual') <
      states('sensor.temperature_cv_virtual') and states('climate.heating') ==
      "heat"  }}
    id: EindeWarmteVraag
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: StartWarmteVraag
        sequence:
          - service: climate.set_hvac_mode
            target:
              entity_id: climate.heating
            data:
              hvac_mode: heat
      - conditions:
          - condition: trigger
            id: EindeWarmteVraag
        sequence:
          - service: climate.set_hvac_mode
            target:
              entity_id: climate.heating
            data:
              hvac_mode: 'off'
    default: []
mode: restart
1 Like

Thanks for the code! I made a dummy thermostat to test it out, this far it works great. Next for me will be to try to incorporate window sensors to determine if a room should be considered for heating.

I was wondering if you ever turn off one of the thermostats? Because if you would, the template would still take it into account and possibly use it to set the main heater. I am trying to integrate windows sensors for each thermostat, but running into this problem. I fixed this now by changed the template a bit:

{% if states('climate.anna') == 'heat' %}
  {% set anna_td = (state_attr('climate.anna','temperature') - states('sensor.tempsensor_anna_temperature') | float) %}
{% else %}
  {%set anna_td ='0' | float %}
{% endif %}

But I would still need to turn off the main thermostat when all of the sub thermostats are on idle or turned off.

@Dujith

I want to built a nearly identical system as yours. I have a boiler with integrated OpenTherm support and all radiators will be fitted with an electronic open/closed valve along a temperature sensor (ds18b20) in each room.

The way I’m reading it is that you do the main part in Home Assistant and using NodeRed for communication with the thermostat shield, is that right? Why don’t you interact with the shield from HomeAssistant? After all, the thermostat shield is powered using the boiler and you could also hook up the (I2C) wires directly to the (in my case) Raspberry Pi running HA. But please correct me if I’m missing something.

And… how are you implementing the (multi-zoned) PID controller? That isn’t quite clear to me.

I’m using node-red to resend the value at intervals. If i do not do that the shield goes to a default value.
Been a while since i dug into that but had something todo with the opentherm standard.
You could do this in HA but node-red was just so damn easy :smiley: and i was learning at the time.

The sketch send to the shield uses a MQTT broker so i’m talking via that on Homeassistant.
Again the node-red was just for the repeat message, the rest is all via HA (setpoints, temps, ect)

I explained this in: Opentherm Multi Room brainstorming / ideas - #5 by Dujith
Its rough but the basic idea is that i take all the rooms, check the delta temperature (difference between setpoint and actual temp) and if there is a heating need it will use the biggest difference to send to the shield. Otherwise it would not pump in enough heat if 1 delta was 0.3 vs a room that has 1.5 degree delta.
The motors themselves i just open with the room thermostat. PID is handled by the sketch on the shield. So the room thermostats are just on/off.

So I could basically alter the sketch to remove the MQTT part and do it directly? Which sketch are you talking about, there are many examples on DIYLESS.

When I have all the hardware hooked up I will run some tests. It will take a while before the shield gets here…

I typed that wrong, the sketch is not on the shield but on ESP32 or 8266. I have no idea if you could run the shield from just your PI.
I’m pretty sure you’ll need a microcontroller for those, which one did you order?

Excuse me for the late reply. The current radiator valves in my home are so old, there isn’t even a replacement thermostatic interior for it. The replacement of the entire valve has provided a new set of problems, so I can’t continue as long as those aren’t solved. I expect that to take another two weeks.

I ordered this one:

https://diyless.com/product/esp8266-thermostat-shield

@Dujith Could you please confirm which Opentherm sketch you used? I’ve got the same setup as yourself (UFH via Manifolds) and spent all day yesterday trying to get the ESPHome sketch to work as I wanted but no joy. It was too complicated ( for me) to get the ESPHome Thermostat to be updated with the values from the templates you described above. I just want to push set point and current temp to the boiler!

I’ve never used MQTT but I think your solution is the simplest… just need to know which sketch to upload!

Thanks!

In the mean time all the valves have been replaced with a thermostatic one and a bypass has been added. The wet part is now done. Also, I received the thermostat shield.

I will make a test setup soon.

Sorry for the late reply, can u post the sketch and how you configured the MQTT in homeassistant?
In essence with MQTT you’ll just create sensors which you then can use however you want.
Best to use their github example since i adjusted mine to get some more sensors.

No need to apologise!

So I have a few devices configured via ESPHome and the ability to upload configuration changes via Wi-Fi has always appealed to me. With that in mind I attempted to use https://github.com/rsciriano/ESPHome-OpenTherm. However; this aims to act as a “Virtual” Thermostat allowing set point to be set via a Lovelace card, and not to be set via a Templated Sensor like the one discussed above.

Tonight when the daughter is asleep and wife at work; I will upload the MQTT sketch above and let you know how I get on!

Hey guys. This thread seems to be the only active one.
I’m currently in the same process of purchasing smart TRVs, getting an OpenTherm shield from DIYLESS and my head will most probably explode from all of this :slight_smile:

I’m having a bit trouble following this topic as it got started over a year ago.

Is the solution still using that Generic multizone thermostat you linked in the first post?
It looks to be the best way to choose which valve (or thermostat) is set to the higherst point.

All of this is very overwhelming but I’m here to learn something new, hopefully :wink:

In the end i just used Generic Thermostat - Home Assistant for the TRV’s to open or close. And created a Template for calculating which setpoint and current temperature needed to be send to the Opentherm Shield.

You just need to follow the steps in their github: GitHub - diyless/home-assistant-opentherm-thermostat: Home Assistant OpenTherm Thermostat
Since the shield just want to know an actual temperature and a setpoint, it will then deal with you boiler itself. No need to make it more complicated.

What my system does:

  1. The generic thermostats are per room and open the TRV of that room if needed.
  2. It will turn on or off the circulation pump of the boiler. (with an on for 10 minutes if the system was idle for a week, to prevent motor locking up)
  3. Whenever a room has a higher setpoint then the actual temperature of that room my template will check all rooms and sends the room which has the biggest difference. Otherwise it may send like a 0.2 difference and the boiler will not send out high enough temperature for another room that could have a delta of 2 degrees.

I’m happy to share whatever code or to help, at least 1 winter of testing done.

1 Like

Thanks @Dujith. I’m still waiting for the hardware to arrive but I will try to follow the GIthub first and see how far I can get.

If you could share your template determing the set values, that would be great :slight_smile:

@Dujith

Everything is received and I’m making a test setup. I’m running into the following difficulties:

  • My boiler keeps the pump running as long as the heating mode is ‘on’, even when there is no heat request. Your solution doesn’t account for that. (In the code DIYLess provided ‘heating’ is on by default unless explicitly turned off via MQTT)
  • My valves (wax motors) need time to fully open and close. There is a solution here, but that doesn’t play well with your solution, as you are using generic thermostats (which only accept on/off switches) (what am I saying - it seems to work fine!)
  • I want to make a ‘boost’ mode, which sets a high target temperature for a specified amount of time to decrease the time needed to get to the desired temperature (be it with higher gas usage).
  • How difficult is it to make an open window detection in this solution?

The following solutions come to mind:

  • Create another (binary) sensor, called ‘heat_request’, which turns on or off based on the thermostats. If there is heat demand, use NodeRed to turn the ‘heating mode’ on.
  • Use a script or automation to get around this? I have no idea what a solution might look like, I’m new to Home Assistant.
  • Create a binary switch ‘boost’, which raises the temperature of the Virtual CV Setpoint by a lot. (Basically another if-statement in the value_template block)

If anyone has a more clever solution to these problems, it’d be more then welcome.

I did take that into account: (scroll up to the code sections)

alias: CV Aan/Uit
description: ''
trigger:
  - platform: template
    value_template: >-
      {{ states('sensor.setpoint_cv_virtual') >
      states('sensor.temperature_cv_virtual') and states('climate.heating') ==
      "off" }}
    id: StartWarmteVraag
  - platform: template
    value_template: >-
      {{ states('sensor.setpoint_cv_virtual') <
      states('sensor.temperature_cv_virtual') and states('climate.heating') ==
      "heat"  }}
    id: EindeWarmteVraag
condition: []
action:
  - choose:
      - conditions:
          - condition: trigger
            id: StartWarmteVraag
        sequence:
          - service: climate.set_hvac_mode
            target:
              entity_id: climate.heating
            data:
              hvac_mode: heat
      - conditions:
          - condition: trigger
            id: EindeWarmteVraag
        sequence:
          - service: climate.set_hvac_mode
            target:
              entity_id: climate.heating
            data:
              hvac_mode: 'off'
    default: []
mode: restart

the entity in question is defined as a mqtt climate:

climate:
  - name: "Heating"
    modes:
      - "off"
      - "heat"
    current_temperature_topic: "opentherm-thermostat/current-temperature/get"
    mode_command_topic: "opentherm-thermostat/mode/set"
    mode_state_topic: "opentherm-thermostat/mode/get"
    temperature_command_topic: "opentherm-thermostat/setpoint-temperature/set"
    temperature_state_topic: "opentherm-thermostat/setpoint-temperature/get"
    min_temp: 12
    max_temp: 28
    value_template: "{{ value }}"
    temp_step: 0.5

You might want to look at this thread i once made for a boost function. While its not exactly for what u want to do. It should be able todo the same thing.

I think in the value_template add another if statement to check the window sensor and just send a fixed value like 7 degrees to the virtual objects.