Multizone thermostat incl various control options

HI. This is not yet possible but can be implemented in a near future update. You could have look to PID thermostat if you need it right now.

Thanks for your reply, when will there be an update? is it possible to add a motion sensor, where after detecting inactivity for some time it will lower the temperature, e.g. by 3 degrees Celsius?

Hi. The motion sensor sounds like a nice option. Hopefully I have some time next week to work on it.

Hey how’s work :slight_smile:

There is progress :wink: but unfortunately not that fast as I thought…
Currently rewriting quite some code to improve the master mode operation. This is necessary as the master mode is not performing as I would like it run. Hope that the changes will work out. First I will run it in my home for a week or so to check it’s performance.

Then the next step will be NO mode (which should be easier (I hope…) so unfortunately no quick release… think it will take a week or two…

I’ve just released a new version. link

This is a complete rewrite of the integration and requires an update to your yaml configuration of your thermostat. It includes numerous changes such as:

  • scheduling of satelites based on a nesting routine in order to create a more balanced heat requirement.
  • specify NO-NC valves
  • update of output (attributes)
  • updated methodology for satelite controller and master
  • update to emergency mode
  • etc

Hello,
at the begginig I wanted to thank you ( @axax ) for sharing this amazing project.

I have an HVAC (supports both heating and cooling) that is outputing air to 4 rooms: 3 of them are pretty identical, whereas the 4th one is the biggest one. It’s an open spaced hall that’s connected to the staircase. This is also the location of HVAC remote control that measures the temperature, which is used in AUTO mode that regulates the power of air stream.

Every room is connected to HVAC via a throttle that can be switched ON or OFF. I want to use Master mode for virtual relay that copies the state of multizone_thermostat and applies it to the HVAC mode. All of the rooms would be set as satellites.

But first, before I configure anything, I wanted to measure the PID parameters. To do that I tried to use autotune from smart_thermostat, but I didn’t achieve positive results. Despite reading lots of posts (mainly from smart_thermostat thread and your GitHub discussion with @stomko ), I don’t get, what some of the parameters mean.

keep_alive - is it the time of my HVAC to go full power?
how does it differ from pwm?

Any help would be appritiated.

Best regards,
Jakub

PS. How can I measure window_open_tempdrop? Where can I place the name of window opening sensor for multizone_thermostat to inform it about the state of the window?

Hi Jakub,

I’ll try to answer your questions one by one.

Every room is connected to HVAC via a throttle that can be switched ON or OFF. I want to use Master mode for virtual relay that copies the state of multizone_thermostat and applies it to the HVAC mode. All of the rooms would be set as satellites.

I wonder if it will work the way you have planned to use it. If you mean hvac state as heat and/or cool or auto switching mode. The multizone thermostat will not sync the hvac mode to the satelites in order to choose which room to heat or cool. The mode needs to be set per thermostat (room).

I doubt if you need a main controller as implemented in the multizone thermostat. IN the multizone the master is actually there to control a main valve by the heat/cool requirements of the satelites. You already have a master which controls the air flow and your satelites will/can not influence the remote control unit.

I think when you place a temperature sensor in each room and setup a standalone thermostat (can be multizone or the ‘pid thermostat’ you can already achieve what you want. Only not the sync of the hvac mode but probably that will be possible by a HA automation/script.

But first, before I configure anything, I wanted to measure the PID parameters. To do that I tried to use autotune from smart_thermostat, but I didn’t achieve positive results. Despite reading lots of posts (mainly from smart_thermostat thread and your GitHub discussion with @stomko ), I don’t get, what some of the parameters mean.

The multizone version does not have an autotune neither the other options you mention. I think you are using the ‘pid thermostat version’? See github for the multizone explanation of options and some examples.

Thank you for the reply. I’ll try to follow your advice.

The multizone version does not have an autotune neither the other options you mention.

Well, in fact the HASmartThermostat supports the autotune option. That’s why I wanted to ask about the meaning of keep_alilve and pwm.

e.g.: It takes about 5 seconds for the trottle to fully open/close. Should I set pwm to 5s then?

EDIT: I decided to go with on/off control as it’s much easier to understand.
Is it possible to link window opening sensor (contact switch) with window open detection (I mean the function incorporated in multizone thermostat)?

Best regards,
Jakub

  • { WORD-WRAP: break-word; FONT-FAMILY: “Segoe UI” }

Hi @axax a big thank you for your work.

If you have couples a time, it would be great. I have a gas boiler Viessmann Vitodens W-111 + outside temp sensor connected to the boiler with this thermostat “VITOTROL 100 OT RT” placed in the center of my living room (49m2). The boiler and the thermostat are opentherm ready. So I ordered an OpenTherm Gateway from nodo shop.

From what I understood, I will be able to control my heating from HA with a climate entity from the OpenTherm Gateway.

I have only floor heating with water pipe. I have in total 9 pipe circuits I bought thermostatic actuator NC and 2 NO they will be connected individually to a zigbee dry contact to operate them.

From reading your githup project, it seems to me that I can use it to achieve the settings below.

Do you think it could be achievable and if yes do you have some sort or configuration to adapt please?

regards

so I would like to :

  • Be able to control heating per room (maybe also activate heat in all room and set the target setpoint once for all room. if one room gets warmer quicker than the other room close only the actuator for that room but leave the climate ON for other room)

  • Based on the temperature of a room if heating is needed open the actuator then activates the climate/burner. (The actuator take up to 2/3 min to get fully open or close, so I want the minimum duration of a heating session to be at lease 30to45min to preserve the boiler.)

  • If no heating is needed turn of the climate and then close the actuator.

It is possible to have two “heat:” for a thermostat? One for the actuator and one to send a command to the OTGW to activate the burner maybe?

I’m aware of the other feature like windows open, etc. I’ll also implement them later.

Hi XsniferX,

I had a quick look on the OpenTherm Gateway. It has the option for a OpenTherm and/or on-off thermostat. But it mentions that running it with an on-off thermostat might be less effcient than with an Opentherm protocol thermostat.

This multizonethermostat does not include the OpenTherm protocol. You could use the on/off signal of the master to operate a relay which is connected to the on/off contacts. If you are thinking to use OpenTherm communication then some work has to be done :stuck_out_tongue:

To anwser your other questions:

so I would like to :
Be able to control heating per room (maybe also activate heat in all room and set the target setpoint once for all room. if one room gets warmer quicker than the other room close only the actuator for that room but leave the climate ON for other room)
Based on the temperature of a room if heating is needed open the actuator then activates the climate/burner. (The actuator take up to 2/3 min to get fully open or close, so I want the minimum duration of a heating session to be at lease 30to45min to preserve the boiler.)
If no heating is needed turn of the climate and then close the actuator.

It is possible to have two “heat:” for a thermostat? One for the actuator and one to send a command to the OTGW to activate the burner maybe?

This multizone thermostat allows indeed multiple room thermostats. For each room a thermostat is configured (satellite), each one reads a temperature sensor and controlling a NO/NC valve. A PID controller determines how long the valve should be open/closed.

An additional thermostat is configured acting as master controller. The master organizes when each room valves opens/closes (method depends on chosen config) and gives a signal to the heater to start and stop (based on the room valves opening).

Just for in case you are busy implementing it. Currently I’m updating a bit of code which might also affect the NO valves. I hope finish it within the next week(s).

hi @axax

sorry i missed your reply. a big thanks you by the way.

i installed my gateway and use this thermostat in beta to manage the “OpenTherm thing” “GitHub - Alexwijn/SAT: The Smart Autotune Thermostat (SAT) is a custom component for Home Assistant that works with an OpenTherm Gateway (OTGW).

so basicaly with those poor settings i am able to turn on the boiler and set the temperature i wanted to test the ability to also turn on a specific actuator to let the hot water flow

alias: test_climate_001
description: “”
trigger:

  • platform: time
    at: “14:50:00”
    condition: []
    action:
  • service: climate.turn_on
    data: {}
    target:
    device_id: 9001247659bd0305c2014d56bb72b9ca
  • service: climate.set_temperature
    data:
    hvac_mode: heat
    temperature: 28
    target:
    device_id: 9001247659bd0305c2014d56bb72b9ca
  • service: mqtt.publish
    data:
    qos: “0”
    retain: true
    topic: zigbee2mqtt/test_actuator_livingroom/set
    payload: “on”
    mode: single

i can wait for your last config update then il will try to implement your solution ton control the main climate that i created “climate.sat_mqtt_otwg” as a master and use dry contact as satelite to enable circuit peer room.

regards,

Hi @axax , I would like to optimize my heating and think this might be a great solution.
I have a gas heater which has on/of contact, so that’s OK. All heating is underfloor (water) heating.
Then my house has multiple zones, each with their own electric valve(s) (also on/off), so the logic would be if one valve opens, I need to switch the heater contact on.
So I would have 1 satelite thermostat per zone, all with weather compensation and then 1 master.
If I am correct, each zone thermostat will control the valve of that zone and it takes timing into acccount of the other zones, to make sure the heating can work more continuous. So that’s the continous mode ?
Then, when one zone requires heat, the master shoud start the gas heater, is there an output foreseen ?

Hi Geert,

You are right. Each room has a satellite, with each satellite having a room temperature sensor and a hvac mode (heat and/or cool) with each mode having a switch to open/close the valve of that room.

The master thermostat does not have a room temperature sensor. It requires also at least one hvac mode (heat and/or cool) with each mode having a switch to switch the heater on/off. The operation_mode options "minimal_on", "balanced" or "continuous" defines the scheduling of the satellites:

  • "minimal_on"': schedule satellites opening and have the heater as short active as possible but thus with high heat requirement;
  • "continuous": tries to keep the heater as long as possible active resulting in low heat requirement
  • "balanced": schedule opening of satellites ‘balanced’ between heater active duration and heat requirement

I use for the satellites: 2 sonoff 4ch relays for the floor heating, 2 zigbee radiator valves. The master switch is a sonoff single relay to activate a honeywell valve (district heating).

Some config examples can be found here github.

This is my current config

# MASTER
- platform: multizone_thermostat
  name: master
  unique_id: mz_master
  initial_hvac_mode: "off"
  initial_preset_mode: "none"
  room_area: 142 # total heated area
  passive_switch_check: True
  heat:
    entity_id: switch.mainvalve
    passive_switch_duration:
      days: 14
    master_mode:
      satelites: [living, sl1, bathroom, sl2, sl3, sl4, sl5]
      operation_mode: "balanced"
      control_interval:
        minutes: 30
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      PID_valve_mode:
        goal: .8
        kp: -0.5
        ki: -0.0003
        kd: 0

  restore_from_old_state: False
  restore_parameters: False
  restore_integral: False

- platform: multizone_thermostat
  name: living
  unique_id: mz_living
  sensor: sensor.temp_living
  filter_mode: 1
  sensor_out: sensor.openweather_temperature
  room_area: 62
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: input_boolean.living # operating multiple switches
    passive_switch_duration:
      days: 15
    initial_target_temp: 19
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -15

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: sl1
  unique_id: mz_sl1
  sensor: sensor.temp_sl1
  filter_mode: 1
  sensor_out: sensor.openweather_temperature
  room_area: 20
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: switch.actuator_8
    passive_switch_duration:
      days: 15
    initial_target_temp: 17.5
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -20

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: sl2
  unique_id: mz_sl2
  sensor: sensor.temp_sl2
  filter_mode: 1
  sensor_out: sensor.openweather_temperature
  room_area: 13
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: switch.actuator_6
    passive_switch_duration:
      days: 15
    initial_target_temp: 17.5
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -20

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: sl3
  unique_id: mz_sl3
  sensor: sensor.temp_sl3
  filter_mode: 2
  sensor_out: sensor.openweather_temperature
  room_area: 7
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: switch.actuator_5
    passive_switch_duration:
      days: 15
    initial_target_temp: 17.5
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -20

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: bathroom
  unique_id: mz_bathroom
  sensor: sensor.temp_bath
  filter_mode: 1
  room_area: 7
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: switch.actuator_7
    passive_switch_duration:
      days: 15
    initial_target_temp: 19.0
    away_temp: 17
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: sl4
  unique_id: mz_sl4
  sensor: sensor.temp_sl4
  filter_mode: 2
  sensor_out: sensor.openweather_temperature
  room_area: 15
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    # proportional valve
    entity_id: number.sl4_valve_control
    passive_switch_duration:
      days: 15
    initial_target_temp: 17.5
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      # proportional valve thus no pwm
      # pwm_duration:
      #   minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 8
        ki: 0.001
        kd: -100000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -20

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

- platform: multizone_thermostat
  name: sl5
  unique_id: mz_sl5
  sensor: sensor.temp_sl5
  filter_mode: 2
  sensor_out: sensor.openweather_temperature
  room_area: 18
  initial_hvac_mode: "off"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    # proportional valve
    entity_id: number.sl5_valve_control
    passive_switch_duration:
      days: 15
    initial_target_temp: 17.5
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      # proportional valve thus no pwm
      # pwm_duration:
      #   minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 8
        ki: 0.001
        kd: -100000
        window_open_tempdrop: -3.6
      weather_mode:
        ka: 2
        kb: -20

  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

Just did my first test, this is the actual config

- platform: multizone_thermostat
  name: beneden
  unique_id: mz_beneden
  sensor: sensor.klimaat_keuken_temperature
  filter_mode: 1
  sensor_out: sensor.molenvelden_sensors_temperature
  room_area: 62
  initial_hvac_mode: "heat"
  precision: 0.1
  sensor_stale_duration:
    hours: 12
  passive_switch_check: True
  heat:
    entity_id: switch.0x94deb8fffe3162c0
    switch_mode: 'NO'
    passive_switch_duration:
      days: 7
    initial_target_temp: 21
    away_temp: 15
    proportional_mode:
      control_interval:
        minutes: 15
      pwm_duration:
        minutes: 30
      pwm_scale: 100
      pwm_resolution: 50
      pwm_threshold: 2
      PID_mode:
        kp: 35
        ki: 0.004
        kd: -150000
      weather_mode:
        ka: 2
        kb: -15
  restore_from_old_state: True
  restore_parameters: True
  restore_integral: True

What I saw is that the thermmostat stay inactive, but I see it calculates PWM value. Also the switch never does nothing (test smart zigbee plug, working in HA)…
This is the entity data

hvac_modes:
  - heat
  - 'off'
min_temp: 17
max_temp: 24
target_temp_step: 0.1
preset_modes:
  - none
  - away
current_temperature: 21.2
temperature: 22
hvac_action: idle
preset_mode: none
Emergency_mode: []
self_controlled: self_controlled
current_outdoor_temp: 13.3
filter_mode: 1
room_area: 62
hvac_def:
  heat:
    temperature: 22
    satelite_allowed: true
    control_mode: proportional_mode
    control_interval: 900
    pwm_duration: 1800
    pwm_scale: 100
    control_output:
      offset: 0
      pwm_out: 100
    detailed_output: false
    Open_window: false
    PID_values:
      - 35
      - 0.004
      - -150000
    PID_P: null
    PID_I: 100
    PID_D: null
    PID_valve_pos: null
    ab_values:
      - 2
      - -15
    wc_valve_pos: null
friendly_name: beneden
supported_features: 17

I see you use a ‘NO’ (normally open) switch while the integral of the PID (PID_I) is 100. The PID is equal to the pwm_scale and therfore sets the valve open 100% of the time. Thus it makes sense the valve is not closing. Has it been running for a while such that the integral was able to rise to 100 as the room temperature was 21.2 and setpoint 22?

The other parts of the PID are by default not shown to save database size. What you could do to see the other PID contributions (PID_P, PID_D) is set the detailed output to True

You also use the restore option. Could you first try with False? This would also reset the integral part.

I think the implementation of the NO switch might not have been working fine. I’ve been working on some updates and merged them just a second ago. Could you give this version a try?

I’ve installed the updated version and indeed, the switch now gets used. I was just wondering, the NO/NC, I think I understood it the opposite way. I used NO as for heating the switch needs to be closed, if I understood your reaction the normal mode is when heating is needed ?
I’ll now start monitoring the behavior and extend with a master.
Thanks for your support !

Nice to hear it works!

NO and NC refer to the idle state of the valve. For normally open the valve is by default open and needs to be powered to close, NC is vice versa.

1 Like


Temperature set to 21.3, but quite some overshoot… What can be done ?

hi Geert,

Are you running the multizone now with a master thermostat?

In order to investigate further you need to get more data, for instance: room and outdoor temperature, valve opening (master and satellite) and P-I-D contributions and the behaviour relative to each other.

Furthermore in thermostat-with-pid-controller (this multizone uses the same control method for a satellite), gives some detailled explanation/discussions about tuning. For instance this post Thermostat with PID controller - #260 by adrien.b reference to the discussion manual tuning. Note that the graph is based on an, I think, on-off thermostat.

You can start control the detailed logging per thermostat via ‘developer tools’ → ‘services’ → ‘multizone_thermostat: detailed_output’. After selection you can use the bottom ‘fill example data’. Noite that a long time use of detailed output will increase the database size thus make sure to disable it when all is working

An example to activate detailed logging:

service: multizone_thermostat.detailed_output
data:
  entity_id: climate.study
  hvac_mode: heat
  new_mode: True

Hereafter via ‘developer tools’ → ‘statuses’ the detailed output is visible. In your previous post these were then reported by ‘null’

To stop detailed logging:

....
  new_mode: False

To get these as sensors to create graphs, you could use templates to create sensors. Something like

- sensor:
    - name: "pwm_master"
      # friendly_name: "pwm master"
      state: "{{ state_attr('climate.master', 'hvac_def')['heat']['control_output']['pwm_out'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_valve_pos"
      # friendly_name: "valve pos sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['control_output']['pwm_out'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_PIDvalve_pos"
      # friendly_name: "PIDvalve pos sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['PID_valve_pos'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_WCvalve_pos"
      # friendly_name: "WCvalve pos sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['wc_valve_pos'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_PID_P"
      # friendly_name: "PID-P sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['PID_P'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_PID_I"
      # friendly_name: "PID-I sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['PID_I'] | float(0)}}"
      unit_of_measurement: "%"
    - name: "sl5_PID_D"
      # friendly_name: "PID-D sl5"
      state: "{{ state_attr('climate.sl5', 'hvac_def')['heat']['PID_D'] | float(0)}}"
      unit_of_measurement: "%"

edit: added link to some discussion about tuning