Mit 7€ bis 15€ die Heizung smarter machen

1. Einleitung

Ziel ist es über die Leistungsaufnahme:

im ersten Teil

  • Heizung schaltbar machen (Urlaub aus?)
  • die Betriebsstunden
  • den Öl-Verbrauch jährlich
  • den Öl-Verbrauch monatlich
  • den Öl-Verbrauch tagesaktuell
  • getrennt nach Gesamtverbrauch und Warmwasserbereitung
  • Den aktuellen Füllstand im Tank in cm
  • Den aktuelle Fehlmenge im Tank in Litern

im 2. Teil

  • mittels Prognose Datum z.B. 15.02.2026 (in d. Zukunft)
  • einen Prognose Füllstand
  • eine Prognose Liefermenge
    darzustellen

leicht mögliche Features (in Eigenregie):

  • ggf. Brennerstarts zählen
  • Rest Öl-Menge in Liter (interessant? in cm bereits o.a.)
  • prozentuale Aufteilung d. Verbrauchs nach Heizbedarf und Warmwasserbereitung

Emofehlung:

Meine eigenartigen Bennenungen :slight_smile: sollten für die Anfangsphase erstmal 1:1 übernommen werden (ggf. inkl. Rechtschreibfehler), da ich mich auch im Teil 2 auf die Bezeichungen (insbesondere im Jinja2-Abschnitt) beziehe. Wenn es mal funktioniert, könnt ihr die Bennenungen immer noch nach euren Wünschen anpassen. Ggf. verleiert ihr dann etwas an Statistiken, die man aber gerade am Anfang nicht sehr vermissen wird.

1.1 Funktionsweise

Die Leistungsaufnahme wird bestimmten Funktionsabschnitten der Heizung (Brennerstart, Warmwasserbereitung o. Aufheizen zur Heizkörpererwärmung, Brennerabschaltung) zugeordnet und deren Zeitdauer gemessen.
Dies sollte grundsätzlich mit allen Ölheizzungen in ähnlicher Weise machbar sein.
Teile könnten auch für andere Heizungen (Gas o. möglw. Wärmepumpen) interessant sein, wenn man die Leistungsaufnahme bestimmten Abläufen zuordnen kann. Alle o.a. Werte lassen sich messen o. errechnen und darstellen und die Heizung ggf. auch für eine Zeit abschalten (prüfe Pufferung der Einstellwerte bzw. Einschaltzustand ect.).

1.2 Situation

In meinem Fall eine Viessmann Trimatik 7450 285-B von 1996 (Microprozessor-Steuerung). Da ich bereits 2011 einen Rechner, Digitalmultimeter, Platine zur Messstellenumschaltung zur Aufnahme von ATS, KTS, STS (Außen., Kessel-, Speicher-Temperatursensor) und des Brennerzustands installiert habe, waren mir die Abläufe und Sonderfunktionen (z.B. Taktung in der Nacht oder Festsetzen der Pumpen durch Schaltphasen verhindern) der Heizung bestens bekannt.
Dabei ist der falsche/ungeschickte Aufbau (ATS wird auf d. Westseite im Herbst angeleuchtet => Nordseite + Brummspannung bringt d. Messung d. ATS durcheinander => Abschirmung) aufgefallen.
Wird der Öltank auf gefüllt, so sollte der Tankwart die Heizung für ca. 1h ausschalten. Die Pufferung der Einstellwerte erfolgt über einen Langzeitbatterie (LS14500) durch die Heizung selbst.

1.3 Das Bauteil

Die Leistungsaufnahme der Heizung kann über einen Tuya Einbau-Energiemesser (1-phasig) bestimmt werden.
Ich habe eine WIFI-Unterputz-Version eingesetzt, finde aber z.Z. (Weder in Ebay, noch bei Temu) nicht exakt die gleiche Version. Deshalb nur ein Bild meiner Bauart - Achtung - es gibt viele ähnliche, aber doch unterschiedliche Einbauschalter. Vielleicht stellen Shellys (Shelly PM Mini Gen. 3 ???) eine gute Alternative für die Leistungsmessung dar?

