Ich nutze die Nachteinspeisung und steuere die Einspeisung über Homeassistant abhängig von Solarprognosen und einem Zielwert, wieweit der Batteriestand in % bis zu dem Zeitpunkt sinken darf, wo die PV wieder ausreichend Strom zum Laden der Batterie liefert.
Ich habe einen Fronius Symo Gen24 und BYD HVM Batterien. Ich möchte für alle diejenigen, die das nicht schaffen, hier meine Automationen und Skripte im as-is Zustand als Vorlage einstellen, damit sie sich leichter tun. Jeder kann sie verwenden und nach seinen Wünschen anpassen, ich leiste aber keinerlei Haftung für eventuelle Folgen. Die Steuerung des Fronius passiert über modbus. Das ist ein wenig knifflig. Wer das verwenden will, sollte genau die angegebene Dokumentation studieren. Natürlich kann jeder seine eigene Nicht-Fronius Anlage programmieren, ich brauche im wesentlichen für meine Automation 2 Funktionen:
-
Zwangsentladung mit vorgegebenen nnnn Watt. und
-
Rücksetzen auf Normalzustand.
DIe Automationen im Detail:
alias: BYD Nacheinspeisesteuerung
description: >+
Nachteinspeisungssteuerung für Fronius Symo Gen24 + BYD HVM.
Läuft von März bis Oktober. Berechnet um 15:00 die nächsten Start/Ende-Zeiten
und startet basierend darauf das BYD_Nachteinspeisung script zum
Ein/Ausschalten der Nachteinspeisung. Die Regelung und Neuberechnung der
Einspeiseleistung erfolgt dann alle 5 Minuten durch die BYD_Nachteinspeisung
Automatisierung.
Benötigte Helper, die zu definieren sind:
input_number.byd_nachteinspeisung_vorgabe: Bis zu wechem Prozentsatz die
Batterie entladen werden darf bi PV Ladestrom liefert.
sensor.byd_nachteinspeisung_total: Utility meter: Summe bisher eingespeist
sensor.byd_nachteinspeisung_verbrauch: Utility meter: Summe bisheriger
Eigenverbrauch zur Schätzung des Stundenverbrauchs bis PV liefert.
input_datetime.byd_nachteinspeisung_start: Nächster Startzeitpunkt
input_datetime.byd_nachteinspeisung_end: Nächster Endzeitpunkt
input_datetime.byd_nachteinspeisung_last_start: Letzter Startzeitpunkt
input_boolean.byd_nachteinspeisung: Schalter: Nachteinspeisung läuft
input_number.byd_discharge_limit: Aktuelle Batterieentladungsvorgabe in Watt
triggers:
- at: "06:00:00"
id: sicherheitsstop
trigger: time
- at: "15:00:00"
id: Settime
trigger: time
- trigger: time
at: input_datetime.byd_nachteinspeisung_start
id: an
- trigger: time
at:
entity_id: input_datetime.byd_nachteinspeisung_ende
offset: "00:05:00"
id: aus
conditions:
- alias: Nur von März bis Oktober
condition: or
conditions:
- condition: trigger
id:
- aus
- sicherheitsstop
- Settime
- condition: and
conditions:
- condition: trigger
id:
- an
- alias: Wenn es März bis Oktober ist
condition: template
value_template: "{{ 3 <= now().month <= 10 }}"
enabled: true
actions:
- choose:
- conditions:
- condition: trigger
id:
- sicherheitsstop
- Settime
sequence:
- action: script.nachteinspeisung
metadata: {}
data:
startstop: stop
- action: input_datetime.set_datetime
data:
datetime: >
{# 1. Dusk holen, 30 Min addieren und dann 1h für das
"Aufrunden" #}
{% set t = state_attr('sun.sun', 'next_dusk') | as_datetime |
as_local + timedelta(hours=1) %}
{# 2. Abrunden auf die volle Stunde #}
{% set t = t.replace(minute=0, second=0, microsecond=0) %}
{# 3. Maximum aus berechneter Stunde und 20 ermitteln #}
{% if t < today_at("20:00") %} {% set t = today_at("20:00") %}
{% endif %}
{{ t }}
target:
entity_id: input_datetime.byd_nachteinspeisung_start
alias: Sicherheitshalber ein 2. Stop um 6:00 Uhr
- conditions:
- condition: trigger
id: an
sequence:
- action: script.nachteinspeisung
metadata: {}
data:
startstop: start
alias: Nachteinspeisung einschalten
- conditions:
- condition: trigger
id: aus
sequence:
- action: script.nachteinspeisung
metadata: {}
data:
startstop: stop
alias: Nachteinspeisung abschalten
mode: parallel
alias: BYD Nachteinspeisung update
description: >-
Läuft alle 5 Minuten und passt die Entladerate der Batterie aufgrund des
gemessenen bisherigen Einspeisungsverlaufs und des gemessenen Eigenverbrauchs
an, sodass in der geplanten Entladezeit die gewünschte Einspeisung erzielt
wird.
Steuerung durch Vorgabe des Grenzwertes, bis zu dem die Batterie entladen
werden soll. Eingespeist wird nur, wenn die Prognosen erwarten lassen, dass am
nächsten Tag die Batterie wieder zu 100% aufgeladen werden kann.
Prognosen: Solcast und Solar Forecast ML Integrationen
PV-Steuerung: über modbus an Fronius Symo Gen24 + BYD HVM Batterien (
BYD_forced_discharge und BYD_reset_charging_default scripts , Doku dazu siehe
https://www.libe.net/byd-modbus )
triggers:
- minutes: /5
trigger: time_pattern
conditions:
- condition: state
entity_id: input_boolean.byd_nachteinspeisung
state: "on"
actions:
- variables:
time: "{{ now().strftime('%H:%M') }}"
wettervorsorge: |
{# Abzug für unerwartete Wetterverschlechterung #}
{% set wv = 10000 %} {{ wv }}
batteriekap: |
{# Nettokapazität der PV Batterie gesamt in Watt #} 40000
eigenverbr: |
{# Geschätzter Eigenverbrauch in der Nacht #}
{% set eigenverbr = 6000 %} {{ eigenverbr }}
normverbrauch: |
{# Erstwert für stündlichen Eigenverbrauch #} 300
forecast_ml: >
{# Solar Forecast ML Ertragsprognose heute/morgen #} {% if now().hour >=
16 %} {{ states('sensor.solar_forecast_ml_forecast_tomorrow') |
float(0) }} {% else %} {{
states('sensor.solar_forecast_ml_expected_daily_production') | float(0)
}} {% endif %}
solcast: >
{# solcast Ertragsprognose heute/morgen #} {% if now().hour >= 16 %} {{
states('sensor.solcast_pv_forecast_forecast_tomorrow') | float(0) }} {%
else %} {{ states('sensor.solcast_pv_forecast_forecast_today') |
float(0) }} {% endif %}
ertragsprognose: >
{# Minimum von 2 Vorhersagen für PV-Ertrag abzgl. wettervorsorge #} {{
( min(solcast, forecast_ml) * 1000 - wettervorsorge ) | int(0) }}
batterie: >
{# aktueller Ladezustand aus Photovoltaiksystem #}
{{ states('sensor.byd_battery_box_premium_hv_state_of_charge') |
round(0) }}
grenzwert: >
{# Grenzwert, bis zu dem die Batterie entladen werden darf #} {{
max(50, (100 - states('input_number.byd_nachteinspeisung_vorgabe') | int
)) | int }}
usable: |
{# Maximal mögliche Einspeisung in Watt, bis Grenzwert erreicht ist #}
{{ max( 0, ( batterie - grenzwert ) * batteriekap / 100 ) | round(0) }}
start_dt: >
{# Startdatum und Zeit der aktuellen Nachteinspeisung #} {% set s =
states('input_datetime.byd_nachteinspeisung_start') %} {{ as_datetime(s)
if as_datetime(s) is not none else now() }}
end_dt: >
{# Endedatum und Zeit der aktuellen Nachteinspeisung #} {% set s =
states('input_datetime.byd_nachteinspeisung_ende') %} {{ as_datetime(s)
if as_datetime(s) is not none else now() + timedelta(hours=8) }}
lade_dt: >
{# Datum und Zeit, wenn wieder hinreichend PV zum Laden der Batterie
vorhanden ist, setze 2 Stunden nach Dawn #} {% set s =
states('sensor.sun_next_dawn') %} {{ as_datetime(s) + timedelta(hours=2)
}}
rest_h: >
{# Restzeit auf end_dt in Std. (float), um entladewert zu kalkuleren #}
{{ max(0, (as_datetime(end_dt) | as_local - now()).total_seconds() /
3600) | round(5) }}
lade_h: >
{# Restzeit, bis wieder genügend Ladung verfügbar ist #} {{ max(0,
(as_datetime(lade_dt) | as_local - now()).total_seconds() / 3600) }}
verbrauch: >
{# Errechnen Eigenverbrauch pro Stunde aus Utility meter Verbrauch seit
start_dt #} {% set s_obj = as_datetime(start_dt) %} {% set h = (now() -
s_obj | as_local).total_seconds() / 3600 %} {% set val =
states('sensor.byd_nachteinspeisung_verbrauch') | float(0) %} {% if h <
0.1 %} {{ normverbrauch }} {% else %} {{ ( val / h ) | int }} {% endif
%}
verbrauchsprognose: >
{# Fortschreibung aktueller Verbrauch bis lade_dt, um nicht am Ende noch
Verbrauch vom Netz zu erzeugen #} {{ verbrauch * lade_h | int }}
ziel: >
{# Restliche Einspeisung gesamt in Watt #} {{ usable -
verbrauchsprognose | round(0) }}
bisher: |
{# Utility meter: bisher eingespeist in Watt seit start_dt #}
{{ states('sensor.byd_nachteinspeisung_total') | int }}
restmenge: "{{ max(0, ziel) | int }}"
entladewert: >
{# Batterieentladung in Watt: restmenge / reststunden + Eigenverbrauch
#}
{% set h = rest_h | float(0) %} {% if h > 0.05 and restmenge > 0 %}
{{ ((restmenge / h) | round(0) + ( verbrauch | int ) ) | int }}
{% else %} 0 {% endif %}
fertig: >
{# Bedingungen zum vorzeitigen Stop der Einspeisung: #} {# wenn
Ladestand bis lade_dt unter Grenzwert sinken würde #} {% if batterie -
verbrauchsprognose * 100 / batteriekap <= grenzwert %} true {# wenn
bereits der Planwert eingespeist ist #} {% elif restmenge < 0 %} true
{# wenn der zu setzende Entladewert negativ wird #} {% elif entladewert
<= 0 %} true {# wenn die zeit abgelaufen ist #} {% elif now() >=
as_datetime(end_dt) | as_local %} true {# wenn der prognostizierte
Ertrag zu niedrig ist #} {% elif ertragsprognose < usable +
verbrauchsprognose + wettervorsorge %} true {% else %} false {%endif %}
- if:
- condition: template
value_template: |
{{ states('input_boolean.byd_nachteinspeisung') == 'on' }}
alias: If byd nachteinspeisung is on
then:
- if:
- alias: If fertig = true
condition: template
value_template: "{{ fertig }}"
then:
- action: input_boolean.turn_off
metadata: {}
target:
entity_id: input_boolean.byd_nachteinspeisung
data: {}
- action: script.nachteinspeisung
metadata: {}
data:
startstop: stop
enabled: true
else:
- action: input_number.set_value
target:
entity_id: input_number.byd_discharge_limit
data:
value: |
{{ entladewert | int }}
- action: script.1751097291791
metadata: {}
data: {}
enabled: true
alias: Nur wenn Nachteinspeisung läuft
- action: persistent_notification.create
data:
title: BYD Nachteinspeisung
message: |
BYD Nachteinspeisung letzte Werte:
Prognose forecast_ml: {{ forecast_ml }} kWh
Prognose solcast: {{ solcast }} kWh
Minimumprognose abzgl. Reserve: {{ ertragsprognose }} Wh
Batterieladung aktuell: {{ batterie }}%
Entladen bis Genzwert: {{ grenzwert }}%
Aktueller Stundenverbrauch {{ verbrauch }} Wh
Prognose bis Ladestart: {{ verbrauchsprognose }} Wh
Nutzbare Bruttokapazität: {{ usable }} Wh
Einspeisung geplant: {{ ziel }} Wh
Offene Restmenge: {{ restmenge }} Wh
Restzeit: {{ rest_h }} Stunden
Bisher eingespeist: {{ bisher }} Wh
Entladewert gesetzt: {{ entladewert }} W
Einspeisung ist fertig: {{ fertig }}
notification_id: eeg_data_fromto
mode: restart
Skripte:
Alles nach dem ersten script ist Fronius/BYD spezifisch !
sequence:
- variables:
starter: "{{startstop}}"
wettervorsorge: |
{# Abzug für unerwartete Wetterverschlechterung #}
{% set wv = 5 %} {{ wv }}
eigenverbr: |
{# Geschätzter Eigenverbrauch in der Nacht #}
{% set eigenverbr = 6 %} {{ eigenverbr }}
normverbrauch: |
{# Erstwert für stündlichen Eigenverbrauch #} 300
ertrag: >
{# Minimum von 2 Vorhersagen für PV- Ertrag morgen abzgl. wettervorsorge
#} {% set ertrag =
min(states('sensor.solcast_pv_forecast_forecast_tomorrow') | round(1),
states('sensor.solar_forecast_ml_forecast_tomorrow') | round(1) ) -
wettervorsorge %} {{ ertrag }}
batterie: >
{# Nutzbare Batteriekapazität abzgl. 50% Reserve für Blackout #} {% set
grenze = 50 %} {# Entladebegenzung 50% #} {% set bat = max(
states('sensor.byd_battery_box_premium_hv_state_of_charge') | round(0) -
grenze , 0 ) %} {{ bat }}
kwmax: >
{# Maximal nutzbare Batteriekapazität in kw - eigenverbrauch #} {% set
kap = 40.0 %} {# Batterie netto 40kw * nutzbare Prozent - eigenverbr #}
{% set kwmax = max( ( batterie * kap / 100 - eigenverbr) , 0) | float(0)
| round(3) %} {{ kwmax }}
usable: >
{# Nutzbare Kapazität in kw für Einspeisung für heute nacht #} {% if
ertrag > eigenverbr %} {% set usable = min( ertrag - eigenverbr, kwmax )
%} {% else %} {% set usable = 0 %} {% endif %} {{ usable }}
verwendbar: |
{{ usable * 1000 | round(0) }} {# in watt #}
- if:
- alias: If parameter = "start"
condition: template
value_template: "{{ starter == \"start\" }}"
then:
- action: input_datetime.set_datetime
metadata: {}
target:
entity_id: input_datetime.byd_nachteinspeisung_last_start
data:
datetime: "{{ now() }}"
- action: input_datetime.set_datetime
data:
datetime: |
{{ now() }}
target:
entity_id: input_datetime.byd_nachteinspeisung_start
- action: input_datetime.set_datetime
data:
datetime: >-
{# 1. Dawn holen, 30 Min addieren und dann 1h für das "Aufrunden" #}
{% set t = state_attr('sun.sun', 'next_dawn') | as_datetime |
as_local - timedelta(minutes=30) %} {# 2. Abrunden auf die volle
Stunde #} {% set t = t.replace(minute=0, second=0, microsecond=0) %}
{{ t }}
target:
entity_id: input_datetime.byd_nachteinspeisung_ende
- action: input_number.set_value
metadata: {}
target:
entity_id: input_number.byd_discharge_limit
data:
value: |
{{ 1500 }}
enabled: true
- action: script.1751097291791
metadata: {}
data: {}
enabled: true
- action: input_boolean.turn_on
metadata: {}
target:
entity_id: input_boolean.byd_nachteinspeisung
data: {}
enabled: true
- action: utility_meter.calibrate
metadata: {}
target:
entity_id: sensor.byd_nachteinspeisung_total
data:
value: "0"
- action: utility_meter.calibrate
metadata: {}
target:
entity_id: sensor.byd_nachteinspeisung_verbrauch
data:
value: "0"
- action: input_number.set_value
metadata: {}
target:
entity_id: input_number.byd_nachteinspeisung_vorgabe
data:
value: 50
- action: chime_tts.say
metadata: {}
data:
volume_level: 1
audio_conversion: Volume 150%
join_players: false
unjoin_players: false
chime_path: /media/sounds/custom/light_tone.mp3
message: >-
Die Nachteinspeisung wird gestartet. Erwarteter Ertrag für morgen
ist {{ ertrag }} Kilowatt, die Batterie ist zu {{
states('sensor.byd_battery_box_premium_hv_state_of_charge') }}
Prozent geladen.
Verwendbar für Nachteinspeisung sind {{ usable | round(1) }}
Kilowatt.
target:
entity_id: media_player.media_player_nest
else:
- action: script.byd_reset_charging
metadata: {}
data: {}
- action: input_boolean.turn_off
metadata: {}
target:
entity_id: input_boolean.byd_nachteinspeisung
data: {}
alias: BYD Nachteinspeisung
description: ""
fields:
startstop:
selector:
text: null
name: Startstop
required: true
alias: BYD Forced Discharge
sequence:
- data:
slave: 1
address: 40348
hub: gen24
value: 3
action: modbus.write_register
- data:
address: 40356
slave: 1
hub: gen24
value: >-
{{ 65536 - (states('input_number.byd_discharge_limit')|int(0) * 10000 /
states('sensor.reading_battery_settings').split(',')[0]|int(1) ) | int
}}
action: modbus.write_register
- data:
address: 40355
slave: 1
hub: gen24
value: 10000
action: modbus.write_register
mode: single
icon: mdi:home-battery
description: >-
"Set 40348 Inout mode, 40355 forced discharge %, 40356 negative forced charge
% from input number byd_discharge_limit"
Doku: https://www.libe.net/byd-modbus
alias: BYD Reset charging default
sequence:
- data:
slave: 1
address: 40348
value: 0
hub: gen24
action: modbus.write_register
- data:
address: 40355
slave: 1
value: 10000
hub: gen24
action: modbus.write_register
- data:
slave: 1
address: 40350
value: 500
hub: gen24
action: modbus.write_register
- data:
address: 40356
slave: 1
value: 10000
hub: gen24
action: modbus.write_register
mode: single
icon: mdi:home-battery
description: >-
"Set 40348 automatic Mode, 40355 100% Max charge, 40356 100% Max discharge and
40350 5% residual battery capacity"
Doku: https://www.libe.net/byd-modbus
configuration.yaml modbus Eintrag ( erstellt Voraussetzungen für modbus Zugriff von homeassistant aus ) Bitte unbedingt die Dokumentation lesen. Die Fronius Anlage muss konfiguriert werden !
modbus:
- type: tcp
# Put your Gen24 IP address here
host: 10.0.0.111
port: 502
name: gen24
sensors:
- name: reading_battery_settings
unique_id: BYD_reading_battery_settings
slave: 1
count: 24
address: 40345
scan_interval: 15
data_type: custom
structure: ">10H2h4H8h"
# > big endian, H unsigned, h signed Halfword
Die für Modbus zu setzenden Werte im Fronius menü findet ihr in der Anleitung: Fronius & BYD Akku über Modbus steuern, Home Assistant Ich verwende die Einstellungen SunSpec Model Type: „int + SF“.
Gutes Gelingen
