Prognosebasierte Ladesteuerung für Sungrow SH10RT

Begonnen von FhemPiUser, 11 Februar 2023, 10:32:20

Vorheriges Thema - Nächstes Thema

FhemPiUser

Ich habe eine prognosebasierte Ladesteuerung für den Sungrow SH10RT realisiert mit Hilfe von httpmod auf api.forecast.solar (public / free account model). Ich hatte mehrere private Anfragen dazu, aber ich kann den Support nicht leisten. Daher teile hier meine Konfiguration für die Community, falls jemand Interesse hat.

Für jedes MPPT habe ich ein httpmod erstellen. Abfrage / URL ist https://api.forecast.solar/estimate/:lat/:lon/:dec/:az/:kwp (siehe https://doc.forecast.solar/api:estimate).


defmod httpmod_forecast_solar_SH10RT_1_MPPT1 HTTPMOD https://api.forecast.solar/estimate/<lat>/<lon>/<dec>/<az>/<kwp> 3600
attr httpmod_forecast_solar_SH10RT_1_MPPT1 bodyDecode auto
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading01JSON result_watts_.*10\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading01Name watts_10
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading02JSON result_watts_.*11\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading02Name watts_11
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading03JSON result_watts_.*12\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading03Name watts_12
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading04JSON result_watts_.*13\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading04Name watts_13
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading05JSON result_watts_.*14\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading05Name watts_14
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading06JSON result_watts_.*15\:00\:00
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading06Name watts_15
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading07JSON message_ratelimit_period
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading07Name message_ratelimit_period
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading08JSON message_ratelimit_limit
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading08Name message_ratelimit_limit
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading09JSON message_ratelimit_remaining
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading09Name message_ratelimit_remaining
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading10JSON message_type
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading10Name message_type
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading11JSON result_watt_hours_day.*
attr httpmod_forecast_solar_SH10RT_1_MPPT1 reading11Name watt_hours_day
attr httpmod_forecast_solar_SH10RT_1_MPPT1 room HTTPMOD,PV-Anlage,Wettervorhersage
attr httpmod_forecast_solar_SH10RT_1_MPPT1 stateFormat watt_hours_day-1
attr httpmod_forecast_solar_SH10RT_1_MPPT1 userReadings watts-mittags-heute {(ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_10-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_11-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_12-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_13-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_14-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_15-1","0"))/6}, watts-mittags-morgen {(ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_10-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_11-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_12-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_13-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_14-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watts_15-2","0"))/6}


Dann zwei dummys für die prognostizierte Leistung heute und morgen


defmod PV_forecast_heute dummy
defmod PV_forecast_morgen dummy


und ein DOIF der diese jede Stunde setzt


defmod di_PV_forecast DOIF ([+01:00]) ({fhem("set PV_forecast_heute ".sprintf("%.2f",((ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watt_hours_day-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT2","watt_hours_day-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_2_MPPT1","watt_hours_day-1","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_2_MPPT2","watt_hours_day-1","0"))/1000)))}) ({fhem("set PV_forecast_morgen ".sprintf("%.2f",((ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT1","watt_hours_day-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_1_MPPT2","watt_hours_day-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_2_MPPT1","watt_hours_day-2","0")+ReadingsVal("httpmod_forecast_solar_SH10RT_2_MPPT2","watt_hours_day-2","0"))/1000)))})
attr di_PV_forecast do always


Dann die DOIFs zum prognosebasierten Setzen der Max_SOC-Werte. Idee ist, dass 1) bei genug Sonne mittags geladen wird, um den Eigenverbrauch zu optimieren und die 70% Wirkleistungsbegrenzung optimal auszunutzen und 2) den Akku möglichst kurz ganz voll zu haben (abhängig vom Sonnenuntergang), um diesen zu schonen.

Des Weiteren soll 100% ca. alle 7 Tage erreicht werden (sonst nur 99%), um die automatische Wartung zu vermeiden und den Akku zu schonen.


