Integralfunktion bei UserReadings

Begonnen von simonberry, 19 August 2014, 16:29:39

Vorheriges Thema - Nächstes Thema

simonberry

Hallo zusammen,

ich habe mich gestern länger mal mit den userReadings beschäftigt, und mir ist aufgefallen, dass es zwar die Differentalfunktion (Ableitung) gibt aber nicht die Umkehrfunktion dazu, also die Integralfunktion.
Anwendungsbeispiel Differentialfunktion:
* Aus einem Energiezähler (kWh) die aktuelle Leistung berechnen (kW)
Anwendungsbeispiel Integralfunktion:
* Aus einer aktuellen Leistung (kW) die Energie berechnen.  (kWh)

Meine Vorstellung der Funktion:
Es wird die Zeitdifferenz zwischen den beiden letzten Messungen multipliziert mit dem Mittelwert der letzen beiden Messsungen  und zum alten "Reading" addiert.
Reading = Reading + difftime * (oldvalue + value) / 2

Da ich so Neugierig bin habe ich mal in den Sourcen nach "differential" gegreped und bin in fhem.pl fündig geworden. (Oh Gott das Herzstück  :o)
Mit den bereits vorhandenen Berechnungsmethoden war es mir ein leichtes mein Vorhaben umzusetzen.  ;)

Ich habe das mal bei mir mit ein paar Handgriffen in der fhem.pl eingebaut und es funktioniert ganz prima:  :D
in der Funktion CommandAttr hinter "differential" "integral" eingetragen

        if(grep { /$modifier/ } qw(none difference differential integral offset monotonic)) {

in der Funktion readingsEndUpdate
einen weiteren elsif für integral ergänzt

      } elsif($modifier eq "differential") {
        my $deltav= $value - $oldvalue if(defined($oldvalue));
        my $deltat= $hash->{".updateTime"} - $oldt if(defined($oldt));
        if(defined($deltav) && defined($deltat) && ($deltat>= 1.0)) {
          $result= $deltav/$deltat;
        }
      } elsif($modifier eq "integral") {
        if (defined($oldt) && defined($oldvalue))
        {
          my $deltat= $hash->{".updateTime"} - $oldt if(defined($oldt));
          my $avgval= ($value + $oldvalue) / 2;
          $result = ReadingsVal($name,$userReading,$value);
          if($deltat>= 1.0) {
            $result+= $avgval*$deltat;
          }
        }


So und nun steht das bei mir in der fhem.pl und beim nächsten Update is es wieder weg.
Besteht Interesse das Aufzunehmen? Wie kann das geschehen.

Viele Grüße

Simonberry
NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

rudolfkoenig

Ich habe zwar nicht wirklich Interesse, aber ich wuerde es aufnehmen, falls ich auch noch Patches fuer commandref_frame.html und commandref_frame_DE.html bekomme.

Das naechste mal bitte nicht in der Wunschliste sondern nach Sonstiges schreiben (fhem.pl Aenderungen gehoeren dahin, siehe MAINTAINER.txt) , Wunschliste lese ich eigentlich aus Prinzip nicht :)

simonberry

Hallo Rudolf,

Danke das Du es aufnimmst
Anbei die beiden patches, ich hoffe das passt so, aber es ist ja nicht viel.

Viele Dank und Grüße

Simonberry
NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

micomat

Hallo Simonberry,

das klingt sehr interessant. Koenntest Du Deine Umsetzung mal kurz fuer doofe erklaeren? =)

Gruesse,
Markus
Synology DS218+ with fhem+iobroker in docker, 2x RasPi w. ser2net, CUL433+868, IT, EGPM2LAN, THZ/LWZ, FB_Callmonitor, HMS100TF, Homematic, 2x TX3-TH, Pushover, USB-IR-SML-Head, SONOS, GHoma, MBus, KLF200

simonberry

#4
Hallo Markus

Am Besten versuche ich es an meinem persönlichem Projekt (leider noch nicht ganz abgeschlossen) erkläre.

