nach dem ich im letzten Jahr eine Balkonsolar-Anlage gekauft und in Betrieb genommen habe und durch Auswertung feststellte, das von der erzeugten Energie ca. 2/3 eingespeist wurden, habe ich mich zu dem Kauf einer Marstek Venus E 3.0 5,12 kWH Batterie entschlossen. Diese wird AC-seitig angeschlossen und auch nur so geladen.
Seit fast 2 Jahren habe ich bereits einen dynamischen Stromtarif (Tibber) zwischenzeitlich wurde bereits ein iMSys installiert.
Da ich eine 11 kW Wallbox habe, habe ich das Modul 1 nach § 14a EnWG aktiviert. Aktuell läuft gerader der Antrag zur Wahl von Modul 3.
Die Wallbox steuere ich mit EVCC, das Programm läuft im Docker. In EVCC habe ich ebenfalls die PV-Anlage eingebunden sowie zwei Modbus-Zähler, für die Wallbox und die Haupteinspeisung, die über RS485 an den Timberwolf angeschlossen sind. Die Kommunikation mit EVCC läuft per MQTT.
Da die Batteriesteuerung des Venus E 3.0 nur über spezielle Zähler PV-Überschuß oder preisgesteuert arbeitet habe ich mich dazu entschlossen die Steuerung selber zu realisieren.
Einerseits benötige ich dazu EVCC und die dazugehörige MQTT-Option. EVCC bietet preisgesteuertes Laden an. Erlaubt und Entladung nur im Zusammenhang mit der Autoladung, dies hat meinen Entschluss die Lösung selbst zu entwickeln bestärkt.
Hier möchte ich jetzt die erste Version der Logik vorstellen. Es gibt noch Verbesserungspotential aber die Funktion ist schon sehr gut.
Die Ansteuerung die Batterie ist in einem anderen Beitrag beschrieben. Modbus TCP-Ansteuerung
Die Logik:

