ESS ctrlEssTimeOfUseTariff Verwendung

Hallo zusammen,

ich versuche verzweifelt zu verstehen, wie die Verbindung zwischen den Hybrid-Invertern (oder auch Batteriespeichern) und dem ctrlEssTimeOfUseTariff Controller funktioniert.
In meinem Log sehe ich:
ctrlEssTimeOfUseTariff0[DELAY_DISCHARGE] - so weit, so gut.
Die zentrale Frage ist, wie denn dem ESS der DELAY_DISCHARGE State übermittelt wird?
Gibt es im Quellcode vielleicht irgendwo ein Beispiel, wo man sich die TimeOfUseTariff Steuerung eines ESS (beispielhaft) anschauen kann?

Grüße
Kai

Hallo Kai,

Ich habe mir den Controller zwar auch noch nicht im Detail angeguckt, aber am Ende setzen alle ESS-Controller ein oder mehrere “Constraints” der Form (Re-)ActivePower = x, (Re-)ActivePower <= x oder (Re-)ActivePower >= x an die ESS. In dem Time-of-use-Tariff-Controller passiert das hier in Zeile 157:

Im Falle eines nicht-hybriden Inverters ist im Zustand Delay-Discharge as.setPoint() == 0, also setzt er die Constraint ActivePower <= 0, und da positive Leistung Entladung entspricht, heißt das in Worten “Entlade die Batterie nicht”.
Bei hybriden Invertern muss dann natürlich für den Setpoint noch die PV-Erzeugung verrechnet werden.

Viele Grüße,
Thomas

Hallo Thomas,

vielen Dank erst einmal für deine Nachricht.
Ich habe im hybriden ESS default eine (CT-Klemmen) “0-Regelung”.
Im ESS Controller für den Batteryinverter erhalte ich bei DELAY_DISCHARGE als ActivePower-Wert ein 0. Dies allerdings auch im BALANCING…
Ich hätte erwartet, dass mir bei ActivePower ein Wert, der dem Wert der angezeigten Abgabe des ESS entspricht (vielleicht mit umgekehrten Vorzeichen) entspricht.
Ich hoffe es wird klar, wo mein Problem ist? Kein Problem dem ESS ein Entladestopp zu setzen, nur weiß ich nicht worauf ich diesen anstoßen soll.
Wenn ich an z.B. DELAY_DISCHARGE kommen würde, alles easy.

Wenn ich es richtig verstehe, würde die Contstraint in meinem Falle also nur greifen, wenn ich auch die 0-Regelung über OpenEMS machen würde?
Mag aber auch sein, dass ich immer noch einen Knoten irgendwo in meinem Verständnis habe…

Grüße
Kai

Hallo zusammen,

vielleicht gibt es ja die Möglichkeit, irgendwie aus einem “Gerätetreiber” heraus auf den EssTimeOfUseTariff State (BALANCING, DELAY_DISCHARGE, etc.) zuzugreifen?
Wenn ja, dann würde das auf einen Schlag alle meine Probleme lösen.

Grüße
Kai

Hallo Kai.

Wenn du immer “0” als Vorgabe bekommst (in applyPower()) könnte es daran liegen, dass OpenEMS gar nicht weiß, dass eine Be-/Entladung überhaupt möglich ist. Dafür müssen die Channel AllowedChargePower, AllowedDischargePower und MaxApparentPower gesetzt sein.

Um welchen Speicher-Typ geht es denn? Kann ich einen Blick auf den Code der Implementierung werfen?

Auf den EssTimeOfUseTariff State der aktuellen Viertelstunde könnte man ggf. über Umwege kommen, aber das umgeht die komplette modulare Struktur von OpenEMS.

Gruß,
Stefan

Hallo Stefan,

vielen Dank für deine Antwort. Ich hatte die drei Channel bereits gesetzt.
Es geht um einen Deye Hybrid Inverter. Ich habe als Basis das verwendet, was hier bereits gepostet wurde.
Die Werte alle meiner Wechselrichter werden im OpenEMS bereits richtig angezeigt.
Nun hatte ich vor, mich an die Steuerung des Deye zu machen.
Zuerst hatte ich den Ansatz verfolgt, über Modbus die Register im Deye zu schreiben, dies dann aber temporär wieder verworfen und stattdessen eine “vituelle” CT-Klemme entwickelt.
Soll heißen, ich habe mit Hilfe eines ESP32 einen netzsynchronen CT-Emulator gebaut, welcher mir per Modbus-TCP erlaubt, beliebige Werte zu den gemessenen Strömen der angeschlossenen Stommesswandler zu setzen.
Das funktioniert alles gut. Klar, die Anzeige im OpenEMS stimmt natürlich nicht, wenn ich manuell Werte zu den gemessenen Werten hinzuaddiere oder abziehe, das wäre aber kein Problem in den Griff zu bekommen, da ich diese natürlich einfach im OpenEMS abziehen wieder herausrechnen könnte.

Anbei mein aktueller Sourcetree.
Ja, nicht sonderlich schön, das räume ich aber gerne auf, sobald wenigstens die Grundfunktionalität steht.
Ob ich am Ende mit der virtuellen CT-Klemme oder über Modbus direkt zum Deye arbeite ist ja auch erst einmal nicht weiter relevant.
Mein Problem ist, dass ich einfach keinen “Trigger” erhalte, um passend zum TimeOfUseTariff (bzw. der Entscheidung des zu steuernden ESS Verhaltens (Delay, Charge)) erhalte und nicht weiß, wie ich darauf zugreifen könnte.

