76_SolarForecast - Informationen/Ideen zu Weiterentwicklung und Support

Begonnen von DS_Starter, 11 Februar 2024, 14:11:00

Vorheriges Thema - Nächstes Thema

roadghost

NUC/Ubuntu 22.04 m. FHEM, div. Tasmota-Steckdosen, HMCFGUSB-2 für 12x HM-CC-RT-DN + 8x HM-TC-IT-WW
Rademacher DuoFern für 12 Jalousien, JeeLink für LaCrosse Temp.Sensor, WLAN-smart-Plugs, 
NUKI smartlock, 2xIP-CAM, Pylontech Speicher + Sungrow WR, Unifi-AP´s + Controller auf weiterem NUC

DS_Starter

#4381
@Gerd, @all,

der Setter "reset" ist nun deutlich aufgewertet. Die KI-Daten lassen sich selektiver löschen:

aiData    
    Mit den nachfolgenden Argumenten können die KI-Daten selektiv oder komplett entfernt werden:
   delDataAll - löscht die KI Instanz inklusive aller Trainings- und Rohdaten sowie Daten auf Fileebene und initialisiert sie neu
   delIndex=<Index>,<Index>,... - löscht einen oder mehrere Datensätze mit dem Index. Der Index kann als Regex angegeben sein.
   Beispiele: 1.) delIndex=2025013023 2.) delIndex=2025013023,2025013024 3.) delIndex=202501.* 4.) delIndex=20250130[0-9]

Weitere Eingrenzungsmöglichkeiten werden bei Bedarf folgen.
Außerdem können die weiteren reset-Optionen mit ihren Argumenten direkt in dem verfügbaren Eingabefeld aufgerufen werden. Dadurch entfällt bei bestimmten Aufrufen mit mehreren Argumenten die Notwendigkeit über die Kommandozeile zu gehen.

Liegt im Contrib.
Es sind nun bereits so viele Weiterentwicklungen eingeflossen, dass ich diese Version demnächst als Minor Release 1.60.0 veröffentlichen werde.

LG,
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

DS_Starter

Thema smartPower Batteriesteuerung...

Meine Vermutung von gestern hat sich erhärtet. Das Ratio ist unter 100% und somit wird auf pinmax gegangen.
Alternativ könnte implementiere:

   Ratio < 100% -> OTP Iterationswert übernehmen (+ safety)
         < 50%  -> OTP pinmax

Allerdings wäre dadurch heute einiges mehr eingespeist worden. So wurden nur geringe Spitzen abgeschnitten.

...
2025.10.30 12:44:01.882 1: SolCast DEBUG> ChargeOTP Bat 01 - current Ratio of surplus / energy requirement to achieve the load target: 40.52 %
2025.10.30 12:44:01.882 1: SolCast DEBUG> ChargeOTP Bat 01 30/12 - hod:13/00, lr/lc:1/1, SocS/E:11082/11811 Wh, SurpH/D:2878/4292 Wh, OTP:5040/2878 W
2025.10.30 12:44:01.883 1: SolCast DEBUG> ChargeOTP Bat 01 30/13 - hod:14/01, lr/lc:1/1, SocS/E:11811/14398 Wh, SurpH/D:2723/1569 Wh, OTP:5040/2723 W
2025.10.30 12:44:01.883 1: SolCast DEBUG> ChargeOTP Bat 01 30/14 - hod:15/02, lr/lc:1/1, SocS/E:14398/16454 Wh, SurpH/D:2164/0 Wh, OTP:5040/2164 W
2025.10.30 12:44:01.884 1: SolCast DEBUG> ChargeOTP Bat 01 30/15 - hod:16/03, lr/lc:1/1, SocS/E:16454/17724 Wh, SurpH/D:1337/0 Wh, OTP:5040/1337 W
..
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Hadl

Zitat von: DS_Starter am 30 Oktober 2025, 14:37:53Meine Vermutung von gestern hat sich erhärtet. Das Ratio ist unter 100% und somit wird auf pinmax gegangen.
Hallo Heiko,
ich hab mich mal selbst an den Code gewagt und folgendes geändert:

