Generic_thermostat - make use of modern algorithms - TPI, load and weather compensation, fuzzy logic

All modern room thermostats (ex. Ecobee, Nest, Tado, Honeywell) make use of those algorithms to provide best user thermal comfort and energy savings.

Especially slow response objects like underfloor heating, under powered boilers, big rooms do requires smarter controlling.

Please refer to Heating Compensation, TPI.pdf

And
https://www.theheatinghub.co.uk/focus-boiler-plus

Generic thermostat should also allowing interact with a time schedule, to provide functionality that allows us to set time and temperature, and it will start heating up earlier to get desired temperature on time.

We do know already that standard PID won’t work here because of changing environment conditions (like open windows)

Good suggestion.
Should probably not be connected to Generic_thermostat, but for all climate devices

Can you clarify : is TPI the same as PI, which seems to be a simpler version of PID ? If yes then there is a PID thermostat in active development : Smart Thermostat - le chauffage contrôlé par PID - Intégration - Home Assistant Communauté Francophone . Sorry this link is mainly in French, but you can find explanations in the github repo: GitHub - ScratMan/HASmartThermostat: Smart Thermostat with PID controller for HomeAssistant

It is mistery for me what it really is. Producers do not shows math behind their algorithms with fancy names like TPI. My thoughts come from original author of HASmartThermostat who had bad experiences using PID, and suggested making that general_thermostat is doing better than his own project. Didn’t know about this fork. Will try it in one room.

My personal idea is that everything should be compensated with external temp, outgoing temp from boiler, solar radiation, and electrical energy consumed inside home. Probably neural network will do :smiley:

People should also be aware of the joy of Schedy.

  schedule_snippets:
    weather:
      - x: "Add(+0.125) if is_on('binary_sensor.spring_season') else Next()"
      - x: "Add(-0.25) if is_on('binary_sensor.summer_season') else Next()"
      - x: "Add(+0.125) if is_on('binary_sensor.autumn_season') else Next()"
      - x: "Add(+0.550) if is_on('binary_sensor.winter_season') else Next()"
      - x: "Add(-0.1) if is_on('input_boolean.heating_eco_mode') else Next()"
      - x: "Add(-0.1) if is_off('input_boolean.home_state_home') else Next()"
      - x: "Add(+0.125) if float(state('sensor.cc_30_min_gust')) > 15 and (state('sensor.wind_dir_cardinal')[:1] == 'N' or state('sensor.wind_dir_cardinal')[:1] == 'E') else Next()"
#      - x: "Add(+0.025) if (float(state('sensor.cc_outside_temperature')) < 15.1 and float(state('sensor.cc_rain_rate')) > 0) else Next()"
      - x: "Add(+0.2) if float(state('sensor.cc_outside_temperature')) < -9.9 else Next()"
      - x: "Add(+0.0750) if float(state('sensor.cc_outside_temperature')) < -4.9 else Next()"
      - x: "Add(+0.045) if float(state('sensor.cc_outside_temperature')) < 0.1 else Next()"
      - x: "Add(+0.035) if float(state('sensor.cc_outside_temperature')) < 5.1 else Next()"
      - x: "Add(+0.025) if float(state('sensor.cc_outside_temperature')) < 10.1 else Next()"
      - x: "Add(+0.025) if float(state('sensor.cc_outside_temperature')) < 14.1 else Next()"
      - x: "Add(-0.2) if float(state('sensor.cc_outside_temperature')) > 30.1 else Next()"
      - x: "Add(-0.2) if float(state('sensor.cc_outside_temperature')) > 24.9 else Next()"
      - x: "Add(-0.2) if float(state('sensor.cc_outside_temperature')) > 22.9 else Next()"
      - x: "Add(-0.2) if float(state('sensor.cc_outside_temperature')) > 21.9 else Next()"
      - x: "Add(-0.2) if float(state('sensor.cc_outside_temperature')) > 20.9 else Next()"
      - x: "Add(-0.1) if float(state('sensor.cc_outside_temperature')) > 16.8 else Next()"
      - x: "Add(+0.025) if (float(state('sensor.cc_outside_temperature')) < 15.1 and float(state('sensor.openweathermap_forecast_precipitation_probability')) > 75) else Next()"
      - x: "Postprocess(lambda result: round(result, 1))"

That’s all my weather logic

      schedule:
        - v: 18.5
          rules:
            - x: "IncludeSchedule(schedule_snippets['weather'])"
            - x: "Add(-0.2) if is_on('input_boolean.heating_night_mode') else Next()"
            - x: "Add(-0.2) if is_off('binary_sensor.livingroom_presence') else Next()"
            - x: "Add(+0.1) if (float(state('sensor.livingroom_temperature_temperature')) < 17.8 and is_on('binary_sensor.livingroom_presence')) else Next()"
            - x: "Postprocess(lambda result: min(result, 19.0))"
            - { v: 16.5, start: "00:00", end: "07:00" }
            - { v: 17.8, start: "07:00", end: "09:00" }
            - { v: 18.0, start: "09:00", end: "11:00" }
            - { v: 18.2, start: "11:00", end: "12:00" }
            - { v: 18.3, start: "12:00", end: "13:00" }
            - { v: 18.4, start: "13:00", end: "14:00" }
            - { v: 18.5, start: "14:00", end: "15:00" }
            - { v: 18.6, start: "15:00", end: "16:00" }
            - { v: 18.7, start: "16:00", end: "18:00" }
            - { v: 18.8, start: "18:00", end: "20:00" }
            - { v: 18.9, start: "20:00", end: "20:30" }
            - { v: 18.8, start: "20:30", end: "21:00" }
            - { v: 18.7, start: "21:00", end: "22:00" }
            - { v: 18.6, start: "22:00", end: "23:00" }
            - { v: 18.5, start: "23:00", end: "00:00" }

And that is my actual temperature logic.

3 Likes