evcc-io / evcc

Sonne tanken ☀️🚘
https://evcc.io
MIT License
3.28k stars 595 forks source link

Home battery discharge control #10379

Closed GrimmiMeloni closed 10 months ago

GrimmiMeloni commented 11 months ago

Overview

Disable home battery discharge during fast mode/planner charging. The intention is to prevent home battery draining while a car is charging. The use case arises either during winter, or when charging at night based on planner. There's prior art in multiple forms (either through messaging or mqtt). However, the general ask comes up time and again, see #5826, #7979, #9090, https://github.com/evcc-io/evcc/discussions/9301, and probably more, so I feel it makes sense to drive towards "standardization" and I am willing to donate my time to do the required groundwork.

The way to keep the battery from discharging is vendor specific. Depending on capabilities of battery hardware the behavior can be achieved either through simple enabling/disabling the battery discharge, or controlling the discharge power of the battery, or by pinning the SOC of the home battery.

For clarity: Independent from the way the discharge is prevented, it generally means that ALL power for the home will be taken from the grid , not just the car charge.

Assumptions

Deliverables

  1. a generic interface for battery discharge control
  2. implementation of required logic in evcc's main control flow
  3. an example implementation of the interface based on Tesla Powerwall (as that's what I own and can test)

The intention is that ideally others can further contribute implementations of the interface for other hardware going forward.

Control Flow

Battery specific configuration options will differ, depending on how control is achieved, for example

Config Validation

API

BatteryDischarge // optional interface implemented by Batteries
- Enable(bool) 
- Enabled() bool //indicates if battery is currently allowed to discharge


Notes

Other considered but scratched solutions

GrimmiMeloni commented 10 months ago

@micw Danke. Ich hatte sowas im Hinterkopf, hatte es auf die schnelle aber nicht wieder gefunden.

Die Idee von SetLimit() ist erst entstanden als ich auch die Steuerung der Entladeleistung mit ins Konzept genommen habe. Vorher hatte ich ein binäres an/aus. Letzteres lässt sich aber auch über setLimit() mit entsprechenden Konventionen abbilden, daher habe ich es darauf hin vereinfacht, und das einfache an/aus als Schnittstelle verworfen. Meine Powerwall kann auch nur indirekt über den SOC vom Entladen abgehalten werden - aber auch die hätte ich ggf. über dieses Interface angebunden. Wenn der Konsens jetzt aber sowieso ist, im ersten Wurf nur eine Binäre Steuerung zu implementieren, dann können wir das Interface auch entsprechend einfach auslegen.

Implementierung muss natürlich pro Hardare erfolgen. Ob es ein neuer Gerätetyp wird, weiß ich ehrlich gesagt noch nicht. Ich werde mich jetzt hier zunächst auf die Steuerung der Entladung fokussieren.

GrimmiMeloni commented 10 months ago

Ich habe die Beschreibung jetzt nochmal aktualisiert. Im ersten Wurf nun reine Batterie Entladesteuerung. Wir können aber sicherlich zeitnah erweitern, wenn das hier gebaut ist.

Wäre toll wenn es nochmal jemand gegenlesen würde.

thebrainkafka commented 10 months ago

@GrimmiMeloni: Hi. Wie läuft es mit 10553? Kommst du voran?

andig commented 10 months ago

Es gibt jetzt einen Draft. Mir stellen sich noch ein paar Fragen:

premultiply commented 10 months ago

soll die Batterie wirklich immer gesperrt werden oder ist das z.B. von der aktuellen Entladeleistung abhängig?

Von der Leistung nicht. Höchstens noch vom SoC. Also bufferSoc, prioritySoc?? Aber das betrifft ja immer das gesamte Haus. Mir erschließt sich daher diese Sperrstrategie nicht wirklich.

Zwangsweises Laden bei preiswertem Strom leuchtet mir hingegen ein.

Also vielleicht die Entladesperre auch nur am Bezugspreis festmachen??

wie soll die Logik bei mehreren Batterien sein?

Alle gleich. Gilt immer für die ganze Site.

andig commented 10 months ago

Von der Leistung nicht.

Wenn ich eine 15kW PV habe und 1 Auto mit 11kW lädt gibts keinen Grund, die Batterie zu sperren. Aber umgekehrt- es gibt auch keinen Grund, es nicht zu tun. Fair point :)

Mir erschließt sich daher diese Sperrstrategie nicht wirklich.

Da bist Du jetzt relativ spät bei der Party. Was sollen wir machen? Der aktuelle Stand wäre als Experiment ok to merge.

premultiply commented 10 months ago

Dann jetzt bitte nochmal Butter bei die Fisch': Wie sieht die Logik bei den "Batteriesperrern" die das derzeit mit externen Tools erledigen aus und was genau soll damit bezweckt werden? Konkrete Beispiele bitte!