Essenziell ist die Energiemonitor-Funktion (Leistungsmessung), da es die gleiche Bauform auch nur als Schalter gibt.
Den Leistungsmesser habe ich unmittelbar “elektrisch vor” dem Heizung-Notschalter (Schaltzustand am Notschalter sichtbar), “mechanisch hinter” dem Schalter in der Dose installiert. Dies sollte natürlich nur vom Fachmann, bei abgeschaltetem Strom, vorgenommen werden.

Nach dem Hinzufügen des Energiemesser in Smarlife (o. Tuya-App) und HA lässt sich die Leistung grafisch über der Zeit darstellen.

grün = Anlauf Brenner bei kalter Nacht, rot = Ende der Warmwasser-Erwärmung (Ladepumpe)

1.4 Leistungszuordnung zu o.a. Diagramm:

  • 35 Watt Hzg-Pumpe (alte Pumpe, Austausch gegen magnetit-resistente Wilo HEP geplant)
  • --------------> 47 Watt Schaltschwelle (+/-12W Schutzabstand)
  • 59 Watt WW-Ladepumpe
  • --------------> 71 Watt Schaltschwelle (+/-12W Schutzabstand)
  • 83 Watt Brenner an

Dazu habe ich zunächst 3 Zähler angelegt:

  • V14_Öl_seit_Ein_10s_Takt *) (messen der Brennerlaufzeitdauer)
  • V14_Öl_Verbrauch_WW_10s_Takt *) (aufaddieren seit … für Warmwasser)
  • V14_Öl_Verbrauch_Ges_10s_Takt *) (aufaddieren seit … für gesamten Verbrauch)

*) habe ich dem Bereich “SoftCrtl” und nicht der “Heizung” zugeordnet.

1.5 Automatisierung erstellen:

A14_Erkennung_Brenner_eon

Über die Leistungsaufnahme wird das Einschalten des Brenners erkannt und der Zähler

  • V14_Öl_seit_Ein_10s_Takt
    gestartet und alle 10s um 1 erhöht.

Wird am Nachlauf der WW-Ladepumpe die Trinkwassererwärmung erkannt, dann wird aufaddiert:
V14_Öl_Verbrauch_WW_10s_Takt = V14_Öl_Verbrauch_WW_10s_Takt + V14_Öl_seit_Ein_10s_Takt
V14_Öl_Verbrauch_Ges_10s_Takt = V14_Öl_Verbrauch_Ges_10s_Takt + V14_Öl_seit_Ein_10s_Takt

anderenfalls (WW-Ladepumpe läuft nicht) nur
V14_Öl_Verbrauch_Ges_10s_Takt = V14_Öl_Verbrauch_Ges_10s_Takt + V14_Öl_seit_Ein_10s_Takt

und dann in beiden Fällen den Zähler zurücksetzen
V14_Öl_seit_Ein_10s_Takt = 0

YAML-Darstellung

alias: A14_Erkennung_Brenner_eon
description: ""
triggers:
  - trigger: time_pattern
    seconds: /10
conditions: []
actions:
  - choose:
      - conditions:
          - condition: numeric_state
            entity_id: sensor.wbp_1g_leistung
            below: 71
        sequence:
          - if:
              - condition: numeric_state
                entity_id: counter.v14_ol_seit_ein_10s_takt
                above: 0
            then:
              - action: counter.set_value
                metadata: {}
                data:
                  value: >-
                    {{
                    (float(states('counter.v14_ol_verbrauch_ges_10s_takt'))+float(states('counter.v14_ol_seit_ein_10s_takt')))
                    |  int }}
                target:
                  entity_id: counter.v14_ol_verbrauch_ges_10s_takt
              - if:
                  - condition: numeric_state
                    entity_id: sensor.wbp_1g_leistung
                    above: 47
                then:
                  - action: counter.set_value
                    metadata: {}
                    data:
                      value: >-
                        {{
                        (float(states('counter.v14_ol_verbrauch_ww_10s_takt'))+float(states('counter.v14_ol_seit_ein_10s_takt')))
                        |  int }}
                    target:
                      entity_id: counter.v14_ol_verbrauch_ww_10s_takt
              - action: counter.reset
                metadata: {}
                data: {}
                enabled: true
                target:
                  entity_id: counter.v14_ol_seit_ein_10s_takt
      - conditions:
          - condition: numeric_state
            entity_id: sensor.wbp_1g_leistung
            above: 85
        sequence:
          - action: counter.increment
            metadata: {}
            data: {}
            target:
              entity_id:
                - counter.v14_ol_seit_ein_10s_takt
