SolarForecast - Solare Prognose (PV Erzeugung) und Verbrauchersteuerung: Unterschied zwischen den Versionen
(42 dazwischenliegende Versionen von 3 Benutzern werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
{{Baustelle}} | {{Baustelle}} | ||
{{Hinweis| | {{Hinweis|Die vorliegende Wiki-Seite befindet sich im Aufbau.}} | ||
{{Infobox Modul | {{Infobox Modul | ||
|ModPurpose=Solarprognose und Verbrauchersteuerung | |ModPurpose=Solarprognose und Verbrauchersteuerung | ||
|ModType= | |ModType=d | ||
|ModCmdRef=76_SolarForecast | |ModCmdRef=76_SolarForecast | ||
|ModFTopic=117864 | |ModFTopic=117864 | ||
Zeile 15: | Zeile 15: | ||
[[Datei:sfc1.png|right|thumb|300px|grafische Ansicht SolarForecast]] | [[Datei:sfc1.png|right|thumb|300px|grafische Ansicht SolarForecast]] | ||
::* zur Gewinnung solarer | ::* zur Gewinnung solarer Prognosewerte können die SolCast API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden | ||
::* | ::* optionale KI Unterstützung bei Verwendung von DWD Stahlungswerten | ||
::* Wetterdaten werden über DWD Wetter-Stationen integriert | ::* Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert | ||
::* Sprachensupport EN | DE | ::* Sprachensupport EN | DE | ||
Zeile 30: | Zeile 30: | ||
::* eine integrierte und umfangreich anpassbare Verbrauchersteuerung vereint die PV Prognose basierte Einplanung der Verbraucher mit der Möglichkeit die Verbraucher durch das Modul schalten zu lassen und dadurch auf PV Erzeugungsschwankungen automatisch dynamisch zu reagieren | ::* eine integrierte und umfangreich anpassbare Verbrauchersteuerung vereint die PV Prognose basierte Einplanung der Verbraucher mit der Möglichkeit die Verbraucher durch das Modul schalten zu lassen und dadurch auf PV Erzeugungsschwankungen automatisch dynamisch zu reagieren | ||
::* Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen | |||
::* trotz der hohen Komplexität wird dem Anwender durch eine "Guided Procedure" bei der Gerätedefinition der Einstieg erleichtert und damit ein optimales Benutzerlebnis geboten | ::* trotz der hohen Komplexität wird dem Anwender durch eine "Guided Procedure" bei der Gerätedefinition der Einstieg erleichtert und damit ein optimales Benutzerlebnis geboten | ||
Zeile 42: | Zeile 44: | ||
== Definition == | == Definition == | ||
Die Hilfe zu dem Modul ist über "help SolarForecast de" aufrufbar. | Die Hilfe zu dem Modul ist über "help SolarForecast de" aufrufbar. | ||
<br> | |||
== Wie funktioniert die Verbrauchsprognose? == | |||
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnte. | |||
Zu diesem Zweck verwendet das Modul die Meterdaten aus dem Reading ''currentMeterDev''. Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher ''pvHistory'' für 31 Tage gespeichert. | |||
Mit dem Kommando "get ... pvHistory [Tag]" wird der Inhalt aufgelistet. Die Schlüssel ''confc'', ''con'' und ''gcon'' zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages. | |||
Die Stunde "99" zeigt die Summen dieser Schlüsssel für den Tag: | |||
99 => etotal: , pvfc: 782, pvrl: 0, rad1h: - | |||
confc: 14540, con: 13873, gcon: 13873, gfeedin: 0 | |||
batintotal: , batin: 0, batouttotal: , batout: 0 | |||
batmaxsoc: -, batsetsoc: - | |||
wid: , wcc: , wrp: , pvcorrf: , dayname: So | |||
cyclescsm01: 0 | |||
cyclescsm02: 0 | |||
cyclescsm03: 0 | |||
cyclescsm04: 1, hourscsme04: 0.00 | |||
cyclescsm05: 0 | |||
cyclescsm06: 0 | |||
cyclescsm07: 1, hourscsme07: 0.00 | |||
cyclescsm08: 1, hourscsme08: 0.00 | |||
cyclescsm09: 1, hourscsme09: 0.03 | |||
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel ''pvrl'' erkennen kann. | |||
Wie wird nun die Verbrauchsprognose ''confc'' erstellt? | |||
Aus den gespeicherten con-Werten der pvHistory wird der Durchschnitt der vergangenen Tage ermittelt und für den kommenden Tag angewendet. Dabei geht per default jeder historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut '''affectConsForecastIdentWeekdays = 1''' kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle. | |||
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile ''Verbrauch'' sowie in diversen Readings wie | |||
* '''RestOfDayConsumptionForecast''' (Verbrauchsprognose für den Rest des Tages) | |||
* '''NextHours_Sum04_ConsumptionForecast''' (Verbrauchsprognose für die nächsten 4 Stunden) | |||
* '''Tomorrow_ConsumptionForecast''' (Verbrauchsprognose für den kommenden Tag) | |||
angezeigt. | |||
Weitere Aggregationen kann man sich über das Attribut '''ctrlStatisticReadings''' bei Bedarf zuschalten: | |||
* '''conForecastTillNextSunrise''' - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang | |||
* '''todayConForecastTillSunset''' - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang | |||
* '''todayConsumptionForecast''' - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24) | |||
<br> | |||
== modulinterne Datenstrukturen == | |||
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen. | |||
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis '''../fhem/FHEM/FhemUtils''' und heißen '''.*_SolarForecast_.*'''. | |||
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut '''ctrlInterval''' eingestellt. | |||
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden. | |||
<pre> | |||
get ... pvHistory [Tag] | |||
</pre> | |||
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde "99" die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält. | |||
Bei Badarf lässt sich mit dem Befehl "set ... reset pvHistory" der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit "set ... reset pvHistory <Tag>" (Daten eines bestimmten Tages löschen) bzw. "set ... reset pvHistory <Tag> <Stunde>" (Daten der Stunde eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden. | |||
<pre> | |||
get ... pvCircular | |||
</pre> | |||
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität. | |||
Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt. | |||
<pre> | |||
get ... nextHours | |||
</pre> | |||
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde. | |||
<pre> | |||
get ... solApiData | |||
</pre> | |||
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere. | |||
<pre> | |||
get ... valCurrent | |||
</pre> | |||
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten. | |||
<pre> | |||
get ... valConsumerMaster [XX] | |||
</pre> | |||
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer '''XX''' kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden '''consumerXX''' Attribut. | |||
Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind: | |||
* epieces - prognostizierte Energiescheiben pro Betriebsstunde | |||
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem [[#Verbrauchersteuerung_-_Registrieren_und_visualisieren_von_Verbrauchern|Abschnitt]]. | |||
=== Schnittstelle für Modulautoren bzw. eigenen Code === | |||
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden. | |||
Dazu stehen die folgenden Funktionen zur Verfügung. | |||
::* [FHEM::SolarForecast::]CurrentVal ($defs{'<Name>'}, '<Key>', <default>) <br> entspricht der Abfrage mit "get ... valCurrent". | |||
::* [FHEM::SolarForecast::]HistoryVal ($defs{'<Name>'}, '<Day>', '<HoD>', '<Key>', <default>) <br> entspricht der Abfrage mit "get ... pvHistory". | |||
::* [FHEM::SolarForecast::]CircularVal ($defs{'<Name>'}, '<HoD>', '<Key>', <default>) <br> entspricht der Abfrage mit "get ... pvCircular". | |||
::* [FHEM::SolarForecast::]NexthoursVal ($defs{'<Name>'}, <nhr>, '<Key>', <default>) <br> entspricht der Abfrage mit "get ... nextHours". | |||
::* [FHEM::SolarForecast::]ConsumerVal ($defs{'<Name>'}, '<c>', '<Key>', <default>) <br> entspricht der Abfrage mit "get ... valConsumerMaster". | |||
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut ''ctrlUserExitFn'') kann darauf verzichtet werden. | |||
Die Bedeutung der Platzhalter sind: | |||
<pre> | |||
<Name> - Name des SolarForecast Devices | |||
<Day> - abzufragender Tag (01 - 31) | |||
<c> - Nummer des Verbrauchers (01, 02, 03, 04,...) | |||
<HoD> - abzufragende Stunde (01 - 24, 99) | |||
<nhr> - nächste Stunde (NextHour00, NextHour01,...) | |||
<Key> - der abzufragende Schlüssel | |||
<default> - def default-Rückgabewert | |||
</pre> | |||
<br> | |||
== Backup und Wiederherstellung der Moduldaten == | |||
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis '''../fhem/FHEM/FhemUtils''' mit folgenden Inhalten: | |||
<pre> | |||
PVH_SolarForecast_<name> - PV History | |||
PVC_SolarForecast_<name> - PV Circular | |||
PVCfg_SolarForecast_<name> - PV Anlagenkonfiguration | |||
PVCsm_SolarForecast_<name> - Consumer Status | |||
ScApi_SolarForecast_<name> - Werte aus verwendeter API | |||
AItra_SolarForecast_<name> - KI Entscheidungsquelle (trainierte Daten) | |||
AIraw_SolarForecast_<name> - KI Input Daten = Raw Trainigsdaten | |||
</pre> | |||
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist '''<name>''' der Name des SolarForecast Devices. | |||
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt. | |||
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. | |||
Der Vorgang ist mit verbose=3 im Log protokolliert: | |||
<pre> | |||
2023.10.02 09:57:07.967 3: SolCast6 - cached data "pvhist" restored | |||
2023.10.02 09:57:07.969 3: SolCast6 - cached data "circular" restored | |||
2023.10.02 09:57:07.970 3: SolCast6 - cached data "consumers" restored | |||
2023.10.02 09:57:07.970 3: SolCast6 - cached data "solcastapi" restored | |||
2023.10.02 09:57:07.974 3: SolCast6 - cached data "aitrained" restored | |||
2023.10.02 09:57:07.976 3: SolCast6 - cached data "airaw" restored | |||
</pre> | |||
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar. | |||
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden: | |||
<br> | |||
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden) | |||
* 2. FHEM stoppen | |||
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien) | |||
* 4. starten von FHEM (bestimmte Daten werden automatisch importiert) | |||
* 5. mit dem Befehl "set <name> plantConfiguration restore" die Anlagenkonfiguration wiederherstellen | |||
<br> | |||
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen: | |||
<br> | |||
* 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden) | |||
* 2. FHEM stoppen | |||
* 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien) | |||
* 4. umbenenen der Dateien, wobei <name> durch den Namen des neuen SolarForecast Devices ersetzt wird | |||
* 5. starten von FHEM (die Daten werden automatisch importiert) | |||
* 6. mit dem Befehl "set <name> plantConfiguration restore" die Anlagenkonfiguration wiederherstellen | |||
<br> | |||
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien "PVCsm_SolarForecast_<name> " bzw. "ScApi_SolarForecast_<name>" von dem Verfahren auszuschließen. | |||
<br> | |||
== dynamische SoC Steuerung für Solarbatterien == | |||
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes. | |||
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimalisiert werden. | |||
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können. | |||
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes '''ctrlBatSocManagement''' z.B. mit diesen Angaben: | |||
ctrlBatSocManagement lowSoc=10 upSoC=50 maxSoC=98 careCycle=20 | |||
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann. <bR> | |||
Das Reading '''Battery_OptimumTargetSoC''' enthält den vom Modul berechneten optimalen Mindest-SoC. | |||
Das Reading '''Battery_ChargeRequest''' wird auf '1' gesetzt, wenn der aktuelle SoC unter den Mindest-SoC gefallen ist. | |||
Die Schlüssel '''lowSoc''' und '''upSoC''' sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll. | |||
Der Schlüssel '''maxSoC''' stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut. <br> | |||
Der maxSoC in Verbindung mit dem durch '''careCycle''' definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann. | |||
Durch die Modullogik erfolgt eine 5%ige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc. | |||
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen. | |||
Dadurch ist immer genügend "Freiplatz" in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt. | |||
=== Nutzung von batteryTrigger === | |||
Ergänzt werden die Möglichkeiten durch das set-Kommando: | |||
batteryTrigger <1on>=<Wert> <1off>=<Wert> [<2on>=<Wert> <2off>=<Wert> ...] | |||
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %). | |||
Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden. | |||
Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading '''batteryTrigger_X = on''' erstellt/gesetzt. | |||
Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading '''batteryTrigger_X = off''' erstellt/gesetzt. | |||
Alle Triggerpunkte können mit dem set-Befehl: | |||
reset batteryTriggerSet | |||
wieder gelöscht werden. | |||
<br> | |||
== Verbrauchersteuerung - Registrieren und visualisieren von Verbrauchern == | |||
Das Modul gestattet es beliebige Verbraucher (Devices) über die Attribute '''consumerXX''' zu registrieren. Durch die Registrierung wird dem Modul der Namen des Devices sowie dessen Eingenschaften durch die Angabe von Schlüssel-Wert Paaren bekannt gemacht. | |||
Nach der Registrierung können die Verbraucher durch das Modul genutzt werden: | |||
* es erfolgt eine Planung der Ein- und Ausschaltzeiten abhängig von der solaren Prognose in Bezug zu den Leistungsdaten des Verbrauchers sowie der anderen registrierten Consumer | |||
* das Modul kann die Ein- und Ausschaltsteuerung der Consumer übernehmen (optional) | |||
* die aktuellen Status (Verbrauchsdaten) werden in der Energiefußgrafik dargestellt | |||
* das Modul lernt mit der Zeit das Verbrauchsverhalten der registrierten Verbraucher | |||
Um einen Verbaucher zu registrieren, wird ein freies '''consumerXX''' Attribut, zum Beispiel consumer01, gesetzt. | |||
=== Beispiel Registrierung eines Shelly Devices === | |||
Nachfolgendes Beispiel zeigt eine Registrierung eines Heizlüfters der an einem Shelly Zwischenstecker angeschlossen ist und durch das Modul gesteuert werden soll. Dabei soll die Steuerung nicht nur von der Solarprognose, sondern auch von der Raumtemperatur abhängig erfolgen. Im Beispiel wird das Attribut consumer03 verwendet. | |||
Zwingende Angaben sind | |||
consumerXX <Device Name> type=<type> power=<power> | |||
Alle Angaben können mehrzeilig eingegeben werden. Die Schlüssel-Werte Paare sind jeweils durch ein Leerzeichen getrennt. | |||
consumerXX Shelly.shellyplug3 type=heater power=1700 | |||
In dem Beispiel ist Shelly.shellyplug3 der Devicename des Shellies in FHEM. Der Schlüssel '''type''' definiert die Art des Verbrauchers. In der Hilfe sind die möglichen Typen aufgeführt. Den richtigen Typ anzugeben hat Einfluß auf die spätere Einschätzung des Leistungsverhaltens über die Laufzeit. So wird von einem '''heater''' gleich nach dem Einschalten die angegebene Nominalleistung abgerufen und wird über die Zeit gleichbleiben. | |||
Eine Waschmaschine oder ein Trockner rufen über ihre Laufzeit die Leistung nicht gleichbleibend ab und ändern die Leistungsaufnahme sich über die Einschaltdauer. | |||
Die Angabe von '''power''' definiert die Nominalleistung (Watt) die für den Verbraucher laut Typenschild vom Hersteller angegeben wird. Diese Angabe wird vom Modul bei der Planung der Einschaltzeiten verwendet indem die Nominalleistung in das Verhältnis zur Solarprognose bzw. Verbrauchsprognose des Netzes gesetzt wird. Weiterhin ist dieser Wert auch wichtig um später den tatsächlichen Einschaltzeitpunkt auszuführen wenn ein realer PV Überschuss festgestellt wird. | |||
Es ist möglich '''power=0''' zu setzen. Das führt dazu, dass die Planung und letztendlich auch der Schaltvorgang unabhängig von der Solarprognose bzw. einem realen PV Überschuss vorgenommen wird. | |||
Es werden weitere Schlüsseleingaben vorgenommen: | |||
:<code>Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off</code> | |||
Mit dem Schlüssel '''icon''' legt man ein Icon fest welches in der Grafik für den Verbraucher verwendet wird. Der '''mode''' definiert die Art und Weise der Einplanung: | |||
;can: Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuss. Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuss. | |||
;must: Der Verbaucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuss vorhanden sein wird. Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuss. | |||
Mit '''notbefore''' wird festgelegt, dass die Einplanung nicht vor neun Uhr morgens erfolgen soll auch falls schon genügend PV Überschuss vorhanden wäre. Der Schlüssel '''mintime''' definiert die Einplanungsdauer des Verbrauchers in Minuten im einfachsten Fall. Die hier verwendete Angabe '''SunPath''' ist ein Spezialfall. Der Verbraucher soll von Sonnenaufgang bis Sonnenuntergang eingeschaltet werden, wobei die Angabe von 60 bzw. -60 ein relative Verschiebung bewirken. Dadurch wird das Einschalten 60 Mintuen nach Sonnenaufgang bis 60 Minuten vor Sonnenuntergang geplant. | |||
Die Schlüssel '''on''' und '''off''' teilen dem Modul die jeweiligen gültigen Ein- und Aus-Kommandos mit, mit dem das (Shelly)Device geschaltet werden kann. Werden diese Schlüssel nicht oder "leer" (on= off=) angegeben, erfolgt kein Schalten durch das Modul, nur die Planungsdaten werden erzeugt. | |||
Die Verbraucherregistrierung wird mit weiteren Angaben ergänzt um das gewünschte Verhalten zu erreichen: | |||
Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off etotal=relay_0_energy_Wh:Wh | |||
pcurr=relay_0_power:W auto=automatic interruptable=og.bad.wandthermostat:diff-temp:[0-9]\.[0-9]:0.2 | |||
In '''etotal''' wird der Readingname des Shelly Devices angegeben welches die Summe der verbrauchten Energie (Wh/kWh) des Consumer Device liefert. D.h. es muß ein sich stetig erhöhender Wert sein. Durch die Auswertung dieses Readings ermittelt das Modul die in bestimmten Zeiteinheiten verbrauchte Energie zur weiteren Verwendung. | |||
In dem Shelly Device ist per default ein solches Reading nicht vorhanden. Über userReadings kann in dem Device Shelly.shellyplug3 ein Reading für etotal erzeugt werden: | |||
userReadings relay_0_energy_Wh:relay_0_energy.* monotonic { sprintf "%.0f", ReadingsVal ($name, 'relay_0_energy', 0) / 60 } | |||
Der Schlüssel '''pcurr''' enthält das Reading in Shelly.shellyplug3 welches den aktuellen Energieverbrauch liefert. | |||
'''auto''' enthält das Reading in Shelly.shellyplug3 welches zur Freigabe/Sperrung der autmatischen Schaltung durch das Modul dienen soll. Ist das angegebene Reading (im Beispiel "automatic") im Shelly.shellyplug3 nicht vorhanden, wird es vom Modul automatisch mit dem Wert "1" angelegt. | |||
Dadurch ist per default das automatische Schalten von Shelly.shellyplug3 durch das Modul freigegeben. | |||
Der User kann durch Setzen des Readings '''automatic=0''' das automatische Schalten durch das Modul sperren und mit "1" wieder freigeben. Dadurch kann man zu bestimmten Zeiten (Urlaub, Feiertage, etc.) die Schaltung temporär deaktivieren. | |||
Wie oben beschrieben, soll der Heizlüfter als weitere Schaltbedingung die Abhängigkeit von der Raumtemperatur beachten. Konkret soll der Heizlüfter mit einer Hysterese von 0.2 (Grad) bei Erreichen einer Soll-Raumtemperatur ausschalten und bei Unterschreiten einer bestimmten Temperatur einschalten. | |||
Der Schlüssel '''interruptable''' übernimmt diese temporäre Schaltsequenzen. | |||
Zunächst wird in dem Sensordevice (In dem Beispiel ein Homatic Wandthermostat HM-TC-IT-WM-W-EU) ein Reading erstellt welches dann im Schlüssel '''interruptable''' angegeben wird. Dieses Reading soll einen Wert enthalten auf den der angegebene Regex ([0-9]\.[0-9]) matchen soll um Shelly.shellyplug3 temporär auszuschalten. | |||
Im Wandthermostat wird dazu ein userReading angelegt: | |||
userReadings diff-temp:desired-temp.* { | |||
sprintf "%.1f", ReadingsVal ($name, 'measured-temp', 0) - ReadingsVal ($name, 'desired-temp', 0) | |||
} | |||
Das bedeutet, wenn die Raumtemperatur die Solltemperatur erreicht oder höher ist, wird diff-temp >= 0. | |||
In diesem Fall matcht der angebene Regex in: | |||
interruptable=og.bad.wandthermostat:diff-temp:'''[0-9]\.[0-9]''':0.2 | |||
und Shelly.shellyplug3 wird ausgeschaltet. | |||
Unterschreitet der Wert von diff-temp 0, matcht der Regex nicht mehr und der Verbraucher wird wieder eingeschaltet. Dabei wird die angegebene Hysterese berücksichtigt, d.h der Verbraucher wird erst ausgeschaltet wenn "diff-temp - 0.2 >= 0" wahr ist. | |||
Für das Wiedereinschalten des Heizlüfters ist außerdem Voraussetzung, dass ein entsprechender PV-Überschuss vorliegt. Diese Bedingung wird durch die Angabe von '''power=1700''' bewirkt. Soll der zwangsweise PV Überschuss ignoriert werden, kann '''power=0''' angegeben werden. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel "spignorecond" im Consumer-Attribut ausgesteuert werden. | |||
<br> | |||
== Konfigurationsbeispiele == | == Konfigurationsbeispiele == | ||
=== Beispiel 1 === | |||
=== Visualisierung solare Vorhersage und reale Erzeugung === | |||
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt. | |||
Der Readingteil dieser Events heißt | |||
AllPVforecastsToEvent | |||
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren. | |||
Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt. | |||
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt. <br> | |||
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings | |||
LastHourPVforecast | |||
LastHourPVreal | |||
[[Datei:Screenshot2023-10-02092846.png|right|thumb|400px|Übersicht solare Vorhersage]] | |||
geloggt werden. | |||
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden. | |||
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank "LogDBShort" sieht das gplot-File wie folgt aus: | |||
<pre> | |||
# Created by FHEM/98_SVG.pm, 2022-05-16 20:17:12 | |||
set terminal png transparent size <SIZE> crop | |||
set output '<OUT>.png' | |||
set xdata time | |||
set timefmt "%Y-%m-%d_%H:%M:%S" | |||
set xlabel " " | |||
set title '<TL>' | |||
set ytics | |||
set y2tics | |||
set grid | |||
set ylabel "Wh" | |||
set y2label "Wh" | |||
set yrange [0:6000] | |||
set y2range [0:6000] | |||
#LogDBShort SolCast:LastHourPVforecast | |||
#LogDBShort SolCast:LastHourPVreal | |||
#LogDBShort SolCast:AllPVforecastsToEvent | |||
plot "<IN>" using 1:2 axes x1y2 title 'aktuelle PV Vorhersage' ls l6fill lw 1 with lines,\ | |||
"<IN>" using 1:2 axes x1y2 title 'reale PV Erzeugung' ls l2fill lw 1 with lines,\ | |||
"<IN>" using 1:2 axes x1y2 title 'initiale PV Vorhersage' ls l4 lw 1 with lines | |||
</pre> | |||
'''Hinweis:''' In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute "fixedrange=3days +1" im SVG löst das Problem. | |||
<br> | |||
=== Beispielkonfiguration 1 === | |||
Dies ist eine Konfiguration mit | Dies ist eine Konfiguration mit | ||
Zeile 197: | Zeile 578: | ||
So sollte es dann als Ergebnis aussehen: | So sollte es dann als Ergebnis aussehen: | ||
[[Datei:Solarforecast Beispiel Screenshot.png|zentriert|mini|Ergebnis nach dieser Konfiguration]] | [[Datei:Solarforecast Beispiel Screenshot.png|zentriert|mini|Ergebnis nach dieser Konfiguration]] | ||
== Praxisbeispiele und Lösungsansätze für Steuerungen == | == Praxisbeispiele und Lösungsansätze für Steuerungen == | ||
Zeile 296: | Zeile 585: | ||
Die nachfolgend beschriebene Lösung soll als Anregung für eigene Optimierungen verstanden werden und ist weiter ausbaufähig bzw. erweiterbar um zum Beipiel jahreszeitliche Anpassungen des Verfahrens. | Die nachfolgend beschriebene Lösung soll als Anregung für eigene Optimierungen verstanden werden und ist weiter ausbaufähig bzw. erweiterbar um zum Beipiel jahreszeitliche Anpassungen des Verfahrens. | ||
Die MultiPlus II Batteriewechselrichter von Victron sollten die Batterien nicht mit dem maximal möglichen Ladestrom beladen, da sich die Effizienz deutlich verschlechtert wenn sich die Ströme den jeweiligen Grenzwerten nähern ([https://www.victronenergy.com/ | Die MultiPlus II Batteriewechselrichter von Victron sollten die Batterien nicht mit dem maximal möglichen Ladestrom beladen, da sich die Effizienz deutlich verschlechtert wenn sich die Ströme den jeweiligen Grenzwerten nähern ([https://www.victronenergy.com/upload/documents/Output-rating-operating-temperature-and-efficiency.pdf Lesestoff]). | ||
Andererseits sollen die Ladeleistungen so gewählt werden, dass die verfügbare Solarenergie eine volle Aufladung der Akkus ermöglicht. | Andererseits sollen die Ladeleistungen so gewählt werden, dass die verfügbare Solarenergie eine volle Aufladung der Akkus ermöglicht. | ||
Zeile 306: | Zeile 595: | ||
eingestellt bzw. variiert werden. | eingestellt bzw. variiert werden. | ||
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut ''ctrlUserExitFn'' eigenen Code zur Auführung zu bringen. Der in diesem Attribut | Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut ''ctrlUserExitFn'' eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut ''ctrlInterval'') ausgeführt. | ||
In dem Attribut wird dieser Code eingetragen dessen Funktion und Zusammenspiel nachfolgend erläutert wird: | In dem Attribut wird dieser Code eingetragen dessen Funktion und Zusammenspiel nachfolgend erläutert wird: | ||
< | <syntaxhighlight lang="Perl"> | ||
{ | { | ||
## Vars | ## Vars | ||
######## | ######## | ||
my $batdev = (split " ", ReadingsVal ($name, 'currentBatteryDev', ''))[0]; # Batteriedevice | my $batdev = (split " ", ReadingsVal ($name, 'currentBatteryDev', ''))[0]; # Batteriedevice | ||
my $vebus = 'MQTT2_cerboGX_c0619ab34e08_vebus'; # Victron Vebus Device | my $vebus = 'MQTT2_cerboGX_c0619ab34e08_vebus'; # Victron Vebus Device | ||
my $maxcspc = | my $mppt1 = 'MQTT2_cerboGX_c0619ab34e08_solarcharger_Common'; # SmartLoader Device | ||
my $spcorr = 0. | my $maxcspc = 105; # max. Ladesollstrom (A) nominal | ||
my $sch = | my $spcorr = 0.9; # Korrekturfaktor Überschuss 90% | ||
my $sch = 0.25; # Verkürzungsfaktor Zeit bis Vollladung vor Sunset | |||
my $cclvl0 = 15; # Ladestrom Level 0 max. 5 A (240 W) pro WR (720 W) | |||
my $cclvl1 = 27; # Ladestrom Level 1 max. 9 A (432 W) pro WR (1296 W) | |||
my $cclvl2 = 54; # Ladestrom Level 2 max. 18 A (864 W) pro WR (2592 W) | |||
my $cclvl3 = 81; # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W) | |||
############### | ############### | ||
my $solh = ReadingsNum ($name, 'statistic_SunHours_Remain', | my $cofc = ReadingsNum ($name, 'statistic_todayConForecastTillSunset', 0); | ||
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0); | |||
my $cpv = ReadingsNum ($name, 'Current_PV', 0); | |||
my $mppt1c = ReadingsNum ($mppt1, 'DC_0_Current_value', 0); # Load I MPPT1 (max. 44 A) | |||
my $ssts = CurrentVal ($hash, 'sunsetTodayTs', 0); | |||
my $srts = CurrentVal ($hash, 'sunriseTodayTs', 0); | |||
my $sdiff = ($ssts - $srts) / 3600; # Sonnengang heute in h | |||
my $solh = ReadingsNum ($name, 'statistic_SunHours_Remain', 0); # h bis SunSet | |||
$solh = $solh - ($sdiff * $sch); # h bis SunSet - X | |||
$solh = $solh < 0 ? 0 : $solh; | $solh = $solh < 0 ? 0 : $solh; | ||
my $ahrem = ReadingsNum ($batdev, 'EnergyRemain', | my $ahrem = ReadingsNum ($batdev, 'EnergyRemain', 0) / 48; # Ah Bat bis SOC | ||
$ahrem = sprintf "%.0f", $ahrem; | $ahrem = sprintf "%.0f", $ahrem; | ||
my $fcdiff = ($pvfc - $cofc) * $spcorr; # Korrektur | my $fcdiff = ($pvfc - $cofc) * $spcorr; # Korrektur d. noch prognostizierten Überschußenergie | ||
$fcdiff = $fcdiff < 0 ? 0 : $fcdiff; # Wh | $fcdiff = $fcdiff < 0 ? 0 : $fcdiff; # Wh | ||
my $ | my $loadcur = $maxcspc; | ||
if ($cpv && $ | if ($cpv && $solh && $ahrem && $fcdiff > $ahrem) { # Ladeanforderung und Überschuss übersteigt | ||
my $cspc = $ahrem / $solh; | # Lademenge | ||
my $cspc = sprintf "%.2f", ($ahrem / $solh); # A = Ah / h -> A Soll Schätzung | |||
Log3 ($name, 3, qq{$name - userFn -> Battery charging process should be completed }. | |||
qq{in >$solh< hours}); | |||
Log3 ($name, 3, qq{$name - userFn -> raw Target charging current: $cspc}); | |||
$ | $cspc = sprintf "%.2f", ($cspc - $mppt1c); # SmartLoader IST berücksichtigen | ||
$cspc <= $cclvl2 ? $cclvl2 : # Ladung mit Level 2 Leistung | |||
$cspc <= $cclvl3 ? $cclvl3 : # Ladung mit Level 3 Leistung | Log3 ($name, 3, qq{$name - userFn -> Charge Current minus MPPT load Current >$mppt1c<: $cspc}); | ||
$maxcspc; | |||
$loadcur = $cspc <= 0 ? 0 : # nur MPPT Ladung | |||
$cspc <= $cclvl0 ? $cclvl0 : # Übergangsbereich | |||
$cspc <= $cclvl1 ? $cclvl1 : # Ladung mit Level 1 Leistung | |||
$cspc <= $cclvl2 ? $cclvl2 : # Ladung mit Level 2 Leistung | |||
$cspc <= $cclvl3 ? $cclvl3 : # Ladung mit Level 3 Leistung | |||
$maxcspc; # max. Ladesollstrom | |||
Log3 ($name, 3, qq{$name - userFn -> MaxChargeCurrent calculated: $loadcur}); | |||
} | } | ||
readingsSingleUpdate ($ | readingsSingleUpdate ($hash, 'userFn_Bat_MaxChargeCurrent', $loadcur.' A', 1); | ||
readingsSingleUpdate ($hash, ' | readingsSingleUpdate ($hash, 'userFn_Bat_HoursUntilChargeFinish', sprintf ("%.2f",$solh), 1); | ||
CommandSet (undef, "$vebus MaxChargeCurrent $ | CommandSet (undef, "$vebus MaxChargeCurrent $loadcur"); | ||
} | } | ||
</ | </syntaxhighlight> | ||
[[Datei:Screenshot 2023-05-03 201457.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]] | [[Datei:Screenshot 2023-05-03 201457.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]] | ||
Zunächst wird der am aktuellen Tag zu erwartende | Zunächst wird der am aktuellen Tag zu erwartende Totalüberschuss solarer Energie ermittelt. Das erfolgt aus der Differenz von ''RestOfDayPVforecast'' und ''RestOfDayConsumptionForecast'' unter Berücksichtigung eines Sicherheitsabschlages. Das Ergebnis liegt in Wh vor und wird bezogen auf 48 V (die Spannung des Batteriesystems) in Ah umgerechnet. | ||
Die noch benötigte Ladung der Batterie zur Erreichung des Soll SOC-Wertes ermittelt das ReadingsNum ''statistic_SunHours_Remain'' aus dem Batteriedevice, welches vom Modulreading ''currentBatteryDev'' ausgelesen wird. | Die noch benötigte Ladung der Batterie zur Erreichung des Soll SOC-Wertes ermittelt das ReadingsNum ''statistic_SunHours_Remain'' aus dem Batteriedevice, welches vom Modulreading ''currentBatteryDev'' ausgelesen wird. | ||
Sofern der so ermittelte solare | Sofern der so ermittelte solare Überschuss des (Rest)Tages die benötigte Lademenge der Batterie übersteigt, wird der DC Ladestrom so verringert, dass er sich in einem effizienten Bereich des MultiPlus II bewegt und dennoch rechnerisch ausreicht auf den Soll SOC-Wert zu laden. | ||
Zu diesem Zweck wird im Modul über die | Zu diesem Zweck wird im Modul über die Auswahl von ''SunHours_Remain'' im Attribut ''ctrlStatisticReadings'' das zusätzliche Reading ''statistic_SunHours_Remain'' erzeugt. Aus dem (noch) erforderlichen Ladungswert '''EnergyRemain''' (Ah) und der um eine Sicherheitszeit (''Verkürzungsfaktor Zeit bis Vollladung vor Sunset'') reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt. | ||
Zeile 370: | Zeile 680: | ||
[[Datei:Screenshot 2023-05-03 201719.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]] | [[Datei:Screenshot 2023-05-03 201719.png|right|thumb|300px|Vorhersage PV Erzeugung und Energieverbrauch des (restlichen) Tages]] | ||
In allen anderen | In allen anderen Fällen, wenn z.B. rechnerisch nicht genügend oder keine Solarenergie erzeugt wird (Nachts) oder der Speicher gefüllt ist, wird der maximale (Sollwert) des Ladestroms ''$maxcspc = 35'' eingestellt. Dieser Wert entspricht dem maximalen Ladestrom gemäß Herstellerunterlagen Pylontech. | ||
Die Einstellung erfolgt per Set-Kommando im Victron vebus MQTT Device ''MQTT2_cerboGX_c0619ab34e08_vebus''. Dieses Device wurde auch während der MQTT Intergration des Victron Systems angelegt und wird hier nicht näher diskutiert. | Die Einstellung erfolgt per Set-Kommando im Victron vebus MQTT Device ''MQTT2_cerboGX_c0619ab34e08_vebus''. Dieses Device wurde auch während der MQTT Intergration des Victron Systems angelegt und wird hier nicht näher diskutiert. | ||
Zeile 377: | Zeile 687: | ||
Neben der Effizienzoptimierung hat dieses Verfahren auch den Vorteil einer möglichst schonenden Batterieaufladung was der Lebensdauer der Komponenten zugute kommen sollte. | Neben der Effizienzoptimierung hat dieses Verfahren auch den Vorteil einer möglichst schonenden Batterieaufladung was der Lebensdauer der Komponenten zugute kommen sollte. | ||
< | === Poolheizung in Abhängigkeit von vorhandenenm Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren) === | ||
Eine (Whirl-)Poolheizung soll bei ausreichend überschüssiger Energie aus einer Photovoltaikanlage dynamisch gesteuert werden (Eigenverbrauchsoptimierung). Im folgenden Beispiel ist ein Device mit der Bezeichnung ''Forecast'' des Typs ''SolarForecast bereits'' angelegt und konfiguriert. Ein freies Consumer-Attribut ''consumer01'' wird beispielhaft wie folgt definiert: | |||
<syntaxhighlight lang="perl"> | |||
attr Forecast consumer01 MQTT2_layzspa type=other power=1950 mode=can on="heater on" off="heater off" pcurr=WATT interruptable=1 swstate=heaterstate:1:0 auto=Automatiksteuerung mintime=SunPath spignorecond=EVCharger22:LadungMitPVUeberschussActive:1 icon=scene_pool notbefore=8 notafter=20 | |||
</syntaxhighlight> | |||
Die Poolheizung ist innerhalb FHEM bereits im Device ''MQTT2_layzspa'' integriert und lässt sich normalerweise per FHEM-Befehl "set ''MQTT2_layzspa heater on"'' oder ''"set MQTT2_layzspa heater off"'' steuern. Entsprechend werden die Schlüssel-Wert-Paare ''"on="'' und ''"off="'' definiert. | |||
Der Stromverbrauch einer aktiven Poolheizung ist uns bekannt und wird im Schlüssel ''"power=1950"'' definiert. Die Heizfunktion soll nur bei ausreichend Überschuss aktiviert werden dürfen und muss bei Unterschreitung sofort abgeschaltet werden. Diese Eigenschaften werden über die Schlüssel ''"mode=can"'' und ''"interruptable="1"'' festgelegt. Zuletzt soll grundsätzlich nur in der Zeit zwischen 08:00 Uhr bis 20:00 Uhr geheizt werden dürfen. | |||
Die Schlüssel ''"notbefore=8"'' und ''"notafter=20"'' legen diese Eigenschaften fest. Zur Anzeige des Schaltzustands der Heizung wurde der Schlüssel ''"swstate=heaterstate:1:0"'' hinzugefügt (Wert 1 = Heizung aktiv, Wert 0= Heizung aus). | |||
==== Priorisierung vor externen PV-Überschuss gesteuerten Verbrauchern ==== | |||
Der Schlüssel-Wert '''"spignorecond="''' bietet optional die Möglichkeit, ein Consumer auch ohne ausreichend PV-Überschuss einzuschalten. Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuss vorliegt. Im obigen Beispiel existiert in der Haus-Elektroinstallation eine Elektroauto-Ladestation mit eigener (externer) dynamischer PV-gesteuerter Fahrzeugladung ohne Integration in ''SolarForecast''. | |||
In Abhängigkeit von PV-Generatorleistung und Sonneneinstrahlung besteht manchmal eine Möglichkeit, dass der gesamte PV-Überschuss zur Fahrzeugladung genutzt wird. Das Modul SolarForecast würde entsprechend keinen (oder zu wenig) PV-Überschuss erkennen und den Consumer ''MQTT2_layzspa'' nicht aktivieren. | |||
Durch Verwendung von ''spignorecond=EVCharger22:LadungMitPVUeberschussActive:1'' wird die Poolheizung gegenüber der Ladestation jedoch priorisiert mit PV-Überschuss versorgt. In diesem Beispiel wird Consumer1 aktiviert, wenn die Ladestation "''EVCharger22''" sich im PV-Überschuss-Modus befindet '''und''' momentan ein Fahrzeug lädt. In der Folge würde der Hausstromverbrauch um ca. 1950 Watt steigen, die externe Fahrzeugladestation diese Änderung registrieren und die Fahrzeugladeleistung entsprechend verringern oder ganz abbrechen. | |||
=== Luftentfeuchter PV-Überschuss gesteuert mit externer Zwangs-Einschaltbedingung === | |||
Im folgenden Beispiel wird ein Luftentfeuchter normalerweise nur bei ausreichend PV-Überschuss Energie eingeschaltet (Eigenverbrauchsoptimierung), soll jedoch bei hoher Luftfeuchtigkeit zusätzlich aktiviert werden.<syntaxhighlight lang="perl"> | |||
attr Forecast SolarForecast ShellyPlug1 type=other power=300 mode=can on=on off=off pcurr=power:W interruptable=1 swstate=state:on:off mintime=SunPath locktime=900 notbefore=07 notafter=22 spignorecond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:high icon=Ventilator_fett | |||
</syntaxhighlight>Das in FHEM bereits angelegte Device namens ''ShellyPlug1'' dient als Zwischenstecker zur Steuerung des Luftentfeuchters. Der Schlüsselwert "''mintime=SunPath''" definiert die zeitliche Einplanung von Sonnenauf- bis untergang. Jedoch soll das Gerät unter keinen Umständen in der Nacht eingeschaltet werden, was über die Schlüssel ''"notbefore=07"'' bzw. ''"notafter=22"'' festgelegt ist. Weiterhin wurde im Schlüssel ''"locktime=900"'' festgelegt, dass zwischen (möglichen) Ein- und Ausschaltintervallen wenigstens 15 Minuten Wartezeit vergehen soll. | |||
Der Schlüssel-Wert '''"spignorecond="''' bietet optional die Möglichkeit, ein Consumer bei erfüllter Bedingung auch ohne ausreichend PV-Überschuss einzuschalten. In diesem Beispiel wird ein Raumluftsensor abgefragt. Bei Vorhandensein der Einschaltschwelle "high" aktiviert sich der Consumer zur geplanten Laufzeit zwischen 07:00 bis 22:00 Uhr solange, bis der Raumluftsensor einen abweichenden Wert meldet. | |||
== weiterführende Links == | == weiterführende Links == | ||
* {{Link2Forum|Topic=117864|LinkText=Forenthema zum Modul}} | * {{Link2Forum|Topic=117864|LinkText=Forenthema zum Modul}} | ||
* Forenthema "{{Link2Forum|Topic= | * Forenthema "{{Link2Forum|Topic=137058|LinkText=76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support}}" | ||
* Solcast API Toolkit: https://toolkit.solcast.com.au | * Solcast API Toolkit: https://toolkit.solcast.com.au | ||
* Kostal Plenticore 10 Plus mit SQL-Datenbank Integration ([[Kostal Plenticore 10 Plus]]) | * Kostal Plenticore 10 Plus mit SQL-Datenbank Integration ([[Kostal Plenticore 10 Plus]]) | ||
* Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html | |||
[[Kategorie:Energieerzeugungsmessung]] | [[Kategorie:Energieerzeugungsmessung]] |
Aktuelle Version vom 12. Juni 2024, 11:11 Uhr
![]() |
An dieser Seite wird momentan noch gearbeitet. |
![Info blue.png](/w/images/thumb/7/7e/Info_blue.png/40px-Info_blue.png)
76_SolarForecast | |
---|---|
Zweck / Funktion | |
Solarprognose und Verbrauchersteuerung | |
Allgemein | |
Typ | Gerätemodul |
Details | |
Dokumentation | EN / DE Thema |
Support (Forum) | Solaranlagen |
Modulname | 76_SolarForecast.pm |
Ersteller | DS_Starter (Forum /Wiki) |
Wichtig: sofern vorhanden, gilt im Zweifel immer die (englische) Beschreibung in der commandref! |
SolarForecast ist ein integratives Modul zur Gewinnung solarer Vorhersagedaten, deren Verarbeitung und grafischen Darstellung. Desweiteren bietet es die Möglichkeit, in FHEM definierte Verbraucher in einem SolarForecast-Device zu registrieren und eine PV Prognose basierte Steuerung der Verbraucher vom Modul übernehmen zu lassen.
Das Modul ist insbesondere durch folgende Eigenschaften gekennzeichnet:
- zur Gewinnung solarer Prognosewerte können die SolCast API, Forecast.Solar API, Victron VRM Portal API oder alternativ DWD Stahlungswerte-Stationen verwendet werden
- optionale KI Unterstützung bei Verwendung von DWD Stahlungswerten
- Wetterdaten werden über DWD Wetter-Stationen oder verschiedene API integriert
- Sprachensupport EN | DE
- die Prognosedaten, Wetterdaten, Verbraucherplanungen und die aktuellen Energieflüsse werden in umfangreich anpassbaren integrierten Grafiken dargestellt
- es wird keine externe SQL-Datenbank benötigt, die Datenhaltung erfolgt in einer Memory basierten Cachedatenbank inkl. einer Filesystempersistenz zur Datensicherung und Wiederherstellung beim Restart
- die Integration von Geräten wie Wechselrichter, Energy Meter, Batterien, Wetterstationen oder Verbrauchern ist offen und universell gestaltet und bietet dem Anwender maximale Freiheiten bei der Einrichtung seines individuellen Solardatensystems.
- eine integrierte und umfangreich anpassbare Verbrauchersteuerung vereint die PV Prognose basierte Einplanung der Verbraucher mit der Möglichkeit die Verbraucher durch das Modul schalten zu lassen und dadurch auf PV Erzeugungsschwankungen automatisch dynamisch zu reagieren
- Bereitstellung von Leitwerten zur optimalen Einstellung/Steuerung von Batteriespeichersystemen
- trotz der hohen Komplexität wird dem Anwender durch eine "Guided Procedure" bei der Gerätedefinition der Einstieg erleichtert und damit ein optimales Benutzerlebnis geboten
Abgrenzung: Das Modul 76_SolarForecast ist nicht zu verwechseln mit der SQL-basierten (DbLog) Prognose-Lösung mit Kostal Plenticore Wechselrichtern, die auf der eigenen Seite Kostal_Plenticore_10_Plus behandelt wird. Diese Lösung beschreibt kein monolithisches Modul, sondern basiert auf einer orchestrierbaren Zusammenstellung individueller Perl Programmbausteine.
Im vorliegenden Wiki-Beitrag wird ausschließlich das Modul 76_SolarForecast behandelt.
Rahmenbedingungen und Voraussetzungen
Definition
Die Hilfe zu dem Modul ist über "help SolarForecast de" aufrufbar.
Wie funktioniert die Verbrauchsprognose?
Im Gegensatz zu der PV Prognose gibt es keine API oder andere externen Datenquellen die für die Verbrauchsprognose herangezogen werden könnte. Zu diesem Zweck verwendet das Modul die Meterdaten aus dem Reading currentMeterDev. Die Verbrauchswerte werden stundengenau erfasst und im Datenspeicher pvHistory für 31 Tage gespeichert.
Mit dem Kommando "get ... pvHistory [Tag]" wird der Inhalt aufgelistet. Die Schlüssel confc, con und gcon zeigen die Verbrauchsprognose, den Verbrauch und den Netzbezug der jeweiligen Stunde des gewählten Tages. Die Stunde "99" zeigt die Summen dieser Schlüsssel für den Tag:
99 => etotal: , pvfc: 782, pvrl: 0, rad1h: - confc: 14540, con: 13873, gcon: 13873, gfeedin: 0 batintotal: , batin: 0, batouttotal: , batout: 0 batmaxsoc: -, batsetsoc: - wid: , wcc: , wrp: , pvcorrf: , dayname: So cyclescsm01: 0 cyclescsm02: 0 cyclescsm03: 0 cyclescsm04: 1, hourscsme04: 0.00 cyclescsm05: 0 cyclescsm06: 0 cyclescsm07: 1, hourscsme07: 0.00 cyclescsm08: 1, hourscsme08: 0.00 cyclescsm09: 1, hourscsme09: 0.03
In dem Beispiel wurden für den Tag 14540 Wh Verbrauch prognostiziert, 13873 Wh tatsächlich verbraucht und davon 13873 Wh aus dem Netz bezogen. Leider war an diesem Tag keinerlei PV Ertrag vorhanden, was man auch an dem Schlüssel pvrl erkennen kann.
Wie wird nun die Verbrauchsprognose confc erstellt?
Aus den gespeicherten con-Werten der pvHistory wird der Durchschnitt der vergangenen Tage ermittelt und für den kommenden Tag angewendet. Dabei geht per default jeder historische Tag gleichberechtigt in die Prognose ein. Mit dem Attribut affectConsForecastIdentWeekdays = 1 kann festgelegt werden, dass nur gleiche Wochentage (Mo..So) für die Prognose verwendet werden. Hierbei spielt die Vermutung, dass das Verbrauchsverhalten eine gewisse Korrelation zum Wochentag hat, eine Rolle.
Das Ergebnis der Prognose wird im Kopf der Grafik in der Zeile Verbrauch sowie in diversen Readings wie
- RestOfDayConsumptionForecast (Verbrauchsprognose für den Rest des Tages)
- NextHours_Sum04_ConsumptionForecast (Verbrauchsprognose für die nächsten 4 Stunden)
- Tomorrow_ConsumptionForecast (Verbrauchsprognose für den kommenden Tag)
angezeigt.
Weitere Aggregationen kann man sich über das Attribut ctrlStatisticReadings bei Bedarf zuschalten:
- conForecastTillNextSunrise - Verbrauchsprognose von aktueller Stunde bis zum kommenden Sonnenaufgang
- todayConForecastTillSunset - Verbrauchsprognose von aktueller Stunde bis Stunde vor Sonnenuntergang
- todayConsumptionForecast - Verbrauchsprognose aufgesplittet pro Stunde des aktuellen Tages (01-24)
modulinterne Datenstrukturen
Das Modul speichert die verschiedenen historischen und aktuellen Daten wie PV-Prognose, Witterungsdaten (Regen, Bewölkung), Strahlungsdaten, Einspeisung, Bezug, reale Erzeugungsdaten und vieles mehr zur Laufzeit im Arbeitsspeicher. Dadurch ist die Verarbeitung dieser Daten im Vergleich zu Lesevorgängen aus dem Filesystem bzw. einer Datenbank sehr performant. Allerdings würden diese Daten bei einem FHEM Absturz bzw. bei einem regulären Shutdown verlorengehen.
Deswegen werden die relevanten Daten regelmäßig in Dateien gesichert und bei Bedarf wiederhergestellt. Diese Dateien befinden sich im Verzeichnis ../fhem/FHEM/FhemUtils und heißen .*_SolarForecast_.*.
Die Daten werden in jedem Zyklus der Zentralschleife (CentralTask) gesammelt bzw. berechnet. Der Zyklus wird mit dem Attribut ctrlInterval eingestellt.
Zur Laufzeit können diese Daten über get-Kommandos abgerufen werden.
get ... pvHistory [Tag]
Der pvHistory Datenspeicher enthält die vergangenen Kennwerte der letzten 31 Tage mit einer Genauigkeit von einer Stunde. Es werden die Prognosewerte für Erzeugung und Verbrauch, die realen Werte für Erzeugung und Verbrauch sowie ebenso die Laufzeiten jedes einzelnen Verbrauchers (Consumer) festgehalten. Für jeden Tag gibt es die Stunde "99" die eine Summierung der Stundenwerte des Tages bzw. Sonderschlüssel enthält.
Bei Badarf lässt sich mit dem Befehl "set ... reset pvHistory" der gesamte Inhalt des Speichers löschen (nicht empfohlen). Selektiver funktioniert die Datenlöschung mit "set ... reset pvHistory <Tag>" (Daten eines bestimmten Tages löschen) bzw. "set ... reset pvHistory <Tag> <Stunde>" (Daten der Stunde eines bestimmten Tages löschen). Die letzten beiden Kommandos müssen über die Kommandozeile im Browser ausgeführt werden.
get ... pvCircular
Dieser Ringspeicher enthält Daten der letzten 24 Stunden sowie fortwährend berechnete Werte wie Korrekturfaktoren der PV-Erzeugung und Prognosequalität. Neue Stundenwerte des Tages überschreiben die gespeicherten Schüssel des vorangegangenen Tages sofern es sich nicht um fortwährend berechnete Werte handelt.
get ... nextHours
Der Speicher enthält sämtliche Prognosewerte der kommenden Stunden beginnend mit der aktuellen Stunde.
get ... solApiData
Abhängig von der ausgewählten Strahlungsdaten API enthält dieser Speicher die von der API gelieferten Rohdaten sowie evtl. weitere für die Funktion benötigte Daten wie API-Keys, Response Messages, Anzahl der API Abruf und weitere.
get ... valCurrent
Diese Struktur wird nicht regelmäßig im Filesystem gespeichert und enthält immer aktuell gesammelte oder berechnete/gelieferte Daten wie z.B. die Autarkierate, letze Laufzeit der Zentralschleife (CentralTask), Zeit des Sonnenauf- und untergangs sowie weitere Betriebsdaten.
get ... valConsumerMaster [XX]
Zeigt die Daten der aktuell im SolarForecast Device registrierten Verbraucher. Mit der Nummer XX kann ein bestimmter Verbraucher angesprungen werden. Die Nummer korrespondiert mit dem entsprechenden consumerXX Attribut. Neben anderen Betriebs- und Energiedaten werden insbesondere folgende Daten ermittelt, die für die zukünftige Planung der Verbraucherschaltzeiten relevant sind:
- epieces - prognostizierte Energiescheiben pro Betriebsstunde
Ausgehend von gespeicherten historischen Verbrauchsdaten des Verbrauchers wird der Energieverbrauch des Verbrauchers in seiner ersten Betriebsstunde prognostiziert, was insbesondere für die Planung der optimalen Startzeit des Verbrauchers in Bezug zu der prognostizierten PV Energie und den Verbrauchswerten weiterer vorhandener bzw. zu planender Verbraucher Berücksichtigung findet. Weitere Informationen zur Verbrauchersteuerung in diesem Abschnitt.
Schnittstelle für Modulautoren bzw. eigenen Code
Die im vorherigen Artikel beschriebenen internen Datenstrukturen können durch externen Code abgefragt und ausgewertet werden. Dazu stehen die folgenden Funktionen zur Verfügung.
- [FHEM::SolarForecast::]CurrentVal ($defs{'<Name>'}, '<Key>', <default>)
entspricht der Abfrage mit "get ... valCurrent".
- [FHEM::SolarForecast::]CurrentVal ($defs{'<Name>'}, '<Key>', <default>)
- [FHEM::SolarForecast::]HistoryVal ($defs{'<Name>'}, '<Day>', '<HoD>', '<Key>', <default>)
entspricht der Abfrage mit "get ... pvHistory".
- [FHEM::SolarForecast::]HistoryVal ($defs{'<Name>'}, '<Day>', '<HoD>', '<Key>', <default>)
- [FHEM::SolarForecast::]CircularVal ($defs{'<Name>'}, '<HoD>', '<Key>', <default>)
entspricht der Abfrage mit "get ... pvCircular".
- [FHEM::SolarForecast::]CircularVal ($defs{'<Name>'}, '<HoD>', '<Key>', <default>)
- [FHEM::SolarForecast::]NexthoursVal ($defs{'<Name>'}, <nhr>, '<Key>', <default>)
entspricht der Abfrage mit "get ... nextHours".
- [FHEM::SolarForecast::]NexthoursVal ($defs{'<Name>'}, <nhr>, '<Key>', <default>)
- [FHEM::SolarForecast::]ConsumerVal ($defs{'<Name>'}, '<c>', '<Key>', <default>)
entspricht der Abfrage mit "get ... valConsumerMaster".
- [FHEM::SolarForecast::]ConsumerVal ($defs{'<Name>'}, '<c>', '<Key>', <default>)
Die Angabe des Packages (FHEM::SolarForecast::) ist nur notwendig wenn die Funktionen von außerhalb des SolarForecast-Devices aufgerufen werden. Innerhalb des Devices (Code-Ausführung im Attribut ctrlUserExitFn) kann darauf verzichtet werden.
Die Bedeutung der Platzhalter sind:
<Name> - Name des SolarForecast Devices <Day> - abzufragender Tag (01 - 31) <c> - Nummer des Verbrauchers (01, 02, 03, 04,...) <HoD> - abzufragende Stunde (01 - 24, 99) <nhr> - nächste Stunde (NextHour00, NextHour01,...) <Key> - der abzufragende Schlüssel <default> - def default-Rückgabewert
Backup und Wiederherstellung der Moduldaten
Neben der Datenhaltung in den Attributen und Readings des SolarForecast Devices, erzeugt jedes SolarForecast Device Dateien im Verzeichnis ../fhem/FHEM/FhemUtils mit folgenden Inhalten:
PVH_SolarForecast_<name> - PV History PVC_SolarForecast_<name> - PV Circular PVCfg_SolarForecast_<name> - PV Anlagenkonfiguration PVCsm_SolarForecast_<name> - Consumer Status ScApi_SolarForecast_<name> - Werte aus verwendeter API AItra_SolarForecast_<name> - KI Entscheidungsquelle (trainierte Daten) AIraw_SolarForecast_<name> - KI Input Daten = Raw Trainigsdaten
Je nach Ausprägung und eingesetzten Features des SolarForecast Devices sind alle oder nur ein Teil dieser Dateien vorhanden. Dabei ist <name> der Name des SolarForecast Devices.
Bei einem Filebackup des FHEM-Servers ist darauf zu achten, dass diese Dateien in dem Backup enthalten sind. Der Inhalt der Dateien ist nicht statisch, sondern kann sich dynamisch aktualisieren. Um im Bedarfsfall einen aktuellen Datenstand zu haben, ist mindestens ein tägliches Backup dieser Dateien empfehlenswert. Eventuell auch öfter mit Hilfe einer Versionierung welche z.B. immer die letzten 3 Versionen aufbewahrt.
Beim Start von FHEM werden bestimmte Dateien automatisch gelesen und in das SolarForecast Device importiert. Der Vorgang ist mit verbose=3 im Log protokolliert:
2023.10.02 09:57:07.967 3: SolCast6 - cached data "pvhist" restored 2023.10.02 09:57:07.969 3: SolCast6 - cached data "circular" restored 2023.10.02 09:57:07.970 3: SolCast6 - cached data "consumers" restored 2023.10.02 09:57:07.970 3: SolCast6 - cached data "solcastapi" restored 2023.10.02 09:57:07.974 3: SolCast6 - cached data "aitrained" restored 2023.10.02 09:57:07.976 3: SolCast6 - cached data "airaw" restored
Bestimmte Betriebsdaten, wie z.B. die witterungsabhängigen Korrekturfaktoren (circular) oder die KI-Daten (aitrained/airaw), bauen sich über die Zeit immer granularer auf und stellen einen wertvollen Datenbestand dar.
Wird das SolarForecast Device gelöscht und anschließend wieder neu mit dem gleichen Namen definiert, können die bisher verfügbaren Daten sehr einfach wiederhergestellt werden:
- 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)
- 2. FHEM stoppen
- 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)
- 4. starten von FHEM (bestimmte Daten werden automatisch importiert)
- 5. mit dem Befehl "set <name> plantConfiguration restore" die Anlagenkonfiguration wiederherstellen
Soll das neue SolarForecast Device mit einem anderen Namen oder weitere SolarForecast Devices erstellt werden, welche die Betriebsdaten des primären Devices verwenden sollen, ist wie folgt vorzugehen:
- 1. definieren des neuen SolarForecast Devices und sichern der FHEM Konfiguration (der Konfigurationsdialog muß nicht durchgeführt werden)
- 2. FHEM stoppen
- 3. wiederherstellen der oben beschriebenen Dateien aus einem Backup in das Verzeichnis ../fhem/FHEM/FhemUtils (Überschreiben evtl. vorhandener Dateien)
- 4. umbenenen der Dateien, wobei <name> durch den Namen des neuen SolarForecast Devices ersetzt wird
- 5. starten von FHEM (die Daten werden automatisch importiert)
- 6. mit dem Befehl "set <name> plantConfiguration restore" die Anlagenkonfiguration wiederherstellen
Wenn sich die SolarForecast Devices hinsichtlich ihres Models oder der integrierten Consumer unterscheiden, sind die Dateien "PVCsm_SolarForecast_<name> " bzw. "ScApi_SolarForecast_<name>" von dem Verfahren auszuschließen.
dynamische SoC Steuerung für Solarbatterien
Das Modul bietet eine Unterstützung zur automatisierten Einstellung eines optimalen SoC Wertes.
Ziel ist es, den Minimum SoC in Abhängigkeit der zu erwartenden Solarerträge des aktuellen und des folgenden Tages so einzustellen, dass der prognostizierte Solarertrag von der Batterie aufgenommen werden kann. Die Einspeisung in das öffentliche Netz soll minimalisiert werden.
Weiterhin soll ein unterer SoC nicht unterschritten, sowie ein oberer Minimum SoC im Normalfall nicht überschritten werden. Der obere Grenzwert stellt sicher, dass die Batterie mindestens bis zu diesem Wert wieder entladen werden kann. Dadurch bleibt innerhalb der Batterie immer genügend Kapazität verfügbar um unvorhergesehene PV Energie aufnehmen zu können.
Aktiviert wird die Unterstützung der Batteriesteuerung durch das Setzen des Attributes ctrlBatSocManagement z.B. mit diesen Angaben:
ctrlBatSocManagement lowSoc=10 upSoC=50 maxSoC=98 careCycle=20
Ist dieses Attribut gesetzt, werden Steuerungs-Readings erstellt, die der Nutzer auswerten und seine Batterieanlage z.B. via notify oder DOIF steuern kann.
Das Reading Battery_OptimumTargetSoC enthält den vom Modul berechneten optimalen Mindest-SoC.
Das Reading Battery_ChargeRequest wird auf '1' gesetzt, wenn der aktuelle SoC unter den Mindest-SoC gefallen ist.
Die Schlüssel lowSoc und upSoC sind die unteren und oberen Grenzen, zwischen denen sich der Minimum SoC im normalen Betrieb bewegen soll.
Der Schlüssel maxSoC stellt eine Ladungsgrenze dar, die mindestens alle X (careCycle) Tage erreicht werden soll. Zu diesem Zweck errechnet das Modul die Anzahl der nötigen Erhöhungen der Minimum Batterieladung von 5% pro Tag um ausgehend vom aktuellen SoC-Level. Der resultierende Minimum SoC Wert wird entsprechend angepasst. Wurde der einstellte maxSoC Level erreicht, startet der Wartungszyklus (careCycle) erneut.
Der maxSoC in Verbindung mit dem durch careCycle definierten Zyklus soll sicherstellen, dass der Batterieverbund in regelmäßigen Abständen einen Ladungsausgleich vollziehen kann.
Durch die Modullogik erfolgt eine 5%ige Anhebung des Minimum SoC wenn am Vortag maxSoC nicht erreicht wurde. Die Anhebung erfolgt aber nicht über upSoC. upSoC ist die obere Grenze des Minimum SoC. Wird am Vortag mindestens die maxSoC Ladung erreicht, verringert sich der Minimum SoC wieder schrittweise um 5%, aber nicht tiefer als lowSoc.
Ergänzt wird die Logik noch um die PV Vorhersage. Dabei wird die obige Minimum SoC Berechnung um die Erwartung der PV Erwartung am aktuellen und folgenden Tag korrigiert. Das bedeutet, dass der Minimum SoC z.B. von heute 50% auf 10% abgesenkt und dadurch die gespeicherte Energie dem Haushalt zugeführt wird, wenn am heutigen oder kommenden Tag eine entsprechende PV Energie zu erwarten ist um die Batterie wieder vollständig zu zuladen. Dadurch ist immer genügend "Freiplatz" in der Batterie und andererseits hat die Batterie in langen Dunkelphasen eine Reserve für einen eventuellen Stromausfall (falls der abgesichert werden soll) und wird vor einem dauerhaften tiefen SoC geschützt.
Nutzung von batteryTrigger
Ergänzt werden die Möglichkeiten durch das set-Kommando:
batteryTrigger <1on>=<Wert> <1off>=<Wert> [<2on>=<Wert> <2off>=<Wert> ...]
Das Kommando setzt Triggerpunkte bei Über- bzw. Unterschreitung bestimmter Batterieladungswerte (SoC in %). Es kann eine beliebige Anzahl von Triggerbedingungen angegeben werden. Xon/Xoff-Bedingungen müssen nicht zwingend paarweise definiert werden. Überschreiten die letzten drei SoC-Messungen eine definierte Xon-Bedingung, wird das Reading batteryTrigger_X = on erstellt/gesetzt. Unterschreiten die letzten drei SoC-Messungen eine definierte Xoff-Bedingung, wird das Reading batteryTrigger_X = off erstellt/gesetzt.
Alle Triggerpunkte können mit dem set-Befehl:
reset batteryTriggerSet
wieder gelöscht werden.
Verbrauchersteuerung - Registrieren und visualisieren von Verbrauchern
Das Modul gestattet es beliebige Verbraucher (Devices) über die Attribute consumerXX zu registrieren. Durch die Registrierung wird dem Modul der Namen des Devices sowie dessen Eingenschaften durch die Angabe von Schlüssel-Wert Paaren bekannt gemacht.
Nach der Registrierung können die Verbraucher durch das Modul genutzt werden:
- es erfolgt eine Planung der Ein- und Ausschaltzeiten abhängig von der solaren Prognose in Bezug zu den Leistungsdaten des Verbrauchers sowie der anderen registrierten Consumer
- das Modul kann die Ein- und Ausschaltsteuerung der Consumer übernehmen (optional)
- die aktuellen Status (Verbrauchsdaten) werden in der Energiefußgrafik dargestellt
- das Modul lernt mit der Zeit das Verbrauchsverhalten der registrierten Verbraucher
Um einen Verbaucher zu registrieren, wird ein freies consumerXX Attribut, zum Beispiel consumer01, gesetzt.
Beispiel Registrierung eines Shelly Devices
Nachfolgendes Beispiel zeigt eine Registrierung eines Heizlüfters der an einem Shelly Zwischenstecker angeschlossen ist und durch das Modul gesteuert werden soll. Dabei soll die Steuerung nicht nur von der Solarprognose, sondern auch von der Raumtemperatur abhängig erfolgen. Im Beispiel wird das Attribut consumer03 verwendet.
Zwingende Angaben sind
consumerXX <Device Name> type=<type> power=<power>
Alle Angaben können mehrzeilig eingegeben werden. Die Schlüssel-Werte Paare sind jeweils durch ein Leerzeichen getrennt.
consumerXX Shelly.shellyplug3 type=heater power=1700
In dem Beispiel ist Shelly.shellyplug3 der Devicename des Shellies in FHEM. Der Schlüssel type definiert die Art des Verbrauchers. In der Hilfe sind die möglichen Typen aufgeführt. Den richtigen Typ anzugeben hat Einfluß auf die spätere Einschätzung des Leistungsverhaltens über die Laufzeit. So wird von einem heater gleich nach dem Einschalten die angegebene Nominalleistung abgerufen und wird über die Zeit gleichbleiben. Eine Waschmaschine oder ein Trockner rufen über ihre Laufzeit die Leistung nicht gleichbleibend ab und ändern die Leistungsaufnahme sich über die Einschaltdauer.
Die Angabe von power definiert die Nominalleistung (Watt) die für den Verbraucher laut Typenschild vom Hersteller angegeben wird. Diese Angabe wird vom Modul bei der Planung der Einschaltzeiten verwendet indem die Nominalleistung in das Verhältnis zur Solarprognose bzw. Verbrauchsprognose des Netzes gesetzt wird. Weiterhin ist dieser Wert auch wichtig um später den tatsächlichen Einschaltzeitpunkt auszuführen wenn ein realer PV Überschuss festgestellt wird.
Es ist möglich power=0 zu setzen. Das führt dazu, dass die Planung und letztendlich auch der Schaltvorgang unabhängig von der Solarprognose bzw. einem realen PV Überschuss vorgenommen wird.
Es werden weitere Schlüsseleingaben vorgenommen:
Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off
Mit dem Schlüssel icon legt man ein Icon fest welches in der Grafik für den Verbraucher verwendet wird. Der mode definiert die Art und Weise der Einplanung:
- can
- Die Einplanung erfolgt zum Zeitpunkt mit wahrscheinlich genügend verfügbaren PV Überschuss. Der Start des Verbrauchers zum Planungszeitpunkt unterbleibt bei ungenügendem PV-Überschuss.
- must
- Der Verbaucher wird optimiert eingeplant auch wenn wahrscheinlich nicht genügend PV Überschuss vorhanden sein wird. Der Start des Verbrauchers erfolgt auch bei ungenügendem PV-Überschuss.
Mit notbefore wird festgelegt, dass die Einplanung nicht vor neun Uhr morgens erfolgen soll auch falls schon genügend PV Überschuss vorhanden wäre. Der Schlüssel mintime definiert die Einplanungsdauer des Verbrauchers in Minuten im einfachsten Fall. Die hier verwendete Angabe SunPath ist ein Spezialfall. Der Verbraucher soll von Sonnenaufgang bis Sonnenuntergang eingeschaltet werden, wobei die Angabe von 60 bzw. -60 ein relative Verschiebung bewirken. Dadurch wird das Einschalten 60 Mintuen nach Sonnenaufgang bis 60 Minuten vor Sonnenuntergang geplant.
Die Schlüssel on und off teilen dem Modul die jeweiligen gültigen Ein- und Aus-Kommandos mit, mit dem das (Shelly)Device geschaltet werden kann. Werden diese Schlüssel nicht oder "leer" (on= off=) angegeben, erfolgt kein Schalten durch das Modul, nur die Planungsdaten werden erzeugt.
Die Verbraucherregistrierung wird mit weiteren Angaben ergänzt um das gewünschte Verhalten zu erreichen:
Shelly.shellyplug3 type=heater power=1700 icon=vent_ventilation mode=can notbefore=09 mintime=SunPath:60:-60 on=on off=off etotal=relay_0_energy_Wh:Wh pcurr=relay_0_power:W auto=automatic interruptable=og.bad.wandthermostat:diff-temp:[0-9]\.[0-9]:0.2
In etotal wird der Readingname des Shelly Devices angegeben welches die Summe der verbrauchten Energie (Wh/kWh) des Consumer Device liefert. D.h. es muß ein sich stetig erhöhender Wert sein. Durch die Auswertung dieses Readings ermittelt das Modul die in bestimmten Zeiteinheiten verbrauchte Energie zur weiteren Verwendung.
In dem Shelly Device ist per default ein solches Reading nicht vorhanden. Über userReadings kann in dem Device Shelly.shellyplug3 ein Reading für etotal erzeugt werden:
userReadings relay_0_energy_Wh:relay_0_energy.* monotonic { sprintf "%.0f", ReadingsVal ($name, 'relay_0_energy', 0) / 60 }
Der Schlüssel pcurr enthält das Reading in Shelly.shellyplug3 welches den aktuellen Energieverbrauch liefert.
auto enthält das Reading in Shelly.shellyplug3 welches zur Freigabe/Sperrung der autmatischen Schaltung durch das Modul dienen soll. Ist das angegebene Reading (im Beispiel "automatic") im Shelly.shellyplug3 nicht vorhanden, wird es vom Modul automatisch mit dem Wert "1" angelegt. Dadurch ist per default das automatische Schalten von Shelly.shellyplug3 durch das Modul freigegeben. Der User kann durch Setzen des Readings automatic=0 das automatische Schalten durch das Modul sperren und mit "1" wieder freigeben. Dadurch kann man zu bestimmten Zeiten (Urlaub, Feiertage, etc.) die Schaltung temporär deaktivieren.
Wie oben beschrieben, soll der Heizlüfter als weitere Schaltbedingung die Abhängigkeit von der Raumtemperatur beachten. Konkret soll der Heizlüfter mit einer Hysterese von 0.2 (Grad) bei Erreichen einer Soll-Raumtemperatur ausschalten und bei Unterschreiten einer bestimmten Temperatur einschalten. Der Schlüssel interruptable übernimmt diese temporäre Schaltsequenzen.
Zunächst wird in dem Sensordevice (In dem Beispiel ein Homatic Wandthermostat HM-TC-IT-WM-W-EU) ein Reading erstellt welches dann im Schlüssel interruptable angegeben wird. Dieses Reading soll einen Wert enthalten auf den der angegebene Regex ([0-9]\.[0-9]) matchen soll um Shelly.shellyplug3 temporär auszuschalten. Im Wandthermostat wird dazu ein userReading angelegt:
userReadings diff-temp:desired-temp.* { sprintf "%.1f", ReadingsVal ($name, 'measured-temp', 0) - ReadingsVal ($name, 'desired-temp', 0) }
Das bedeutet, wenn die Raumtemperatur die Solltemperatur erreicht oder höher ist, wird diff-temp >= 0.
In diesem Fall matcht der angebene Regex in:
interruptable=og.bad.wandthermostat:diff-temp:[0-9]\.[0-9]:0.2
und Shelly.shellyplug3 wird ausgeschaltet. Unterschreitet der Wert von diff-temp 0, matcht der Regex nicht mehr und der Verbraucher wird wieder eingeschaltet. Dabei wird die angegebene Hysterese berücksichtigt, d.h der Verbraucher wird erst ausgeschaltet wenn "diff-temp - 0.2 >= 0" wahr ist.
Für das Wiedereinschalten des Heizlüfters ist außerdem Voraussetzung, dass ein entsprechender PV-Überschuss vorliegt. Diese Bedingung wird durch die Angabe von power=1700 bewirkt. Soll der zwangsweise PV Überschuss ignoriert werden, kann power=0 angegeben werden. Alternativ kann die Berücksichtigung des zwangsweisen PV Überschuss mit dem Schlüssel "spignorecond" im Consumer-Attribut ausgesteuert werden.
Konfigurationsbeispiele
Visualisierung solare Vorhersage und reale Erzeugung
Zu Beginn jedes neuen Tages gegen 00:00 Uhr werden durch das SolarForecast Device Events für die initiale PV Prognose des kommenden Tages erstellt. Der Readingteil dieser Events heißt
AllPVforecastsToEvent
Die Uhrzeiten der Events sind so aufbereitet und können direkt geloggt werden um sie in einen SVG Plot zu integrieren. Im SolarForecast Device ist dieses Reading nicht sichtbar, nur die Events werden erstellt.
Die meteorologischen Bedingungen verändern sich über den Tag permanent. Je nach gewählter Strahlungsdatenquelle (eine API oder DWD Device) erfolgt eine mehr oder weniger dynamische Anpassung der Prognose an die sich verändernde Umwelt.
Aktuelle Prognosedaten sowie die reale PV Erzeugung der vergangenen Stunde können über die Readings
LastHourPVforecast LastHourPVreal
geloggt werden.
Werden alle drei Werte in einem SVG kombiniert, kann die Entwicklung der Prognose über den Tag und die Beziehung von Prognose zu realer PV Erzeugnung pro Stunde visualisiert werden.
Für das rechts abgebildete Beispiel des Plots aus einer Datenbank "LogDBShort" sieht das gplot-File wie folgt aus:
# Created by FHEM/98_SVG.pm, 2022-05-16 20:17:12 set terminal png transparent size <SIZE> crop set output '<OUT>.png' set xdata time set timefmt "%Y-%m-%d_%H:%M:%S" set xlabel " " set title '<TL>' set ytics set y2tics set grid set ylabel "Wh" set y2label "Wh" set yrange [0:6000] set y2range [0:6000] #LogDBShort SolCast:LastHourPVforecast #LogDBShort SolCast:LastHourPVreal #LogDBShort SolCast:AllPVforecastsToEvent plot "<IN>" using 1:2 axes x1y2 title 'aktuelle PV Vorhersage' ls l6fill lw 1 with lines,\ "<IN>" using 1:2 axes x1y2 title 'reale PV Erzeugung' ls l2fill lw 1 with lines,\ "<IN>" using 1:2 axes x1y2 title 'initiale PV Vorhersage' ls l4 lw 1 with lines
Hinweis: In manchen Fällen werden die Vorhersagewerte im SVG-Plot nicht angezeigt wenn FileLog verwendet wird. Ein Setzen des Attribute "fixedrange=3days +1" im SVG löst das Problem.
Beispielkonfiguration 1
Dies ist eine Konfiguration mit
SummenDummy für 2 BatterieWR (Namen : SBS25 / SBS25_2)
SummenDummy für 3 PV-Wechselrichter (Namen : SB25 / SB30 / SB40)
mit verschiedenen InverterStrings / ModulDirection / ModulTiltAngle, ModulPeakString
und auch mit den notwendigen zugehörigen anderen Modul-Konfigs.
ACHTUNG: Zusätzlich enthalten ist bei dem Beispiel-Notify eine Sonderkonstellation für eine Brennstoffzelle "FCU" als weitere bzw. zusätzliche Stromerzeugungsquelle. Diese "FCU" wird dadurch mit in der Grafik mit deren Erzeugungsleistung Tag und Nacht in der Erzeugersumme (am Symbol = Sonne) berücksichtigt.
(ReadingsVal("FCU","FCU-Strom-aktuelle-Leistung",0)/1000)
DWD
define DWD DWD_OpenData
attr DWD DbLogExclude .*
attr DWD forecastDays 7
attr DWD forecastProperties SunUp, SunRise, SunSet, Rad1h, R101, TTT, Tx, Tn, Tg, DD, FX1, RR6c, R600, RRhc, Rh00, ww, wwd, Neff
attr DWD forecastResolution 1
attr DWD forecastStation H568
attr DWD forecastWW2Text 1
attr DWD group Umwelt
attr DWD icon rc_WEB
attr DWD room 021_DWD
attr DWD stateFormat Tomorrow Tmax fc1_Tx °C on fc1_date at Blintrop
attr DWD verbose 2
InverterDummy
define InverterDummy dummy
attr InverterDummy DbLogExclude .*
attr InverterDummy DbLogInclude Today_PVforecast,etoday
attr InverterDummy event-on-change-reading .*
attr InverterDummy group Energy Meter
attr InverterDummy icon measure_photovoltaic_inst@green
attr InverterDummy room 020_PV,Energie
attr InverterDummy stateFormat {sprintf("current %9.3f kW Today_PVforecast %9.3f kWh Today_PV %9.3f kWh Total_PV %9.3f kWh",\
ReadingsVal($name,"total_pac",0)/1,\
ReadingsNum("Forecast","Today_PVforecast",0)/1000,\
ReadingsVal($name,"etoday",0)/1,\
ReadingsVal($name,"etotal",0)/1,)}
attr InverterDummy verbose 2
SMA_Energymeter
define SMA_Energymeter SMAEM
attr SMA_Energymeter DbLogExclude state
attr SMA_Energymeter diffAccept 50
attr SMA_Energymeter disable 0
attr SMA_Energymeter disableSernoInReading 1
attr SMA_Energymeter event-on-update-reading state,Saldo_Wirkleistung,Bezug_Wirkleistung,Einspeisung_Wirkleistung,Bezug_Wirkleistung_Zaehler,Einspeisung_Wirkleistung_Zaehler
attr SMA_Energymeter group Energy Meter
attr SMA_Energymeter icon measure_power@green
attr SMA_Energymeter interval 15
attr SMA_Energymeter room 020_PV,Energie
attr SMA_Energymeter serialNumber XXXXXXXXXX
attr SMA_Energymeter stateFormat state W (IN -) P1: L1_Saldo_Wirkleistung P2: L2_Saldo_Wirkleistung P3:L3_Saldo_Wirkleistung
attr SMA_Energymeter verbose 2
BatteryDummy
define BatteryDummy dummy
attr BatteryDummy DbLogExclude .*
attr BatteryDummy event-on-change-reading .*
attr BatteryDummy group Energy Meter
attr BatteryDummy icon batterie@green
attr BatteryDummy room 020_PV,Energie
attr BatteryDummy stateFormat {ReadingsVal("$name","total_pac", undef)." kW ".\
" - total ".ReadingsVal("$name","bat_loadtotal", undef)." kWh (-in)".\
" - ".ReadingsVal("$name","bat_unloadtotal", undef)." kWh (out)".\
" - charged ".ReadingsVal("$name","chargestatus", undef)." %"}
"Berechnungs"-Notify der Werte für Batterie- und InverterDummy
define N.PV.TotalConsumption.Dum.Energy notify SMA_Energymeter:Saldo_Wirkleistung:.* {\
# Forecast Invertererzeugung InverterDummy \
fhem "setreading InverterDummy Today_PVforecast ".sprintf("%.3f",(ReadingsNum("Forecast","Today_PVforecast",0)));;\
# Invertererzeugung InverterDummy \
fhem "setreading InverterDummy etotal ".sprintf("%.3f",(ReadingsNum("SB25","etotal",0))+(ReadingsNum("SB30","etotal",0))+(ReadingsNum("SB40","etotal",0)));;\
# Invertererzeugung InverterDummy \
fhem "setreading InverterDummy total_pac ".sprintf("%.3f",(ReadingsVal("FCU","FCU-Strom-aktuelle-Leistung",0)/1000)+(ReadingsNum("SB25","total_pac",0))+(ReadingsNum("SB30","total_pac",0))+(ReadingsNum("SB40","total_pac",0)));;\
# Invertererzeugung InverterDummy \
my $wert1234 = "0" ;;\
$wert1234 = sprintf("%.3f",(ReadingsNum("SB25","etoday",0))+(ReadingsNum("SB30","etoday",0))+(ReadingsNum("SB40","etoday",0)));; \
fhem ("setreading InverterDummy etoday ".sprintf("%.3f",$wert1234));;\
# Batterie-Bezug -Batterieentnahme InverterDummy\
fhem "setreading BatteryDummy power_out ".sprintf("%.0f",(ReadingsNum("SBS25","power_out",0))+(ReadingsNum("SBS25_2","power_out",0)));;\
# Batterie-Beladung InverterDummyBatterie mit Strom füllen\
fhem "setreading BatteryDummy power_in ".sprintf("%.0f",(ReadingsNum("SBS25","power_in",0))+(ReadingsNum("SBS25_2","power_in",0)));;\
# Batterie-Bezug -bat_loadtotal Batterieentnahme InverterDummy\
fhem "setreading BatteryDummy bat_unloadtotal ".sprintf("%.3f",(ReadingsNum("SBS25","bat_unloadtotal",0))+(ReadingsNum("SBS25_2","bat_unloadtotal",0)));;\
# Batterie-Beladung bat_loadtotal InverterDummyBatterie mit Strom füllen\
fhem "setreading BatteryDummy bat_loadtotal ".sprintf("%.3f",(ReadingsNum("SBS25","bat_loadtotal",0))+(ReadingsNum("SBS25_2","bat_loadtotal",0)));;\
# Batteriestatus InverterDummy\
my $wert5 = sprintf("%.2f",(((ReadingsNum("SBS25","chargestatus",0))/2) + ((ReadingsNum("SBS25_2","chargestatus",0))/2)));; \
fhem ("setreading BatteryDummy chargestatus ".sprintf("%.2f",$wert5));;\
# Batterie-total_pac InverterDummy\
my $wert6 = sprintf("%.3f",((ReadingsNum("SBS25","total_pac",0))+(ReadingsNum("SBS25_2","total_pac",0))));; \
fhem ("setreading BatteryDummy total_pac ".sprintf("%.3f",$wert6));;\
}
attr N.PV.TotalConsumption.Dum.Energy DbLogExclude .*
attr N.PV.TotalConsumption.Dum.Energy room Energie
attr N.PV.TotalConsumption.Dum.Energy verbose 2
SolarForecast
define Forecast SolarForecast
attr Forecast DbLogExclude .*
attr Forecast affect70percentRule 0
attr Forecast comment update per "wget -qO /opt/fhem/FHEM/76_SolarForecast.pm https://svn.fhem.de/fhem/trunk/fhem/contrib/DS_Starter/76_SolarForecast.pm"
attr Forecast ctrlInterval 10
attr Forecast disable 0
attr Forecast event-on-change-reading .*
attr Forecast flowGraphicAnimate 1
attr Forecast flowGraphicShowConsumer 1
attr Forecast flowGraphicShowConsumerDummy 1
attr Forecast flowGraphicShowConsumerPower 1
attr Forecast flowGraphicShowConsumerRemainTime 1
attr Forecast flowGraphicSize 400
attr Forecast graphicBeam1Color 3C14FF
attr Forecast graphicBeam1Content pvForecast
attr Forecast graphicBeam2Color 19FF29
attr Forecast graphicBeam2Content pvReal
attr Forecast graphicHeaderDetail all
attr Forecast graphicHistoryHour 4
attr Forecast graphicLayoutType double
attr Forecast graphicShowDiff top
attr Forecast graphicShowNight 0
attr Forecast group Energy Meter
attr Forecast room 020_PV,Energie
attr Forecast stateFormat Current_PV
attr Forecast verbose 2
setstate Forecast 2023-03-03 19:35:46 currentBatteryDev BatteryDummy pin=-pout:kW pout=total_pac:kW intotal=bat_loadtotal:kWh outtotal=bat_unloadtotal:kWh charge=chargestatus
setstate Forecast 2023-02-27 19:53:12 currentForecastDev DWD
setstate Forecast 2023-02-27 22:42:02 currentInverterDev InverterDummy pv=total_pac:kW etotal=etotal:kWh capacity=9500
setstate Forecast 2022-03-29 08:44:11 currentMeterDev SMA_Energymeter gcon=Bezug_Wirkleistung:W contotal=Bezug_Wirkleistung_Zaehler:kWh gfeedin=Einspeisung_Wirkleistung:W feedtotal=Einspeisung_Wirkleistung_Zaehler:kWh
setstate Forecast 2022-03-06 20:12:10 currentRadiationDev DWD
setstate Forecast 2023-04-05 16:44:50 inverterStrings Garage_SE,Garage_NW,Haus_NW,Haus_SW
setstate Forecast 2023-04-05 16:44:32 moduleDirection Garage_SE=SE Garage_NW=NW Haus_NW=NW Haus_SW=SW
setstate Forecast 2023-04-05 16:45:13 modulePeakString Garage_SE=2.75 Garage_NW=3.2 Haus_NW=2.230 Haus_SW=2.230
setstate Forecast 2023-04-05 16:45:39 moduleTiltAngle Garage_SE=35 Garage_NW=35 Haus_NW=45 Haus_SW=45
So sollte es dann als Ergebnis aussehen:
Praxisbeispiele und Lösungsansätze für Steuerungen
dynamische Ladestromsteuerung eines Victron MultiPlus II Chargers mit Pylontech Batterie
Die nachfolgend beschriebene Lösung soll als Anregung für eigene Optimierungen verstanden werden und ist weiter ausbaufähig bzw. erweiterbar um zum Beipiel jahreszeitliche Anpassungen des Verfahrens.
Die MultiPlus II Batteriewechselrichter von Victron sollten die Batterien nicht mit dem maximal möglichen Ladestrom beladen, da sich die Effizienz deutlich verschlechtert wenn sich die Ströme den jeweiligen Grenzwerten nähern (Lesestoff). Andererseits sollen die Ladeleistungen so gewählt werden, dass die verfügbare Solarenergie eine volle Aufladung der Akkus ermöglicht.
Das Victron System ermöglicht das Auslesen und die Steuerung der Anlage via MQTT. Die Einbindung in FHEM über MQTT soll hier nicht beschrieben werden. Aber wenn dies erfolgt ist, kann der Ladestrom z.B. mit dem Kommando:
set <Device> MaxChargeCurrent <Wert>
eingestellt bzw. variiert werden.
Das Modul bietet dem Nutzer die Möglichkeit in dem Attribut ctrlUserExitFn eigenen Code zur Auführung zu bringen. Der in diesem Attribut enthaltene Code wird am Ende jedes Zyklus (siehe Attribut ctrlInterval) ausgeführt. In dem Attribut wird dieser Code eingetragen dessen Funktion und Zusammenspiel nachfolgend erläutert wird:
{
## Vars
########
my $batdev = (split " ", ReadingsVal ($name, 'currentBatteryDev', ''))[0]; # Batteriedevice
my $vebus = 'MQTT2_cerboGX_c0619ab34e08_vebus'; # Victron Vebus Device
my $mppt1 = 'MQTT2_cerboGX_c0619ab34e08_solarcharger_Common'; # SmartLoader Device
my $maxcspc = 105; # max. Ladesollstrom (A) nominal
my $spcorr = 0.9; # Korrekturfaktor Überschuss 90%
my $sch = 0.25; # Verkürzungsfaktor Zeit bis Vollladung vor Sunset
my $cclvl0 = 15; # Ladestrom Level 0 max. 5 A (240 W) pro WR (720 W)
my $cclvl1 = 27; # Ladestrom Level 1 max. 9 A (432 W) pro WR (1296 W)
my $cclvl2 = 54; # Ladestrom Level 2 max. 18 A (864 W) pro WR (2592 W)
my $cclvl3 = 81; # Ladestrom Level 3 max. 27 A (1296 W) pro WR (3888 W)
###############
my $cofc = ReadingsNum ($name, 'statistic_todayConForecastTillSunset', 0);
my $pvfc = ReadingsNum ($name, 'RestOfDayPVforecast', 0);
my $cpv = ReadingsNum ($name, 'Current_PV', 0);
my $mppt1c = ReadingsNum ($mppt1, 'DC_0_Current_value', 0); # Load I MPPT1 (max. 44 A)
my $ssts = CurrentVal ($hash, 'sunsetTodayTs', 0);
my $srts = CurrentVal ($hash, 'sunriseTodayTs', 0);
my $sdiff = ($ssts - $srts) / 3600; # Sonnengang heute in h
my $solh = ReadingsNum ($name, 'statistic_SunHours_Remain', 0); # h bis SunSet
$solh = $solh - ($sdiff * $sch); # h bis SunSet - X
$solh = $solh < 0 ? 0 : $solh;
my $ahrem = ReadingsNum ($batdev, 'EnergyRemain', 0) / 48; # Ah Bat bis SOC
$ahrem = sprintf "%.0f", $ahrem;
my $fcdiff = ($pvfc - $cofc) * $spcorr; # Korrektur d. noch prognostizierten Überschußenergie
$fcdiff = $fcdiff < 0 ? 0 : $fcdiff; # Wh
my $loadcur = $maxcspc;
if ($cpv && $solh && $ahrem && $fcdiff > $ahrem) { # Ladeanforderung und Überschuss übersteigt
# Lademenge
my $cspc = sprintf "%.2f", ($ahrem / $solh); # A = Ah / h -> A Soll Schätzung
Log3 ($name, 3, qq{$name - userFn -> Battery charging process should be completed }.
qq{in >$solh< hours});
Log3 ($name, 3, qq{$name - userFn -> raw Target charging current: $cspc});
$cspc = sprintf "%.2f", ($cspc - $mppt1c); # SmartLoader IST berücksichtigen
Log3 ($name, 3, qq{$name - userFn -> Charge Current minus MPPT load Current >$mppt1c<: $cspc});
$loadcur = $cspc <= 0 ? 0 : # nur MPPT Ladung
$cspc <= $cclvl0 ? $cclvl0 : # Übergangsbereich
$cspc <= $cclvl1 ? $cclvl1 : # Ladung mit Level 1 Leistung
$cspc <= $cclvl2 ? $cclvl2 : # Ladung mit Level 2 Leistung
$cspc <= $cclvl3 ? $cclvl3 : # Ladung mit Level 3 Leistung
$maxcspc; # max. Ladesollstrom
Log3 ($name, 3, qq{$name - userFn -> MaxChargeCurrent calculated: $loadcur});
}
readingsSingleUpdate ($hash, 'userFn_Bat_MaxChargeCurrent', $loadcur.' A', 1);
readingsSingleUpdate ($hash, 'userFn_Bat_HoursUntilChargeFinish', sprintf ("%.2f",$solh), 1);
CommandSet (undef, "$vebus MaxChargeCurrent $loadcur");
}
Zunächst wird der am aktuellen Tag zu erwartende Totalüberschuss solarer Energie ermittelt. Das erfolgt aus der Differenz von RestOfDayPVforecast und RestOfDayConsumptionForecast unter Berücksichtigung eines Sicherheitsabschlages. Das Ergebnis liegt in Wh vor und wird bezogen auf 48 V (die Spannung des Batteriesystems) in Ah umgerechnet.
Die noch benötigte Ladung der Batterie zur Erreichung des Soll SOC-Wertes ermittelt das ReadingsNum statistic_SunHours_Remain aus dem Batteriedevice, welches vom Modulreading currentBatteryDev ausgelesen wird.
Sofern der so ermittelte solare Überschuss des (Rest)Tages die benötigte Lademenge der Batterie übersteigt, wird der DC Ladestrom so verringert, dass er sich in einem effizienten Bereich des MultiPlus II bewegt und dennoch rechnerisch ausreicht auf den Soll SOC-Wert zu laden.
Zu diesem Zweck wird im Modul über die Auswahl von SunHours_Remain im Attribut ctrlStatisticReadings das zusätzliche Reading statistic_SunHours_Remain erzeugt. Aus dem (noch) erforderlichen Ladungswert EnergyRemain (Ah) und der um eine Sicherheitszeit (Verkürzungsfaktor Zeit bis Vollladung vor Sunset) reduzierte Zeit bis zum Sonnenuntergang wird die rechnerisch erforderliche mindest Ladestromstärke ermittelt.
Dieser Wert wird auf die zu Anfang des Codeblocks definierten Ladelevel (Ladestrom Level X) abstrahiert und ein passender effizienter Ladestrom-Bereich ausgewählt.
In allen anderen Fällen, wenn z.B. rechnerisch nicht genügend oder keine Solarenergie erzeugt wird (Nachts) oder der Speicher gefüllt ist, wird der maximale (Sollwert) des Ladestroms $maxcspc = 35 eingestellt. Dieser Wert entspricht dem maximalen Ladestrom gemäß Herstellerunterlagen Pylontech.
Die Einstellung erfolgt per Set-Kommando im Victron vebus MQTT Device MQTT2_cerboGX_c0619ab34e08_vebus. Dieses Device wurde auch während der MQTT Intergration des Victron Systems angelegt und wird hier nicht näher diskutiert. Zur Kontrolle des kalkulierten Wertes werden noch die Readings SolCast_userFn_MaxChargeCurrent im Batteriedevice und userFn_Bat_MaxChargeCurrent im SolarForecast Device generiert.
Neben der Effizienzoptimierung hat dieses Verfahren auch den Vorteil einer möglichst schonenden Batterieaufladung was der Lebensdauer der Komponenten zugute kommen sollte.
Poolheizung in Abhängigkeit von vorhandenenm Photovoltaik-Überschuss aktivieren/deaktivieren (Eigenverbrauch optimieren)
Eine (Whirl-)Poolheizung soll bei ausreichend überschüssiger Energie aus einer Photovoltaikanlage dynamisch gesteuert werden (Eigenverbrauchsoptimierung). Im folgenden Beispiel ist ein Device mit der Bezeichnung Forecast des Typs SolarForecast bereits angelegt und konfiguriert. Ein freies Consumer-Attribut consumer01 wird beispielhaft wie folgt definiert:
attr Forecast consumer01 MQTT2_layzspa type=other power=1950 mode=can on="heater on" off="heater off" pcurr=WATT interruptable=1 swstate=heaterstate:1:0 auto=Automatiksteuerung mintime=SunPath spignorecond=EVCharger22:LadungMitPVUeberschussActive:1 icon=scene_pool notbefore=8 notafter=20
Die Poolheizung ist innerhalb FHEM bereits im Device MQTT2_layzspa integriert und lässt sich normalerweise per FHEM-Befehl "set MQTT2_layzspa heater on" oder "set MQTT2_layzspa heater off" steuern. Entsprechend werden die Schlüssel-Wert-Paare "on=" und "off=" definiert.
Der Stromverbrauch einer aktiven Poolheizung ist uns bekannt und wird im Schlüssel "power=1950" definiert. Die Heizfunktion soll nur bei ausreichend Überschuss aktiviert werden dürfen und muss bei Unterschreitung sofort abgeschaltet werden. Diese Eigenschaften werden über die Schlüssel "mode=can" und "interruptable="1" festgelegt. Zuletzt soll grundsätzlich nur in der Zeit zwischen 08:00 Uhr bis 20:00 Uhr geheizt werden dürfen.
Die Schlüssel "notbefore=8" und "notafter=20" legen diese Eigenschaften fest. Zur Anzeige des Schaltzustands der Heizung wurde der Schlüssel "swstate=heaterstate:1:0" hinzugefügt (Wert 1 = Heizung aktiv, Wert 0= Heizung aus).
Priorisierung vor externen PV-Überschuss gesteuerten Verbrauchern
Der Schlüssel-Wert "spignorecond=" bietet optional die Möglichkeit, ein Consumer auch ohne ausreichend PV-Überschuss einzuschalten. Bei erfüllter Bedingung wird der Verbraucher entsprechend der Planung eingeschaltet auch wenn zu dem Zeitpunkt kein PV Überschuss vorliegt. Im obigen Beispiel existiert in der Haus-Elektroinstallation eine Elektroauto-Ladestation mit eigener (externer) dynamischer PV-gesteuerter Fahrzeugladung ohne Integration in SolarForecast.
In Abhängigkeit von PV-Generatorleistung und Sonneneinstrahlung besteht manchmal eine Möglichkeit, dass der gesamte PV-Überschuss zur Fahrzeugladung genutzt wird. Das Modul SolarForecast würde entsprechend keinen (oder zu wenig) PV-Überschuss erkennen und den Consumer MQTT2_layzspa nicht aktivieren.
Durch Verwendung von spignorecond=EVCharger22:LadungMitPVUeberschussActive:1 wird die Poolheizung gegenüber der Ladestation jedoch priorisiert mit PV-Überschuss versorgt. In diesem Beispiel wird Consumer1 aktiviert, wenn die Ladestation "EVCharger22" sich im PV-Überschuss-Modus befindet und momentan ein Fahrzeug lädt. In der Folge würde der Hausstromverbrauch um ca. 1950 Watt steigen, die externe Fahrzeugladestation diese Änderung registrieren und die Fahrzeugladeleistung entsprechend verringern oder ganz abbrechen.
Luftentfeuchter PV-Überschuss gesteuert mit externer Zwangs-Einschaltbedingung
Im folgenden Beispiel wird ein Luftentfeuchter normalerweise nur bei ausreichend PV-Überschuss Energie eingeschaltet (Eigenverbrauchsoptimierung), soll jedoch bei hoher Luftfeuchtigkeit zusätzlich aktiviert werden.
attr Forecast SolarForecast ShellyPlug1 type=other power=300 mode=can on=on off=off pcurr=power:W interruptable=1 swstate=state:on:off mintime=SunPath locktime=900 notbefore=07 notafter=22 spignorecond=ESPEasy_ESP_Easy1_am2302_sensor:humidity:high icon=Ventilator_fett
Das in FHEM bereits angelegte Device namens ShellyPlug1 dient als Zwischenstecker zur Steuerung des Luftentfeuchters. Der Schlüsselwert "mintime=SunPath" definiert die zeitliche Einplanung von Sonnenauf- bis untergang. Jedoch soll das Gerät unter keinen Umständen in der Nacht eingeschaltet werden, was über die Schlüssel "notbefore=07" bzw. "notafter=22" festgelegt ist. Weiterhin wurde im Schlüssel "locktime=900" festgelegt, dass zwischen (möglichen) Ein- und Ausschaltintervallen wenigstens 15 Minuten Wartezeit vergehen soll.
Der Schlüssel-Wert "spignorecond=" bietet optional die Möglichkeit, ein Consumer bei erfüllter Bedingung auch ohne ausreichend PV-Überschuss einzuschalten. In diesem Beispiel wird ein Raumluftsensor abgefragt. Bei Vorhandensein der Einschaltschwelle "high" aktiviert sich der Consumer zur geplanten Laufzeit zwischen 07:00 bis 22:00 Uhr solange, bis der Raumluftsensor einen abweichenden Wert meldet.
weiterführende Links
- Forenthema zum Modul
- Forenthema "76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support"
- Solcast API Toolkit: https://toolkit.solcast.com.au
- Kostal Plenticore 10 Plus mit SQL-Datenbank Integration (Kostal Plenticore 10 Plus)
- Photovoltaik Ingenieurbüro Junge: https://www.ing-büro-junge.de/html/photovoltaik.html