Optic00 commented 10 months ago

Fall: PV-Modus mit Ladeplaner. Auto wird um 1 Uhr nachts geladen weil Tibber Strom günstig ist. Hausbatterie sollte dann nicht entladen werden, weil der Preis vom Strom bis zum frühen vormittag wieder ansteigt. Vermutlich würde man sogar die Hausbatterie zusätzlich Laden weil aktuell kaum PV-Ertrag zu erwarten ist.

premultiply commented 10 months ago

Bitte konkret: Wie sieht die Logik dahinter aus? Nix vermutlich, könnte, sollte, würde, vielleicht sondern: Ich habe es so gebaut dass wenn, dann...

deadrabbit87 commented 10 months ago

So sieht meine Logik in NodeRed aus: grafik

Ich erreiche damit, dass beim Zielladen oder wenn der Strom günstig ist, die Entladung des Hausspeichers, wenn SoC < 50 % ,deaktiviert ist.

json ```json [ { "id": "9fc0f809.f00518", "type": "tab", "label": "disable-battery-discharging", "disabled": false, "info": "" }, { "id": "69d3ebb87d314db0", "type": "inject", "z": "9fc0f809.f00518", "name": "", "props": [ { "p": "payload" }, { "p": "topic", "vt": "str" } ], "repeat": "10", "crontab": "", "once": false, "onceDelay": 0.1, "topic": "", "payload": "", "payloadType": "date", "x": 150, "y": 300, "wires": [ [] ] }, { "id": "b51f2c57b46cfdf3", "type": "switch", "z": "9fc0f809.f00518", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "false" }, { "t": "true" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 510, "y": 120, "wires": [ [ "a824c7b1042d8991" ], [ "269d4a791ea63c01" ] ] }, { "id": "a824c7b1042d8991", "type": "debug", "z": "9fc0f809.f00518", "name": "Zielladen nicht aktiv", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 880, "y": 80, "wires": [] }, { "id": "832e19233b7c6bdf", "type": "buffer-maker", "z": "9fc0f809.f00518", "name": "", "specification": "spec", "specificationType": "ui", "items": [ { "name": "float", "type": "floatle", "length": 1, "dataType": "msg", "data": "payload" } ], "swap1": "swap16", "swap2": "", "swap3": "", "swap1Type": "swap", "swap2Type": "swap", "swap3Type": "swap", "msgProperty": "payload", "msgPropertyType": "str", "x": 970, "y": 240, "wires": [ [ "a5e2af6ad2457e4a" ] ] }, { "id": "a5e2af6ad2457e4a", "type": "buffer-parser", "z": "9fc0f809.f00518", "name": "", "data": "payload", "dataType": "msg", "specification": "spec", "specificationType": "ui", "items": [ { "type": "uint16be", "name": "data", "offset": 0, "length": 2, "offsetbit": 0, "scale": "1", "mask": "" } ], "swap1": "", "swap2": "", "swap3": "", "swap1Type": "swap", "swap2Type": "swap", "swap3Type": "swap", "msgProperty": "payload", "msgPropertyType": "str", "resultType": "value", "resultTypeType": "return", "multipleResult": true, "fanOutMultipleResult": false, "setTopic": true, "outputs": 1, "x": 490, "y": 340, "wires": [ [ "67062c1ccec57ec9" ] ] }, { "id": "67062c1ccec57ec9", "type": "modbus-write", "z": "9fc0f809.f00518", "name": "1034 (Ent-/Ladeleistung)", "showStatusActivities": true, "showErrors": true, "showWarnings": true, "unitid": "71", "dataType": "MHoldingRegisters", "adr": "1034", "quantity": "2", "server": "a1b432331279e425", "emptyMsgOnFail": false, "keepMsgProperties": false, "delayOnStart": false, "startDelayTime": "", "x": 750, "y": 340, "wires": [ [ "85bf2b359a49c492" ], [] ] }, { "id": "85bf2b359a49c492", "type": "debug", "z": "9fc0f809.f00518", "name": "Zielladen aktiv", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1020, "y": 320, "wires": [] }, { "id": "269d4a791ea63c01", "type": "api-current-state", "z": "9fc0f809.f00518", "name": "", "server": "8161678f.30be58", "version": 3, "outputs": 1, "halt_if": "", "halt_if_type": "str", "halt_if_compare": "is", "entity_id": "sensor.scb_battery_soc", "state_type": "str", "blockInputOverrides": false, "outputProperties": [ { "property": "payload", "propertyType": "msg", "value": "", "valueType": "entityState" }, { "property": "data", "propertyType": "msg", "value": "", "valueType": "entity" } ], "for": "0", "forType": "num", "forUnits": "minutes", "override_topic": false, "state_location": "payload", "override_payload": "msg", "entity_location": "data", "override_data": "msg", "x": 580, "y": 240, "wires": [ [ "adeebeb74855588a" ] ] }, { "id": "adeebeb74855588a", "type": "switch", "z": "9fc0f809.f00518", "name": "", "property": "payload", "propertyType": "msg", "rules": [ { "t": "gte", "v": "50", "vt": "str" }, { "t": "lt", "v": "50", "vt": "str" } ], "checkall": "true", "repair": false, "outputs": 2, "x": 830, "y": 140, "wires": [ [ "b32a4111c8bebdbe" ], [ "832e19233b7c6bdf" ] ] }, { "id": "b32a4111c8bebdbe", "type": "debug", "z": "9fc0f809.f00518", "name": "battery SoC > 50%", "active": true, "tosidebar": true, "console": false, "tostatus": false, "complete": "payload", "targetType": "msg", "statusVal": "", "statusType": "auto", "x": 1160, "y": 160, "wires": [] }, { "id": "06702b95ad5fd531", "type": "mqtt in", "z": "9fc0f809.f00518", "name": "", "topic": "evcc/loadpoints/2/planActive", "qos": "2", "datatype": "auto-detect", "broker": "d6c82b6abc04c385", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 180, "y": 100, "wires": [ [ "b51f2c57b46cfdf3" ] ] }, { "id": "3c63fbeac145b1e4", "type": "mqtt in", "z": "9fc0f809.f00518", "name": "", "topic": "evcc/loadpoints/1/planActive", "qos": "2", "datatype": "auto-detect", "broker": "d6c82b6abc04c385", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 180, "y": 40, "wires": [ [ "b51f2c57b46cfdf3" ] ] }, { "id": "f205ee073b655a5b", "type": "mqtt in", "z": "9fc0f809.f00518", "name": "", "topic": "evcc/loadpoints/1/smartCostActive", "qos": "2", "datatype": "auto-detect", "broker": "d6c82b6abc04c385", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 200, "y": 160, "wires": [ [ "b51f2c57b46cfdf3" ] ] }, { "id": "a5466c4ce4e90337", "type": "mqtt in", "z": "9fc0f809.f00518", "name": "", "topic": "evcc/loadpoints/2/smartCostActive", "qos": "2", "datatype": "auto-detect", "broker": "d6c82b6abc04c385", "nl": false, "rap": true, "rh": 0, "inputs": 0, "x": 200, "y": 220, "wires": [ [ "b51f2c57b46cfdf3" ] ] }, { "id": "a1b432331279e425", "type": "modbus-client", "name": "Kostal Plenticore", "clienttype": "tcp", "bufferCommands": true, "stateLogEnabled": false, "queueLogEnabled": false, "failureLogEnabled": false, "tcpHost": "192.168.188.109", "tcpPort": "1502", "tcpType": "DEFAULT", "serialPort": "/dev/ttyUSB", "serialType": "RTU-BUFFERD", "serialBaudrate": "9600", "serialDatabits": "8", "serialStopbits": "1", "serialParity": "none", "serialConnectionDelay": "100", "serialAsciiResponseStartDelimiter": "0x3A", "unit_id": 71, "commandDelay": 5, "clientTimeout": 1000, "reconnectOnTimeout": true, "reconnectTimeout": 2000, "parallelUnitIdsAllowed": false }, { "id": "8161678f.30be58", "type": "server", "name": "Home Assistant", "addon": true }, { "id": "d6c82b6abc04c385", "type": "mqtt-broker", "name": "", "broker": "192.168.188.15", "port": "1884", "clientid": "", "autoConnect": true, "usetls": false, "protocolVersion": "4", "keepalive": "60", "cleansession": true, "birthTopic": "", "birthQos": "0", "birthPayload": "", "birthMsg": {}, "closeTopic": "", "closeQos": "0", "closePayload": "", "closeMsg": {}, "willTopic": "", "willQos": "0", "willPayload": "", "willMsg": {}, "userProps": "", "sessionExpiry": "" } ] ```
premultiply commented 10 months ago

