Wettervorhersage mit in den TimeofUseTariffic Controller berücksichtigen

Guten Abend,

auf der letzten openEMS Tagung haben sich mehrere Teilnehmer zum Thema PV-Forecast unter Berücksichtigung von aktuellen Wetterdaten ausgetauscht. Diesen Ball möchte ich hier im Forum noch einmal aufgreifen, um sich zu verschiedenen Ideen und Lösungen auszutauschen und diese im Idealfall in die Tat umzusetzen.

Vorab, uns ist bewusst das die Wettervorhersage an sich ein komplexes Thema ist und das die individuellen Eigenschaften der PV-Anlage (Ausrichtung, Wirkungsgrad, Verschattung etc.) einen maßgeblichen Einfluss auf die Vorhersage haben. Daher möchte ich zunächst einen einfachen Ansatz vorstellen, den wir in einer ersten Version umgesetzt haben.

Wir greifen via API von Dienstleister „open-meteo“ die Vorhersagedaten für die „shortwave radiation“ anhand der Koordinaten für die nächsten 24h ab. Der Dienst ist für den „non commercial“ Gebrauch kostenfrei. Der Wert wird in w/m² angegeben. Diesen Wert rechnen wir auf die installierte Anlagengröße hoch (Anz. Module * Fläche pro Modul * shortwave radiation w/m²). Anhand von historischen Daten haben wir den durchschnittlichen Wirkungsgrad der betrachteten Anlage berechnet und können somit den PV-Ertrag der Anlage auf Basis der shortwave radiation im 1h Raster vorhersagen.

Hier ein kleiner Auszug aus der Admin-UI.

Den Sourcecode stellen wir in kürze als Request zur Verfügung.

Neben diesem Ansatz haben wir auch Regressionsmodelle, KKN (closest nearest neigbour) oder eine Integration in den LSTM-Predictor (Long Short-Term Memory) in Betracht gezogen. Aufgrund der Einfachheit und der dennoch beachtlichen Genauigkeit haben wir uns im ersten Schritt für diesen Ansatz entschieden.

Wir freuen uns auf eure Ideen, Ergänzungen und Lösungen.

Stephan

5 Likes

Hallo Stephan,

wahnsinns Arbeit und danke für die Bereitstellung im Vorraus!
Das hat noch gefehlt ! :slight_smile:

Grüße !

1 Like

Hi Stephan,

Wir hatten ja schon über dieses Thema philosophiert. Ich kann mich @Sn0w3y nur anschließen: Vielen Dank vorab!

Man hört öfter die Frage: “Warum habt ihr keine PV-Vorhersage?”. Über den Sinn und Zweck kann man sicherlich streiten.
Aber ich denke, dass euer approach Kreise ziehen wird.

Ich bin sehr gespannt.

Alles Gute & Gruß,
klinki

2 Likes

Hier ist noch der Weg zum Pullrequest:

3 Likes

Hi Stephan,

Ich habe euren Controller seit heute im Einsatz. Bisher sieht es ziemlich gut aus - was man halt nach ein paar Stunden so sagen kann…
Mit dem Faktor muss man ein bisschen spielen und kommt dann auch ziemlich nah an die Wahrheit.
Ob eine Betrachtung von mehreren Anlagen/Ausrichtungen nachher praktisch überhaupt sinnvoll ist, muss man mal beobachten.

Ich bin bei den predictors nicht wirklich im Thema: kann man mehrere predictors auf einem Kanal “loslassen”? Falls ja, reicht es ja schon mehrere Controller eures Typs zu nutzen.
Wobei die shortwave radiation unabhängig von der Ausrichtung ist…

Gruß,
klinki

Ich bin ja (fast) sprachlos… genau zu dem Zeitpunkt hatte ich einen Support Call mit Fenecon und nebenbei genau das Thema angesprochen - dass ich manchmal den Eindruck habe dass mein “FEMS Dynamischer Stromtarif” machmal etwas zu optimistisch/pessimistisch plant was den PV Ertrag betrifft.

Ich hatte dann meine Idee als Konzept zu Papier gebracht und stelle fest dass das unnötig war da Ihr das gerade schon gemacht habt! :rofl:

Einzigster Unterschied mag wohl sein dass ich daran dachte den PV Ertrag des Vortags zu boosten oder Dimmen - abhängig vom Strahlungsindex…

1 Like

Hallo Gemeinde,