defmod di_PV_Akku_Ladesteuerung_Max_SOC DOIF (([?PV_forecast_heute] > 50) and ([05:00]) and (($month >= 3) and ($month <= 10))) ({&setIfChanged("SH10rt_1","Max_Charging_Power","3");;;; &setIfChanged("SH10rt_1","Max_SOC",(ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "50") > 50 ? (ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "50")) : 50)) }) DOELSEIF (([?PV_forecast_heute] > 50) and (($month >= 3) and ($month <= 10)) and ([11:30])) ({&setIfChanged("SH10rt_1","Max_Charging_Power","2");;;; &setIfChanged("SH10rt_1","Max_SOC",(ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "80") > 80 ? (ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "80")) : 80)) }) DOELSEIF ([{sunset("REAL",-12600,"13:00","20:00")}]) ({&setIfChanged("SH10rt_1","Max_SOC",((ReadingsAge("SH10rt_1","SOC100_erreicht", "0") > 604800) ? 100 : ((([PV_forecast_morgen] < 25) or (($month < 3) or ($month > 10))) ? 99 : (ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "90") > 90 ? (ReadingsVal("SH10rt_1","Battery_Level_korrigiert", "90")) : 90))));;;; &setIfChanged("SH10rt_1","Max_Charging_Power","5") })
attr di_PV_Akku_Ladesteuerung_Max_SOC do always


Dann die DOIFs zum prognosebasierten Setzen der Min_SOC-Werte (bzw. "Reserved SOC for backup" bei netzunabhängigem Betrieb/Notstrom). Idee ist, dass wenn am nächsten Tag viel Sonne ist den Abend vorher stark entladen wird bzw. der Akku ausgenutzt wird. Wenn aber im Winter der nächste Tag kaum Sonne ist, nur etwa halb entladen wird, um den Akku zu schonen (sollte nicht lange Zeit bei z.B. 5% Ladung rumdümpeln) und Reserven für Notstrom vorzuhalten.


defmod di_PV_Akku_Ladesteuerung_Min_SOC DOIF ([19:30] and (($month < 3) or ($month > 10))) ({ &setIfChanged("SH10rt_1",(([SH10rt_1:Off-Grid-Option] == 170) ? "Reserved_SOC_for_backup" : "Min_SOC"),(([PV_forecast_morgen] < 10) ? 60 : (([PV_forecast_morgen] < 40) ? 45 : 15))) }) DOELSEIF ([20:00] and (($month >= 3) and ($month <= 10))) ({ &setIfChanged("SH10rt_1",(([SH10rt_1:Off-Grid-Option] == 170) ? "Reserved_SOC_for_backup" : "Min_SOC"),(([SH10rt_1:Battery_Level_korrigiert] < 40) ? 10 : 5)) })
attr di_PV_Akku_Ladesteuerung_Min_SOC do always


Eine Funktion &setIfChanged habe ich in 99_myUtils.pm eingeführt, um unnötiges Registerschreiben zu vermeiden und damit die Lebensdauer unnötig zu verkürzen:


sub setIfChanged($$$)
{
  my ($device,$reading,$value) = @_;
 
 
  my $redVal = ReadingsVal($device,$reading,"0");
  if ($redVal != $value) {
    {fhem("set ".$device." ".$reading." ".$value);}
  }
}


Die entsprechenden Register und userreadings im modbusattr des SH10rt sind wie folgt:


attr SH10rt_1 obj-i13022-expr $val/10
attr SH10rt_1 obj-i13022-poll 1
attr SH10rt_1 obj-i13022-reading Battery_Level

attr SH10rt_1 obj-h33046-expr $val/100
attr SH10rt_1 obj-h33046-poll 1
attr SH10rt_1 obj-h33046-polldelay x10
attr SH10rt_1 obj-h33046-reading Max_Charging_Power
attr SH10rt_1 obj-h33046-set 1
attr SH10rt_1 obj-h33046-setexpr $val*100
attr SH10rt_1 obj-h33046-type U16

attr SH10rt_1 obj-h13057-expr $val/10
attr SH10rt_1 obj-h13057-poll 1
attr SH10rt_1 obj-h13057-polldelay x10
attr SH10rt_1 obj-h13057-reading Max_SOC
attr SH10rt_1 obj-h13057-set 1
attr SH10rt_1 obj-h13057-setexpr $val*10

attr SH10rt_1 obj-h13058-expr $val/10
attr SH10rt_1 obj-h13058-poll 1
attr SH10rt_1 obj-h13058-polldelay x10
attr SH10rt_1 obj-h13058-reading Min_SOC
attr SH10rt_1 obj-h13058-set 1
attr SH10rt_1 obj-h13058-setexpr $val*10