Ich will meinen Wärmeverbrauch der bezogenen Fernwärme loggen. In meiner Heizung ist zwar ein Wärmemengenzähler vom Energieversorger (Sharky 775 von Diehl) aber der ist verblomt und die Infrarotschnittstelle sendet nix... :'(

Mit Google und Wiki und Restwissen vom Studium habe ich herausgefunden:
Um die aktuelle Leistung der Fernwärmeübergabe zu berechnen benötigt man 3 Werte:

  • Temperatur Vorlauf
  • Temperatur Rücklauf
  • Volumenfluss vom Wasser
Die Aktuelle Leistung berechnet sich nach folgender Formel:
P = VolumenFluss * Spezifische Wärmekapazität Wasser * (TempVorlauf - TempRücklauf)

Die Bezogene Wärmemenge (das was ich bezahlen muss) ist dann das Integral bzw die Fläche unter dem Graphen.
Angenommen die Leistung ist 1 Stunde konstant:
E = P * 1h
Ändert sich die Leistung ist es die Summe von mehreren kleinen Zeitintervallen * Leistung
E = P1 * t1 + P2 * t2 + P3 *t3
Genau dieses tut meine Erweiterung nun.


Mittels 2 Temperatursensoren messe ich Vor  und Rücklauf, den Volumenfluss kann ich bis jetzt leider nur Raten, weshalb ich noch nicht ganz glücklich bin.
Der Volumenfluss wird durch die Heizung durch ein Stellglied eingestellt (mein Ansatz hier was ab zugreifen). Mein Wärmezähler misst den und zeigt den auch an, weshalb ich jetzt immer mit 135 Liter/h rechne.
Da das Stellglied aber nicht immer offen ist, muss ich außerdem noch raten, wann es offen ist. Das ist offensichtlich dann der Fall, wenn der Vorlauf plötzlich heiß wird (von ca. 28° auf 55°). Momentan frage ich einfach ab ob die Vorlauftemperatur größer als 45 ° ist.

Per notify ausgelöst durch die Vorlauftemperatur berechne ich nun die Leistung und speichere sie als reading einem dummy. Der Dummy berechnet dann per "userReading integral "die Wärmemenge.

Hier mein Code aus der fhem.cfg

define Fernwaerme dummy
attr Fernwaerme alias Fernwaerme
attr Fernwaerme icon sani_earth_source_heat_pump
attr Fernwaerme stateFormat {sprintf("%.1f kWh %.1f kW\n", ReadingsVal("Fernwaerme","Energie",0), ReadingsVal("Fernwaerme","Leistung",0));;}
attr Fernwaerme userReadings Energie integral {ReadingsVal("Fernwaerme","Leistung",0)/3600}
define notiVor notify Vorlauf {\
  fhem("setreading Fernwaerme Vorlauf ". $EVENT);;\
  fhem("setreading Fernwaerme Ruecklauf ". Value("Ruecklauf"));;\
  my $tempdiff = $EVENT - Value("Ruecklauf");;\
  if ($tempdiff < 0) \
  {\
    $tempdiff = 0;;\
  }\
  fhem("setreading Fernwaerme TempDiff ". $tempdiff);;\
  if ($EVENT > 45)\
  {\
    my $Leistung = 0.135 * 4.182 / 3.6 * $tempdiff;;\
    fhem("setreading Fernwaerme Leistung $Leistung");;\
  }\
  else\
  {\
    fhem("setreading Fernwaerme Leistung 0");;\
  }\
}
define FileLog_Fernwaerme FileLog log/Fernwaerme-%Y-%m.log Fernwaerme
define SVG_FileLog_Fernwaerme_1 SVG FileLog_Fernwaerme:SVG_FileLog_Fernwaerme_1:CURRENT