mode: single

Das dürfte dann so aussehen:

2.1 Helfer: Zahlenwert-Eingabe

Zur Umrechnung werden 2 Werte Tank: (“1cm in Liter” und Verbrauch: “Liter/h”) gebraucht.

Wieviel Liter im Tank erzeugen eine Änderung des Füllstands von 1cm?
Angaben am Tank 4800 Liter bei 150cm Höhe = 32 Liter/cm. Tatsächlich liegt der Wert bei mir darunter. Inklusive Bauchbildung, liegt der im Mittel bei 31.5 Liter / cm

Wieviel Liter Öl verbraucht die Heizung pro Stunde?
Als Abschätzung kann die Düse herangezogen werden. Eine “0.50”-er Düse verbraucht etwa 0.5 USgal/h bei 7 bar = 0.5 USgal/h * 3.785 = ca. 1,89 Liter/h
Bei mir hat sich der Wert über Jahre bei 1.67 Liter/h eingependelt.
Tipp: Vor der Tankbefüllung die Höhe mit einem Zollstock/Meterstab und nach der Befüllung, wenn die Temperatur einigermaßen angeglichen ist (Wärmeausdehnung!), auf den Millimeter genau messen und notieren.

Nun 2 Helfer “Zahlenwert-Eingabe” anlegen
V14_Tank cm_in_Liter *) mit 0.1 Schritten, Bereich = Heizung, Wert = 31.5
V14_Ölverbr. Liter / h *) mit 0.01 Schritten, Bereich = Heizung, Wert = 1.67

*) habe ich dem Bereich “SoftCrtl” und nicht der “Heizung” zugeordnet.

2.2 Helfer: Template-Sensoren

Ich habe die folgenden Template-Sensoren angelegt:
Der Divisor von 360 resultiert aus
60s*60Minuten/10s-Takt
und muss bei ggf. anderer Taktrate angepaßt werde.

V14_Betriebstunden_Ges
{{ (float(states(‘counter.v14_ol_verbrauch_ges_10s_takt’))/360) | round(1) }}

V14_Betriebstunden_WW
{{ (float(states(‘counter.v14_ol_verbrauch_ww_10s_takt’))/360) | round(1) }}

V14_Öl_Verbrauch_in_Liter *)
{{ (float(states(‘counter.v14_ol_verbrauch_ges_10s_takt’))/360 * float(states(‘input_number.v14_olverbr_liter_h’))) | round(2) }}

V14_Öl_Verbrauch_WW_in_Liter *)
{{ (float(states(‘counter.v14_ol_verbrauch_ww_10s_takt’))/360 * float(states(‘input_number.v14_olverbr_liter_h’))) | round(2) }}

V14_Öl Füllstand aktuell (123.16cm ermittelter Füllstand am 13.12.2025, 4 Tage Party-Modus)
{% set b = 360* float(states(‘input_number.v14_tank_cm_in_liter’)) / float(states(‘input_number.v14_olverbr_liter_h’)) %}
{{ (123.16-float(states(‘counter.v14_ol_verbrauch_ges_10s_takt’))/b) | round(1) }}

V14_Öl_Fehlmenge aktuell (145cm reguläre Füllhöhe bei Tank voll)
{{ ((145-float(states(‘sensor.v14_ol_fullstand_aktuell’)))*float(states(‘input_number.v14_tank_cm_in_liter’))) | round(0) }}

*) habe ich dem Bereich “SoftCrtl” und nicht der “Heizung” zugeordnet.

2.2 Helfer: Verbrauchssensoren

