mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-05-04 22:19:38 +00:00
76_SolarForecast.pm: contrib 0.66.0
git-svn-id: https://svn.fhem.de/fhem/trunk@26256 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
a2545a5a5a
commit
1afe19c07d
@ -120,6 +120,10 @@ BEGIN {
|
|||||||
|
|
||||||
# Versions History intern
|
# Versions History intern
|
||||||
my %vNotesIntern = (
|
my %vNotesIntern = (
|
||||||
|
"0.66.0 "=> "24.07.2022 insert function calcPeaklossByTemp to calculate peak power reduction by temperature ",
|
||||||
|
"0.65.8 "=> "23.07.2022 change calculation of cloud cover in calcRange function ",
|
||||||
|
"0.65.7 "=> "20.07.2022 change performance ratio in calcPVforecast to 0.85 ",
|
||||||
|
"0.65.6 "=> "20.07.2022 change __calcEnergyPieces for consumer types with \$hef{\$cotype}{f} == 1 ",
|
||||||
"0.65.5 "=> "13.07.2022 extend isInterruptable and isAddSwitchOffCond ",
|
"0.65.5 "=> "13.07.2022 extend isInterruptable and isAddSwitchOffCond ",
|
||||||
"0.65.4 "=> "11.07.2022 new function isConsumerLogOn, minor fixes ",
|
"0.65.4 "=> "11.07.2022 new function isConsumerLogOn, minor fixes ",
|
||||||
"0.65.3 "=> "10.07.2022 consumer with mode=must are now interruptable, change hourscsme ",
|
"0.65.3 "=> "10.07.2022 consumer with mode=must are now interruptable, change hourscsme ",
|
||||||
@ -518,8 +522,6 @@ my %weather_ids = (
|
|||||||
);
|
);
|
||||||
|
|
||||||
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
|
my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten
|
||||||
my $defpvme = 16.52; # default Wirkungsgrad Solarmodule
|
|
||||||
my $definve = 98.3; # default Wirkungsgrad Wechselrichter
|
|
||||||
my $kJtokWh = 0.00027778; # Umrechnungsfaktor kJ in kWh
|
my $kJtokWh = 0.00027778; # Umrechnungsfaktor kJ in kWh
|
||||||
my $defmaxvar = 0.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor
|
my $defmaxvar = 0.5; # max. Varianz pro Tagesberechnung Autokorrekturfaktor
|
||||||
my $definterval = 70; # Standard Abfrageintervall
|
my $definterval = 70; # Standard Abfrageintervall
|
||||||
@ -535,10 +537,14 @@ my @dweattrmust = qw(TTT Neff R101 ww SunUp SunRise SunSet);
|
|||||||
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
|
my @draattrmust = qw(Rad1h); # Werte die im Attr forecastProperties des Radiation-DWD_Opendata Devices mindestens gesetzt sein müssen
|
||||||
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
|
my $whistrepeat = 900; # Wiederholungsintervall Schreiben historische Daten
|
||||||
|
|
||||||
my $cldampdef = 35; # Dämpfung (%) des Korrekturfaktors bzgl. effektiver Bewölkung, siehe: https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
|
my $prdef = 0.85; # default Performance Ratio (PR)
|
||||||
|
my $tempcoeffdef = -0.45; # default Temperaturkoeffizient Pmpp (%/°C) lt. Datenblatt Solarzelle
|
||||||
|
my $tempmodinc = 25; # default Temperaturerhöhung an Solarzellen gegenüber Umgebungstemperatur bei wolkenlosem Himmel
|
||||||
|
my $tempbasedef = 25; # Temperatur Module bei Nominalleistung
|
||||||
|
my $cldampdef = 35; # Gewichtung (%) des Korrekturfaktors bzgl. effektiver Bewölkung, siehe: https://www.energie-experten.org/erneuerbare-energien/photovoltaik/planung/sonnenstunden
|
||||||
my $cloud_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
|
my $cloud_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
|
||||||
|
|
||||||
my $rdampdef = 10; # Dämpfung (%) des Korrekturfaktors bzgl. Niederschlag (R101)
|
my $rdampdef = 10; # Gewichtung (%) des Korrekturfaktors bzgl. Niederschlag (R101)
|
||||||
my $rain_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
|
my $rain_base = 0; # Fußpunktverschiebung bzgl. effektiver Bewölkung
|
||||||
|
|
||||||
my $maxconsumer = 9; # maximale Anzahl der möglichen Consumer (Attribut)
|
my $maxconsumer = 9; # maximale Anzahl der möglichen Consumer (Attribut)
|
||||||
@ -572,7 +578,7 @@ my $cssdef = qq{.flowg.text { stroke: none; fill: gray; font-siz
|
|||||||
|
|
||||||
my %hef = ( # Energiedaktoren für Verbrauchertypen
|
my %hef = ( # Energiedaktoren für Verbrauchertypen
|
||||||
"heater" => { f => 1.00, m => 1.00, l => 1.00, mt => 240 },
|
"heater" => { f => 1.00, m => 1.00, l => 1.00, mt => 240 },
|
||||||
"other" => { f => 1.00, m => 1.00, l => 1.00, mt => $defmintime }, # f = Faktor Energieverbrauch in erster Stunde
|
"other" => { f => 1.00, m => 1.00, l => 1.00, mt => $defmintime }, # f = Faktor Energieverbrauch in erster Stunde (wichtig auch für Kalkulation in __calcEnergyPieces !)
|
||||||
"charger" => { f => 1.00, m => 1.00, l => 1.00, mt => 120 }, # m = Faktor Energieverbrauch zwischen erster und letzter Stunde
|
"charger" => { f => 1.00, m => 1.00, l => 1.00, mt => 120 }, # m = Faktor Energieverbrauch zwischen erster und letzter Stunde
|
||||||
"dishwasher" => { f => 0.45, m => 0.10, l => 0.45, mt => 180 }, # l = Faktor Energieverbrauch in letzter Stunde
|
"dishwasher" => { f => 0.45, m => 0.10, l => 0.45, mt => 180 }, # l = Faktor Energieverbrauch in letzter Stunde
|
||||||
"dryer" => { f => 0.40, m => 0.40, l => 0.20, mt => 90 }, # mt = default mintime (Minuten)
|
"dryer" => { f => 0.40, m => 0.40, l => 0.20, mt => 90 }, # mt = default mintime (Minuten)
|
||||||
@ -2981,6 +2987,10 @@ sub __calcEnergyPieces {
|
|||||||
my $ctote = ConsumerVal ($hash, $c, "avgenergy", undef); # gemessener durchschnittlicher Energieverbrauch pro Stunde (Wh)
|
my $ctote = ConsumerVal ($hash, $c, "avgenergy", undef); # gemessener durchschnittlicher Energieverbrauch pro Stunde (Wh)
|
||||||
$ctote //= ConsumerVal ($hash, $c, "power", 0); # alternativer nominaler Energieverbrauch in W (bzw. Wh bezogen auf 1 h)
|
$ctote //= ConsumerVal ($hash, $c, "power", 0); # alternativer nominaler Energieverbrauch in W (bzw. Wh bezogen auf 1 h)
|
||||||
|
|
||||||
|
if (int($hef{$cotype}{f}) == 1) { # bei linearen Verbrauchertypen die nominale Leistungsangabe verwenden statt Durchschnitt
|
||||||
|
$ctote = ConsumerVal ($hash, $c, "power", 0);
|
||||||
|
}
|
||||||
|
|
||||||
my $epiecef = $ctote * $hef{$cotype}{f}; # Gewichtung erste Laufstunde
|
my $epiecef = $ctote * $hef{$cotype}{f}; # Gewichtung erste Laufstunde
|
||||||
my $epiecel = $ctote * $hef{$cotype}{l}; # Gewichtung letzte Laufstunde
|
my $epiecel = $ctote * $hef{$cotype}{l}; # Gewichtung letzte Laufstunde
|
||||||
|
|
||||||
@ -6321,7 +6331,6 @@ sub calcPVforecast {
|
|||||||
|
|
||||||
my $type = $hash->{TYPE};
|
my $type = $hash->{TYPE};
|
||||||
my $stch = $data{$type}{$name}{strings}; # String Configuration Hash
|
my $stch = $data{$type}{$name}{strings}; # String Configuration Hash
|
||||||
my $pr = 1.0; # Performance Ratio (PR)
|
|
||||||
my $fh1 = $fh+1;
|
my $fh1 = $fh+1;
|
||||||
|
|
||||||
my $chour = strftime "%H", localtime($t+($num*3600)); # aktuelle Stunde
|
my $chour = strftime "%H", localtime($t+($num*3600)); # aktuelle Stunde
|
||||||
@ -6342,7 +6351,9 @@ sub calcPVforecast {
|
|||||||
my $cloudcover = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), "cloudcover", 0); # effektive Wolkendecke nächste Stunde X
|
my $cloudcover = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), "cloudcover", 0); # effektive Wolkendecke nächste Stunde X
|
||||||
my $ccf = 1 - ((($cloudcover - $cloud_base)/100) * $clouddamp/100); # Cloud Correction Faktor mit Steilheit und Fußpunkt
|
my $ccf = 1 - ((($cloudcover - $cloud_base)/100) * $clouddamp/100); # Cloud Correction Faktor mit Steilheit und Fußpunkt
|
||||||
|
|
||||||
my $range = calcRange ($cloudcover); # V 0.50.1 # Range errechnen
|
my $range = calcRange ($cloudcover); # Range errechnen
|
||||||
|
|
||||||
|
my $temp = NexthoursVal ($hash, "NextHour".sprintf("%02d",$num), "temp", $tempbasedef); # vorhergesagte Temperatur Stunde X
|
||||||
|
|
||||||
## Ermitteln des relevanten Autokorrekturfaktors
|
## Ermitteln des relevanten Autokorrekturfaktors
|
||||||
if ($uac eq "on") { # Autokorrektur soll genutzt werden
|
if ($uac eq "on") { # Autokorrektur soll genutzt werden
|
||||||
@ -6375,18 +6386,33 @@ sub calcPVforecast {
|
|||||||
|
|
||||||
for my $st (@strings) { # für jeden String der Config ..
|
for my $st (@strings) { # für jeden String der Config ..
|
||||||
my $peak = $stch->{"$st"}{peak}; # String Peak (kWp)
|
my $peak = $stch->{"$st"}{peak}; # String Peak (kWp)
|
||||||
|
|
||||||
|
$paref->{peak} = $peak;
|
||||||
|
$paref->{cloudcover} = $cloudcover;
|
||||||
|
$paref->{temp} = $temp;
|
||||||
|
|
||||||
|
my ($peakloss, $modtemp) = calcPeaklossByTemp ($paref); # Reduktion Peakleistung durch Temperaturkoeffizienten der Module (vorzeichengehaftet)
|
||||||
|
$peak += $peakloss;
|
||||||
|
|
||||||
|
delete $paref->{peak};
|
||||||
|
delete $paref->{cloudcover};
|
||||||
|
delete $paref->{temp};
|
||||||
|
|
||||||
$peak *= 1000; # kWp in Wp umrechnen
|
$peak *= 1000; # kWp in Wp umrechnen
|
||||||
my $ta = $stch->{"$st"}{tilt}; # Neigungswinkel Solarmodule
|
my $ta = $stch->{"$st"}{tilt}; # Neigungswinkel Solarmodule
|
||||||
my $moddir = $stch->{"$st"}{dir}; # Ausrichtung der Solarmodule
|
my $moddir = $stch->{"$st"}{dir}; # Ausrichtung der Solarmodule
|
||||||
|
|
||||||
my $af = $hff{$ta}{$moddir} / 100; # Flächenfaktor: http://www.ing-büro-junge.de/html/photovoltaik.html
|
my $af = $hff{$ta}{$moddir} / 100; # Flächenfaktor: http://www.ing-büro-junge.de/html/photovoltaik.html
|
||||||
|
|
||||||
my $pv = sprintf "%.1f", ($rad * $af * $kJtokWh * $peak * $pr * $ccf * $rcf);
|
my $pv = sprintf "%.1f", ($rad * $af * $kJtokWh * $peak * $prdef * $ccf * $rcf);
|
||||||
|
|
||||||
$lh = { # Log-Hash zur Ausgabe
|
$lh = { # Log-Hash zur Ausgabe
|
||||||
"moduleDirection" => $moddir,
|
"moduleDirection" => $moddir,
|
||||||
"modulePeakString" => $peak." W",
|
"modulePeakString" => $peak." W",
|
||||||
"moduleTiltAngle" => $ta,
|
"moduleTiltAngle" => $ta,
|
||||||
|
"Forecasted temperature" => $temp." °C",
|
||||||
|
"Module Temp (calculated)" => $modtemp." °C",
|
||||||
|
"Loss String Peak Power by Temp" => $peakloss." kWP",
|
||||||
"Area factor" => $af,
|
"Area factor" => $af,
|
||||||
"Cloudcover" => $cloudcover,
|
"Cloudcover" => $cloudcover,
|
||||||
"CloudRange" => $range,
|
"CloudRange" => $range,
|
||||||
@ -6445,6 +6471,40 @@ sub calcPVforecast {
|
|||||||
return $pvsum;
|
return $pvsum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
###################################################################
|
||||||
|
# Zellen Leistungskorrektur Einfluss durch Wärmekoeffizienten
|
||||||
|
# berechnen
|
||||||
|
#
|
||||||
|
# Die Nominalleistung der Module wird bei 25 Grad
|
||||||
|
# Umgebungstemperatur und bei 1.000 Watt Sonneneinstrahlung
|
||||||
|
# gemessen.
|
||||||
|
# Steigt die Temperatur um 1 Grad Celsius sinkt die Modulleistung
|
||||||
|
# typisch um 0,4 Prozent. Solartellen können im Sommer 70°C heiß
|
||||||
|
# werden.
|
||||||
|
#
|
||||||
|
# Das würde für eine 10 kWp Photovoltaikanlage folgenden
|
||||||
|
# Leistungsverlust bedeuten:
|
||||||
|
#
|
||||||
|
# Leistungsverlust = -0,4%/K * 45K * 10 kWp = 1,8 kWp
|
||||||
|
#
|
||||||
|
# https://www.enerix.de/photovoltaiklexikon/temperaturkoeffizient/
|
||||||
|
#
|
||||||
|
###################################################################
|
||||||
|
sub calcPeaklossByTemp {
|
||||||
|
my $paref = shift;
|
||||||
|
my $hash = $paref->{hash};
|
||||||
|
my $name = $paref->{name};
|
||||||
|
my $peak = $paref->{peak} // return (0,0);
|
||||||
|
my $cloudcover = $paref->{cloudcover} // return (0,0); # vorhergesagte Wolkendecke Stunde X
|
||||||
|
my $temp = $paref->{temp} // return (0,0); # vorhergesagte Temperatur Stunde X
|
||||||
|
|
||||||
|
my $modtemp = $temp + ($tempmodinc * (1 - ($cloudcover/100))); # kalkulierte Modultemperatur
|
||||||
|
|
||||||
|
my $peakloss = sprintf "%.2f", $tempcoeffdef * ($temp - $tempbasedef) * $peak / 100;
|
||||||
|
|
||||||
|
return ($peakloss, $modtemp);
|
||||||
|
}
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# 70% Regel kalkulieren
|
# 70% Regel kalkulieren
|
||||||
################################################################
|
################################################################
|
||||||
@ -6678,7 +6738,8 @@ return;
|
|||||||
sub calcRange {
|
sub calcRange {
|
||||||
my $range = shift;
|
my $range = shift;
|
||||||
|
|
||||||
$range = sprintf("%.0f", $range/10);
|
#$range = sprintf "%.0f", $range/10;
|
||||||
|
$range = sprintf "%.0f", $range;
|
||||||
|
|
||||||
return $range;
|
return $range;
|
||||||
}
|
}
|
||||||
@ -7032,7 +7093,7 @@ sub listDataPool {
|
|||||||
my $cret;
|
my $cret;
|
||||||
for my $ckey (sort keys %{$h->{$idx}}) {
|
for my $ckey (sort keys %{$h->{$idx}}) {
|
||||||
if(ref $h->{$idx}{$ckey} eq "HASH") {
|
if(ref $h->{$idx}{$ckey} eq "HASH") {
|
||||||
my $hk;
|
my $hk = qq{};
|
||||||
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{$ckey}}) {
|
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{$ckey}}) {
|
||||||
$hk .= " " if($hk);
|
$hk .= " " if($hk);
|
||||||
$hk .= "$f=".$h->{$idx}{$ckey}{$f};
|
$hk .= "$f=".$h->{$idx}{$ckey}{$f};
|
||||||
@ -7069,22 +7130,26 @@ sub listDataPool {
|
|||||||
my $batin = CircularVal ($hash, $idx, "batin", "-");
|
my $batin = CircularVal ($hash, $idx, "batin", "-");
|
||||||
my $batout = CircularVal ($hash, $idx, "batout", "-");
|
my $batout = CircularVal ($hash, $idx, "batout", "-");
|
||||||
|
|
||||||
my $pvcf;
|
my $pvcf = qq{};
|
||||||
if(ref $pvcorrf eq "HASH") {
|
if(ref $pvcorrf eq "HASH") {
|
||||||
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{pvcorrf}}) {
|
for my $f (sort {$a<=>$b} keys %{$h->{$idx}{pvcorrf}}) {
|
||||||
$pvcf .= " " if($pvcf);
|
$pvcf .= " " if($pvcf);
|
||||||
$pvcf .= "$f=".$h->{$idx}{pvcorrf}{$f};
|
$pvcf .= "$f=".$h->{$idx}{pvcorrf}{$f};
|
||||||
|
my $ct = ($pvcf =~ tr/=// // 0) / 10;
|
||||||
|
$pvcf .= "\n " if($ct =~ /^([1-9])?$/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$pvcf = $pvcorrf;
|
$pvcf = $pvcorrf;
|
||||||
}
|
}
|
||||||
|
|
||||||
my $cfq;
|
my $cfq = qq{};
|
||||||
if(ref $quality eq "HASH") {
|
if(ref $quality eq "HASH") {
|
||||||
for my $q (sort {$a<=>$b} keys %{$h->{$idx}{quality}}) {
|
for my $q (sort {$a<=>$b} keys %{$h->{$idx}{quality}}) {
|
||||||
$cfq .= " " if($cfq);
|
$cfq .= " " if($cfq);
|
||||||
$cfq .= "$q=".$h->{$idx}{quality}{$q};
|
$cfq .= "$q=".$h->{$idx}{quality}{$q};
|
||||||
|
my $ct1 = ($cfq =~ tr/=// // 0) / 10;
|
||||||
|
$cfq .= "\n " if($ct1 =~ /^([1-9])?$/);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@ -8648,8 +8713,9 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
|
|||||||
|
|
||||||
<a id="SolarForecast-attr-cloudFactorDamping"></a>
|
<a id="SolarForecast-attr-cloudFactorDamping"></a>
|
||||||
<li><b>cloudFactorDamping </b><br>
|
<li><b>cloudFactorDamping </b><br>
|
||||||
Prozentuale Berücksichtigung (Dämpfung) des Bewölkungprognosefaktors bei der solaren Vorhersage. <br>
|
Prozentuale Mehrgewichtung der Berücksichtigung des Bewölkungsfaktors bei der solaren Vorhersage. <br>
|
||||||
Größere Werte vermindern, kleinere Werte erhöhen tendenziell den prognostizierten PV Ertrag.<br>
|
Größere Werte vermindern, kleinere Werte erhöhen tendenziell den prognostizierten PV Ertrag (Dämpfung der PV
|
||||||
|
Prognose durch den Bewölkungsfaktor).<br>
|
||||||
(default: 35)
|
(default: 35)
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
@ -9046,8 +9112,9 @@ Ein/Ausschaltzeiten sowie deren Ausführung vom SolarForecast Modul übernehmen
|
|||||||
|
|
||||||
<a id="SolarForecast-attr-rainFactorDamping"></a>
|
<a id="SolarForecast-attr-rainFactorDamping"></a>
|
||||||
<li><b>rainFactorDamping </b><br>
|
<li><b>rainFactorDamping </b><br>
|
||||||
Prozentuale Berücksichtigung (Dämpfung) des Regenprognosefaktors bei der solaren Vorhersage. <br>
|
Prozentuale Mehrgewichtung der Berücksichtigung des Regenprognosefaktors bei der solaren Vorhersage. <br>
|
||||||
Größere Werte vermindern, kleinere Werte erhöhen tendenziell den prognostizierten PV Ertrag.<br>
|
Größere Werte vermindern, kleinere Werte erhöhen tendenziell den prognostizierten PV Ertrag (Dämpfung der PV
|
||||||
|
Prognose durch den Regenfaktor).<br>
|
||||||
(default: 10)
|
(default: 10)
|
||||||
</li>
|
</li>
|
||||||
<br>
|
<br>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user