NEWS
Steuerung zweiter Hausakku (Victron Multi Plus)
-
Ich würde erstmal nur auf einen Wert und zwar den vom Smartmeter triggern. Wenn Überschuss dann laden wenn bedarf dann entladen. Zuerst den BYD voll/leer machen wenn voll/leer dann lade/entladesperre für den Victron setzen.
z.B. Beispiel_blockly.txt
-
Hallo zusammen,
ich habe mir jetzt sehr lange den Kopf zerbrochen und probiert aber ich glaube ich habe inzwischen einen Logik Fehler in meinem Kopf der nicht weichen möchte.
Ausgangssituation:
PV Anlage mit Kostal Wechselrichter und BYD Speicher, B-Control Smart Meter Zähler zur Steuerung.Dazu habe ich nun Victron Multi Plus mit Batteriespeicher zusätzlich am Netz. Das Victron System soll das bisherige System Unterstützen und geladen bzw. entladen werden wenn der BYD Speicher leer bzw. voll ist.
Es klappt nicht wirklich auf 50W Bezug oder Einspeisung zu regulieren und mir fehlen langsam die Ideen. Zudem versagt dann auch zwischen durch der Java Script Adapter oder es wir kein Wert mehr angepasst mit dieser Form des Skripts.
Zuerst habe ich nur auf Wirkleistung Bezug und Einspeisung gesteuert, was aber logisch war das dann eine Achterbahnkurve kommt...Vielleicht hat einer in der Community ein Ähnliches Projekt realisiert und kann mir den entscheidenden Tipp geben?