(http://M:%5Cfernwaerme.png)



NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

rudolfkoenig

Habs eingecheckt.

Bitte demnaechst "diff -u" zum Patch-Bauen verwenden, mit einem reinen diff kann man wenig anfangen.
Weitehin waere praktisch, wenn die deutsche Doku auch deutsch waere (habs jetzt selbst uebersetzt).
Ich habe eine weitere Pruefung beim Rechnen gesetzt, habe trotzdem das Gefuehl, dass eine noch fehlt (fuer value). Kannst Du das alles bitte pruefen?

Gruss,
  Rudi

simonberry

Hallo Rudi,

sorry für den zwei englischen Versionen, hab mir wohl beim kopieren die deutsche Version überbügelt.<br>  diff -u werde ich verwenden und zwar für folgendes:
Die Methode "integral" wird beim Start von FHEM noch abgelehnt...
Die Prüfungen hab ich mir angeschaut, ich hatte oldt und oldval auch geprüft im if oben drüber... jetzt wird's doppelt geprüft, schadet auch nicht.

Viele Grüße

Simonberry




NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

UvG

Hallo zusammen,
ich bin neu in diesem Forum und wollte bei userreadings die Funktion integral ausprobieren.
Leider bekomme ich eine Fehlermeldung:

PCA301_01A196: unknown modifier integral for userReading Timediff, this userReading will be ignored

Definiert habe ich
Timediff:power integral {ReadingsVal($name,'power',0)/3600}
Fhem ist auf dem neuestem Stand

Was kann falsch sein

Gruß
Ulrich

simonberry

Hallo Ulrich
es kann sein, dass der letzt Patch noch nicht aktiviert wurde, such mal in fhem.pl nach der Zeile

if(grep { /$modifier/ } qw(none difference differential offset monotonic)) {

Und ergänze "integral", so dass es so aussieht:

if(grep { /$modifier/ } qw(none difference differential integral offset monotonic)) {


Viele Grüße

NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

UvG

Hallo Simonberry,

danke für die Antwort.
Änderung habe ich gemacht und es funktioniert.
Lieder wird dies woll nach der nächsten Änderung von fhem.pl wieder geändert.

Danke

Ulrich

simonberry

Hallo Ulrich

Rudi hat die Änderung übernommen, ist also beim nächsten update erledigt.

siehe
http://forum.fhem.de/index.php/topic,33260.0/topicseen.html

Gruß

Simonberry
NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

cwagner

Nach Rücksprache mit dem Autor: In Beitrag #4 gibt es eine falsche Einheitenbezeichnung: Das Ergebnis des Rechenweges ergibt MWh bzw. MW (im Code Beispiel ist das attr stateformat anzupassen)

Christian
PI 2B+/3B+ Raspbian 12, Perl 5.36.0, FHEM 6.3: 295 Module in ConfigDB: Steuerung Heizkessel, FBH, Solarthermie, kontr. Lüftung mit WRG. Smarthome u.a. HMCUL, 1-Wire (FT232RL ; DS2480B), EnOcean (TCM EPS3), MQTT2. DOIF, PID20, Threshold, OWX; Micropelt IRTV, Volkszähler, SolarForecast; MariaDB

buennerbernd

Ich habe userReadings mit integral-Funktion entdeckt.
Leider passt die Implementierung nicht auf jeden Use-Case. Es wird der Durchschnitt zwischen altem und neuem Wert zur Berechnung herangezogen.
Ich habe eine Datenquelle, die nur bei Änderungen Daten liefert. Die Durchschnittsberechnung verfälscht in diesem Fall sehr.
Wünschenswert wäre eine Alternative, die nur den alten Wert heranzieht. (z.B. ein Gerät war lange Zeit ausgeschaltet und hat in dieser Zeit nichts verbraucht. Der Zähler sollte sich im Moment des Anschaltens noch nicht erhöhen.)
Modulentwickler von KLF200 und KLF200Node

simonberry

Hallo buennerbernd,

so ganz verstehe ich Dein Problem leider nicht. Kannst Du das evtl etwas konkreter erläutern?

Evtl hilft es ja auch die Events mittels event-on-change-reading etwas besser zu dosieren.
Oder die Datenquelle muss künstlich so eingestellt werden, dass im Fall von "aus" 0 liefert.

Viele Grüße

Simonberry

NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

buennerbernd

Die Daten kommen bei mir per MQTT.
Sie kommen nicht in regelmäßigen Intervallen, sondern sehr zeitnah, wenn es einen neuen Wert gibt.
Bei mir z.B. eine Klimaanlage, die liefert den aktuellen Strom per MQTT:

Die Klimaanlage ist tagelang aus -> wenige mal am Tag kommt CT = 0
Die Klimaanlage wird eingeschaltet -> sofort kommt CT = 4,39 einmalig bis zur nächsten Änderung
Die Klimaanlage schaltet etwas runter -> Änderung auf CT = 3,84 einmalig bis zur nächsten Änderung

Bei jedem Dateneingang kann ich den bisherigen Verbrauch abrechnen. Dabei ist es unerheblich, was der neue Wert ist. Der alte Wert hat bis dahin gegolten. Der Durchschnitt aus altem und neuem Wert würde den Verbrauch extrem verfälschen.

Die aktuelle Integtral-Implementierung Reading = Reading + difftime * (oldvalue + value) / 2 ist gut geeignet für Daten, die in regelmäßigen Intervallen kommen und unklar ist, wann in einem Intervall sich die Daten geändert haben.

Für den Fall, dass die Intervalle unterschiedlich lang sind, dafür aber klar ist, dass der Wert seit Anfang des Intervalls gilt, passt folgende Formel besser: Reading = Reading + difftime * oldvalue.
Es ist klar, dass der Verbrauch so immer einen Wert hinterher hinkt. Dafür ist er aber deutlich genauer.

Super wäre es, wenn es für solche Datenquellen eine alternative Integralberechnung gäbe.

Viele Grüße,
buennerbernd.
Modulentwickler von KLF200 und KLF200Node

buennerbernd

Mir ist aufgefallen, dass userReadings, bei jeder Änderung im Device aktualisiert werden.
Dadurch halten sich meine Befürchtungen wegen Verfälschungen durch zu lange Intervalle nun in Grenzen.
Modulentwickler von KLF200 und KLF200Node

Ajuba

Ich versuche nach obiger Erklärung die Funktion "intergral" bei UserReadings zur Berechnung der Gesamtenergie meiner Wärmepumpe einzusetzen habe aber starke Abweichungen zu der händischen Berechnung. Siehe Screenshot des Excel.

Zitat von: simonberry am 19 August 2014, 20:26:48

attr Fernwaerme userReadings Energie integral {ReadingsVal("Fernwaerme","Leistung",0)/3600}


Ich wende es auf ein UserReding eines MQQT Devices an. myElEnergy ist die unterste Zeile des codes.

defmod WP MQTT2_DEVICE ESPAltherma_dev
attr WP DbLogInclude myThPowerBW,myElPowerBW,myThEnergyBW,myElEnergyBW,myElPowerBUH1,myElEnergy,Raumheizbetrieb,2-Wege-Ventil_ON-Heizen/OFF-Kuehlen,3-Wege-Ventil_ON-DHW/OFF-Raum,Abtauung,Aktuelle_Betriebsart,Alarmausgabe,Aussentemperatur_R1T,Betrieb/Stoerung,BSH,Drehzahl_Verdichter_U/Sek,Durchflussmenge_l/min,Heizstab_Stufe-1,Heizstab_Stufe-2,Hochleistungs-DHW-Betrieb,INV_Primaerstrom_A,Raumtemperatur_R1T,Notbetrieb_aktiviert/nicht_aktiviert,R1T-Wasser_Vorlauftemperatur_nach_Plattenwaermetauscher,R2T-Wasser_Vorlauftemperatur_nach_Heizstab,R4T-Wasser_Ruecklauftemperatur_vor_Plattenwaermetauscher,R5T-Brauchwassertemperatur_im_Speicher,Raumheizbetrieb,Raumheizung_Betriebsleistung,Schallreduzierter_Betrieb,Sollwert_Brauchwasser,Sollwert_Heizungsvorlauf,Spannung_N-Phase_V,Stoercode,System_AUS,Umwaelzpumpenbetrieb,Ventilator_1_Stufe,Ventilator_2_Stufe,Waermetauscher_Mitteltemperatur,Wasserdruck,myCOP,myElPower,myThPower
attr WP IODev myBroker
attr WP event-on-change-reading myThPowerBW,myBW,myElPowerBW,myThEnergyBW,myElEnergyBW,myElPowerBUH1,myElEnergy,Raumheizbetrieb,2-Wege-Ventil_ON-Heizen/OFF-Kuehlen,3-Wege-Ventil_ON-DHW/OFF-Raum,Abtauung,Aktuelle_Betriebsart,Alarmausgabe,Aussentemperatur_R1T,Betrieb/Stoerung,BSH,Durchflussmenge_l/min,Heizstab_Stufe-1,Heizstab_Stufe-2,Hochleistungs-DHW-Betrieb,INV_Primaerstrom_A,Raumtemperatur_R1T,Notbetrieb_aktiviert/nicht_aktiviert,R1T-Wasser_Vorlauftemperatur_nach_Plattenwaermetauscher,R2T-Wasser_Vorlauftemperatur_nach_Heizstab,R4T-Wasser_Ruecklauftemperatur_vor_Plattenwaermetauscher,R5T-Brauchwassertemperatur_im_Speicher,Raumheizbetrieb,Raumheizung_Betriebsleistung,Schallreduzierter_Betrieb,Sollwert_Brauchwasser,Sollwert_Heizungsvorlauf,Spannung_N-Phase_V,Stoercode,System_AUS,Umwaelzpumpenbetrieb,Ventilator_1_Stufe,Ventilator_2_Stufe,Waermetauscher_Mitteltemperatur,Wasserdruck,myCOP,myElPower,myThPower
attr WP event-on-update-reading Drehzahl_Verdichter_U/Sek
attr WP eventMap /Fan Only:Fan_Only
attr WP readingList ESPAltherma_dev:homeassistant/sensor/espAltherma/config:.* { json2nameValue($EVENT) }\
ESPAltherma_dev:espaltherma/LWT:.* LWT\
ESPAltherma_dev:homeassistant/switch/espAltherma/config:.* { json2nameValue($EVENT) }\
ESPAltherma_dev:espaltherma/log:.* log\
ESPAltherma_dev:espaltherma/ATTR:.* { json2nameValue($EVENT) }
attr WP room MQTT2_DEVICE,WP
attr WP userReadings myAbtauung {((ReadingsVal ("WP","Abtauung",0))) eq "ON" ? (1) : (0)},\
myBW {((ReadingsVal ("WP","3-Wege-Ventil_ON-DHW/OFF-Raum",0))) eq "ON" ? (1) : (0)},\
myElPower {(((ReadingsVal ("WP","INV_Primaerstrom_A",0))*230)+(ReadingsVal ("WP","myElPowerBUH1",0))+(ReadingsVal ("WP","myElPowerBUH2",0))) ;;;;},\
myElPowerBUH1 {((ReadingsVal ("WP","Heizstab_Stufe-1",0))) eq "ON" ? (3000) : (0)},\
myElPowerBUH2 {((ReadingsVal ("WP","Heizstab_Stufe-2",0))) eq "ON" ? (6000) : (0)},\
myElPowerBW {(ReadingsVal ("WP","myElPower",0))*(ReadingsVal ("WP","myBW",0)) ;;;;},\
myThPowerBW {((ReadingsVal ("WP","R5T-Brauchwassertemperatur_im_Speicher",0) - ReadingsVal ("myBWStart","state",0))*230*1.1639)*(ReadingsVal ("WP","myBW",0)) ;;;;},\
myThPower {((ReadingsVal ("WP","R1T-Wasser_Vorlauftemperatur_nach_Plattenwaermetauscher",0) - ReadingsVal ("WP","R4T-Wasser_Ruecklauftemperatur_vor_Plattenwaermetauscher",0))*ReadingsVal ("WP","Durchflussmenge_l/min",0)*60*1.1639);;;;},\
myCOP {((ReadingsVal ("WP","myThPower",0))/(ReadingsVal ("WP","myElPower",0))) > 0 ? ((ReadingsVal ("WP","myThPower",0))/(ReadingsVal ("WP","myElPower",0)+0.1)) : (0)},\
myThEnergyBW integral {ReadingsVal ("WP","myBW",0) * ((ReadingsVal ("WP","R5T-Brauchwassertemperatur_im_Speicher",0) - ReadingsVal ("myBWStart","state",0))*230*1.1639/3600/1000) ;;;;},\
myElEnergyBW integral {ReadingsVal ("WP","myElPowerBW",0)/3600/1000},\
myElEnergy integral {ReadingsVal("WP","myElPower",0)/3600/1000}\


Das Ergebnis der Fhem Integral Berechnung weicht vollkommen von meiner händischen Excel Berechnung und vom Smartmeter ab.
Die Fhem Integral Berechnung liefert viel kleinere Werte.

Die Zeitabstände der Readings sind unterschiedlich aber das sollte ja nichts ausmachen.
myElEnergy ist auch als event-on-change-reading gesetzt und die Timestamps passen auch zusammen.
Die Division durch 3600 und durch 1000 ist um von Wattsekunden auf kWh zu kommen.

Wo könnte der Fehler liegen?
FHEM auf RPi3, Homematic CCU3 mit Cuxd und CUL 868 für FS20, Siemens S7 über CP343-1,
DbLog zu MySQL auf NAS QNAP TS-253D,
Yeelight

simonberry

Hallo Ajuba,

leider verstehe ich Dein Excel Tabelle nicht ganz. Welche Seite ist die von FHEM ermittelte Energie, und welche hast Du mit Excel berechnet, und wie hast Du die Energie in Excel berechnet?

viele Grüße
Simonberry

NUC5i3RYK#DBLOG; MYSQL; LIRC; MPD; HM-CFG-HM-USB-2: HM-divers; MQTT2; Signalduino; Shelly; Sonoff; dash_dhcp; FS20; IT; FroniusWR; Somfy RTS; NFS-Server
Rpi B#: nfsmount; ser2net CUL868; CUL433; GPIO4:DS18B20; WEMOS-D1-MINI#JVC-via-IR;

Ajuba

#18
Ich habe das Problem gelöst durch Entfernen von UserReading Definition und Löschen des UserReadings.
Nach Neueingabe zählt integral korrekt.
FHEM auf RPi3, Homematic CCU3 mit Cuxd und CUL 868 für FS20, Siemens S7 über CP343-1,
DbLog zu MySQL auf NAS QNAP TS-253D,
Yeelight

Reisbaua

Hallo zusammen. Ich habe auch ein Problem mit der integral Funktion.
Mein Use Case ist ganz einfach: Ich habe einen Zeitabschnitt über Stunden hinweg, wo meine WP 400W benötigt. Wenn ich das Userreading mit integral nutze um die kWh zu berechnen kommt ein zu kleinerer Wert heraus, nämlich ca 0,386kWh. Wenn ein 400W Verbraucher allerdings konstant eine Stunde läuft, müsste es 0,4kWh ergeben.

User Reading: WPheizen_kWh integral { ReadingsVal ("ModbusWP","EnergieverbrauchHeizen",0)/3600.0/1000.0 ; }
EnergieverbrauchHeizen: hat 400 als Wert

Und so sieht das DbLog dazu aus (davor und danach war noch ganz lang 400W):

2023-02-06 17:11:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.414374342061 WPheizen_kWh 189.414374342061
2023-02-06 17:06:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 17:01:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.349986331798 WPheizen_kWh 189.349986331798
2023-02-06 16:55:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:51:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.285617735694 WPheizen_kWh 189.285617735694
2023-02-06 16:45:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:41:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.221216923519 WPheizen_kWh 189.221216923519
2023-02-06 16:35:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:31:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.156850880958 WPheizen_kWh 189.156850880958
2023-02-06 16:25:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:21:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.092470236345 WPheizen_kWh 189.092470236345
2023-02-06 16:15:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:11:38 ModbusWP MODBUSATTR WPheizen_kWh: 189.028077016185 WPheizen_kWh 189.028077016185
2023-02-06 16:04:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 16:01:38 ModbusWP MODBUSATTR WPheizen_kWh: 188.963702454001 WPheizen_kWh 188.963702454001
2023-02-06 15:54:39 ModbusWP MODBUSATTR EnergieverbrauchHeizen: 400 EnergieverbrauchHeizen 400
2023-02-06 15:51:38 ModbusWP MODBUSATTR WPheizen_kWh: 188.896078621405 WPheizen_kWh 188.896078621405

Die Differenz zwischen den Werten um 16:01 und 17:01 ist ca 0,386kWh

Und so die FileLogs:

2023-02-06_15:54:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:04:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:15:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:25:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:35:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:45:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_16:55:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_17:06:39 ModbusWP EnergieverbrauchHeizen: 400
2023-02-06_17:16:40 ModbusWP EnergieverbrauchHeizen: 400

2023-02-06_15:51:38 ModbusWP WPheizen_kWh: 188.896078621405
2023-02-06_16:01:38 ModbusWP WPheizen_kWh: 188.963702454001
2023-02-06_16:11:38 ModbusWP WPheizen_kWh: 189.028077016185
2023-02-06_16:21:38 ModbusWP WPheizen_kWh: 189.092470236345
2023-02-06_16:31:38 ModbusWP WPheizen_kWh: 189.156850880958
2023-02-06_16:41:38 ModbusWP WPheizen_kWh: 189.221216923519
2023-02-06_16:51:38 ModbusWP WPheizen_kWh: 189.285617735694
2023-02-06_17:01:38 ModbusWP WPheizen_kWh: 189.349986331798
2023-02-06_17:11:38 ModbusWP WPheizen_kWh: 189.414374342061


Irgendwelche Ideen was hier falsch läuft?
Danke!

buennerbernd

Ich tippe auf aufsummierte Rundungsfehler.
Wie viele Werte kommen denn wirklich auf ModbusWP:EnergieverbrauchHeizen rein? Das ist doch nicht wirklich nur alle 10 min. einer?
Entsprechend oft wird beim Umrechnen von Sekunden auf Stunden gerundet. Vielleicht wird zufälligerweise immer abgerundet.
Modulentwickler von KLF200 und KLF200Node

Reisbaua

Könnte sein. Modbus kriegt alle 1min Daten, das Logfile und DbLog wird wie in meinem Post ersichtlich nicht so oft updated.
Aber auch wenn ich jetzt abrunden würde, sagen wir mal 400/3600/1000 ergibt dann 0,0001
Und nehmen wir an ich berechne alle Minuten diesen gerundeten Wert: 0,0001*60 für eine Minute, und das 60 Mal um die kWh zu bekommen, käme ich auf 0,0001*3600=0,36


  • 0,0001111*3600=0,39996
  • 0,00011*3600=0,396
  • 0,0001*3600=0,360

Egal an welche Stelle ich runde, und wie ich es drehe, auf den erhaltenen (falschen!) Wert von 0,386 komme ich nicht.

Vielleicht ist das auch egal, und ich kann irgendwie selbst den Wert (korrekt) berechnen? Eigentlich müsste ja die Delta Zeit zwischen jetzt und vorigem Energiewert * vorigem Energiewert auch das Ergebnis liefern, oder?
kWh = SekundenDelta * EnergiePrevious
Dann seh ich zB: 60s sind vergangen, der alte Wert war 400W, der neue jetzt 800W => 60s*400W=24000Ws=24kWs=0,0066666kWh in dieser einen Minute...

buennerbernd

Ich denke, du bekommst als Reading konstant 400W

Den Verbrauch in Watt * Sekunde bekommst du, in dem du bei jedem neuen Wert in Watt

(alter Wert in Watt + neuer Wert) Watt / 2 * (neuer Zeitstempel - alter Zeitstempel) rechnest
und diese Werte kontinuierlich aufsummierst.


Jetzt, wo ich so darüber nachdenke, wäre es vermutlich genauer, das komplette Integral in Watt Sekunden zu berechnen und das jeweilige Endergebnis als ein neues UserReading in kWh umzurechnen. Dann wäre die Fehlerquelle durch aufsummiertes Runden beseitigt, da nur noch einmal am Ende gerundet wird.
Modulentwickler von KLF200 und KLF200Node

Reisbaua

Ja, mit den Ws und Runden hast du recht, das probier ich einfach mal.
Das mit WattAlt + WattNeu / 2 kann ich nur bedingt unterschreiben, weil es darauf ankommt wie sich das Gerät verhält.

Beispiel A:
Ich bekomme bei JEDEM WECHSEL der Momentanenergie ein Reading Update.
Minute 0: 400W
Minute 23: 800W

Ab Minute 23 gelten also 800W. Davor war durchgehend 400W.
Jetzt wäre es bei mir falsch 800+400/2=600W für die ersten 23 Minuten anzunehmen.

Beispiel B:
Ich bekomme alle 10 Minuten einen Wert, der Wert kann sich innerhalb der 10 Minutenfenster beliebig oft ändern.
Dann wäre tatsächlich die beste Näherung einen Durchschnitt im letzten 10 Minuten Fenster zu berechnen mit (Alt+Neu)/2.

In meinem WP Beispiel hab ich all diese Unwägsamkeiten ausgeschaltet, weil ich einen Bereich gewählt habe der durchgehend den selben Momentwert hatte. Aber ich habe halt nicht die erwarteten 0,4kWh ablesen können. Das ist mein Problem hier.

buennerbernd

#24
Dann darfst du nicht den Durchschnitt zwischen altem und neuem Wert nehmen, sondern nur den alten Wert, denn der hat ja das gesamte letzte Intervall gegolten.

Mein Tipp: den alten Wert in einem UserReading merken.

WPheizen_Ws:EnergieverbrauchHeizen.* integral { ReadingsVal ("ModbusWP","EnergieverbrauchHeizenOld",0); },
WPheizen_kWh:EnergieverbrauchHeizen.* { ReadingsVal ("ModbusWP","WPheizen_Ws",0)/3600000.0 ; },
EnergieverbrauchHeizenOld:EnergieverbrauchHeizen.* { ReadingsVal ("ModbusWP","EnergieverbrauchHeizen",0); }

Alle 3 UserReadings triggern nur, wenn sich EnergieverbrauchHeizen ändert.
Als Wert wird EnergieverbrauchHeizenOld herangezogen, welcher erst nach der Integralberechnung aktualisiert wird.
Modulentwickler von KLF200 und KLF200Node

Reisbaua


buennerbernd

PS: Habe noch ein Komma zwischen die UserReadings gesetzt.

Viel Erfolg! Mich würde interessieren, ob du so endlich auf 400kWh kommst.
Modulentwickler von KLF200 und KLF200Node

Reisbaua

ja ich gebe Bescheid, dafür muss es aber jetzt eine zeitlang laufen.
danke schon mal.
und die Kommas sind mir natürlich aufgefallen :-)

Reisbaua

ja, mit Ws sind die Werte tatsächlich korrekt, nämlich 399,96333kWh bei 400W Momentanleistung!
Danke nochmals.

Reisbaua

und stimmen übrigens auch sehr gut mit den Werten überein, die an der WP direkt abgelesen werden können!

kask

Wieso ist in der Integral funktion eine Mindestzeitdifferenz (>=1s) enthalten?
if($deltat>= 1.0)
Kann mir das einer erklären? Bzw. den Grund nennen wieso das Sinnvoll ist?