- Aktuelle Stunden erhält wieder den Überschuss Anteilig der Rest-Minuten
- Der Überschuss des Rest Tages bis zum letzen Überschuss wird in RemainingSurp gespeichert
- RemainingSurp wird zur SmartPower Margin Berechnung verwendet statt spday
- Wenn der SOC unterhalb lowSoc ist wird die Ladeleistung nichtmehr auf bpinreduced nach oben hin begrenzt, sondern minimal bpinreduced gesetzt.

Damit hab ich schon nen relativ gleichmäßigen Verlauf über den Tag hinbekommen.

Die kleinen Wellen innerhalb einer Stunde möchte ich auch noch wegbekommen, dazu fehlt mir aber gerade der Ansatz. Ich glaube aber ich hab den Grund verstanden.

Wenn ich in einer Stunde 5kWh Überschuss habe, und im Schnitt 1kW brauche, dann passt das zu Beginn der Stunde.
Nach einer halben Stunde rechne ich noch mit 2,5kWh Überschuss in der Stunde. Die Stundenbasierte Suche nach minimaler Ladeleistung sieht also damit immer noch diese Stunde so als könnte man daraus 1kW ziehen. Der Akku ist aber schon voller, dadurch sinkt ungerechtfertigt die Ladeleistung.

Das ganze geht dann bis 10 Minuten vor der vollen Stunde. Dort sind von den 5kW nur noch 1kW übrig, aber auch das wird voll eingerechnet. Wir laden aber diese 1kWh nicht in 10 Minuten rein, sonst müssten wir mit 6kW laden. Hier ist der Fehler am größten.

Anschließend ist weniger als 1kW verfügbar, der Fehler wird kleiner und die Ladeleistung steigt wieder zur notwendigen Leistung hoch.

Hast du eine Idee, wie man die restliche Energiemenge der aktuellen Stunde so einrechnen könnte, das diese nur der minimal notwendigen Ladeleistung mal Rest-Zeit der Stunde entspricht?

Den Verlauf sieht man gut zwischen 13:00 und 15:00
Du darfst diesen Dateianhang nicht ansehen.
schlechtester Punkt wenn OTP ~= SurpH
Zitat2025.10.30 12:51:53 1: PV_SolarForecast DEBUG> ChargeOTP Bat 01 30/12 - hod:13/00, lr/lc:1/1, SocS/E:4524/4638 Wh, SurpH/D/R:880/6407/12207 Wh, OTP:877/731 W

Aber der Fehler ist klein genug so das er von den default Margin leicht aufgefangen wird.

VG

Hadl
FHEM: Rpi 5 + SSD / WR: Fronius Symo Gen24 10.0 Plus + BYD HVS 7.7, Fronius Symo Gen24 12.0 SC (60%) PV: (Ost=3.5 West=6.6 Nord=9.9 Ost=4.5) / Homematic BidCoS / Shelly / Viessmann

Max_Meyer

Zitat von: DS_Starter am 30 Oktober 2025, 14:05:38der Setter "reset" ist nun deutlich aufgewertet. Die KI-Daten lassen sich selektiver löschen:

Guten Morgen Heiko,
Danke! - der Reset klappt gut.
Ich werde jetzt das Ergebnis beobachten - eigentlich müssten die 'Today_PVdeviation' wesentlich besser werden
Viele Grüße
Gerd
FHEM: PI3...5 FB7590/7530/EnOcean/FS20 /Revolt/FHEM2FHEM/HTTPMOD-->Solmaxx-, Deye-, Bosswerk-Inverter/ModBusTCP -->SMA-Inverter, GoE-Charger, BröntjeWP/Solarforecast/DbLog/DbRep/PostgreSQLDB/Grafana/MQTT-->Shelly,FHEM,HMS/HCCON/Netatmo/KLF etc.

DS_Starter

#4385
Moin Hadl,
ich habe mir die Kodierung mal genau angesehen und wir schauen  ob/wo Unterschiede zu finden sind...

Zitat- Aktuelle Stunden erhält wieder den Überschuss Anteilig der Rest-Minuten
- Der Überschuss des Rest Tages bis zum letzen Überschuss wird in RemainingSurp gespeichert
Vermutlich hast du nicht meine Version gändert in #4377 als Vorlage genommen.
Jedenfalls war die Zeitgewichtichtung nicht raus, sondern steckt in $total (= $RemainingSurp  bei dir).

