diff --git a/contrib/DS_Starter/76_SolarForecast.pm b/contrib/DS_Starter/76_SolarForecast.pm index 072b1bb5a..e8a5cd125 100644 --- a/contrib/DS_Starter/76_SolarForecast.pm +++ b/contrib/DS_Starter/76_SolarForecast.pm @@ -132,6 +132,21 @@ my %hset = ( # Ha pvCorrectionFactor_20 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_21 => { fn => \&_setpvCorrectionFactor }, pvCorrectionFactor_Auto => { fn => \&_setpvCorrectionFactorAuto }, + moduleTiltAngle => { fn => \&_setmoduleTiltAngle }, +); + +my %htilt = ( # Neigungswinkel der Solarmodule + "0" => 1.00, # https://www.labri.fr/perso/billaud/travaux/Helios/Helios2/resources/de04/Chapter_4_DE.pdf + "10" => 1.06, + "20" => 1.15, + "30" => 1.35, + "40" => 1.43, + "45" => 1.44, + "50" => 1.47, + "60" => 1.50, + "70" => 1.44, + "80" => 1.35, + "90" => 1.26 ); my @chours = (5..21); # Stunden des Tages mit möglichen Korrekturwerten @@ -240,6 +255,8 @@ sub Set { push @cfs, "pvCorrectionFactor_".sprintf("%02d",$h); } $cf = join " ", @cfs if(@cfs); + + my $tilt = join ",", sort keys %htilt; $setlist = "Unknown argument $opt, choose one of ". "forecastDevice:$fcd ". @@ -248,6 +265,7 @@ sub Set { "meterDevice ". "moduleArea ". "moduleEfficiency ". + "moduleTiltAngle:$tilt ". "pvCorrectionFactor_Auto:on,off ". $cf ; @@ -383,6 +401,24 @@ sub _setmoduleEfficiency { ## no critic "not used" return; } +################################################################ +# Setter moduleTiltAngle +################################################################ +sub _setmoduleTiltAngle { ## no critic "not used" + my $paref = shift; + my $hash = $paref->{hash}; + my $name = $paref->{name}; + my $prop = $paref->{prop} // return qq{no tilt angle was provided}; + + if($prop !~ /[0-9]/x) { + return qq{The tilt angle must be specified by numbers}; + } + + readingsSingleUpdate($hash, "moduleTiltAngle", $prop, 1); + +return; +} + ################################################################ # Setter inverterEfficiency ################################################################ @@ -648,11 +684,11 @@ sub _transferForecastValues { $fh = $fh - ($fd * 24); next if($fd > 1); - - Log3($myName, 5, "$myName - collect DWD data: device=$fcname, rad=fc${fd}_${fh}_Rad1h, wid=fc${fd}_${fh}_ww"); $v = ReadingsVal($fcname, "fc${fd}_${fh}_Rad1h", 0); + Log3($myName, 5, "$myName - collect DWD data: device=$fcname, rad=fc${fd}_${fh}_Rad1h, wid=fc${fd}_${fh}_ww, Val=$v"); + ## PV Forecast ############### if($num == 0) { @@ -666,12 +702,12 @@ sub _transferForecastValues { my $calcpv = calcPVforecast ($myName, $v, $fh); # Vorhersage gewichtet kalkulieren - push @$daref, "${time_str}_PVforecast:".$calcpv; + push @$daref, "${time_str}_PVforecast:".$calcpv." Wh"; push @$daref, "${time_str}_Time:" .TimeAdjust ($epoche); # Zeit fortschreiben - $myHash->{HELPER}{"fc${fd}_".sprintf("%02d",$fh)."_PVforecast"} = $calcpv; # Vorhersagedaten zur Berechnung Korrekturfaktor in Helper speichern + $myHash->{HELPER}{"fc${fd}_".sprintf("%02d",$fh)."_PVforecast"} = $v." Wh"; # original Vorhersagedaten zur Berechnung Auto-Korrekturfaktor in Helper speichern - if($fd == 0 && $calcpv > 0) { # Vorhersagedaten des aktuellen Tages zum manuellen Vergleich in Reading speichern + if($fd == 0 && int $calcpv > 0) { # Vorhersagedaten des aktuellen Tages zum manuellen Vergleich in Reading speichern push @$daref, "Today_Hour".sprintf("%02d",$fh)."_PVforecast:$calcpv"; } @@ -1770,13 +1806,18 @@ sub calcPVforecast { my $fh = shift; # Stunde des Tages my $ma = ReadingsNum ($name, "moduleArea", 0 ); # Solar Modulfläche (gesamt) + my $ta = ReadingsNum ($name, "moduleTiltAngle", 45 ); # Neigungswinkel Solarmodule my $me = ReadingsNum ($name, "moduleEfficiency", $defpvme ); # Solar Modul Wirkungsgrad (%) my $ie = ReadingsNum ($name, "inverterEfficiency", $definve ); # Solar Inverter Wirkungsgrad (%) my $hc = ReadingsNum ($name, "pvCorrectionFactor_".sprintf("%02d",$fh), 1 ); # Korrekturfaktor für die Stunde des Tages - my $pv = sprintf "%.1f", ($rad * $kJtokWh * $ma * $me/100 * $ie/100 * $hc * 1000); + $hc = 1 if(1*$hc == 0); -return $pv." Wh"; + my $pv = sprintf "%.1f", ($rad * $kJtokWh * $ma * $htilt{"$ta"} * $me/100 * $ie/100 * $hc * 1000); + + Log3($name, 5, "$name - calcPVforecast - Hour: ".sprintf("%02d",$fh)." ,moduleTiltAngle factor: ".$htilt{"$ta"}.", pvCorrectionFactor: $hc"); + +return $pv; } ################################################################ @@ -1786,7 +1827,7 @@ sub calcVariance { my $paref = shift; my $myHash = $paref->{myHash}; my $myName = $paref->{myName}; - + my $dcauto = ReadingsVal ($myName, "pvCorrectionFactor_Auto", "off"); # nur bei "on" automatische Varianzkalkulation if($dcauto =~ /^off/x) { Log3($myName, 4, "$myName - automatic Variance calculation is switched off."); @@ -1814,9 +1855,14 @@ sub calcVariance { my $fcnum = int ((split " ", $fcval)[0]); next if(!$fcnum); - my $oldfac = ReadingsNum ($myName, "pvCorrectionFactor_".sprintf("%02d",$h), 1); # bisher definierter Korrekturfaktor my $pvval = ReadingsNum ($myName, "Today_Hour".sprintf("%02d",$h)."_PVreal", 0); + next if(!$pvval); + + my $oldfac = ReadingsNum ($myName, "pvCorrectionFactor_".sprintf("%02d",$h), 1); # bisher definierter Korrekturfaktor + $oldfac = 1 if(1*$oldfac == 0); + my $factor = sprintf "%.2f", ($pvval / $fcnum); # Faktor reale PV / Prognose + Log3($myName, 5, "$myName - Hour: ".sprintf("%02d",$h).", Today PVreal: $pvval, PVforecast: $fcnum"); if(abs($factor - $oldfac) > $maxvariance) { $factor = sprintf "%.2f", ($factor > $oldfac ? $oldfac + $maxvariance : $oldfac - $maxvariance); @@ -2077,6 +2123,15 @@ Um eine Anpassung an die persönliche Anlage zu ermöglichen, können Korrekturf
+ +
+