Leistungsprognose für Wechselrichter

Begonnen von ch.eick, 18 Januar 2021, 08:35:46

Vorheriges Thema - Nächstes Thema

kask

Ich könnte mir vorstellen das die subs im timing hinken. Aber bei mir bessere Werte liefert weil das eventuell mit meinen Geräten gut harmoniert.
Oder liegt es eventuell daran das die integral funktion nur durch Ganzzahlen teilt und die subs durch floats? Stichwort: Rundungsfehler?
Ich weiß nicht wie das so in Perl von statten geht. Hab dies bezüglich auch nicht wirklich was gefunden.

Das läst mir keine Ruhe. Im Grunde ist es die gleiche Funktion.

DS_Starter

Es gibt noch einen wesentlichen Unterschied.
userReading verwendet und speichert intern $hash->{".updateTime"} der auf gettimeofday() basiert.

Als User hat man nur Zugriff auf ReadingsTimestamp. Der Wert ist nur sekundengenau. Es sei denn man treibt mehr Aufwand und führt die jeweilige Zeit auch separat mit.
Nur mal so aus meiner Perspektive um mögliche Ursachen für Differenzen beider Verfahren zu beschreiben.
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

kask

#2552
Zitat von: DS_Starter am 24 Mai 2023, 23:32:23--> https://perldoc.perl.org/functions/time  dort steht es beschrieben wen es interessiert.

Und wenn man da mal weiter schaut dann findet man folgendes:

time ()

    Returns a floating seconds since the epoch. This function can be imported, resulting in a nice drop-in replacement for the time provided with core Perl; see the "EXAMPLES" below.

    NOTE 1: This higher resolution timer can return values either less or more than the core time(), depending on whether your platform rounds the higher resolution timer values up, down, or to the nearest second to get the core time(), but naturally the difference should be never more than half a second. See also "clock_getres", if available in your system.

    NOTE 2: Since Sunday, September 9th, 2001 at 01:46:40 AM GMT, when the time() seconds since epoch rolled over to 1_000_000_000, the default floating point format of Perl and the seconds since epoch have conspired to produce an apparent bug: if you print the value of Time::HiRes::time() you seem to be getting only five decimals, not six as promised (microseconds). Not to worry, the microseconds are there (assuming your platform supports such granularity in the first place). What is going on is that the default floating point format of Perl only outputs 15 digits. In this case that means ten digits before the decimal separator and five after. To see the microseconds you can use either printf/sprintf with "%.6f", or the gettimeofday() function in list context, which will give you the seconds and microseconds as two separate values.


Da fehlt "nur" die 6te Stelle. Also < einer hunderttausendstell Sekunde. 0.000009.

Aber egal..das guck ich mir an...werde berichten!


btw.: Readingstimestamp wird es sein der das in meinem fall (für mich) optimiert. Mal rumprobieren.

DS_Starter

Gutem Morgen,