V14_Öl /Jahr Gesamt Eingangssensor: V14_Öl_Verbrauch_in_Liter
V14_Öl /Monat Gesamt Eingangssensor: V14_Öl_Verbrauch_in_Liter
V14_Öl /Tag Gesamt Eingangssensor: V14_Öl_Verbrauch_in_Liter
V14_Öl /Jahr WW Eingangssensor: V14_Öl_Verbrauch_WW_in_Liter
V14_Öl /Tag WW Eingangssensor: V14_Öl_Verbrauch_WW_in_Liter
V14_Öl /Monat WW Eingangssensor: V14_Öl_Verbrauch_WW_in_Liter

Weiter geht es im “Teil 2” mit der Prognose (Öl-Bestellung zu einem bestimmten Datum).

R. Hsm

3. Prognose

Wenn der ungefähre Ölverbrauch im Jahr (ggf. über mehrere Jahre gemessen oder bestätigt), dann macht eine Prognose Sinn. Hilfsweise könnte man auch einen ungefähren Wert erstmal annehmen und nach einigen Monaten, durch Messung mit dem Zollstock / Meterstab, angleichen.

Zur Prognose legen wir einen “Helfer / Zeitpunkteingabe” an:
V14_Öl_Progn. Datum

Dort geben wir ein Datum vor, dass in der Zukunft liegt z.B.: 15.02.2026.

3.1 Wärmebedarf aus offizellen Quellen

Beispielhaft führe ich mal folgende Quelle an.

3.2 Wärmebedarf als Funktion

Der Höhenwinkel der Sonne verändert sich cosinusförmig ab dem 21.06. des Jahres.
Der Wärmebedarf ist um etwa 180° phaenverschoben zum Sommer. Auch dieser lässt sich recht gut, mittels Cosinus annähern. Das Maximum liegt wg, der Wärmekapazität der Erde und der Athmosspähre, etwa beim 17. Januar (kältester Tag im Durchschnitt in Deutschland, je nach Quelle, ab dem 15.01 bis 2. Hälfte des Januar). Dies habe ich durch “hineinpeilen” in die interpolierten offiziellen Werte bestimmen können, was mit den “kältesten Tagen” recht gut korreliert. Durch Hinzufügen eines Gleichanteils auf die Cos-Funktion ergab sich eine bessere Übereinstimmung (ab ca. 15°C entsteht im Haus ein Wärmebedarf, mittlere Temp. in Deutschland ist ca. 10°C, kältester Tag im Jahr etwas unterhalb von 0°C). Eine Kappung, nach unten (im Sommer, Warmwasser-Erwärmung?), wird durch einen Mindestverbrauch erreicht.

Die Übereinstimmung (blaue Kurve) kann aus folgender Abbildung entnommen werden.