Du hast es nur etwas umgemodelt. Erst das Replacement direkt ersetzt:

      if ($nh eq '00') {
              ...
              $hsurp->{$k}{surplswh} = $replacement;
              ...
      }

Und später:

      for my $h (@remaining_hods) {                                                                             
          my $val = $hsurp->{$h}{nhr} eq '00'
                    ? $replacement // 0
                    : $hsurp->{$h}{surplswh};
         
          $RemainingSurp += int $val;      (heißt bei mir nur $total += int $val;)
      }

Hier wird wird in der Stunde 00 das Replacement verwendet und sonst der Originalwert. Deswegen hättest du oben nicht das Replacement ersetzen müssen sondern nur extrahieren wie ich es bereits getan hatte.
Also bis zu diesem Punkt sind die Versionen identisch, nur dass $total nun $RemainingSurp heißt.
Das ist allerdings ein besserer Name den ich übernehmen werde.

Zitat- RemainingSurp wird zur SmartPower Margin Berechnung verwendet statt spday
Du verwendest:

          if ($strategy eq 'smartPower') {
              $pneedmin = ___batAdjustPowerByMargin ($name,                                                     
                                                     $limpower,
                                                     $bpinmax,
                                                     $runwhneed,
                                                     $otpMargin,
                                                     $RemainingSurp
                                                    );         
          }

Was wieder zu meinem

          if ($strategy eq 'smartPower') {
              $pneedmin = ___batAdjustPowerByMargin ($name,                                                     
                                                     $limpower,
                                                     $bpinmax,
                                                     $runwhneed,
                                                     $otpMargin,
                                                     $total
                                                    );         
          }

identisch ist wegen $total==$RemainingSurp ($spday ist hier schon in der Vorversion raus wenn ich mich recht erinnere).

Hier ist eine Stelle die den Nutzern von optPower wie Parallix nicht gefallen wird:

          my $fref      = ___batFindMinPhWh ($hsurp, \@remaining_hods, $runwhneed);
          my $limpower  = $fref->{ph};


Es wird die gewählte Strategie bzw. Erreichbarkeit des Ziel keine Beachtung mehr geschenkt. Im Original

          my $limpower  = $achievable || $strategy eq 'optPower'
                          ? min ($fref->{ph}, $spls)                                                           
                          : $fref->{ph};

wird eine Fallentscheidung vorgenommen und bei Erreichbarkeit des Ladeziels oder bei optPower Verwendung der Surplus-Wert als (zunächst) begrenzender Wert herangezogen. Achtung: wichtige Unterscheidung in der Ladeaggressivität was natürlich so bleiben soll.

Weiterhin wird nun durch die direkte Replacement-Ersetzung in der Iteration der Überschuß der aktuellen Stunde tendienziell gegen 0 gehen mit fortschreitender Zeit. Das hatte ich schonmal drin und hat sich als kontraproduktiv gezeigt, weswegen es entfernt wurde. 

Das hast du selbst auch erkannt und in dem Text beschrieben:
Zitat....
Die kleinen Wellen innerhalb einer Stunde möchte ich auch noch wegbekommen, dazu fehlt mir aber gerade der Ansatz. Ich glaube aber ich hab den Grund verstanden.

Wenn ich in einer Stunde 5kWh Überschuss habe, und im Schnitt 1kW brauche, dann passt das zu Beginn der Stunde.
Nach einer halben Stunde rechne ich noch mit 2,5kWh Überschuss in der Stunde. Die Stundenbasierte Suche nach minimaler Ladeleistung sieht also damit immer noch diese Stunde so als könnte man daraus 1kW ziehen. Der Akku ist aber schon voller, dadurch sinkt ungerechtfertigt die Ladeleistung.
....

Deswegen verwenden wir für die Iteration die Surplus-Stunden ohne Replacement und berechnen Zielerreichbarkeit und Steilheit der Margin bei smartPower mit dem Replacement. Dann hast du auch keine Wellen mehr in der Leistungsvorgabe bzw. eigentlich ja Ladeleistungsbeschränkung.