attr SH10rt_1 obj-h13074-hint 170,85
attr SH10rt_1 obj-h13074-poll 1
attr SH10rt_1 obj-h13074-polldelay x10
attr SH10rt_1 obj-h13074-reading Off-Grid-Option
attr SH10rt_1 obj-h13074-set 1

attr SH10rt_1 userReadings Battery_Level_korrigiert:Battery_Level.* {sprintf("%.1f", ReadingsVal("SH10rt_1","Min_SOC","0")+(ReadingsVal("SH10rt_1","Battery_Level","0")*(ReadingsVal("SH10rt_1","Max_SOC","0")-ReadingsVal("SH10rt_1","Min_SOC","0"))/100));;},SOC100_erreicht:Battery_Level_korrigiert.* {if (ReadingsVal("SH10rt_1","Battery_Level_korrigiert","0") >=100) {return ReadingsTimestamp("SH10rt_1","Battery_Level_korrigiert","0");;} else { return undef;; }}


Ich hoffe es hilft.

softwear

Wie akkurat sind denn Deine erfahrenen Prognosewerte der api? Hast Du Statistiken erstellt bzw. eine Gesamtwertigkeit/-genauigkeit errechnet? Ist schon interessant, dieser Weg.

FhemPiUser

Die Genauigkeit des Forecasts ist aus meiner Sicht für die Lade-Logik absolut ausreichend. Ich nutze das jetzt seit fast einem Jahr und beobachte das täglich und bis jetzt hätte ich das manuell auch nicht anders gemacht.

Es gibt schon Abweichungen des Forecasts zu den nachher gemessenen Werten, aber die Lade-Logik unterscheidet am Ende ja nur zwischen "es wird ausreichend sonnig (>50)" und "es gibt kaum Sonne (<25)". Dafür reicht die Genauigkeit.

DS_Starter

ESXi@NUC+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

ch.eick

Oder auch für die Datenbank Liebhaber

Eine KI Prognose, die ohne Cloud Dienst läuft
, ist aber auch noch nicht im Wiki.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

softwear

Danke euch! Ich werde die Optionen alle mal durcharbeiten.

DS_Starter

Die Unterstützung für die api.forecast.solar API baue ich gerade ein.
Diese API scheint einige sehr brauchbare Vorteile anzubieten.
ESXi@NUC+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

ch.eick

#7
Zitat von: FhemPiUser am 25 Mai 2023, 16:39:02Die Genauigkeit des Forecasts ist aus meiner Sicht für die Lade-Logik absolut ausreichend. Ich nutze das jetzt seit fast einem Jahr und beobachte das täglich und bis jetzt hätte ich das manuell auch nicht anders gemacht.