bei time() muss man ein bisschen aufpassen.
Das "normale" time aus Perl Core (https://perldoc.perl.org/functions/time) gibt Sekunden zurück.

Das time() aus dem Paket Time::HiRes (https://perldoc.perl.org/5.8.0/Time::HiRes) Returns a floating seconds since the epoch.

Jetzt kommt es darauf an ob time() aus Time::HiRes eingebunden wurde. fhem.pl macht das per default.
Aber ich wollte euch darauf hinweisen dass time nicht gleicht gleich time ist bzw. sein kann.  ;)
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

kask

#2554
Also ich hab mir das alles mal angeguckt.
Die sub umgestrickt mit DS_Starter's anmerkungen (Danke dafür an dich).
Damit funktioniert zählt die sub wie die integral funktion.
Zeit beim aufrufen holen und mit dem alten wert verrechnen. Also hinken die subs im timing.
Ich muss/will die subs erweitern. Mit untenstehender Erweiterung, der Grund kommt jetzt.

Wenn der Zählwert vom positive in den negativen wert fällt, oder umgekehrt, dann wird es kritisch.
Sub:
Bis jetzt wird der Mittelwert betrachtet, auch wenn z.B. es einen neuen positiven Wert hat. Sagen wir 20W..der alte Wert war -100w. Dann würde der Rechnungswert 20w + -100W = -80W /2 = -40w betragen..also würde der Wert in den negativen bereich fallen und da dazu addieren trotz positiven Wert.
Userreadings:
Beim Userreading mit integral würde es folgend aussehen. 20W + 0W = 20W /2 = 10W..Hier wird jetzt positiv gezählt. Da beide Userreadings getrennt sind.
Wenn man jetzt eine PV-Anlage mit Speicher hat der gegen Null regeln will/soll, oder Nulleinspeisung. Dann wird sehr oft von + nach - (über 0) und umgekehrt der Wert wechseln.

Dann verrechnet sich das userreading mit der integral funktion mehr, da es zwei getrennte Readings sind (Zweirichtungszähler).
Ich vermute das das der Grund war/ist warum die werte der subs bei mir besser funktionieren trotz mangelhaftem timing.

Eigentlich müsste man, um es genauer zu machen, die Differenz beider Werte mit dem Zeitanteil bei der mutmasslichen "0-Überquerung" (wir gehen von einer idealen Streck aus, sonst wird es extrem kompliziert) verrechnen. Um dann beide Werte anzupassen.

Das 20/-100 Beispiel.
Wir nehmen an das beide Messungen 10sec. auseinander liegen.
Die Summe ist -80W
Die Differenz 120W.
Also 120W/10s = 12w/s
Anteilig wären das für den:
Positivenwert: 1 / 120W * 20W = 0,16667s * 10s = 1.6667 s
Negativen wert : 10s - 0,16667s = 8,3333s 

Also müssten 20/2 * 1.6667s auf den positiven wert addiert werden.
Und 100/2 * 8,3333s auf den negativen wert addiert werden.

Hier das umgestrickte zum testen,nur der vollständigkeit halber.
sub EnergieCounterInOut($$) {
   my ($device,$reading) = @_;
   my $tnow = (sprintf("%.6f",time()));
   my $told = ReadingsNum($device,"ec".$reading."InOutTime",$tnow);
   my $value = (ReadingsNum($device,$reading,0));
   my $value_old = ReadingsNum($device,"ec".$reading."InOutOld",-$value);
   #my $t_base = (time() - time_str2num(ReadingsTimestamp($device,"ec".$reading."InOutOld",time())) );
   my $t_base = ($tnow  - $told);
   fhem ("setreading ".$device." ec".$reading."InOutOld " . $value);
   my $value_add = ( (($value + $value_old)/2.0) / 3600.0 * $t_base);
   my $total = 0;
   if ($value_add > 0) {
     $total = ((ReadingsNum($device,"ec".$reading."InTotal",0)) + ($value_add/1000));
     fhem ("setreading ".$device." ec".$reading."In " . $value);
fhem ("setreading ".$device." ec".$reading."Out 0");
     fhem ("setreading ".$device." ec".$reading."InTotal " . $total);
   } elsif ($value_add < 0) {
     $total = ((ReadingsNum($device,"ec".$reading."OutTotal",0)) + abs($value_add/1000));
     fhem ("setreading ".$device." ec".$reading."Out " . abs($value));
fhem ("setreading ".$device." ec".$reading."In 0");
     fhem ("setreading ".$device." ec".$reading."OutTotal " . $total);
   } else {
fhem ("setreading ".$device." ec".$reading."In 0");
fhem ("setreading ".$device." ec".$reading."Out 0");
   }
   fhem ("setreading ".$device." ec".$reading."InOutTime " . $tnow);
   return;
}

stefanru

Hi Kask,

ah super dass du es nachstellen konntest.

Sag mal deine Beschreibung mit +20 und -100 verstehe ich zwar, aber passiert das wirklich?
Wenn ich ein Wert mit Plus und Minus habe aber mit folgender Formel auseinander steuere, dann ist das doch nicht so:
User_Energy_Bat_out:PowerFlow_Site_P_Akku.* integral {ReadingsVal("$name","PowerFlow_Site_P_Akku","")>0?ReadingsVal("$name","PowerFlow_Site_P_Akku","")/3600000:0},
User_Energy_Bat_in:PowerFlow_Site_P_Akku.* integral {ReadingsVal("$name","PowerFlow_Site_P_Akku","")<0?ReadingsVal("$name","PowerFlow_Site_P_Akku","")/-3600000:0},

Ich verstehe das so, z.B. bei User_Energy_Bat_out:
Wenn der Wert ReadingsVal("$name","PowerFlow_Site_P_Akku","") > 0 ist wird der Wert zum Integral hinzu, ist er kleiner als 0 wird 0 genommen. Ist das nicht korrekt so?

Gruß,
Stefan

DS_Starter

Damit man keinen Knoten ins Hirn bekommt, kann man sich das Leben etwas einfacher machen.
Ich habe ein MQTT2 Device für meine Pylontech Batterien. In/Out ist auch vorzeichenbehaftet.

Zunächst erstelle ich zwei userReadings für In und Out, die jeweils nur noch positive Werte besitzen:

    

BatIn:DC_Power_value.* {
  my $pwr = ReadingsVal ($name, 'DC_Power_value', 0);
  $pwr    = $pwr > 0 ? $pwr : 0;
  $pwr
},
BatOut:DC_Power_value.* {
  my $pwr = ReadingsVal ($name, 'DC_Power_value', 0);
  $pwr    = $pwr < 0 ? abs $pwr : 0;
  $pwr
},


Die Werte kann man dann separat weiterverarbeiten, stören sich aber nicht gegenseitig. Das vereinfacht die Arbeit damit.
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

kask

Nunja, Ich denke das userreading mit der integral funktioniert super wenn es nur in eine richtung geht. Oder nicht häufig durch 0. dann wird das vernachlässigbar, denke ich. Bei Nulleinspeisung und ständig ändernde lasten verzählt sich das ganze.
Bei Richtungswechseln wird da halt immer von 0 an gerechnet bei Nulldurchgang.
Also wird immer auf die Seite (positiv/negativ) geschrieben was der aktuelle Wert hat aber mit der Zeit von dem letzten schreiben.

Und das geht nur mit einer funktion die beides beherbergt. Mit zwei Userreadings wird das nie gehen. Auch nicht mit getrennten funktionen wie DS_Starter aufgeführt hat.

ZitatWenn der Wert ReadingsVal("$name","PowerFlow_Site_P_Akku","") > 0 ist wird der Wert zum Integral hinzu, ist er kleiner als 0 wird 0 genommen. Ist das nicht korrekt so?
Doch so ist das. Funktioniert ja auch wenn in eine Richtung gezählt wird. Wie z.B. ne Steckdose. Bei einem Zweirichtungsgerät ist das nicht so einfach um relativ genau zu sein. Natürlich hängt das auch von dem Wert ab. bekommst du den schon "aufbereitet" von dem Gerät wird auch das mit den Userreading funktionieren.
Bekommst du es aber nicht aufbereitet sondern den aktuellen Ist wert, dann wird das mit dem Userreading nicht gut funktionieren.

Es steht und fällt mit den Daten die man bekommt.

Ich für mich weiß jetzt warum die integral funktion bei meinen Tests einst andere Werte lieferten wie ich diese erwartet hat.
Das ist gut.

kask

Ich möchte wenn ich was einsetze auch Verstehen was da passiert und warum (wenn da was unplausible für mich ist).
Deshalb bin ich ja auch hier im Thread gelandet weil das Solcastapi timing mich nicht überzeugt hat.
Und DS_Starter hat das gefixt das es für mich, und ich hoffe für andere auch plausibel erscheint.
Ein Dank noch einmal an den Ersteller des Forcast Moduls. Funktioniert für mich und meinem momentanen Vorhaben super!

Und ich habe immer noch 50 Requests auf meinen APIkeys ;)