Wieso in der Grafik der Eingang Residual_Last_PV doppelt auftaucht, ist mr nicht klar, in der Logik ist der Eingang nur einmal vorhanden.
Hier die kommentierte Logik:
Code: Alles auswählen
/**
* Laderegelung für Akku
* Nulleinspeisung (Residual_Last PV) bei PV-Überschuß
* Entladung bei hohen Preisen ($Last_Ent)
* Ladung bei Strompreis unter
*/
{
"_Meta": { // Laderegelung für Akku
"Description": "Nulleinspeisung bei PV und Entladung bei hohen Preisen",
"Author": "Arno Zietz",
"Version": "1.00"
},
"Input": [
["Leistung Hauptzähler","Leistung Hauptzähler","$Leistung_HZ","a"],
["Leistung Bezug Hauptzähler","Leistung Bezug Hauptzähler","$Leistung_Bezug","a"],
["Leistung PV","Leistung PV","$Leistung_PV","a"],
["max Ladeleistung","max. Ladeleistung Batterie","$Max_Leistung_Bat","a"],
["aktuelle Strompreis","aktuelle Strompreis","$akt_Tarif","a"],
["min Strompreis","minimaler Strompreis","$min_Tarif","a"],
["max Strompreis","maximaler Strompreis","$max_Tarif","a"],
["Median Strompreis","Median Strompreis","$med_Tarif","a"],
["Verluste_Laden","Verluste Be- und Entladen als Puffer","$Verluste","a"],
["SOC Akku","SOC Akku","$SOC_Akku","a"],
["SOC max Akku","SOC max Akku","$SOC_max","a"],
["SOC min Akku","SOC min Akku","$SOC_min","a"],
["Last_Ent","Last Entladen","$Last_Ent","a"],
["Residual_Last_PV","Residual Last PV Einspeisung","$Residual_Last_PV","a"]
],
"Output": [
["Laden","Laden","$Laden","c"],
["Entladen","Entladen","$Entladen","c"],
["Leistung_Laden","Leistung zum Laden oder Entladen","$Leistung_Laden","c"],
["Leistung_Entladen","Leistung zum Entladen","$Leistung_Entladen","c"]
],
"Level": [
["$Leistung_HZ","float",0.0],
["$Leistung_Bezug","float",0.0],
["$Leistung_PV","float",0.0],
["$SOC_Akku","float",0.0],
["$SOC_max","float",0.0],
["$SOC_min","float",0.0],
["$Max_Leistung_Bat","float",0.0],
["$akt_Tarif","float",0.0],
["$min_Tarif","float",0.0],
["$max_Tarif","float",0.0],
["$med_Tarif","float",0.0],
["$Tarif_Diff","float",0.0],
["$Grenze_Entladen","float",0.0],
["$Grenze_Laden","float",0.0],
["$Grenze_Laden_max","float",0.0],
["$Verluste","float",0.0],
["$Last_Ent","float",0.0],
["$Residual_Last_PV","float",0.0],
["$Soll_Last","float",0.0],
["$Laden","bool",false],
["$PreisLaden","bool",false],
["$PreisEntladen","bool",false],
["$Entladen","bool",false],
["$Einspeisung","bool",false],
["$PV_Erzeugung","bool",false],
["$Akku_Ladung_max","bool",false],
["$Akku_Ladung_min","bool",false],
["$Akku_nicht_voll","bool",false],
["$Leistung_Akku","float",0.0],
["$Leistung_Laden","float",0.0],
["$Leistung_Entladen","float",0.0],
["$Konst0","float",0.0],
["$Konst1","float",1.0],
["$Konst01","float",0.1],
["$Konst001","float",0.01],
["$Konst100","float",100.0],
["$KonstTrue","bool",true],
["$KonstFalse","bool",false],
["$Kp","float",0.7],
["$Ki","float",0.06],
["$Kd","float",0.0],
["$Formel_Grenze_Laden","string","(X1+X2)/2"]
],
"Module": [
//
//Prüfen ob PV Erzeugung und init der Variablen
//Prüfung ob Akku voll ist
//
["Latch","$Konst0","$Leistung_Akku","$KonstTrue",0],
["Latch","$Konst0","$Leistung_Laden","$KonstTrue",0],
["Latch","$Konst0","$Leistung_Entladen","$KonstTrue",0],
["Latch","$Leistung_HZ","$Soll_Last","$KonstTrue",0],
["Comparator" , "$Leistung_PV" , "$PV_Erzeugung" , "$Konst0"],
["Comparator" , "$Leistung_PV" , "$Einspeisung" , "$Leistung_Bezug"],
["Comparator" , "$Konst100" , "$Akku_nicht_voll" , "$SOC_Akku"],
//
// Soll-Last für Regler einstellen: Residual_Last_PV bei Einspeisung
// aktuelle Leistung, damit Regler nicht arbeitet, wenn der Akuu vol ist
//
["Latch","$Residual_Last_PV","$Soll_Last","$Einspeisung",0],
["Latch","$Leistung_HZ","$Soll_Last","-$Akku_nicht_voll",0],
//
// Prüfung ob Akkuladung durch Prei nur bis $SOC_max mit voller Leistung
// Entladung nur nis $SOC_min
//
["Comparator" , "$SOC_max" , "$Akku_Ladung_max" , "$SOC_Akku"],
["Comparator" , "$SOC_Akku" , "$Akku_Ladung_min" , "$SOC_min"],
//
//prüfen ob Preisladen
// $Tarif_Diff um Verluste zu kompensieren
// Entladen ab Median Preis + $Tarif_Diff
// laden ab Median Preis - Tarif_Diff = Max Ladepreis
// (min Preis + Max_ladepreis)/2 um nur wirklich Preiswert zu Laden
//
["Polynomial", "$Verluste", "$Tarif_Diff",["$Konst0", "$Konst001"]],
["Polynomial", "$med_Tarif", "$Grenze_Entladen",["$med_Tarif", "$Tarif_Diff"]],
["Polynomial", "$med_Tarif", "$Grenze_Laden_max",["$med_Tarif", "-$Tarif_Diff"]],
["CalcFormula",["$min_Tarif","$Grenze_Laden_max"], "$Grenze_Laden", "$Formel_Grenze_Laden"],
["Comparator" , "$Grenze_Laden" , "$PreisLaden" , "$akt_Tarif"],
["Comparator" , "$akt_Tarif" , "$PreisEntladen" , "$Grenze_Entladen"],
//
// Bei Preis entladen, Reglgröße auf $Last_Ent setzen
//
["Latch","$Last_Ent","$Soll_Last","$PreisEntladen",0],
//
// Stellgröße errechnen
//
["PID_awu","$Soll_Last","$Leistung_HZ","$Leistung_Akku","$Kp","$Ki", "$Kd","-$Max_Leistung_Bat","$Max_Leistung_Bat"],
//
//Laden oder Entladen ?
// und Ausgangsgrößen setzen
//
["Latch","$KonstFalse","$Laden","$KonstTrue",0],
["Latch","$KonstFalse","$Entladen","$KonstTrue",0],
["Comparator" , "$Leistung_Akku" , "$Laden" , "$Konst0"],
["Comparator" , "$Konst0" , "$Entladen" , "$Leistung_Akku"],
["And", ["$PreisLaden", "$Akku_Ladung_max"], "$PreisLaden"],
["Or", ["$Laden", "$PreisLaden"], "$Laden"],
["And", ["$Laden", "$Akku_nicht_voll"], "$Laden"],
["And", ["$Entladen", "$PreisEntladen" , "$Akku_Ladung_min"], "$Entladen"],
["Latch","$Max_Leistung_Bat","$Leistung_Akku","$PreisLaden",0],
["Latch","$Leistung_Akku","$Leistung_Laden","$Laden",0],
["Latch","-$Leistung_Akku","$Leistung_Entladen","$Entladen",0]
]
}| Eingangsvariable | Beschreibung |
|---|---|
| Leistung Hauptzähler | Zähler am Einspeiesepunkt |
| Leistung Bezug Hauptzähler | Bezugslesitung am Einspeisepunkt |
| Leistung PV | Pv erzeugungsleistung |
| maximale Ladeleistung | Leistung zur Begrenzung von Lade- und Entladeleistung |
| aktueller Strompreis | aktueller Bezugsstrompreis |
| minimaler Strompreis | minimaler Strompreis aus vorgelagerter Statistik |
| maximaler Strompreis | maximaler Strompreis aus vorgelagerter Statistik |
| Median Strompreis | Median Strompreis aus vorgelagerter Statistik |
| Ladeverlsute | Basis zur Berechnung der oberen un unteren Ladegrenze |
| SOC Akku | aktueller SOC des Akku |
| SOC max | maximaler SOC bsi zu dem der Akku über Preis geladen werden soll |
| SOC min | minimaler SOC bis zu dem entladen werden soll |
| Last_Ent | Last auf die beim Entladen über Preis reduziert werden soll |
| Residual_last_PV | Last auf die geregelt werden soll, wenn PV-Überschuss vorhanden ist |
Die Preise des Stromtarifes kommen per JSON-Array aus EVCC per MQTT und werden über eine Statistiklogik ausgewertet.

Die beiden Binärwerte werden für den Modbus über eine Logik in einen Integer-Wert umgewandelt.

Die Testphase läuft noch, aber ich bin mit dem aktuellen Stand zufrieden.
Mir schwebt noch eine Berechnung des Durchschnittspreises der Akkuladung vor, die die Entladegrenze bei hohen Preisen auslöst.
Über Fragen, Anmerkungen, Ideen, Kritik, Fehlerhinweise freue ich mich.
Arno