Es gibt schon Abweichungen des Forecasts zu den nachher gemessenen Werten, aber die Lade-Logik unterscheidet am Ende ja nur zwischen "es wird ausreichend sonnig (>50)" und "es gibt kaum Sonne (<25)". Dafür reicht die Genauigkeit.
Ich verwende ja seit geraumer Zeit die KI Prognose, ohne Cloud Dienst, in Verbindung mit DbLog MySQL und habe jetzt mal die Abweichung ermittel.
2023-05-28 17:00:00 5965 8137 36.4
2023-05-28 16:00:00 9168 10223 11.5
2023-05-28 15:00:00 10604 12075 13.9
2023-05-28 14:00:00 12270 13226 7.8
2023-05-28 13:00:00 13359 13555 1.5
2023-05-28 12:00:00 13201 13157 -0.3
2023-05-28 11:00:00 12279 11879 -3.3
2023-05-28 10:00:00 10574 9759 -7.7
2023-05-28 09:00:00 8739 7420 -15.1
2023-05-27 17:00:00 5965 8321 39.5
2023-05-27 16:00:00 9168 10484 14.4
2023-05-27 15:00:00 10604 12135 14.4
2023-05-27 14:00:00 12270 13373 9.0
2023-05-27 13:00:00 12859 13631 6.0
2023-05-27 12:00:00 12684 13071 3.1
2023-05-27 11:00:00 11783 11690 -0.8
2023-05-27 10:00:00 10446 9522 -8.8
2023-05-27 09:00:00 8775 7261 -17.3
2023-05-26 17:00:00 5965 8174 37.0
2023-05-26 16:00:00 8990 10390 15.6
2023-05-26 15:00:00 10604 12228 15.3
2023-05-26 14:00:00 12270 13502 10.0
2023-05-26 13:00:00 13292 13720 3.2
2023-05-26 12:00:00 13062 13212 1.1
2023-05-26 11:00:00 11738 11962 1.9
2023-05-26 10:00:00 10350 9907 -4.3
2023-05-26 09:00:00 8748 7483 -14.5
2023-05-26 08:00:00 6264 5966 -4.8
2023-05-25 17:00:00 5965 8274 38.7
2023-05-25 16:00:00 8833 10463 18.5
2023-05-25 15:00:00 9868 12270 24.3
2023-05-25 14:00:00 11241 13391 19.1
2023-05-25 13:00:00 12154 13801 13.6
2023-05-25 12:00:00 11837 13434 13.5
2023-05-25 11:00:00 11306 11993 6.1
2023-05-25 10:00:00 10460 9866 -5.7
2023-05-25 09:00:00 8651 7426 -14.2
2023-05-25 08:00:00 6233 5229 -16.1
2023-05-24 18:00:00 3108 4892 57.4
2023-05-24 17:00:00 5965 9168 53.7
2023-05-24 15:00:00 9124 7819 -14.3
2023-05-24 14:00:00 9351 12187 30.3
2023-05-24 13:00:00 9126 13971 53.1
2023-05-24 12:00:00 9417 13893 47.5
2023-05-24 11:00:00 10127 10135 0.1
2023-05-24 10:00:00 9236 8089 -12.4
2023-05-24 09:00:00 7672 7465 -2.7
2023-05-24 08:00:00 5846 5304 -9.3
2023-05-23 18:00:00 3108 3685 18.6
2023-05-23 17:00:00 5799 5581 -3.8
2023-05-23 16:00:00 7289 6396 -12.3
2023-05-23 14:00:00 8519 8297 -2.6
2023-05-23 13:00:00 8588 8101 -5.7
2023-05-22 18:00:00 3108 2847 -8.4
2023-05-22 17:00:00 5785 8012 38.5
2023-05-22 16:00:00 6918 9511 37.5
2023-05-22 15:00:00 8023 9652 20.3
2023-05-22 14:00:00 10462 12548 19.9
2023-05-22 13:00:00 11921 11543 -3.2
2023-05-22 12:00:00 11396 10964 -3.8
2023-05-22 10:00:00 9944 10520 5.8
2023-05-22 09:00:00 7978 7670 -3.9
2023-05-22 08:00:00 5602 5165 -7.8

Im Winter sieht es dann oft natürlich schlechter aus, da dort die Wolken und andere Unwegsamkeiten zu starken Schwankungen führen.

VG  Christian
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick

FhemPiUser

Interessant, aber was zeigt die Tabelle / spalten genau?

Die andere Frage ist, was die Auswirkungen der höheren Genauigkeit auf die Ladelogik sind bzw was am Ende dann der Nutzen der höheren Genauigkeit ist.

Ich bin bisher zufrieden mit dem einfachen Ansatz bzw hab nichts vermisst, lass mich aber gerne überzeugen.

ch.eick

Zitat von: FhemPiUser am 11 Juni 2023, 13:06:09Interessant, aber was zeigt die Tabelle / spalten genau?

Die andere Frage ist, was die Auswirkungen der höheren Genauigkeit auf die Ladelogik sind bzw was am Ende dann der Nutzen der höheren Genauigkeit ist.
Die Tabelle zeigt nur die KI Prognose und den echten Ertrag mit der Abweich in % . Es sollte nur als Vergleich zu der Prognose über einen cloud Dienst und der KI Prognose als Beispiel herhalten.
Außer dem Wetter, dem Sonnenstand und dem tatsächlichen Ertrag braucht die KI keinerlei Angaben zur PV-Anlage.
Eine noch höhere Genauigkeit bringt nicht wirklich einen Vorteil.
RPI4; Docker; CUNX; Eltako FSB61NP; SamsungTV H-Serie; Sonos; Vallox; Luxtronik; 3x FB7490; Stromzähler mit DvLIR; wunderground; Plenticore 10 mit BYD; EM410; SMAEM; Modbus TCP
Contrib: https://svn.fhem.de/trac/browser/trunk/fhem/contrib/ch.eick