DS_Starter

Mal wieder zum eigentlichen Thema zurück ...  ;)

Ich bin gerade auf diese Seite https://doc.forecast.solar/api:estimate aufmerksam geworden.
In der freien Version kann man wie ich verstanden habe 12 Stunden lang 4 Requests pro Stunde abrufen.

Das wären 48 Abrufe, also vergleichbar mit SolCast in der früheren Ausprägung.
Es könnte sich für alle User interessant werden die erst neu dazu stoßen.
Über die Qualität kann ich noch nichts sagen.

Kennt jemand diesen Dienst genauer ?

Eine Implementierung und Abrufoptimierung macht vor allem bei mehreren Strings durchaus Aufwand weswegen es schon Sinn machen sollte den Dienst zu intergrieren.
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

stefanru

@Kask: Ja finde ich auch gut dass wir es jetzt verstehen. Möchte ja auch wissen wie Dinge funktionieren.
Habe das heute mal den ganzen Tag bei mir laufen lassen ist bei einem KW Wert bei mir auf 3 Nachkommstellen genau gewesen.
Für mich ist das absolut ausreichend. Klar es kam auch über tag ja nur positive Werte.

@DS_Starter
Für mich wäre das schon interessant.
Ich war bei SolCast zu spät und hätte jetzt nur die 10 Calls.
Arbeite zur Zeit mit DWD, das reicht mir eigentlich auch locker.
Wenn es natürlich besser geht wäre das auch Top.
Ich lese es so dass man beim Free Account 12 Calls pro IP pro Stunde frei hat, also massig.
Die Daten werden beim Free Account auch nur jede Stunde aktualisiert.
Und Daten bekommt man für heute + morgen. Also 48h sollte auch passen.