Ich habe den Controller ein paar Wochen im Einsatz und immer wieder die Vorhersage mit der Realität verglichen. Grundsätzlich passt alles recht gut. Mich hatte nur etwas gestört, dass meine “Winteranlage” (Garagendach, 45° Aufständerung, Süden) nicht so recht abgebildet werden kann. Sie produziert halt praktisch nur Mittags Peaks über wenige Stunden.

In meinem Fork habe die ganze Geschichte ein wenig aufgebohrt: Man kann nun 3 Anlagen mit Ausrichtung (tilt, azimuth) anlegen. Außerdem wird der zeitnächste Vorhersagewert (Summe) nach Influx geschrieben. Dazu habe ich einen Channel hinzugefügt. Somit lässt sich später der Faktor besser justieren.
Außerdem bin ich auf das “global_tilted_irradiance-Modell” inkl. “best match”-Wettervorhersage gewechselt.
Mal sehen, was das bringt und ob tatsächlich die Genauigkeit erhöht werden kann.

@s.alberternst: ich wollte mich zunächst mal nicht an eurem PR beteiligen und etwas experimentieren. Wenn es Sinn macht, können wir später alles in einen Topf werfen :wink:

Gruß, klinki

1 Like

Hi @klinki ,

wie hast du das denn in dein TimeOfUse Tariff eingebunden?

Meiner zeigt die Erzeugung irgendwie nicht korrekt an…

Bekomme immer:

3.2.2025, 01:24:29
INFO
io.openems.edge.predictor.api.prediction.AbstractPredictor
[predictor0] Prediction for [_sum/ProductionActivePower]: Prediction{EMPTY}
3.2.2025, 01:24:29
ERROR
io.openems.edge.predictor.weather.forecast.PredictorWeatherForecastModelImpl
Error creating prediction:

Edit:

Fehler gefunden, ag aber tatsächlich am Code. Ich werde eventuell einen PR stellen, wenn ich Zeit habe dazu. Aktuell konzentriere ich mich auf die Implementierung für:

Eventuell auch Interessant, da nicht nur die Einstrahlung sondern die tatsächliche Leistung ausgegeben wird :wink:

Grüße

1 Like

Moin @Sn0w3y,

Der Fehler ist mir neu - konnte ich bisher nicht nachvollziehen.
Ab und an ein Problem bei der Verarbeitung. Das scheint aber am ToU selbst zu liegen