PV-Modus mit Ladeplaner. Auto wird um 1 Uhr nachts geladen weil Tibber Strom günstig ist. Hausbatterie sollte dann nicht entladen werden, weil der Preis vom Strom bis zum frühen vormittag wieder ansteigt. Vermutlich würde man sogar die Hausbatterie zusätzlich Laden weil aktuell kaum PV-Ertrag zu erwarten ist.

Ich sehe hier noch keinen Grund die Entladung zu unterbinden sondern neben dem Fahrzeug (auch) die Batterie aus dem Netz zu laden (was natürlich dort eine Entladesperre impliziert)?

Hieße also in Bezug auf bestehende die evcc-Funktion "Smartes Netzladen" dass bei Unterschreitung eines (unabhängig?) festgelegten Preises (auch) der Hausspeicher aus dem Netz vollgeladen wird.

Jetzt habe ich aber immer noch keine Strategie wann ich (nur) die Entladung des Speichers unterbinden sollte und somit bewusst sämtlichen Verbrauch den ich nicht mit Eigenerzeugung ausgleichen kann aus dem Netz einkaufe. :(

mdkeil commented 10 months ago

Jetzt habe ich aber immer noch keine Strategie wann ich (nur) die Entladung des Speichers unterbinden sollte und somit bewusst sämtlichen Verbrauch den ich nicht mit Eigenerzeugung ausgleichen kann aus dem Netz einkaufe. :(

Meine Strategie ist, sobald der Speicher bei günstigen Preisen ebenfalls geladen wird, dass die Entladesperre solange aktiv ist, bis der (Ladepreis / 0.8) < aktueller Preis ist, um die Speicherverluste einzupreisen.

Es gibt aber auch Nächte, die nicht ganz so günstig sind, das Auto aber dennoch geladen werden muss.. in diesem Zeitraum wird bei mir nur die Entladesperre gesetzt, solange das Auto geladen wird. Während der PV-Monate ist die Entladesperre nur aktiv, wenn der Battery-SOC < 40% ist.. Das ganze kann man noch auf die Spitze treiben und in dieser Autoladezeit nur die Entladung der Batterie auf z.B. 500W zu begrenzen.

andig commented 10 months ago

Ich sehe hier noch keinen Grund die Entladung zu unterbinden sondern neben dem Fahrzeug (auch) die Batterie aus dem Netz zu laden (was natürlich dort eine Entladesperre impliziert)?

Die Diskussion hatten wir eigentlich schon. Ich finde es jetzt ein bisschen unglücklich, damit- nachdem die Implementierung da ist- wieder von vorne anzufangen?

Das ganze kann man noch auf die Spitze treiben und in dieser Autoladezeit nur die Entladung der Batterie auf z.B. 500W zu begrenzen.

Das bedeutet aber auch, dass es für den UC Entladung (und nur um den geht es hier!), bisher keine allgemein gültige Strategie gibt.

premultiply commented 10 months ago

Es geht mir nur um die Logik. Da braucht es jetzt reale Beispiele der Logiken damit wir darauf als Essenz irgendetwas ableiten, exktrahieren und einbauen können. Sonst können wir hier an der Stelle bzgl. Entladesperre gleich abbrechen und uns der forcierten Ladung zuwenden.

premultiply commented 10 months ago

Meine Strategie ist, sobald der Speicher bei günstigen Preisen ebenfalls geladen wird, dass die Entladesperre solange aktiv ist, bis der (Ladepreis / 0.8) < aktueller Preis ist, um die Speicherverluste einzupreisen.

Sprich der Speicher wird bei (Ladepreis / 0.8) < aktueller Preis immer aus dem Netz geladen?

Es gibt aber auch Nächte, die nicht ganz so günstig sind, das Auto aber dennoch geladen werden muss.. in diesem Zeitraum wird bei mir nur die Entladesperre gesetzt, solange das Auto geladen wird. Während der PV-Monate ist die Entladesperre nur aktiv, wenn der Battery-SOC < 40% ist..

Sprich wenn ein Ladeplan aktiv ist und gerade mindestens ein Fahrzeug geladen wird aber der Hausspeicher durch die obige Bedingung nicht forciert geladen wird und der batterySoc < prioritySoc ist?

Das ganze kann man noch auf die Spitze treiben und in dieser Autoladezeit nur die Entladung der Batterie auf z.B. 500W zu begrenzen.

Wir machen ohnehin nur ja/nein aber davon abgesehen wäre das ziemlich willkürlich und bringt genau was?

mdkeil commented 10 months ago

Sprich der Speicher wird bei (Ladepreis / 0.8) < aktueller Preis immer aus dem Netz geladen?

Nein, ich lade z.B. für 14Cent den Speicher.. die Entladesperre bleibt dann solange aktiv, bis der aktuelle Strompreis mind. 17.5Cent erreicht. Der Preis, ab wann geladen wird, ist abhängig wie hoch die Preisspreizung über den Tag und die PV Prognose unter einen bestimmten Wert ist.

Sprich wenn ein Ladeplan aktiv ist und gerade mindestens ein Fahrzeug geladen wird aber der Hausspeicher durch die obige Bedingung nicht forciert geladen wird und der batterySoc < prioritySoc ist?

Könnte man so machen und den prioritySoc als Grenze nehmen.

Wir machen ohnehin nur ja/nein aber davon abgesehen wäre das ziemlich willkürlich und bringt genau was?

Das wäre imaginär der Hausverbrauch, der über den Speicher läuft.. aber bei 11kW aus dem Netz, machen 500W mehr oder weniger den Kohl auch nicht fett.

GrimmiMeloni commented 10 months ago

Wie sieht die Logik bei den "Batteriesperrern" die das derzeit mit externen Tools erledigen aus und was genau soll damit bezweckt werden?

Logik: Wenn entweder Modus schnell, oder der Planner aktiv ist, schalte die Entladung der Hausbatterie ab. Ziel: Ressourcenschonende Nutzung der Hausbatterie durch Unterbinden von unnötigen Ladezyklen, zur Optimierung der Gesamtlebensdauer.

premultiply commented 10 months ago

Generell? Also ganz bewusst die Kosten maximieren?

GrimmiMeloni commented 10 months ago

Generell? Also ganz bewusst die Kosten maximieren?

Kosten steigern sich dadurch nur marginal. Ich lade mein Auto im Winter eigentlich immer Nachts - die 200W die dann noch als Grundlast durchs Gebäude rauschen und zusätzlich aus dem Netz gezogen werden machen den Bock nicht fett. Gleichzeitig gehe ich davon aus, daß die längere Lebensdauer des Hausakkus das langfristig ausgleicht. Wenn jetzt mal eine Wärmepumpe ins Haus kommt, und die Grundlast deutlich steigt, muß ich sicherlich die Kosten/Nutzen Rechnung nochmal neu betrachten.

Aber mir geht es in diesem Szenario im Kern auch gar nicht um die Kosten oder wirtschaftliche Aspekte. Ich sehe es schlicht nicht als ökologisch an von einer Batterie in die andere Energie zu transferieren - ich erzeuge dadurch mehr Abnutzungseffekte als nötig. Ich lade mein Laptop ja auch nicht täglich die ersten 15% über eine unterdimensionierte Powerbank die ich dann häufig ersetzen müßte, sondern einfach komplett mit einem Netzteil.

micw commented 10 months ago

Außerdem handelt sich hier um den ersten Wurf zu dem Thema. Aus meiner Sicht ist die einfache Logik gut genug, um die prinzipiellen Teile umzusetzen und das eine oder andere BMS daran anzubinden. Dass die Kosten real damit steigen, sehe ich auch nicht. Das Auto lädt ja, wenn der Strom am günstigsten ist. Ohne Entladesperre wäre da der Akku schnell leer, vom günstigen Strom nimmt man entsprechend weniger mit. Wenn dann früh der Strom wieder teuer ist, hat man nix mehr im Akku.

In einem späteren Schritt kann man das ganze vielleicht noch zur Ladeplanung ausbauen, so dass die Hausbatterie preiswert geladen wird und bei teurem Strom entladen wird. Das kann aber beliebig komplex werden. Außerdem lohnt das tatsächlich nur bei sehr großen Differenzen im Strompreis, da das Speichern ja auch nicht umsonst ist. Ich hatte mal grob überschlagen, dass das Speichern pro kWh mit meinem Akku 9 Cent kostet (Anschaffungspreis durch Kapazität und Ladezyklen). Hinzu kommen die Ladeverluste, die je nach Strompreis nochmal um die 2-4 Cent liegen dürfen.

mdkeil commented 10 months ago

Ich hatte mal grob überschlagen, dass das Speichern pro kWh mit meinem Akku 9 Cent kostet (Anschaffungspreis durch Kapazität und Ladezyklen).

Das betrachte ich bei mir gar nicht, da der Speicher bereits bezahlt ist.. zudem werden es meiner Ansicht nach nicht die Ladezyklen sein, die am Ende das Problem darstellen werden.. aber das zeigen sicherlich erst Langzeitbetrachtungen.

premultiply commented 10 months ago

Oha. Ich muss jetzt ganz stark sein und verkneife mir alle Kommentare. Wir sammeln hier ja einfach nur 😅

Nur etwas zum Ladeplaner:

Der Ladeplaner sagt nichts darüber aus ob der Netzbezug wirklich wirtschaftlich günstiger als der Eigenverbrauch ist. Wenn ein Fahrzeug in einer vglw. teuren Phase geladen werden muss sind auch die lokalen Preistäler nicht automatisch "günstig". Der Plan setzt nur Kostenoptimierung unter den Rahmenbedingungen um.

mdkeil commented 10 months ago

Genau deshalb kann man nicht automatisch den Planer mit dem Laden der Batterie verknüpfen :) ..da müsste man dann wieder einen separaten "Hausbatterie-Planer", der vom "Auto-Ladeplaner" entkoppelt ist.

LegoLusch commented 10 months ago

Fall: PV-Modus mit Ladeplaner. Auto wird um 1 Uhr nachts geladen weil Tibber Strom günstig ist. Hausbatterie sollte dann nicht entladen werden, weil der Preis vom Strom bis zum frühen vormittag wieder ansteigt. Vermutlich würde man sogar die Hausbatterie zusätzlich Laden weil aktuell kaum PV-Ertrag zu erwarten ist.

Ich würde sogar sagen, dass das der Standardfall sein sollte, weil man sich sonst unnötig Ladezyklen auf die Batterie schaufelt (vor allem bei kleinen Speichern)

GrimmiMeloni commented 10 months ago

Danke in die Runde für die Zusammenstellung der Use Cases.

@andig @premultiply @naltatis - aus meiner Sicht ist es wichtig jetzt mal von Euch als Maintainer ein klares Ja oder Nein zu dieser Idee zu bekommen. Die Basis in #10553 ist vorhanden, spätestens jetzt braucht es aber eine Entscheidung. So lange die nicht da ist, macht es keinen Sinn mit Implementierungen für die Hardware zu starten.

premultiply commented 10 months ago

LGTM

andig commented 10 months ago

Sollen wir hier als "Battery control" weiter machen oder das auf ein neues Issue verlagern?

micw commented 10 months ago

Ich fände neue Tickets pro Sub-Feature mit Verweis auf dieses hier ganz gut. Ansonsten geht das eigentliche Feature in Diskussionen unter. Ich lege gleich mal eins an für ModBus-TCP BMS (z.B. Victron).

andig commented 10 months ago

Mir ging es eher um die Steuerungslogik für die Ladung da ein Großteil der Diskussion oben darum ging. Aber wie ihr wollt...

andig commented 10 months ago

Ich fände neue Tickets pro Sub-Feature mit Verweis auf dieses hier ganz gut. Ansonsten geht das eigentliche Feature in Diskussionen unter. Ich lege gleich mal eins an für ModBus-TCP BMS (z.B. Victron).

Statt Tickets gerne auch direkt die entsprechenden PRs. Aus dem Kernteam wird sich niemand damit auseinander setzen- wir haben die entsprechenden Geräte nicht im Zugriff. Es geht ja nur noch um die Anpassung der entsprechenden Templates. Ggf. kann die Lösung zu https://github.com/evcc-io/evcc/issues/10716 dann als Kopiervorlage dienen.

premultiply commented 10 months ago

Und ohne die Euphorie groß bremsen zu wollen, aber so realistisch muss man sein: Ich gehe nicht davon aus dass dies bei der Mehrzahl (oder allen??) Batteriewechselrichtern mittels Templates oder gar einfachen Custom-Konfigs funktionieren wird, da dafür eher regelmäßig gleich mehrere Register gelesen, verändert, gemerkt und auch wieder zurückgesetzt werden müssen. Deutlich komplizierter als bei den dämlichsten Wallbox-APIs. Es hat sich ja nichts daran verändert dass die wenigstens Systeme vom Hersteller für solche Funktionen nicht wirklich vorgehen sind. Oft müssen daher regelmäßig zu bedienende Testfunktionen und andere krude Umwege und temporäre Modifikation von Gerätegrundeinstellungen dafür herhalten. Daher dürfte der Weg nur über eine jeweils eigene go-Implementierung führen.

thebrainkafka commented 10 months ago

Das Schließen der #10716 ist nun aber etwas konträr der Aussage dass dies ggf als template dienen kann, und wenn überhaupt von der Community, nicht dem Kernteam, erstellt werden müsste. Nur wenn closed funktioniert das ja eher nicht.

Ist ein super Projekt und ich bin total happy damit. Läuft auch 1a und fixes kommen adhoc. Danke an dieser Stelle nochmals! Manchmal sind Eure Kernteamentscheidung/Aussagen aber nach außen schwer nachvollziehbar und wirken teilweise rude. Hoffentlich hat sich GrimmiMelonies input gelohnt. Ich verstehe gerade wird eh nix werden für die Mehrheit.


Nachtrag. Danke für die zusätzliche Erklärung in 10716

premultiply commented 10 months ago

@thebrainkafka Vom schnellen wiederholten Erstellen von Wunsch-Issues, fleissigem Daumen rauf und runter und viel Textoutput wird eben trotzdem niemand diese Arbeit für dich machen oder es sonst wie irgendwie vorwärts gehen. Mal ganz davon abgesehen dass noch nicht einmal klar ist ob dein System überhaupt entsprechende und kompatible Ansatzpunkte bietet.

Von daher kann und wird sich nur jemand an das Thema wagen können die/der entsprechende Fähigkeiten und vor allem ein passendes Testobjekt im persönlichen Zugriff hat und auch noch die nötige Zeit und Muße hat dies umzusetzen.

Vgl. was @GrimmiMeloni hier im ersten Post geschriben hat, der dieses Thema sehr dankenswerter Weise bisher real vorangetrieben hat.

an example implementation of the interface based on Tesla Powerwall (as that's what I own and can test)

andig commented 10 months ago

an example implementation of the interface based on Tesla Powerwall (as that's what I own and can test)

Das ist super. Wir brauchen aber auch ein Template.

Manchmal sind Eure Kernteamentscheidung/Aussagen aber nach außen schwer nachvollziehbar und wirken teilweise rude.

Danke fürs Feedback! Da haben wir Potenzial...

micw commented 10 months ago

Ich gehe nicht davon aus dass dies bei der Mehrzahl (oder allen??) Batteriewechselrichtern mittels Templates oder gar einfachen Custom-Konfigs funktionieren wird, da dafür eher regelmäßig gleich mehrere Register gelesen, verändert, gemerkt und auch wieder zurückgesetzt werden müssen

Dann lasst uns das noch mal zusammentragen und schauen, wie generisch das geht. Was wäre da der geeignete Kanal? Eine bestehende oder neue Diskussion dazu?

Beim Victron müsste man für "laden" und "entladen/normalbetrieb" nur ein Register (Min SoC) schreiben. Für "Entladesperre" den current SoC lesen und in Min SoC schreiben.

premultiply commented 10 months ago

Das ist aber etwas einfach gedacht, oder?

Du musst also in jedem Fall erstmal den ursprünglich vom Anwender konfigurierten "MinSoC" vom WR abfragen, diesen irgendwo zwischenspeichern (soll ja später auch wieder eingestellt werden, oder?) dann einen neuen temporären nicht fixen Wert (aktueller SoC) setzen, sich irgendwie merken dass man jetzt gerade in der verordneten, automatischen Sperre ist (und nicht der Anwender selbst manuell etwas anderes eingestellt hat) und anschließend das ganze sicher wieder zurückschreiben wenn wieder Normalbetrieb ist. Das Ganze am besten auch noch so dass es Neustarts überlebt und immer in einem definierten, nachvollziehbaren Zustand ist ;)

mdkeil commented 10 months ago

Alleine bei Victron gibt es mehrere Möglichkeiten der Umsetzung.. ich setze z.B. via MQTT einfach MaxDischargePower auf 0, wenn ich eine Entladesperre habe möchte.. Dies entspricht im gui die Einstellung unter ESS "limit Inverter Power".

premultiply commented 10 months ago

Ok, und wenn sie wieder aufgehoben werden soll? Was setzt du dann "einfach"? Wenn's kein Fixwert ist der überall und immer gleich ist ist's blöd.

mdkeil commented 10 months ago

Um die Sperre aufzuheben wird -1 gesetzt, was die Limitierung deaktiviert.

micw commented 10 months ago

Die Register im Beispiel stimmen nicht, waren nur als Beispiel zusammengewürfelt. Man kann es natürlich auch beliebig kompliziert machen, dann braucht man eine spezfische Implementierung. "MaxDischargePower auf 0" kannte ich noch nicht, das macht es am Ende noch einfacher, weil man nix lesen muss.

Beispiel Victron: Normalbetrieb = MinSoc auf 5% (oder 10% oder was immer man halt haben will), MaxDischargePower auf -1 Ladesperre = MinSoc auf 5% (oder 10% oder was immer man halt haben will), MaxDischargePower auf 0 Laden = MinSoc auf 100%, MaxDischargePower auf 0

d.h. 2 Register auf statische, für den jeweiligen Modus passende Werte setzen.

PeterPablo commented 10 months ago

Ich habe bei SofarSolar vor einigen Tagen bezüglich des Themas eine Supportanfrage gestellt, bisher aber noch keine Rückmeldung erhalten. Ich besitze einen Batteriespeicher GTX 3000-H. Betrieben wird er in meinem Fall an einem Hybrid-Wechselrichtern HYD 5-20KTL-3PH. Dafür gibt es bisher keine native evcc-Implementierung, deswegen nutze ich aktuell den Umweg über mqtt mit HomeAssistant. Das sollte für dieses Thema keine Ausschlusskriterium sein, falls man es schafft mqtt-Befehle für die drei von @micw genannten Zustände zu realisieren. (Im HomeAssistant wird die Integration "Solarman" mit der Konfiguration "sofar_g3hyd.yaml" genutzt. ref. https://github.com/evcc-io/evcc/issues/5727#issuecomment-1470218467) Falls zu wenig konkret und daher als off-topic eingestuft, dann markiert den Kommentar einfach als solchen. No hard feelings, ich versuche im Rahmen meiner Möglichkeiten beim Design der API und Realisierung der ersten Testimplementierungen zu helfen.

micw commented 10 months ago

Ich besitze einen Batteriespeicher GTX 3000-H

Wie würde man bei diesem denn die 3 Zustände erreichen (also mit welcher Konfiguration)?

PeterPablo commented 10 months ago

Die im von mir eben verlinkten Issue hinterlegte Excel-Tabelle bietet für SofarSolar einen Ansatz:

<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html40">

104C | BatConfig_Current_Discharge_Limit | U16 | 0,01 | A | 0 | 65535 | RW | Battery Parameter-Maximum discharge current limit | End user | 1 | 4096 -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- | -- 104D | BatConfig_Depth_of_Discharge | U16 | 1 | % | 1 | 90 | RW | Dod indicates the max discharge power, when SOC<1-DOD, inverter will stop power discharge , inverter will stop power discharge caused by other issues.        DOD<=EOD | End user | 1 | 8192

Der "DoD" entspricht im Beispiel von @micw dem "MinSoc". Die Korrespondenz zu "MaxDischargePower" ist meines Erachtens nach "BatConfig_Current_Discharge_Limit". Hier ist es ein Strom und keine Leistung, das muss also noch über eine Skalierung von einer Leistung zurückgerechnet werden.

premultiply commented 10 months ago

Dafür gibt es bisher keine native evcc-Implementierung,

Klar gibt es die.

deswegen nutze ich aktuell den Umweg über mqtt mit HomeAssistant.

Kann man machen, muss man aber nicht. Geht auch nativ.

PeterPablo commented 10 months ago

Vgl. mein verlinkter Kommentar. Ich war hier zu unspezifisch: Keine native evcc-Implementierung, die mittels TCP/IP und dem LSW3-Dongle arbeitet. Die von u.a. @cschlipf erfolgreich getetstete Implementierung benötigt zusätzliche RS485-Modbus-Hardware die ich bisher nicht habe. Falls ich zunächst nur mit solcher in puncto Batterie-Kontrolle vorankomme würde ich mir selbige zulegen. Das ist nun aber tatsächlich off-topic :-)

cschlipf commented 10 months ago

Vgl. mein verlinkter Kommentar. Ich war hier zu unspezifisch: Keine native evcc-Implementierung, die mittels TCP/IP und dem LSW3-Dongle arbeitet. Die von u.a. @cschlipf erfolgreich getetstete Implementierung benötigt zusätzliche RS485-Modbus-Hardware die ich bisher nicht habe. Falls ich zunächst nur mit solcher in puncto Batterie-Kontrolle vorankomme würde ich mir selbige zulegen. Das ist nun aber tatsächlich off-topic :-)

Ich bin mittlerweile auf den LSE-3 Dongle (Ethernet) umgesteigen. Dieser kann natives ModBus TCP über den Port 8899 (siehe auch https://github.com/evcc-io/evcc/discussions/9598). Im Gegensatz zu allen RS485 Sticks, die ich ausprobiert habe, läuft der LSE-3 absolut zuverlässig. Ich denke da braucht man keine native Implementierung mehr. Man muss nur den richtigen Stick einsetzen.

steve0564 commented 10 months ago

Wird mit diesem neuen Feature auch die Mindestladung mit berücksichtigt. Je nach Einstellung zuzelt es da auch den Hausakku leer....

cschlipf commented 10 months ago

Ich frage mich ob das hier wirklich im Scope von EVCC ist? Wir automatisieren damit nicht die Autoladung, sondern den Wechselrichter und hier hat jeder andere APIs und Eigenheiten.

Meinen SofarSolar HYD 10 KTL muss ich so erst in den Passive Mode bringen (ein Register mit mehreren werten, von denen eines davon der Passive Mode ist), dann die Lade/Entladeleistung auf 0 stellen, und da das hier nur im Bulk geht, dann die geänderten Werte Committen. Beim Schreiben muss man dazu 'Holdings', statt 'Holding' als Input Type nutzen. Und das ist nur ein Wechselrichter. Wie soll EVCC das für alle möglichen Varianten machen?

Und z.B. mit Home Assistant mit EVCC und Wechselrichter Einbindung (Solax Modbus integration) geht dies sehr einfach. Sobald EVCC auf 'schnell' umschaltet, wird der Speicher deaktiviert. Wenn Auto voll oder der Modus von schnell zu was anderem gewechselt wird, wieder beendet.

Wer meine Automation will kann sie gerne haben. Wer aber EVCC zum laufen gebracht hat, bekommt das auch locker mit Home Assistant hin.

image image

VolkerK62 commented 10 months ago

Was bewirkt der Eintrag batteryDischargeControl: true in der site? Ich vermute, dann wird unter bestimmten Bedingungen der Wert von evcc/stite/batteryMode geändert? Welche Bedingungen sind das? Nur schnell und plan active?

steve0564 commented 10 months ago

Wird mit diesem neuen Feature auch die Mindestladung mit berücksichtigt. Je nach Einstellung zuzelt es da auch den Hausakku leer....

Ich zitiere mich bei der Gelegenheit gleich mal selbst....