Der Charm wäre man bräuchte ja nichtmal einen Account sondern nur
:lat - latitude of location, -90 (south) ... 90 (north); handeled with a precission of 0.0001 or abt. 10 m
:lon - longitude of location, -180 (west) ... 180 (east); handeled with a precission of 0.0001 or abt. 10 m
:dec - plane declination, 0 (horizontal) ... 90 (vertical); integer
:az - plane azimuth, -180 ... 180 (-180 = north, -90 = east, 0 = south, 90 = west, 180 = north); integer
:kwp - installed modules power in kilo watt; float

Das müsste dann einfach in den Call einfließen.

Von der Arbeit her musst du natürlich wissen und ich bin auch super zufrieden mit DWD.

Und auch ich will nochmals danke sagen für das tolle Modul.

Gruß,
Stefan



DS_Starter

#2561
Ja ist schon charmant und wir haben auch schon alle benötigten Werte an Board.
Latitude, Longitude kann man im global Device hinterlegen, da gibt es die entsprechenden Attr.

Es reizt mich durchaus, aber vor meinem Urlaub nicht mehr ... muß auch mal ein bisschen pausieren.  ;)

Zur Zeit mache ich ein paar Abrufe per Browser um ein Gefühl für die API und die Abrufmöglichkeiten zu bekommen.

Und wenn ich es richtig lese, werden neben anderen Diensten DarkSky und Wunderground für eine kombinierte Wolkenbedeckungsprognose und die Temperaturen für die Vorhersage der Solarproduktion verwendet.

https://doc.forecast.solar/used_sources

Ist auch witzig, der Dienst heißt Forecast.Solar, das Modul SolarForecast ... Zufälle gibts  :)
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

kask

Ich habe auf jedenfall auch interresse. Benutze beide um zu schauen was besser passt für mich. Aber irgendwie habe ich keinen favoriten bis jetzt. sieht man ja am bild das es mal so mal so ist.

edit.: oben solcast unten DWD

DS_Starter

Bis jetzt habe ich das Gefühl, dass im Winterhalbjahr DWD besser passt, im Sommerhalbjahr SolCast.
Aber in der letzten Zeit passt SolCast bei mir wirklich sehr gut -> Abweichung heute: 3,8 %, gestern: 18,1 %
Davor war die Abweichung auch nur im einstelligen Bereich.

Und bei der Stundenverteilung kann man echt nicht meckern, ist immernoch eine Vorhersage, mehr nicht.
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

stefanru

Wow, das klingt schon ziemlich gut.
Wunderground verwende ich selbst und habe auch eine Wetterstation die dorthin daten meldet.
Greife auch Daten über die API von IBM ab, da ist auch Wunderground dahinter.
Leider gibt es die Wunderground Strahlungswerte nicht in der API, zumindest habe ich in der IBM Doku nichts gefunden.

Also ich finde das forecast.solar klingt sehr interessant.

Dann erstmal einen schönen Urlaub und danach bin ich beim Testen gerne dabei ;-)

Gruß,
Stefan