Mittelung der D Anteil Berechnung in PID20

Begonnen von dun3, 19 Februar 2017, 10:48:13

Vorheriges Thema - Nächstes Thema

dun3

Hallo zusammen,

erstmal: tolles Tool, tolle Community! Hier mein erster Versuch etwas zurückzugeben.

Für mich war die D Anteilsberechnung im PID20 nicht passend, da sie extrem sprunghaft war. Daher habe ich zwei Annahmen getroffen:
1.) der D-Anteil sollte über einen Zeitraum gemittelt werden.
2.) der D-Anteil wird erst in Calc bestimmt, in Notify wird nur "mitgeschrieben".

Herausgekommen ist der angehängte Code. Er ist vor allem hinsichtlich der Einstellbarkeit der Mittelung, etc. noch nicht direkt endbenutzergeeignet. Bevor ich das allerdings mache, würde ich mich erst über Feedback freuen, damit ich weiß, dass sich der Aufwand lohnt.

Gruß
Tobias

P.S.: Zusätzlich eingebaut

200a201,202
>   my $actorCommandProcessed = $cmd;
>   $actorCommandProcessed =~ tr/\$/ /;
202c204
<   $hash->{helper}{actorCommand}  = ( defined($cmd) ) ? $cmd : '';
---
>   $hash->{helper}{actorCommand}  = ( defined($cmd) ) ? $actorCommandProcessed : '';



Damit kann man jetzt auch Kommandos mit Leerzeichen verschicken, indem man einfach das Leerzeichen mit einem $ ersetzt.

--------------

Diff:

$ diff 98_PID20.pm,orig 98_PID20.pm
200a201,202
>   my $actorCommandProcessed = $cmd;
>   $actorCommandProcessed =~ tr/\$/ /;
202c204
<   $hash->{helper}{actorCommand}  = ( defined($cmd) ) ? $cmd : '';
---
>   $hash->{helper}{actorCommand}  = ( defined($cmd) ) ? $actorCommandProcessed : '';
241a244,250
>   my $epocNow = time();
>   my $bufferTime = ();
>   my $bufferValue = ();
>
>   $bufferTime = $hash->{helper}{bufferTime}  if ( defined( $hash->{helper}{bufferTime} ) );
>   $bufferValue = $hash->{helper}{bufferValue}  if ( defined( $hash->{helper}{bufferValue} ) );
>
257,287c266,267
<     # calc difference of delta/deltaOld
<     my $delta    = $desired - $sensorValue           if ( defined($desired) );
<     my $deltaOld = ( $hash->{helper}{deltaOld} + 0 ) if ( defined( $hash->{helper}{deltaOld} ) );
<     my $deltaDiff = ( $delta - $deltaOld ) if ( defined($delta) && defined($deltaOld) );
<     PID20_Log $hash, 5,
<         "Diff: delta["
<       . sprintf( "%.2f", $delta ) . "]"
<       . " - deltaOld["
<       . sprintf( "%.2f", $deltaOld ) . "]"
<       . "= Diff["
<       . sprintf( "%.2f", $deltaDiff ) . "]"
<       if ($DEBUG);
<
<     # ----- build difference of timestamps (ok)
<     my $deltaOldTsStr = $hash->{helper}{deltaOldTS};
<     my $deltaOldTsNum = time_str2num($deltaOldTsStr) if ( defined($deltaOldTsStr) );
<     my $nowTsNum      = gettimeofday();
<     my $tsDiff        = ( $nowTsNum - $deltaOldTsNum )
<       if ( defined($deltaOldTsNum) && ( ( $nowTsNum - $deltaOldTsNum ) > 0 ) );
<     PID20_Log $hash, 5, "tsDiff: tsDiff = $tsDiff " if ($DEBUG);
<
<     # ----- calculate gradient of delta
<     my $deltaGradient = $deltaDiff / $tsDiff
<       if ( defined($deltaDiff) && defined($tsDiff) && ( $tsDiff > 0 ) );
<     $deltaGradient = 0 if ( !defined($deltaGradient) );
<     my $sdeltaDiff     = ($deltaDiff)     ? sprintf( "%.2f", $deltaDiff )     : '';
<     my $sTSDiff        = ($tsDiff)        ? sprintf( "%.2f", $tsDiff )        : '';
<     my $sDeltaGradient = ($deltaGradient) ? sprintf( "%.6f", $deltaGradient ) : '';
<     PID20_Log $hash, 5,
<       "deltaGradient: (Diff[$sdeltaDiff]" . "/tsDiff[$sTSDiff]" . "=deltaGradient per sec [$sDeltaGradient]"
<       if ($DEBUG);
---
>     push(@$bufferTime, $epocNow);
>     push(@$bufferValue, $sensorValue);
290,292c270,271
<     $hash->{helper}{deltaGradient} = $deltaGradient;
<     $hash->{helper}{deltaOld}      = $delta;
<     $hash->{helper}{deltaOldTS}    = TimeNow();
---
>     $hash->{helper}{bufferTime} = $bufferTime;
>     $hash->{helper}{bufferValue} = $bufferValue;
444d422
<   my $deltaGradient    = ( $hash->{helper}{deltaGradient} ) ? $hash->{helper}{deltaGradient} : 0;
540c518,560
<       $dPortion = ($deltaGradient) * $hash->{helper}{calcInterval} * $hash->{helper}{factor_D};
---
>       my $epocNow = time();
>
>       my $bufferTime = ();
>       my $bufferValue = ();
>
>       $bufferTime = $hash->{helper}{bufferTime}  if ( defined( $hash->{helper}{bufferTime} ) );
>       $bufferValue = $hash->{helper}{bufferValue}  if ( defined( $hash->{helper}{bufferValue} ) );
>
>       my $diffPerMinute = 0;
>
>       if ( defined($bufferTime) &&  scalar(@$bufferTime) > 1 ) {
>         my $minutesToConsider = 10;
>
>         my $cutoffDiff = $minutesToConsider * 60;
>         my $cutoffTime = $epocNow - $cutoffDiff;
>
>         # @$bufferTime[1] is correct!
>         while ( scalar(@$bufferTime) > 1 && $bufferTime->[1] < $cutoffTime ) {
>           shift(@$bufferTime);
>           shift(@$bufferValue);
>         }
>
>         $hash->{helper}{bufferTime} = $bufferTime;
>         $hash->{helper}{bufferValue} = $bufferValue;
>
>         my $posAtCutoffTime = $bufferValue->[1] - ($bufferValue->[1]-$bufferValue->[0])/($bufferTime->[1]-$bufferTime->[0]) * ($bufferTime->[1]-$cutoffTime);
>
>         my $diffPerSecond = ($sensorValue - $posAtCutoffTime)/($epocNow - $cutoffTime);
>         $diffPerMinute = $diffPerSecond * 60;
>
>         PID20_Log $hash, 5,
>             "posAtCutoffTime: ["
>           . sprintf( "%.2f", $posAtCutoffTime ) . "]"
>           . " - sensorValue["
>           . sprintf( "%.2f", $sensorValue ) . "]"
>           . "= diffPerMinute["
>           . sprintf( "%.2f", $diffPerMinute ) . "]"
>           if ($DEBUG);
>       }
>
>       my $deltaGradient = $diffPerMinute;
>
>       $dPortion = ($deltaGradient) * $hash->{helper}{factor_D} * -1;