Inzwischen habe ich auch gelesen das die Schleife für den Absturz verantwortlich ist und nicht dafür zu verwenden ist....
@Bock.Johannes Ja, die Schleife ist das Problem. Ein Skript im JavaScript-Adapter darf nie aktiv warten, sonst blockiert es den ganzen Adapter. Lös das Skript stattdessen über einen Trigger aus (Änderung der Netzleistung) oder per Zeitplan alle paar Sekunden.
Zum Schwingen: Setz den Victron-Sollwert nicht direkt auf die gemessene Netzleistung. Korrigier den letzten Sollwert jedes Mal nur um einen Teil der Abweichung (Integral-Regler) und lass ein Totband stehen. Weil Kostal/BYD am selben Zähler auch regeln, muss der Victron deutlich langsamer sein, sonst arbeiten die beiden gegeneinander.
Etwa so (IDs anpassen, Vorzeichen: Netz positiv = Bezug, Victron positiv = Entladen):
const ID_NETZ = 'xxx.netzleistung'; // B-Control, W const ID_BYD_SOC = 'xxx.byd_soc'; // % const ID_VICTRON = '0_userdata.0.victron_soll'; // bzw. dein Victron-Sollwert const ZIEL = 0, TOTBAND = 50, K = 0.4, MAX = 2500; let soll = 0; schedule('*/5 * * * * *', async () => { const netz = (await getStateAsync(ID_NETZ)).val; const soc = (await getStateAsync(ID_BYD_SOC)).val; const fehler = netz - ZIEL; if (Math.abs(fehler) < TOTBAND) return; soll += fehler * K; // Victron nur arbeiten lassen, wenn BYD leer (entladen) bzw. voll (laden) if (soll > 0 && soc > 10) soll = 0; if (soll < 0 && soc < 98) soll = 0; soll = Math.max(-MAX, Math.min(MAX, Math.round(soll))); setState(ID_VICTRON, soll); });In Blockly geht das genauso: Block "Zeitplan" mit Cron, eine Variable für den Sollwert außerhalb des Triggers, dann "Sollwert = Sollwert + (Netz - Ziel) * 0.4", danach begrenzen. K und das Intervall musst du ausprobieren. Schwingt es noch, K kleiner machen oder das Intervall verlängern.
Wie schreibst du den Sollwert zum Multiplus (Modbus, MQTT, welcher ESS-Modus)? Und hat der Victron einen eigenen Zähler? Wenn ja, kann der Victron die Regelung selbst übernehmen, und du schreibst nur noch den Grid-Setpoint.
-
Guten Morgen zusammen,
vielen Dank für die Ideen. Es hat mir alles keine Ruhe gelassen und ich habe die vorletzte Nacht nochmal experimentiert und es gestern getestet. Das Laden hat sehr gut funktioniert, das entladen kann ich erst testen wenn mal nicht so viel vom Dach kommt und der BYD leer ist. Ich habe das Skript versucht zu vereinfachen damit ich das System nicht zu sehr belaste da ich relativ viel über IOBroker steuere. So sieht es aktuell aus:ESS steht auf externe Steuerung und ich Regele über das Register 2700
var Netzbezug, Netzeinspeisung, Smartmeter;
var Netzbezug, Netzeinspeisung, Smartmeter; on({ id: [].concat(['b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Bezug']).concat(['b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Einspeisung']), change: 'ne' }, async (obj) => { Netzbezug = getState('b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Bezug').val; Netzeinspeisung = getState('b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Einspeisung').val; Smartmeter = Netzeinspeisung - Netzbezug; if (Smartmeter >= 200) { setStateDelayed('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint' /* ESS Mode 2 - Setpoint for the ESS control-loop in the CCGX. The control-loop will increase/decrease the Multi charge/discharge power to get the grid reading to this setpoint */, (getState('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint').val + ((Smartmeter + 50) - getState('modbus.0.holdingRegisters.106_Home_own_consumption_from_battery').val)), 2000, false); } else if (Smartmeter <= 200) { setStateDelayed('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint' /* ESS Mode 2 - Setpoint for the ESS control-loop in the CCGX. The control-loop will increase/decrease the Multi charge/discharge power to get the grid reading to this setpoint */, (getState('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint').val + Smartmeter + 50), 2000, false); } });Das einzige was hier noch nicht optimal funktioniert ist das Entladen der Batterie unter Berücksichtigung des vorhandenen Akkus... Hier muss ich auch noch was einbauen das bei 11kw Auto laden der Hausakku nicht mit entlädt sondern nur der neue 64kw speicher.
-
Guten Morgen zusammen,
vielen Dank für die Ideen. Es hat mir alles keine Ruhe gelassen und ich habe die vorletzte Nacht nochmal experimentiert und es gestern getestet. Das Laden hat sehr gut funktioniert, das entladen kann ich erst testen wenn mal nicht so viel vom Dach kommt und der BYD leer ist. Ich habe das Skript versucht zu vereinfachen damit ich das System nicht zu sehr belaste da ich relativ viel über IOBroker steuere. So sieht es aktuell aus:ESS steht auf externe Steuerung und ich Regele über das Register 2700
var Netzbezug, Netzeinspeisung, Smartmeter;
var Netzbezug, Netzeinspeisung, Smartmeter; on({ id: [].concat(['b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Bezug']).concat(['b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Einspeisung']), change: 'ne' }, async (obj) => { Netzbezug = getState('b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Bezug').val; Netzeinspeisung = getState('b-control-em.0.Teridian_Total_Kanal.Wirkleistung_Einspeisung').val; Smartmeter = Netzeinspeisung - Netzbezug; if (Smartmeter >= 200) { setStateDelayed('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint' /* ESS Mode 2 - Setpoint for the ESS control-loop in the CCGX. The control-loop will increase/decrease the Multi charge/discharge power to get the grid reading to this setpoint */, (getState('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint').val + ((Smartmeter + 50) - getState('modbus.0.holdingRegisters.106_Home_own_consumption_from_battery').val)), 2000, false); } else if (Smartmeter <= 200) { setStateDelayed('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint' /* ESS Mode 2 - Setpoint for the ESS control-loop in the CCGX. The control-loop will increase/decrease the Multi charge/discharge power to get the grid reading to this setpoint */, (getState('modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint').val + Smartmeter + 50), 2000, false); } });Das einzige was hier noch nicht optimal funktioniert ist das Entladen der Batterie unter Berücksichtigung des vorhandenen Akkus... Hier muss ich auch noch was einbauen das bei 11kw Auto laden der Hausakku nicht mit entlädt sondern nur der neue 64kw speicher.
@Bock.Johannes
Welchen Wertebereich hat der DP "modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint" und wann ist er negativ? -
Mein neuster Entwurf mit KI Hilfe
les/1792151240307-f78d05e5-a0bf-4f8d-ad22-2d24f7e95196-image.jpeg)Aber es läuft nur teilweise rund... bzw. Java stürzt ab
@Bock.Johannes [sagte]: es läuft nur teilweise rund...
Vorschlag für einen PI-Regler (Entladen: negativer Sollwert):

