Ausgangslage
Das Szenario ist ein mittel gut isoliertes Reihenendhaus. Bei etwa 5 °C Aussentemperatur sinkt die Innentemperatur über Nacht in rund zwölf Stunden um etwa 0.5 bis 1 °C. Die beheizte Wohnfläche beträgt 150 m² mit Bodenheizung. Es gibt keinen Pufferspeicher, die Luft-Wasser-Wärmepumpe ist direkt mit der Bodenheizung verbunden. Eine Einzelraumregelung ist nicht im Einsatz. Auf dem Dach arbeitet eine Photovoltaikanlage mit 15.6 kWp.
Die Steuerung erfolgt mit Home Assistant. Heishamon dient als Schnittstelle zur Wärmepumpe.
Ziel des Übergangszeit-Modus
In der Übergangszeit steht tagsüber oft ausreichend PV-Leistung zur Verfügung. Ziel ist es, möglichst kosteneffizient mit PV-Strom zu heizen und überschüssige Energie gezielt in der Gebäudemasse zu speichern. Die Raumtemperaturen sollen im Tagesverlauf nicht mehr als ± 1 K schwanken. Die Anlage fährt weiterhin mit Heizkurve, damit die Aussentemperatur berücksichtigt bleibt. In der Nacht bleibt die Heizung aus.
Funktionsprinzip
Der «Übergangszeit-Modus» orientiert sich an der Sonnenhöhe als stabilem Indikator für die zu erwartende PV-Leistung. Die momentane Netzeinspeisung schwankt je nach Wetter und je nach Verbrauchern im Haus. Die Sonnenhöhe bildet das tägliche Produktionsfenster zuverlässig ab. So startet die Wärmepumpe in der Tagesphase, in der mit hoher Wahrscheinlichkeit genügend PV-Leistung vorhanden ist. Sobald tatsächlich PV-Überschuss anliegt, läuft die Heizung kostenoptimiert weiter und der Wohnkomfort bleibt stabil.
-
Einschalten am Morgen
Die Wärmepumpe startet, sobald die Sonne den konfigurierten Schwellwert der Sonnenhöhe überschreitet. Ab dann ist in der Regel genügend PV-Leistung verfügbar. -
Ausschalten am Abend
Die Wärmepumpe schaltet ab, wenn die Sonnenhöhe wieder unter den Schwellwert fällt. Vor dem Abschalten müssen die minimalen Betriebsstunden erreicht sein. Im Frühherbst entscheidet meist die Sonnenhöhe. Im Spätherbst gewinnt die Mindestlaufzeit an Bedeutung, weil die Tage kürzer werden. Der Betrieb reicht dann eher in den Abend, wenn der COP oft günstiger ist. -
Automatischer Temperaturhub
Ist der Temperaturhub aktiv, hebt das System die Heizkurve proportional zum PV-Überschuss an. Der Anstieg ist durch einen maximalen Temperaturhub begrenzt. In der Übergangszeit kommt zusätzlich ein Zuschlag von plus 2 K hinzu. So lässt sich thermische Energie in der Gebäudemasse speichern und ein unbeabsichtigtes Abschalten vermeiden.
Beispielrechnung: 2 K Überhitzung über die Bodenplatte
Annahme: 150 m² Bodenfläche, 20 cm Beton, Laufzeit 8 h, COP = 5.
- Volumen Beton: 150 m² × 0.20 m = 30 m³
- Masse Beton: 30 m³ × 2300 kg/m³ ≈ 69 000 kg
- Spezifische Wärmekapazität Beton: ca. 0.84 kJ/(kg·K)
- Temperaturhub: 2 K
Thermische Energiemenge:
69 000 kg × 0.84 kJ/(kg·K) × 2 K = 115 920 kJ ≈ 32.2 kWh
Mittlere thermische Leistung über 8 h:
32.2 kWh ÷ 8 h ≈ 4.0 kW
Benötigte elektrische Energie bei COP = 5:
32.2 kWh ÷ 5 ≈ 6.44 kWh
Mittlere elektrische Leistung:
6.44 kWh ÷ 8 h ≈ 0.80 kW
Diese einfache Rechnung betrachtet nur die Bodenplatte. In der Praxis nehmen auch Estrich, Wände und Einrichtung Energie auf. Die gewählte Überhitzung von 2 K bleibt in der Regel komfortabel und hilft, PV-Überschuss sinnvoll zu speichern. Ein Wasser-Pufferspeicher von rund 3000 Litern deckt bei 10 K Spreizung die gleiche Energiemenge ab.
Home-Assistant-Automationen
Die folgende Automation schaltet am Morgen in den Modus «Heat only» und startet die Wärmepumpe. Der Haupttrigger ist die Sonnenhöhe. Zusätzlich kann ein stabiler PV-Überschuss von mindestens 500 W über zehn Minuten als Startkriterium dienen wenn das Wetter sehr gut ist.
YAML-Code "Übergangzeit Einschalten"
alias: Übergangzeit Einschalten
description: ""
triggers:
- trigger: numeric_state
entity_id:
- sun.sun
attribute: elevation
above: input_number.hpctl_transition_elevation_threshold
alias: Sobald Sonnehöhe über Horizont > Schwellwert (Morgen)
id: sunrise
- trigger: numeric_state
entity_id:
- sensor.power_export
for:
hours: 0
minutes: 10
seconds: 0
above: 500
enabled: true
conditions:
- condition: state
entity_id: input_select.hpctl_mode
state: Übergangszeit
- condition: time
before: "10:00:00"
enabled: true
- condition: state
entity_id: switch.panasonic_heat_pump_main_heatpump_state
state: "off"
enabled: true
actions:
- alias: Heat Only auwählen
action: select.select_option
metadata: {}
data:
option: Heat only
target:
entity_id: select.panasonic_heat_pump_main_operating_mode_state
- wait_for_trigger:
- trigger: state
entity_id:
- select.panasonic_heat_pump_main_operating_mode_state
from: null
to: Heat only
timeout:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
- action: switch.turn_on
metadata: {}
data: {}
target:
entity_id: switch.panasonic_heat_pump_main_heatpump_state
mode: single
Die Ausschalt-Automation beendet den Betrieb am Abend, wenn die Sonnenhöhe wieder unter den Schwellwert fällt. Alternativ greift ein Template-Trigger, sobald die minimalen Betriebsstunden erreicht sind. Beim Ausschalten setzt die Automation den Heizkurven-Offset auf 0 K zurück. So startet der nächste Tag ohne Altlasten.
YAML-Code "Übergangszeit Ausschalten"
alias: Übergangszeit Ausschalten
description: >-
Die LWWP wird ausgeschaltet wenn:
* Die Sonnenhöhe den Schwellwert unterschreitet (Anfangs Herbst relevant ->
Keine Leistung mehr vom Dach, Betriebsstunden vorher erreicht)
* Die Minimalen Betriebsstunden erreicht sind (Spät Herbst relevant da Tage
immer kürzer werden, besser am Abend längerer Betrieb da besserer COP)
triggers:
- trigger: numeric_state
entity_id:
- sun.sun
attribute: elevation
below: input_number.hpctl_transition_elevation_threshold
alias: Sonnenhöhe < Schwellwert (Abend)
id: sonne
- trigger: template
value_template: >+
{% set betriebsstunden_soll =
states('input_number.hpctl_transition_min_operating_hours') | float %}
{% set betriebsstunden_ist =
states('sensor.lwwp_betriebsstunden_taglich') | float %}
{{ betriebsstunden_ist >= betriebsstunden_soll }}
alias: Minimale Betriebsstunden erreicht
id: stunden
conditions:
- condition: state
entity_id: input_select.hpctl_mode
state: Übergangszeit
- condition: template
value_template: |2
{% set betriebsstunden_soll = states('input_number.hpctl_transition_min_operating_hours') | float %}
{% set betriebsstunden_ist = states('sensor.lwwp_betriebsstunden_taglich') | float %}
{{ betriebsstunden_ist >= betriebsstunden_soll }}
alias: Min. Betriebsstunden erreicht
enabled: true
- condition: numeric_state
entity_id: sun.sun
attribute: elevation
below: input_number.hpctl_transition_elevation_threshold
alias: Sonnenhöhe < Schwellwert (Abend)
actions:
- action: switch.turn_off
metadata: {}
data: {}
target:
entity_id: switch.panasonic_heat_pump_main_heatpump_state
- wait_for_trigger:
- trigger: state
entity_id:
- switch.panasonic_heat_pump_main_heatpump_state
from: null
to: "off"
timeout:
hours: 0
minutes: 0
seconds: 10
milliseconds: 0
- action: number.set_value
metadata: {}
data:
value: "0"
target:
entity_id: number.panasonic_heat_pump_main_z1_heat_request_temp
enabled: true
alias: Heizkurve Temperaturhub zurücksetzen
mode: single
Heizkurven-Offset abhängig vom PV-Überschuss
Der Temperaturhub der Heizkurve folgt dem PV-Überschuss. Die Berechnung ist so ausgelegt, dass bei maximal verfügbarer elektrischer Leistung der Wärmepumpe der konfigurierte maximale Offset erreicht wird.
YAML-Code "LWWP Heizkurve Temperaturhub"
# LWWP Heizkurve Offset abhängig von Solarüberschuss
- name: "LWWP Heizkurve Temperaturhub"
unique_id: lwwp_heizkurve_temperaturhub
unit_of_measurement: "K"
device_class: temperature
state: >
{# Maximal erlaubter Offset der Heizkurve (K), kommt aus Helper #}
{% set max_offset = states('input_number.hpctl_transition_heat_curve_offset') | float(0) %}
{# COP-Absicherung:
- Sensor liefert gelegentlich 0/ungültig -> setze min. 1
- zusätzlich -1, weil der Sensor tendenziell zu hoch misst (Kompensation)
- Ergebnis wird nicht kleiner als 1 zugelassen, um Division durch 0 zu vermeiden #}
{% set cop = [ states('sensor.panasonic_heat_pump_cop') | float(0) - 1, 1 ] | max %}
{# Maximale elektrische Leistungsaufnahme der WP (W):
max. thermische Leistung / COP = max. elektrische Leistung #}
{% set max_hp_power = (5000.0 / cop) %}
{# Aktuelle elektrische Leistung der WP (W) #}
{% set act_hp_power = states('sensor.lwwp_leistung_heizen') | float(0) %}
{# Steigung (K pro Watt PV-Überschuss), so dass bei "max_hp_power" der "max_offset" erreicht würde #}
{% set steigung = max_offset / max_hp_power %}
{# PV-Überschuss/Netzeinspeisung (W). #}
{% set pv = states('sensor.power_export') | float(0) %}
{# Zusatz-Offset in der Übergangszeit (K):
- wenn Modus "Übergangszeit" aktiv -> +2 K
- sonst 0 K #}
{% set n = 2 if is_state('input_select.hpctl_mode', 'Übergangszeit') else 0 %}
{# Vorläufiger Offset gemäss PV-Überschuss + Modusaufschlag #}
{% set offset = steigung * pv + n %}
{# Begrenzungslogik:
1) Deckelung: wenn berechneter Offset "max_offset" übersteigt ODER
wenn noch genügend PV-Überschuss vorhanden ist, um die WP auf ihre
Maximalleistung (elektrisch) zu bringen
-> setze auf "max_offset".
2) Sonst, wenn Offset im (0, max_offset) liegt und COP > 1 (robust),
-> gebe den berechneten Offset aus.
3) In allen anderen Fällen -> 0 K. #}
{% if offset > max_offset or pv > max_hp_power - act_hp_power %}
{{ max_offset | round(2) }}
{% elif offset > 0 and offset < max_offset and cop > 1 %}
{{ offset | round(2) }}
{% else %}
0
{% endif %}
attributes:
# dies ist ein workaround. Nur wenn dieser Sensor eine Änderung erfährt, dann wird auch der Filter dazu upgedatet.
last_update: "{{ now().strftime('%Y-%m-%d %H:%M:%S') }}"
Aus der maximalen thermischen Heizleistung der Wärmepumpe und dem bereinigten COP ergibt sich die maximale elektrische Aufnahmeleistung. Die Steigung verknüpft PV-Überschuss in Watt mit dem Heizkurven-Offset in Kelvin. Liegt PV-Überschuss vor, steigt der Offset linear, zusätzlich kommen in der Übergangszeit pauschal + 2 K hinzu. Sobald entweder der berechnete Offset den Maximalwert erreicht oder die PV-Leistung ausreichen würde, um die Wärmepumpe auf ihre maximale elektrische Leistung zu bringen, greift die Deckelung. Bei unplausiblen COP-Werten gibt der Sensor 0 K aus. Dadurch bleibt die Anlage berechenbar.
Dashboard
Das Dashboard dient vor allem der Prozesswertüberwachung und der Analyse. Zusätzlich erlaubt es wenige gezielte Einstellungen sowie das Umschalten der Betriebsmodi. Welche Prozesswerte sich langfristig als wirklich aussagekräftig erweisen, erprobe ich im laufenden Betrieb.
Ergebnisse vom 7. September bis 25. Oktober
- Elektrische Energie: 202 kWh (externe Messung mit Shelly Pro 3em)
- Thermische Energie: 1406 kWh (externe Messung mit WMZ)
- COP: 6.9
- Durchschnittliche Aussentemperatur: rund 10 °C
- Kosten: 18.40 CHF bei einem Mix aus PV und Netzstrom
- Gaskosten zum Vergleich: 182 CHF
- PV-Anteil am Strom: 185 kWh, das entspricht rund 91.5 %
Über 49 Tage ergibt das im Mittel rund 4.1 kWh elektrische Energie pro Tag und etwa 28.7 kWh thermische Energie. Im direkten Kostenvergleich ergibt sich eine Einsparung von rund 90 % gegenüber Gas in dieser Periode. Der hohe PV-Anteil zeigt, dass die Regelung den Eigenverbrauch wirksam steigert.
Hinweise und Grenzen
Die hier beschriebene Vorgehensweise ist auf mein Gebäude und meine Wärmepumpe abgestimmt. Das Haus ist realtiv gut gedämmt und die Wärmeabgabe erfolgt über eine Fussbodenheizung mit grosser Speichermasse. In einem schlecht isolierten Gebäude mit Radiatoren funktioniert der Ansatz nur begrenzt. Radiatoren benötigen höhere Vorlauftemperaturen und bieten weniger thermische Masse. Dadurch sinkt der COP und die Speicherkapazität im Gebäude ist kleiner. Die Temperaturschwankungen fallen eher grösser aus und der gewünschte Betrieb über den PV-Überschuss lässt sich weniger stabil halten. Wer eine ähnliche Strategie testen möchte, sollte die Grenzen des eigenen Systems kennen und die Parameter vorsichtig anpassen.
Ich bin kein Heizungspezialist. Meine Stärken liegen in der Softwareentwicklung und in der Elektrotechnik mit viel Erfahrung aus der Industrie. Es ist gut möglich, dass ich noch nicht alle Zusammenhänge kenne. Bei atypischer Hydraulik ist eine fachliche Prüfung sinnvoll.
Fazit
Der Übergangszeit-Modus hat sich in der Praxis bewährt. Die Steuerung arbeitet nachvollziehbar, nutzt die Gebäudemasse zur Zwischenspeicherung und erreicht in der Übergangszeit einen hohen PV-Anteil bei geringen Kosten. Die Raumtemperaturen bleiben konstant innerhalb der Grenzen.
Für die kältere und dunklere Jahreszeit wird dieser Modus nicht mehr funktionieren. Erwiesenermassen lohnt sich eine Nachtabsenkung bei gut isolierten Gebäuden mit Luft-Wasser-Wärmepumpe nicht. Die spätere Sollwerterhöhung benötigt mehr Energie als in der Nacht eingespart wird. Für den Winter plane ich einen separaten Modus. Die Heizkurve wird bei PV-Überschuss moderat angehoben, was aber in dieser Jahreszeit selten vorkommt. Im Normalfall bleibt der Betrieb kontinuierlich und auf Komfort ausgelegt, ohne gezieltes Aufheizen zur Speicherung.
Für die gesamte Arbeit wurde ein Large Language Model (LLM) als Hilfsmittel verwendet statt klassischer Werkzeuge. Es half bei der Überarbeitung und Korrektur von Texten, bei der Recherche und bei Teilen des Codes. Die kognitive Leistung stammt vom Autor.






Super interessanter, informativer Artikel.
Vielen Dank dafür!
Lieber Remo, absolut genialer Beitrag. Ich ziehe Home Assistant schön länger in Erwägung. Wollte das teure Modbus-Modul kaufen was gelesen habe nur mässig Daten ausgibt. Ist das Dashboard von Dir oder von der Community? TOP Lg Patrick
Danke für die lobenden Worte. Von welchem Modbus Modul sprichst du? Das Dashboard ist von mit erstellt.
Hallo Remo, vielen Dank für Deine Arbeit. Hast Du eventuell einen "Workaround" für Dein Dashboard für einen Interessierten Laien? Habe selbst eine Jeisha mit Heishamon in Betrieb, Dein Dashboard hat´s mir angetan. :-)
Ich könnte das Dadhboard schon teilen wenn du willst, allerdings stecken da viele Entitäten, Automationen und Berechnungen dahinter, die du dann irgendwie erstellen müsstest. Ich empfele dir, selbst für deine Bedürfnisse etwas zu erstellen. Am besten klein anfangen. Ich denke, dass ist einfacher. Fragen beantworten ich dir natürlich gern.
So ganz stimmt das nicht mit dem schlecht isoliertem Haus. Ich habe ein altes Bauernhaus 1900 gebaut, 60cm dicke Wände. Keine Aussenisolation. Doppelglasfenster und Dach isoliert. Heizkörper 35 Jahre alt, ausgelegt für ein 70° System. Haus liegt auf 880m Höhe in der Schweiz. 600m 2 zu heizen. Öl Heizung zurzeit. Grundsätzlich eine schlechte Ausgangssituation für eine WP. Ich habe mir überlegt wie ich maximal die Vorlauftemperatur senken könnte, auch weil wir vor 20 Jahren zwecks Heizungsunterstützung eine Solarthermie gebaut haben. Diese braucht die tiefst mögliche Rücklauf Temperatur. Seit Jahren hatte ich das subjektive Gefühl, das am Anfang der Heizperiode ich irgendwie noch die Sommerwärme im Haus habe. Da habe ich mit einer KI (Claude.ai) mal unterhalten und herausgefunden das wahrscheinlich ich eine sehr grosse thermische Masse habe. Also habe ich die Zeitkonstante Tau für das Haus errechnet, indem ich einfach die Heizung abgeschaltet habe und die Innentemperatur aufgeschrieben habe und die Durchschnitsaussentemperatur über den Wetterdienst. Fazit ein Tau von 140 Stunden, heisst in 140 Stunden verliere ich 63% der gespeicherten Wärme nach aussen, wenn nichts nachkommt.
Damit dann eine Regelung entworfen, wo die Idee ist eine simulierte Aussentemperatur zu errechnen mit einer Dämpfung von 140 Stunden anhand der richtigen Aussentemperatur und ausserdem das Haus so zu sagen aufzuladen, wenn sich eine Kältewelle vorhergesehen ist, so das die WP noch mit einer hohen COP laufen kann. Das Bad wo es wenig benutzt wird, dient als Referenzzimmer für die Innentemperatur, wo diese zwischen -0.5 bis +1K schwanken kann, ohne dass das System die simulierte Aussentemperatur verändert. Diese Regelung hat viele Iterationen durchlaufen. Und ich habe in der Messzeit auch eine WP simuliert, eine Panasonic Aquera anhand ihrer Datenblätter. Sowie auch die Rentabilität berechnet anhand des Ölpreises und des Strompreises, wobei wir Nacht und Tagesstrom haben.
Fazit: Eine absolut stabile Vorlauftemperatur die sich ganz langsam verändert. Die höchste Temperatur hatte ich Anfang Januar bei -15°, 41.5° Vorlauftemperatur und das nur während ein paar Tagen, sonst zwischen 32-37 Vorlauf Temperatur. Heute ist sie bei 24°.
Die errechnete, wirklich gemittelte COP ist heute zwischen dem 01.01 bei 3.6. Dürfte kaum weiter steigen, weil eben in der Zwischensaison die Solarthermie viel bringt. Aber wenn es die nicht gäbe, weit über 4.
Das heisst man kann, indem man eine völlig unkonventionelle Heizungsteuerung baut, ein Haus, das überhaupt nicht für eine WP gebaut ist mit minimalen Kosten WP fit machen. Es ändert natürlich nichts an den thermischen Verlusten.
Der Öl Verbrauch dürfte nach meinen Hochrechnungen bei 3800l/Jahr sein. Bei einer COP von 3.6 werden das 10'000 KWh Strom. Neben dem CO2 Abdruck bei heute 1.4 die 10Kwh Öl und 2.5 die 10Kwh Strom, absolut rentabel. 5320.- vs 2'500.-. Der Energieverbrauch des Hauses sinkt auf 16Kw/m2/Jahr, das lässt sich sehen.
Technisch: 1 ESP, ein paar T° Sensoren, 1 relais, 1 Raspberry. Kosten 100.- Die Heizungsregelung läuft auf dem ESP. Home Assistent auf dem Raspberry. Es kommt eine Panasonic aquera 12KW serie M und Heishamon.
Hallo Remo,
danke für deinen tollen Beitrag, ich habe mir auf der Basis ein eigenes ähnliches Dashboard in HA gebaut.
Dazu hätte ich noch zwei Fragen:
Danke nochmal und Grüße aus dem Schwarzwald Michael
` features:
ah, nice. Danke für den Tipp und das Beispiel.
Die Erweiterung kannte ich noch nicht, sieht aber richtig gut aus und scheint sehr flexibel zu sein :)
Super interessanter, informativer Artikel.
Wie hast du das Diagram für die Heizkurve erstellt? Würdest du den Code teilen?
VG Alex
Hier der Code der Heizkurve:
type: custom:plotly-graph config: staticPlot: true refresh_interval: 1 disable_pinch_to_zoom: true defaults: entity: show_value: false showlegend: false line: shape: line layout: margin: b: 70 t: 20 r: 30 font: color: white xaxis: type: number autorange: true title: text: AT [°C] font: color: white fixedrange: true dtick: 5 yaxis: title: text: VL [°C] font: color: white fixedrange: true dtick: 2 entities:
parseFloat(hass.states['number.panasonic_heat_pump_main_z1_heat_request_temp'].state)
Danke, leider bekomme ich es bei mir nicht so hin.
Danke, leider bekomme ich es nicht hin
VG