Zur Berechnung legen wir 2 weitere Template-Sensoren an.
Zur einfachen Kontrolle habe ich einige Variablen in Kommentare ({# , #}) eingeschlossen, stehen gelassen.

V14_Öl_Progn. Füllstand

{# Der Höhenwinkel der Sonne und damit die Temperatur folgt in etwa einer Sinusschwingung #}
{# Der Heizbedarf entspricht daher einer "unten gekappten" Cosinus-Funktion #}
{# 1/2026 R. Hsm #}

{# Berechnung der Liefermenge z.B.: am 15.02. des Folgejahres #}
{% set Max = "-01-17" %}				{# Datm Verbrauchs-Maximum #}
{% set Lief = "-02-15" %}				{# Öl-Lieferdatum in der Zukunft #}
{% set Amp = 0.003025 %} 				{# Cosinus-Amplitude #}
{% set Breite = 365 %}					{# Cosinus-Spreizung / Periodendauer #}
{% set Y_Off = 0.0026%}					{# Y-Offset o. Gleich-Anteil #}
{% set Min = 0.00043 %}					{# Mindestbedarf im Sommer, Warmwasser #}
{% set JVerbr = 1350 %}					{# Jahresverbrauch in Litern #}
{% set Proz = namespace(value=0) %}			{# Prozent d. Jahresverbrauchs #}

{# Folgejahr wir aus dem Prognosedatum abgeleitet  #}
{% set dat_Lief = states('input_datetime.v14_ol_progn_datum') | as_datetime %}		
{% set FolgeJahr = dat_Lief.strftime('%Y')  %}
{% set Jahr =  now().strftime('%Y')  %}
{% set dat_now = (now().strftime('%Y-%m-%d'))  | as_datetime %}
{% set dat_Max=(FolgeJahr + Max) | as_datetime %}	

{#
{{ FolgeJahr }}
{{ dat_Lief }}
{{ dat_Max }}
#}
								{# Tag d. Jahres z.B.: 46 = 31+15 = 15.Feb #}
{% set Tag_Max = int(dat_Max.strftime('%j')) %}			{# 17 = 17.01.2026 #}
{% set Tag_Lief = int(dat_Lief.strftime('%j'))-Tag_Max %}	{# 17 abziehen, wg. Maximum #}
{% set Tag_now = int(now().strftime('%j'))-Tag_Max %}		{# 17 abziehen #}
{% set Tag_now = Tag_now-(int(FolgeJahr)-int(Jahr))*365 %}	{# Tag des Jahres wird ggf. negativ #}

{#
{{ Tag_now }}
{{ Tag_Lief }}
#}

{#  Restzeit von heute liniaresiert dazu => Tagesschwankung verringern #}
{%  set TagesAnteil = namespace(value= 1-(int(now().strftime('%s')) % 86400/86400)) %}

{%- for Tag in range(Tag_now,Tag_Lief + 1) -%}		{# Prozentwerte jedes Tages aufaddieren #}
  {%- set Prognose =(Y_Off+ Amp * cos((Tag)/Breite*2*pi)) * TagesAnteil.value -%}
  {% if Prognose < Min %}
    {%- set Prognose = Min %}
  {% endif %}
{#
  {{ Tag }}    {{ Prognose }}
#}
  {%- set Proz.value = Proz.value + Prognose -%}
  {%- set TagesAnteil.value = 1 -%}
{% endfor %}

{#
{{ Proz.value }}
#}

{{ (float(states('sensor.v14_ol_fullstand_aktuell')) - Proz.value*JVerbr/float(states('input_number.v14_tank_cm_in_liter'))) | round(1) }}

V14_Öl_Progn. Liefermenge

{% set Tank = 145*float(states('input_number.v14_tank_cm_in_liter')) %}		{# Tankvolumen in Liter #}
{{ (Tank- float(states('sensor.v14_ol_progn_fullstand'))*float(states('input_number.v14_tank_cm_in_liter'))) | round(0) }}

4. Schluss

Damit sollten wir eine erste Prognose zu dem o. gewählten Datum (z.B.: 15.02.) erhalten.
Die Funktionsweise war bereits in meinem Mess- u. Auswerte-Programm von 2011 mit den Umrechnungswerten (31.5 L/cm, 1.67 L/h und 1350 L/Jahr) enthalten und haben sich bei den Öl-Bestellungen über die sehr bewährt.
Es kommt also darauf an, die drei Werte bei euren Heizungen möglichst treffend zu wählen, damit die Prognose gut stimmt.

Weitere Ideen

  • Ich habe bei mir noch die übliche mechanische Zeitschaltuhr (Warmwasserzitkulation) gegen einen Smart-Plug ausgetauscht. Über einen Schalter kann so die Zirkulation auch außerhalb der üblichen Schaltzeiten angestoßen werden.
  • 2 Thermometer, direkt an dem Vor- und Rücklauf, brachten weniger Erkenntnisse als gedacht, da diese etwas schwerfällig die Änderungen übertragen.
  • Sowohl die Heizungspumpe (für VL, RL d. Heizkörper) als auch die Warmwasser-Ladepumpe erhalten jetzt Smart-Plugs mit Leisungsanzeige.
  • Wer will, kann auch die aufgenommene elektrische Energie bestimmen, aber dazu gibt es schon genug Beiträge.

Schöne Feiertage u. viele Grüße
R. Hsm

3 „Gefällt mir“