Zitat- Wenn der SOC unterhalb lowSoc ist wird die Ladeleistung nichtmehr auf bpinreduced nach oben hin begrenzt, sondern minimal bpinreduced gesetzt.
Das ist nicht gut. Wenn die Ladung unter lowSoc gefallen ist (was eigentlich nicht vorkommen sollte) wird die Batterie ggf. durch Netzstrom geladen. Das soll nur zaghaft mit pinreduced vorgenommen werden.
Aus welchem Grund bist du der Meinung dies ändern zu wollen?

ZitatHast du eine Idee, wie man die restliche Energiemenge der aktuellen Stunde so einrechnen könnte, das diese nur der minimal notwendigen Ladeleistung mal Rest-Zeit der Stunde entspricht?
Deswegen wird die Iteration ohne Zeitgewichtung vorgenommen. Dadurch bleibt die Leistungsbegrenzung über die Stunde weitgehend konstant. Nehmen wir an es ist ein Überschuß von 5kWh für die aktuelle Stunde prognostiziert und in der Gesamtkalkulation reicht es aus mit 1kW über diese eine Stunde zu laden, d.h. eine 1kWh in die Bat zu verbringen. Dann ist es völlig in Ordnung wenn zu Beginn der Stunde mit einer Leistung von 1kW geladen wird und am Ende dieser Stunde ebenfalls. Denn dann haben wir genau 1 kWh in der Batterie unter der Voraussetzung, dass über die gesamte Zeit mehr Überschuß als gewünschte/begrenzte Ladeleistung vorliegt.


LG,
Heiko
Proxmox+Debian+MariaDB, PV: SMA, Victron MPII+Pylontech+CerboGX
Maintainer: SSCam, SSChatBot, SSCal, SSFile, DbLog/DbRep, Log2Syslog, SolarForecast,Watches, Dashboard, PylonLowVoltage
Kaffeekasse: https://www.paypal.me/HMaaz
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/DS_Starter

Hadl

Hallo Heiko,
vielen Dank für deine Analyse.
Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Du hast es nur etwas umgemodelt. Erst das Replacement direkt ersetzt:
Wunderbar, ja das ist mir auch aufgefallen, das man das vereinfachen könnte. Hab mich aber erstmal auf die Energiedaten fokusiert.
Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Also bis zu diesem Punkt sind die Versionen identisch, nur dass $total nun $RemainingSurp heißt.
Ja, das hat mir etwas beim Denken geholfen das umzubenennen, ist aber ansonsten identisch
Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Es wird die gewählte Strategie bzw. Erreichbarkeit des Ziel keine Beachtung mehr geschenkt. Im Original
Code Auswählen Erweitern
          my $limpower  = $achievable || $strategy eq 'optPower'
                          ? min ($fref->{ph}, $spls)                                                           
                          : $fref->{ph};