Es wird auf 50 W Einspeisung geregelt.
-
@Bock.Johannes
Welchen Wertebereich hat der DP "modbus.3.holdingRegisters.100.2700_ESS_control_loop_setpoint" und wann ist er negativ?@paul53 Positiv heißt die Batterien werden geladen, Negativ, die Batterie wird entladen. Mit den drei Multi Plus geht das bei 10800W je Richtung
-
@Bock.Johannes [sagte]: es läuft nur teilweise rund...
Vorschlag für einen PI-Regler (Entladen: negativer Sollwert):

Es wird auf 50 W Einspeisung geregelt.
@paul53 hast Du das so am laufen? Ähnlich sah mein dritter Entwurf aus und hat den Java Adapter nach einer gewissen Laufzeit zum Absturz gebracht...
-
@paul53 Positiv heißt die Batterien werden geladen, Negativ, die Batterie wird entladen. Mit den drei Multi Plus geht das bei 10800W je Richtung
@Bock.Johannes [sagte: 10800W je Richtung

Xp muss wahrscheinlich größer sein (80000 ? ausprobieren), da die Regelung sonst instabil wird (schwingt).
-
@Bock.Johannes Ja, die Schleife ist das Problem. Ein Skript im JavaScript-Adapter darf nie aktiv warten, sonst blockiert es den ganzen Adapter. Lös das Skript stattdessen über einen Trigger aus (Änderung der Netzleistung) oder per Zeitplan alle paar Sekunden.
Zum Schwingen: Setz den Victron-Sollwert nicht direkt auf die gemessene Netzleistung. Korrigier den letzten Sollwert jedes Mal nur um einen Teil der Abweichung (Integral-Regler) und lass ein Totband stehen. Weil Kostal/BYD am selben Zähler auch regeln, muss der Victron deutlich langsamer sein, sonst arbeiten die beiden gegeneinander.
Etwa so (IDs anpassen, Vorzeichen: Netz positiv = Bezug, Victron positiv = Entladen):
const ID_NETZ = 'xxx.netzleistung'; // B-Control, W const ID_BYD_SOC = 'xxx.byd_soc'; // % const ID_VICTRON = '0_userdata.0.victron_soll'; // bzw. dein Victron-Sollwert const ZIEL = 0, TOTBAND = 50, K = 0.4, MAX = 2500; let soll = 0; schedule('*/5 * * * * *', async () => { const netz = (await getStateAsync(ID_NETZ)).val; const soc = (await getStateAsync(ID_BYD_SOC)).val; const fehler = netz - ZIEL; if (Math.abs(fehler) < TOTBAND) return; soll += fehler * K; // Victron nur arbeiten lassen, wenn BYD leer (entladen) bzw. voll (laden) if (soll > 0 && soc > 10) soll = 0; if (soll < 0 && soc < 98) soll = 0; soll = Math.max(-MAX, Math.min(MAX, Math.round(soll))); setState(ID_VICTRON, soll); });In Blockly geht das genauso: Block "Zeitplan" mit Cron, eine Variable für den Sollwert außerhalb des Triggers, dann "Sollwert = Sollwert + (Netz - Ziel) * 0.4", danach begrenzen. K und das Intervall musst du ausprobieren. Schwingt es noch, K kleiner machen oder das Intervall verlängern.
Wie schreibst du den Sollwert zum Multiplus (Modbus, MQTT, welcher ESS-Modus)? Und hat der Victron einen eigenen Zähler? Wenn ja, kann der Victron die Regelung selbst übernehmen, und du schreibst nur noch den Grid-Setpoint.
@Bluefox hat einen reinen I-Regler programmiert.
Wenn die Bezugs- bzw. Einspeiseleistung zyklisch aktualisiert werden, ist es besser, diese als Trigger zu verwenden.
I-Regler als Blockly:
Die kurze Verzögerung verhindert eine Doppelauslösung, wenn Bezug und Einspeisung unmittelbar nacheinander aktualisiert werden.
-
@Bluefox hat einen reinen I-Regler programmiert.
Wenn die Bezugs- bzw. Einspeiseleistung zyklisch aktualisiert werden, ist es besser, diese als Trigger zu verwenden.
I-Regler als Blockly:
Die kurze Verzögerung verhindert eine Doppelauslösung, wenn Bezug und Einspeisung unmittelbar nacheinander aktualisiert werden.
@paul53 das probiere ich mal aus, das sieht doch etwas besser aus als das was ich aktuell programmiert habe.....
-
@Bluefox hat einen reinen I-Regler programmiert.
Wenn die Bezugs- bzw. Einspeiseleistung zyklisch aktualisiert werden, ist es besser, diese als Trigger zu verwenden.
I-Regler als Blockly:
Die kurze Verzögerung verhindert eine Doppelauslösung, wenn Bezug und Einspeisung unmittelbar nacheinander aktualisiert werden.
@paul53 ich habe mal den neuen Akku gestern voll gemacht um auch etwas zu probieren. Das Skript funktioniert zum laden super, jedoch jetzt wo der BYD heute Nacht leer war und das Victron System liefert habe ich das Phänomen das sich das ganze aufschaukelt, der BYD geladen wird und dann wieder entlädt, so das ich ein hoch und runterfahren der beiden Systeme habe. Ich habe auch schon das Totband erhöht aber es wirkt noch nicht so....
-
@paul53 ich habe mal den neuen Akku gestern voll gemacht um auch etwas zu probieren. Das Skript funktioniert zum laden super, jedoch jetzt wo der BYD heute Nacht leer war und das Victron System liefert habe ich das Phänomen das sich das ganze aufschaukelt, der BYD geladen wird und dann wieder entlädt, so das ich ein hoch und runterfahren der beiden Systeme habe. Ich habe auch schon das Totband erhöht aber es wirkt noch nicht so....
@Bock.Johannes [sagte: der BYD geladen wird
Das muss nachts verhindert werden.
-
@paul53 ich habe mal den neuen Akku gestern voll gemacht um auch etwas zu probieren. Das Skript funktioniert zum laden super, jedoch jetzt wo der BYD heute Nacht leer war und das Victron System liefert habe ich das Phänomen das sich das ganze aufschaukelt, der BYD geladen wird und dann wieder entlädt, so das ich ein hoch und runterfahren der beiden Systeme habe. Ich habe auch schon das Totband erhöht aber es wirkt noch nicht so....
@Bock.Johannes Zur Ergänzung von paul53: Das Aufschaukeln entsteht, weil beim Entladen auch auf 50 W Einspeisung geregelt wird. Der Kostal sieht diese Einspeisung als Überschuss und lädt damit den BYD. Danach fehlt die Leistung, der Victron legt nach, und so arbeiten beide Regler gegeneinander.
Drei Dinge helfen:
- Asymmetrisches Ziel: Beim Laden auf etwa 50 W Einspeisung regeln, beim Entladen (Sollwert negativ) auf etwa 50 bis 100 W Bezug. Dann sieht der Kostal nie einen Überschuss, den er in den BYD stecken könnte.
- Den Victron-Regler einfrieren, solange der BYD lädt oder entlädt (Batterieleistung vom Kostal abfragen, z. B. abs(Leistung) > 100 W). Dann wird der Sollwert nicht weiter angepasst. So regelt immer nur ein System.
- Wenn möglich, das Laden des BYD sperren, solange keine PV-Leistung da ist. Kannst du das beim Kostal per Modbus vorgeben? Dann ist das Problem in der Nacht grundsätzlich weg.
Das Totband zu erhöhen hilft dabei kaum, weil sich die Systeme gegenseitig hochschaukeln. Eine Störung durch Messrauschen ist das nicht.
-
Ohne den Kostal auf externe Steuerung umzustellen, kann ich die Ladung im Modbus für die BYD Batterie nicht unterbinden. Das möchte ich eigentlich nicht umstellen.
Das Aufschaukeln ist nicht nur während der Phase in der die BYD Batterie leer ist, sondern auch in der Phase in der die PV Produktion langsam wieder startet bis Sie dann letztlich den Hausverbrauch überschreitet.
Was ich jedoch steuern könnte, anhand einer Bedingung ist über den Plenticore Adapter die Entladung der Batterie zu unterbinden bis PV Produktion einen Gewissen Wert überschritten hat. Das könnte vielleicht helfen. Diese Funktion nutze ich wenn ich die Wallbox ohne entladen der Batterie betreiben möchte.
Das würde ich dann aber mal in einem extra Skript unterbringen. -
Ohne den Kostal auf externe Steuerung umzustellen, kann ich die Ladung im Modbus für die BYD Batterie nicht unterbinden. Das möchte ich eigentlich nicht umstellen.
Das Aufschaukeln ist nicht nur während der Phase in der die BYD Batterie leer ist, sondern auch in der Phase in der die PV Produktion langsam wieder startet bis Sie dann letztlich den Hausverbrauch überschreitet.
Was ich jedoch steuern könnte, anhand einer Bedingung ist über den Plenticore Adapter die Entladung der Batterie zu unterbinden bis PV Produktion einen Gewissen Wert überschritten hat. Das könnte vielleicht helfen. Diese Funktion nutze ich wenn ich die Wallbox ohne entladen der Batterie betreiben möchte.
Das würde ich dann aber mal in einem extra Skript unterbringen.@Bock.Johannes Die Entladesperre des BYD hilft, weil dann morgens nur noch der Victron die Last deckt und die beiden sich nicht mehr die Arbeit teilen. Das Laden des BYD verhindert sie aber nicht. Sobald der Victron auf Einspeisung regelt, sieht der Kostal Überschuss und lädt den BYD trotzdem. Deshalb würde ich das asymmetrische Ziel zusätzlich einbauen: Ist der Sollwert negativ (Victron entlädt), regelst du auf etwa 50 bis 100 W Bezug statt auf Einspeisung. Hast du das schon drin?
Zwei Punkte für das extra Skript:
- Die PV-Schwelle braucht eine Hysterese, sonst schaltet die Sperre bei wechselnder Bewölkung dauernd hin und her. Zum Beispiel sperren unter 1500 W, freigeben erst über 2000 W, und das Ganze erst, wenn der Wert ein paar Minuten anliegt. Die Werte sind nur Beispiele, die musst du an euren Grundverbrauch anpassen.
- Beim Umschalten (BYD gesperrt bzw. freigegeben) springt die Last sprunghaft von einem System auf das andere. Der I-Anteil im Victron-Skript braucht dann eine Weile, bis er nachgezogen hat. Es hilft, den Victron-Regler beim Umschalten kurz einzufrieren oder den Sollwert gezielt zu setzen, statt ihn von irgendeinem alten Wert aus weiterlaufen zu lassen.
Ein eigenes Skript ist dafür in Ordnung. Wichtig ist nur, dass es keinen Sollwert für den Victron schreibt. Das darf nur ein Skript machen.
-
@Bock.Johannes Die Entladesperre des BYD hilft, weil dann morgens nur noch der Victron die Last deckt und die beiden sich nicht mehr die Arbeit teilen. Das Laden des BYD verhindert sie aber nicht. Sobald der Victron auf Einspeisung regelt, sieht der Kostal Überschuss und lädt den BYD trotzdem. Deshalb würde ich das asymmetrische Ziel zusätzlich einbauen: Ist der Sollwert negativ (Victron entlädt), regelst du auf etwa 50 bis 100 W Bezug statt auf Einspeisung. Hast du das schon drin?
Zwei Punkte für das extra Skript:
- Die PV-Schwelle braucht eine Hysterese, sonst schaltet die Sperre bei wechselnder Bewölkung dauernd hin und her. Zum Beispiel sperren unter 1500 W, freigeben erst über 2000 W, und das Ganze erst, wenn der Wert ein paar Minuten anliegt. Die Werte sind nur Beispiele, die musst du an euren Grundverbrauch anpassen.
- Beim Umschalten (BYD gesperrt bzw. freigegeben) springt die Last sprunghaft von einem System auf das andere. Der I-Anteil im Victron-Skript braucht dann eine Weile, bis er nachgezogen hat. Es hilft, den Victron-Regler beim Umschalten kurz einzufrieren oder den Sollwert gezielt zu setzen, statt ihn von irgendeinem alten Wert aus weiterlaufen zu lassen.
Ein eigenes Skript ist dafür in Ordnung. Wichtig ist nur, dass es keinen Sollwert für den Victron schreibt. Das darf nur ein Skript machen.
@Bluefox Guten Morgen,
nein das Asymmetrische Ziel habe ich noch nicht eingebaut, mir ist aber auch noch nicht klar an welcher Stelle.
Ich habe jetzt mal mit einem Zustäzlichen Skript probiert was die Entladesperre setzt. Trotzdem schaukel es sich noch auf was wahrscheinlich mit der steigenden PV Leistung zu tun hat. Ganz verstehen kann ich das verhalten noch nicht. Das laden was in die BYD Batterie erfolgt ist mit 20-100w schwankend für mich nicht störend.
Mein aktuelles Skript blockt auch wieder die Java Engine, ich glaube da muss ich nochmal ran... -
@Bluefox hat einen reinen I-Regler programmiert.
Wenn die Bezugs- bzw. Einspeiseleistung zyklisch aktualisiert werden, ist es besser, diese als Trigger zu verwenden.
I-Regler als Blockly:
Die kurze Verzögerung verhindert eine Doppelauslösung, wenn Bezug und Einspeisung unmittelbar nacheinander aktualisiert werden.
@paul53 wenn ich es richtig sehe fängt der Victron erst an zu laden, wenn die BYD Batterie bei 98% ist? Hier würde ich noch eine oder Bedingung mit einbauen, denn er lädt nur mit maximal 6500W, die restliche Energie verschenke ich ja im Moment. Würde draus mal testweise ein oder machen und auf PV-Erzeugung größer 7500W abfragen....
-
@Bluefox hat einen reinen I-Regler programmiert.
Wenn die Bezugs- bzw. Einspeiseleistung zyklisch aktualisiert werden, ist es besser, diese als Trigger zu verwenden.
I-Regler als Blockly:
Die kurze Verzögerung verhindert eine Doppelauslösung, wenn Bezug und Einspeisung unmittelbar nacheinander aktualisiert werden.
@paul53 Leider schwingt das Skript beim Entladen wenn nur die Victron Batterie tätig ist und der BYD gesperrt ist. Das Verhalten ist mir noch unklar... EIne Idee? Den Speed habe ich auf 1 gesetzt
-
@paul53 Leider schwingt das Skript beim Entladen wenn nur die Victron Batterie tätig ist und der BYD gesperrt ist. Das Verhalten ist mir noch unklar... EIne Idee? Den Speed habe ich auf 1 gesetzt
@Bock.Johannes [sagte: Leider schwingt das Skript beim Entladen ... Den Speed habe ich auf 1 gesetzt
Dann verringere den Speed.
Hey! Du scheinst an dieser Unterhaltung interessiert zu sein, hast aber noch kein Konto.
Hast du es satt, bei jedem Besuch durch die gleichen Beiträge zu scrollen? Wenn du dich für ein Konto anmeldest, kommst du immer genau dorthin zurück, wo du zuvor warst, und kannst dich über neue Antworten benachrichtigen lassen (entweder per E-Mail oder Push-Benachrichtigung). Du kannst auch Lesezeichen speichern und Beiträge positiv bewerten, um anderen Community-Mitgliedern deine Wertschätzung zu zeigen.
Mit deinem Input könnte dieser Beitrag noch besser werden 💗
Registrieren Anmelden