java[466]: 2025-02-03T08:14:54,841 [_energy ] INFO  [i.prediction.AbstractPredictor] [predictorWeather1] Prediction for [_sum/ProductionActivePower]: Prediction{start=2025-02-03T08:00+01:00[Europe/Berlin], values=0,0,540,1236,1933,2531,3146,3644,4057,4420,4721,5105,5504,5849,6160,6418,6642,6832,6950,7034,7064,7043,6947,6817,6733,6669,6544,6351,6109,5786,5400,4969,4524,3992,3310,2447,1305,434,21,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,88,209,316,443,602,814,1152,1574,1964,2219,2320,2332,2345,2503,2807,3133,3389,3427,3207,2917,2721,2782,3083,3514,3941,4209,4459,4612,4622,4464,4167,3740,3143,2395,1444,531,40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
Feb  3 08:14:54 java[466]: 2025-02-03T08:14:54,843 [_energy ] ERROR [s.common.worker.AbstractWorker] Worker error. IllegalStateException: No valid Genotype found during evolution.

Aber schau Dir das mal an! Gestern hatten wir praktisch den ganzen Tag Sonne. Auch wenn der Predictor hier mal eine Wolke vorhergesehen hat (PredictorPV2 - Westen).
Leider konnte ich meine Nachbarn nicht davon überzeugen ihre Häuser abzureißen. Verschattung ist halt bei mir ein Thema. Ansonsten liegen die Predictor-Summe (lila) und die reale Produktion (hellblau) schon sehr nah beisammen.

Den Weather-Predictor ist auf _sum/ProductionActivePower eingestellt. Im SimilarDay habe ich den Kanal entfernt. Vermutlich hast Du das auch so. Die Meldung kommt aus der Wettervorhersage wenn sie nichts ermitteln konnte.

Ich habe vor zwei Tagen noch die Zeitzone mit reingenommen. Ansonsten geht openMeteo von GMT aus.

Ist noch nicht im GitHub - kommt in den nächsten Stunden.

Gruß,
klinki

EDIT: Abzuwarten bleiben die Tagen mit Wolken. Da muss man schauen welches Wettermodell sich bewährt. Mit “best_match” habe ich bisher die besten Erfahrungen. Tatsächlich sogar besser als mit dem DWD.
Aber: abwarten und beobachten

1 Like

Hallo zusammen,

es freut mich sehr, dass dieses Thema auf viel Zuspruch trifft und ihr euch gleich an Verbesserungen/Erweiterungen aufgemacht habt. Nach der 2 monatigen “Testphase” bin ich sehr zufrieden.

Neben den inhaltlichen Quellen würde mich interessieren, ob es kostenfreie Anbieter gibt, die ggf. eine bessere oder gleich gute Datenqualität zur Verfügung stellen. Im kommerziellen Bereich kenne ich bereits ein paar. Denn neben dem einfachen Ansatz, wie hier umgesetzt, gibt es ja noch weitere Faktoren (z.B. Schnee, Nebel) die im Zweifel einen sehr großen Einfluss haben, aber nur an wenigen Tagen im Jahr zum Tragen kommen. Wenn es also ein Modell gibt, dass die Wetterdaten so aufbereitet zur Verfügung stellt, und wir diese einfach mit individuellen Gegebenheiten vor Ort kombinieren können, würde dies aus meiner Sicht eine weitere Steigerung darstellen. Hat hier jemand eine Idee oder kennt bereits Lösungen?

@Sn0w3y hat hier ja bereits einen Anfang gemacht.

Vielen Dank und Gruß

Stephan

Hallo zusammen,

aufgrund eines Crashes musste ich mein Edge neu aufsetzen ärger. Nun bringt er mir folgendes:

Feb 03 19:18:53 sems200 java[6750]: 2025-02-03T19:18:53,982 [_energy ] ERROR [s.common.worker.AbstractWorker] Worker error. RuntimeException: Error in getting prediction execution - Caused by: java.util.NoSuchElementException
Feb 03 19:18:53 sems200 java[6750]: java.lang.RuntimeException: Error in getting prediction execution
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.PredictorLstmImpl.createNewPrediction(PredictorLstmImpl.java:162)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.api.prediction.AbstractPredictor.getPrediction(AbstractPredictor.java:68)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.core.predictormanager.PredictorManagerImpl.getPrediction(PredictorManagerImpl.java:94)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.energy.v1.optimizer.UtilsV1.createSimulatorParams(UtilsV1.java:84)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.energy.v1.optimizer.OptimizerV1.createParams(OptimizerV1.java:114)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.energy.v1.optimizer.OptimizerV1.forever(OptimizerV1.java:62)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.common.worker.AbstractWorker$1.run(AbstractWorker.java:155)
Feb 03 19:18:53 sems200 java[6750]: Caused by: java.util.concurrent.ExecutionException: java.util.NoSuchElementException
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.CompletableFuture.reportGet(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.CompletableFuture.get(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.PredictorLstmImpl.createNewPrediction(PredictorLstmImpl.java:147)
Feb 03 19:18:53 sems200 java[6750]:         ... 6 more
Feb 03 19:18:53 sems200 java[6750]: Caused by: java.util.NoSuchElementException
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.ArrayList$Itr.next(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.Collections.min(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.common.HyperParameters.getMinimumErrorModelTrend(HyperParameters.java:688)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.common.HyperParameters.getBestModelTrend(HyperParameters.java:762)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.common.LstmPredictor.predictTrend(LstmPredictor.java:86)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.PredictorLstmImpl.predictTrend(PredictorLstmImpl.java:245)
Feb 03 19:18:53 sems200 java[6750]:         at io.openems.edge.predictor.lstm.PredictorLstmImpl.lambda$1(PredictorLstmImpl.java:135)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.exec(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.ForkJoinTask.doExec(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.ForkJoinPool$WorkQueue.topLevelExec(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.ForkJoinPool.scan(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.ForkJoinPool.runWorker(Unknown Source)
Feb 03 19:18:53 sems200 java[6750]:         at java.base/java.util.concurrent.ForkJoinWorkerThread.run(Unknown Source)

@stefan.feilmeier an was kann das liegen?

Zudem:

predictor0[State:INFO: When the data set is empty, entirely null, or contains 50% null values.]

für das LSTM.

Grüße !