Nov 28 21:15:22 projectx java[421323]: 2024-11-28T21:15:22,369 [_cycle ] INFO [ebuglog.ControllerDebugLogImpl] [ctrlDebugLog0] _sum[State:Ok Ess SoC:40 %|L:1426 W Grid:15 W Production:0 W Consumption:1441 W] ctrlEssTimeOfUseTariff0[DELAY_DISCHARGE] ess0[SoC:40 %|L:1426 W|Active Power:1426;|Allowed:0;-12000 W] meter0[L:15 W] meter1[L:0 W] modbus0[CycleDelay:2447 ms] pvInverter0[L:UNDEFINED] timeOfUseTariff0[Price:0.3237 EUR/kWh]
Nov 28 21:15:22 projectx java[421323]: CHAOSMAN activePower: 0 reactivePower: 0

Grüße
Kai

Hallo Kai,

der “dirty way” um an den Status zu kommen ist:

  1. Hole dir eine @Reference auf TimeOfUseTariffController
    • dazu musst du eine “package-info.java”-Datei im TimeOfUseTariffController-Package anlegen
    • in deiner “bnd.bnd”-Datei eine time-of-use-tariff zum -buildpath hinzufügen
    • die Referenz muss “optional” sein, sonst bekommst du einen circular dependency-Fehler
  2. Mit TimeOfUseController.getStateMachine() (openems/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff/TimeOfUseTariffController.java at main · chaosman123/openems · GitHub) kommst du an den State und kannst ihn entsprechend auswerten.

DISCLAIMER: das wird mit dem nächsten Update auf das neueste OpenEMS vermutlich Merge-Konflikte geben, aber ich denke damit kannst du umgehen.

Gruß,
Stefan

Hallo Stefan,

ja, getStateMachine() hatte ich auch schon als eine brauchbare Quelle identifiziert. Nur leider habe ich es absolut nicht geschafft, darauf zuzugreifen.

root@projectx:/usr/src/openems# ./gradlew buildEdge

Task :io.openems.edge.batteryinverter.deye:compileJava
/usr/src/openems/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java:57: error: package io.openems.edge.controller.ess does not exist
import io.openems.edge.controller.ess.timeofusetariff;
^
/usr/src/openems/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java:114: error: cannot find symbol
private TimeOfUseController timeOfUseController;
^
symbol: class TimeOfUseController
location: class DeyeSunHybridImpl
2 errors

Es mag daran liegen, dass ich nicht der Java-Gott vorm Herrn bin, sondern meistens in anderen Sprachen unterwegs bin…

Unter openems/io.openems.edge.controller.ess.timeofusetariff/src/io/openems/edge/controller/ess/timeofusetariff existiert bereits ein package-info.java.
Im bnd.bnd file habe ich ‘io.openems.edge.controller.ess.timeofusetariff’ hinzugefügt.
Dies hatte ich vorher, wenn ich mich noch richtig erinnere, noch nicht getan.
Nur leider hat das auch nichts geändert.

Ich habe die Changes auch per git eingecheckt und gepusht.

Grüße
Kai

Hallo Kai,

ich kann leider nicht pushen, deshalb hier ein patch-file:

---
 io.openems.edge.batteryinverter.deye/bnd.bnd                  | 1 +
 .../src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java       | 4 ++--
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/io.openems.edge.batteryinverter.deye/bnd.bnd b/io.openems.edge.batteryinverter.deye/bnd.bnd
index 9c44639795..402d06bef2 100644
--- a/io.openems.edge.batteryinverter.deye/bnd.bnd
+++ b/io.openems.edge.batteryinverter.deye/bnd.bnd
@@ -16,5 +16,6 @@ Bundle-Version: 1.0.0.${tstamp}
 	io.openems.edge.timedata.api,\
 	io.openems.edge.pvinverter.api, \
 	io.openems.edge.controller.ess.timeofusetariff
+
 -testpath: \
 	${testpath}
diff --git a/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java b/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java
index 75c45d3a30..114da4cf2c 100644
--- a/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java
+++ b/io.openems.edge.batteryinverter.deye/src/io/openems/edge/deye/ess/DeyeSunHybridImpl.java
@@ -54,7 +54,7 @@ import org.slf4j.LoggerFactory;
 
 import java.time.LocalDateTime;
 
-import io.openems.edge.controller.ess.timeofusetariff;
+import io.openems.edge.controller.ess.timeofusetariff.TimeOfUseTariffController;
 
 @Designate(ocd = Config.class, factory = true)
 @Component(//
@@ -111,7 +111,7 @@ public class DeyeSunHybridImpl extends AbstractOpenemsModbusComponent implements
 	private volatile Timedata timedata = null;
 
 	@Reference(policy = ReferencePolicy.DYNAMIC, policyOption = ReferencePolicyOption.GREEDY, cardinality = ReferenceCardinality.OPTIONAL)
-	private TimeOfUseController timeOfUseController;
+    private volatile TimeOfUseTariffController timeOfUseController;
 
 	private Config config;
 
-- 
2.47.0.windows.2