wird eine Fallentscheidung vorgenommen und bei Erreichbarkeit des Ladeziels oder bei optPower Verwendung der Surplus-Wert als (zunächst) begrenzender Wert herangezogen. Achtung: wichtige Unterscheidung in der Ladeaggressivität was natürlich so bleiben soll.
Ich hab das absichtlich rausgenommen, weil mir das bei meinen Tests einen deutlich ungleichmäßigeren Verlauf beim stundenwechsel gegeben hat.
Das "$fref->{ph}" ist ja schon ein sehr gleichmäßiges Signal und garnicht aggresiv. Es stellt die niedrigsmögliche konstante Ladeleistungsbegrenzung dar mit der mit dem letzten Überschuss am Tag der Akku gerade noch voll wird. Das sah mir hier für beide Strategien hier am besten geeignet aus. Die Aggressivität kommt dann ja hinterher mit den Aufschlägen.
Evtl hilft hier auch schon das die aktuelle Stunde gewichtet eingerechnet wird, wodurch diesen "min" nichtmehr gebraucht wird. Falls doch müsste man $spls durch etwas besseres ersetzen, den am Ende der Stunde war das immer viel zu hoch, wodurch die Stunden-Sägezähne mit verursacht wurden.

Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Weiterhin wird nun durch die direkte Replacement-Ersetzung in der Iteration der Überschuß der aktuellen Stunde tendienziell gegen 0 gehen mit fortschreitender Zeit. Das hatte ich schonmal drin und hat sich als kontraproduktiv gezeigt, weswegen es entfernt wurde. 
Das zu behalten ist aber physikalisch richtig, ich hab nun auch die Lösung dazu gefunden, warum das Probleme gemacht hatte. Dazu hab ich noch eine Zeile in ___batFindMinPhWh eingefügt. Siehe weiter unten.

Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Das ist nicht gut. Wenn die Ladung unter lowSoc gefallen ist (was eigentlich nicht vorkommen sollte) wird die Batterie ggf. durch Netzstrom geladen. Das soll nur zaghaft mit pinreduced vorgenommen werden.
Aus welchem Grund bist du der Meinung dies ändern zu wollen?
Mit der Variante vor meiner Änderung wurde obwohl Überschuss vorhanden war und ein gleichmäßiges Laden mit mittlerer Leistung zum Ladeziel geführt hätte trotzdem nur mit pinreduced geladen. Dadurch wurde vom Überschuss nur wenig genutzt, sobald aber dann SocMin erreicht war musste um wieder aufzuholen mit etwas höherer Leistung weitergeladen werden. Das wiederspricht dem Ziel einer schonenden Akku-Ladung und der Nutzung von Energie für den Fall von Stromausfällen.
Falls überhaupt Netzstrom geladen werden kann, würde das ja nur im Fall fehlender Überschüsse passieren, dann wird auch in meinem Fall bei Null Überschuss mit pinreduced geladen.
Ich habe bei mir sogar nochmal außerhalb des Moduls in dem Fall das SOC < (lowSoc <) OptimumTargetSoC die Ladeleistungsbegrenzung fast komplett rausgenommen und sperre optionale Verbraucher. Ich erlaube aber auch keine Netzladung. (Außer die, die der Wechselrichter selbstständig macht zum Akkuschutz)
Das sieht man bei mir immer früh, wenn in der Nacht der Akku unter 40% sinkt.

Zitat von: DS_Starter am 31 Oktober 2025, 08:57:59Nehmen wir an es ist ein Überschuß von 5kWh für die aktuelle Stunde prognostiziert und in der Gesamtkalkulation reicht es aus mit 1kW über diese eine Stunde zu laden, d.h. eine 1kWh in die Bat zu verbringen. Dann ist es völlig in Ordnung wenn zu Beginn der Stunde mit einer Leistung von 1kW geladen wird und am Ende dieser Stunde ebenfalls. Denn dann haben wir genau 1 kWh in der Batterie unter der Voraussetzung, dass über die gesamte Zeit mehr Überschuß als gewünschte/begrenzte Ladeleistung vorliegt.
Perfekt, ich hatte genau die gleiche Vorstellung. Das hab ich erreicht indem ich noch mit einer Zeile die Zeitgewichtung der aktuellen Stunde in ___batFindMinPhWh eingebaut habe. Dadurch wurde am Ende der Stunde nichtmehr erwartet das man in deinem Beispiel 12 Minuten vor Stundenende von den 5kWh noch 1kWh Überschuss übrig hat und man denke man kann das mit 1kW Leistung reinladen. Das klappt auf 12 Minuten nicht, sondern da kriegt man nur 200Wh rein.
Damit sieht die Leistung heute morgen auch über die Stundengrenzen hinweg super gleichmäßig aus!

Ich hab heute wieder genügend Überschuss und erwarte dadurch eine sehr schonende gleichmäßige Ladung trotz des aggressiveren SmartPowers.
Bisher sehe ich garkeine Stunden-Abweichungen!  :D
Die aggressiveren Varianten könnte ich evtl. am Sonntag mit viel Wolken und Regen wieder sehen.


Viele Grüße

Hadl
FHEM: Rpi 5 + SSD / WR: Fronius Symo Gen24 10.0 Plus + BYD HVS 7.7, Fronius Symo Gen24 12.0 SC (60%) PV: (Ost=3.5 West=6.6 Nord=9.9 Ost=4.5) / Homematic BidCoS / Shelly / Viessmann