98_PID20 : Bugfix: processing of D-Portion and handling of disable

git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@7025 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
john99sr
2014-11-20 08:35:49 +00:00
parent 242c289655
commit 02458fc8c2

View File

@@ -43,7 +43,8 @@
# V 1.01 # V 1.01
# 19.10.2014 fix in sub PID20_Set : wrong parameter $hash instead of $name, when calling PID20_Calc # 19.10.2014 fix in sub PID20_Set : wrong parameter $hash instead of $name, when calling PID20_Calc
# V 1.0.0.2 30.10.14 - fix in PID20_Calc when setting $retStr (thanks to Thorsten Pferdekaemper) # V 1.0.0.2 30.10.14 - fix in PID20_Calc when setting $retStr (thanks to Thorsten Pferdekaemper)
# # V 1.0.0.3
# 20.11.2014 Bug: processing of D-Portion and handling of disable
#################################################################################################### ####################################################################################################
package main; package main;
use strict; use strict;
@@ -53,25 +54,19 @@ use vars qw(%defs);
use vars qw($readingFnAttributes); use vars qw($readingFnAttributes);
use vars qw(%attr); use vars qw(%attr);
use vars qw(%modules); use vars qw(%modules);
my $PID20_Version = "1.0.0.3";
my $PID20_Version="1.0.0.2";
sub PID20_Calc($); sub PID20_Calc($);
######################################## ########################################
sub PID20_Log($$$) sub PID20_Log($$$)
{ {
my ( $hash, $loglevel, $text ) = @_; my ( $hash, $loglevel, $text ) = @_;
my $xline = (caller(0))[2]; my $xline = ( caller(0) )[2];
my $xsubroutine = ( caller(1) )[3];
my $xsubroutine = (caller(1))[3]; my $sub = ( split( ':', $xsubroutine ) )[2];
my $sub = (split( ':', $xsubroutine ))[2]; $sub = substr( $sub, 6 ); # without PID20
$sub = substr ($sub, 6); # without PID20
my $instName = ( ref($hash) eq "HASH" ) ? $hash->{NAME} : "PID20"; my $instName = ( ref($hash) eq "HASH" ) ? $hash->{NAME} : "PID20";
Log3 $hash, $loglevel, "PID20 $instName: $sub.$xline " . $text; Log3 $hash, $loglevel, "PID20 $instName: $sub.$xline " . $text;
} }
######################################## ########################################
sub PID20_Initialize($) sub PID20_Initialize($)
{ {
@@ -100,41 +95,37 @@ sub PID20_Initialize($)
. "pidSensorTimeout " . "pidSensorTimeout "
. "pidReverseAction " . "pidReverseAction "
. "pidUpdateInterval " . "pidUpdateInterval "
# . "pidDebugEnable:0,1 ";
# . "pidDebugEnable:0,1 ";
. "pidDebugSensor:0,1 " . "pidDebugSensor:0,1 "
. "pidDebugActuation:0,1 " . "pidDebugActuation:0,1 "
. "pidDebugCalc:0,1 " . "pidDebugCalc:0,1 "
. "pidDebugDelta:0,1 " . "pidDebugDelta:0,1 "
. "pidDebugUpdate:0,1 " . "pidDebugUpdate:0,1 "
. "pidDebugNotify:0,1 " . "pidDebugNotify:0,1 "
. "disable:0,1 " . "disable:0,1 "
. $readingFnAttributes; . $readingFnAttributes;
} }
######################################## ########################################
sub PID20_TimeDiff($) { sub PID20_TimeDiff($)
my ($strTS)=@_; {
my ($strTS) = @_;
#my ( $package, $filename, $line ) = caller(0); #my ( $package, $filename, $line ) = caller(0);
#print "PID $strTS line $line \n"; #print "PID $strTS line $line \n";
my $serTS = ( defined($strTS) && $strTS ne "" ) ? time_str2num($strTS) : gettimeofday();
my $serTS = (defined($strTS) && $strTS ne "") ? time_str2num($strTS) : gettimeofday(); my $timeDiff = gettimeofday() - $serTS;
my $timeDiff = gettimeofday()- $serTS; $timeDiff = 0 if ( $timeDiff < 0 );
$timeDiff=0 if ( $timeDiff<0);
return $timeDiff; return $timeDiff;
} }
######################################## ########################################
sub PID20_Define($$$) sub PID20_Define($$$)
{ {
my ( $hash, $def ) = @_; my ( $hash, $def ) = @_;
my @a = split( "[ \t][ \t]*", $def ); my @a = split( "[ \t][ \t]*", $def );
my $name = $a[0]; my $name = $a[0];
my $reFloat ='^([\\+,\\-]?\\d+\\.?\d*$)'; # gleitpunkt my $reFloat = '^([\\+,\\-]?\\d+\\.?\d*$)'; # gleitpunkt
if ( @a != 4 )
if ( @a != 4)
{ {
return "wrong syntax: define <name> PID20 " . "<sensor>:reading:[regexp] <actor>[:cmd] "; return "wrong syntax: define <name> PID20 " . "<sensor>:reading:[regexp] <actor>[:cmd] ";
} }
@@ -151,43 +142,36 @@ sub PID20_Define($$$)
} }
# if reading of sender is unkown # if reading of sender is unkown
if (ReadingsVal($sensor,$reading,'unknown') eq 'unkown') if ( ReadingsVal( $sensor, $reading, 'unknown' ) eq 'unkown' )
{ {
my $msg = "$name: Unknown reading $reading for sensor device $sensor specified"; my $msg = "$name: Unknown reading $reading for sensor device $sensor specified";
PID20_Log $hash, 1, $msg; PID20_Log $hash, 1, $msg;
return $msg; return $msg;
} }
$hash->{helper}{sensor} = $sensor; $hash->{helper}{sensor} = $sensor;
# defaults for regexp # defaults for regexp
if ( !$regexp ) if ( !$regexp )
{ {
$regexp=$reFloat; $regexp = $reFloat;
} }
$hash->{helper}{reading} = $reading; $hash->{helper}{reading} = $reading;
$hash->{helper}{regexp} = $regexp; $hash->{helper}{regexp} = $regexp;
# Actor # Actor
my ( $actor, $cmd ) = split( ":", $a[3],2 ); my ( $actor, $cmd ) = split( ":", $a[3], 2 );
if ( !$defs{$actor} ) if ( !$defs{$actor} )
{ {
my $msg = "$name: Unknown actor device $actor specified"; my $msg = "$name: Unknown actor device $actor specified";
PID20_Log $hash, 1, $msg; PID20_Log $hash, 1, $msg;
return $msg; return $msg;
} }
$hash->{helper}{actor} = $actor; $hash->{helper}{actor} = $actor;
$hash->{helper}{actorCommand}= (defined ($cmd)) ? $cmd :""; $hash->{helper}{actorCommand} = ( defined($cmd) ) ? $cmd : "";
$hash->{helper}{stopped}=0; $hash->{helper}{stopped} = 0;
$hash->{helper}{adjust}=""; $hash->{helper}{adjust} = "";
$modules{PID20}{defptr}{$name} = $hash;
$modules{PID20}{defptr}{$name}=$hash; readingsSingleUpdate( $hash, 'state', 'initializing', 1 );
readingsSingleUpdate( $hash, 'state', 'initializing',1 );
RemoveInternalTimer($name); RemoveInternalTimer($name);
InternalTimer( gettimeofday() + 10, "PID20_Calc", $name, 0 ); InternalTimer( gettimeofday() + 10, "PID20_Calc", $name, 0 );
return undef; return undef;
@@ -196,88 +180,87 @@ sub PID20_Define($$$)
sub PID20_Undef($$) sub PID20_Undef($$)
{ {
my ( $hash, $arg ) = @_; my ( $hash, $arg ) = @_;
RemoveInternalTimer($hash->{NAME}); RemoveInternalTimer( $hash->{NAME} );
return undef; return undef;
} }
sub sub
######################################## ########################################
# we need a gradient for delta as base for d-portion calculation # we need a gradient for delta as base for d-portion calculation
# #
PID20_Notify($$) PID20_Notify($$)
{ {
my ($hash, $dev) = @_; my ( $hash, $dev ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $sensorName = $hash->{helper}{sensor}; my $sensorName = $hash->{helper}{sensor};
my $DEBUG = AttrVal( $name, 'pidDebugNotify', '0' ) eq '1';
my $DEBUG = AttrVal($name, 'pidDebugNotify', '0' ) eq '1'; my $disable = AttrVal( $name, 'disable', '0' );
# no action if disabled # no action if disabled
if (defined($attr{$name}) && defined($attr{$name}{disable}) ) if ( $disable eq '1' )
{ {
$hash->{helper}{sensorTsOld}=undef; return "";
return "" ;
} }
return if ( $dev->{NAME} ne $sensorName );
return if($dev->{NAME} ne $sensorName);
my $sensorReadingName = $hash->{helper}{reading}; my $sensorReadingName = $hash->{helper}{reading};
my $regexp = $hash->{helper}{regexp}; my $regexp = $hash->{helper}{regexp};
my $desiredName = AttrVal( $name, 'pidDesiredName', 'desired' ); my $desiredName = AttrVal( $name, 'pidDesiredName', 'desired' );
my $desired = ReadingsVal( $name,$desiredName, undef ); my $desired = ReadingsVal( $name, $desiredName, undef );
my $max = int( @{ $dev->{CHANGED} } );
PID20_Log $hash, 4, "check $max readings for " . $sensorReadingName;
my $max = int(@{$dev->{CHANGED}}); for ( my $i = 0 ; $i < $max ; $i++ )
PID20_Log $hash, 4, "check $max readings for ". $sensorReadingName; {
for (my $i = 0; $i < $max; $i++) {
my $s = $dev->{CHANGED}[$i]; my $s = $dev->{CHANGED}[$i];
# continue, if no match with reading-name # continue, if no match with reading-name
$s = "" if(!defined($s)); $s = "" if ( !defined($s) );
PID20_Log $hash, 5, "check event:<$s>"; PID20_Log $hash, 5, "check event:<$s>";
next if($s !~ m/$sensorReadingName/); next if ( $s !~ m/$sensorReadingName/ );
# ---- build difference current - old value # ---- build difference current - old value
# get sensor value # get sensor value
my $sensorStr = ReadingsVal( $sensorName, $sensorReadingName, undef ); my $sensorStr = ReadingsVal( $sensorName, $sensorReadingName, undef );
$sensorStr =~ m/$regexp/; $sensorStr =~ m/$regexp/;
my $sensorValue = $1; my $sensorValue = $1;
# calc difference of delta/deltaOld # calc difference of delta/deltaOld
my $delta = $desired - $sensorValue if (defined($desired)); my $delta = $desired - $sensorValue if ( defined($desired) );
my $deltaOld = ($hash->{helper}{deltaOld}+0) if (defined($hash->{helper}{deltaOld})); my $deltaOld = ( $hash->{helper}{deltaOld} + 0 ) if ( defined( $hash->{helper}{deltaOld} ) );
my $deltaDiff = ( $delta - $deltaOld ) if ( defined($delta) && defined($deltaOld) );
my $deltaDiff = ($delta - $deltaOld) if (defined($delta) && defined($deltaOld)); PID20_Log $hash, 5,
PID20_Log $hash, 5, "Diff: delta[".sprintf( "%.2f",$delta)."]" "Diff: delta["
." - deltaOld[".sprintf( "%.2f",$deltaOld)."]" . sprintf( "%.2f", $delta ) . "]"
."= Diff[".sprintf( "%.2f",$deltaDiff)."]" . " - deltaOld["
. sprintf( "%.2f", $deltaOld ) . "]"
. "= Diff["
. sprintf( "%.2f", $deltaDiff ) . "]"
if ($DEBUG); if ($DEBUG);
# ----- build difference of timestamps (ok) # ----- build difference of timestamps (ok)
my $deltaOldTsStr = $hash->{helper}{deltaOldTS}; my $deltaOldTsStr = $hash->{helper}{deltaOldTS};
my $deltaOldTsNum =time_str2num($deltaOldTsStr) if (defined($deltaOldTsStr)); my $deltaOldTsNum = time_str2num($deltaOldTsStr) if ( defined($deltaOldTsStr) );
my $nowTsNum = gettimeofday(); my $nowTsNum = gettimeofday();
my $tsDiff = ($nowTsNum - $deltaOldTsNum) my $tsDiff = ( $nowTsNum - $deltaOldTsNum )
if ( defined($deltaOldTsNum) && (($nowTsNum - $deltaOldTsNum)>0)); if ( defined($deltaOldTsNum) && ( ( $nowTsNum - $deltaOldTsNum ) > 0 ) );
PID20_Log $hash, 5, "tsDiff: tsDiff = $tsDiff " if ($DEBUG); PID20_Log $hash, 5, "tsDiff: tsDiff = $tsDiff " if ($DEBUG);
# ----- calculate gradient of delta # ----- calculate gradient of delta
my $deltaGradient =$deltaDiff/$tsDiff if(defined($deltaDiff) && defined($tsDiff) && ($tsDiff>0)); my $deltaGradient = $deltaDiff / $tsDiff
$deltaGradient = 0 if (!defined($deltaGradient)); if ( defined($deltaDiff) && defined($tsDiff) && ( $tsDiff > 0 ) );
$deltaGradient = 0 if ( !defined($deltaGradient) );
my $sdeltaDiff = ($deltaDiff)?sprintf( "%.2f",$deltaDiff):""; my $sdeltaDiff = ($deltaDiff) ? sprintf( "%.2f", $deltaDiff ) : "";
my $sTSDiff = ($tsDiff)?sprintf( "%.2f",$tsDiff):""; my $sTSDiff = ($tsDiff) ? sprintf( "%.2f", $tsDiff ) : "";
my $sDeltaGradient=($deltaGradient)?sprintf( "%.6f",$deltaGradient):""; my $sDeltaGradient = ($deltaGradient) ? sprintf( "%.6f", $deltaGradient ) : "";
PID20_Log $hash, 5, "deltaGradient: (Diff[$sdeltaDiff]" PID20_Log $hash, 5,
."/tsDiff[$sTSDiff]" "deltaGradient: (Diff[$sdeltaDiff]"
."=deltaGradient per sec [$sDeltaGradient]" if ($DEBUG); . "/tsDiff[$sTSDiff]"
. "=deltaGradient per sec [$sDeltaGradient]"
if ($DEBUG);
# ----- store results # ----- store results
$hash->{helper}{deltaGradient}=$deltaGradient; $hash->{helper}{deltaGradient} = $deltaGradient;
$hash->{helper}{deltaOld}= $delta; $hash->{helper}{deltaOld} = $delta;
$hash->{helper}{deltaOldTS}= TimeNow(); $hash->{helper}{deltaOldTS} = TimeNow();
last; last;
} }
return ""; return "";
@@ -307,7 +290,7 @@ sub PID20_Get($@)
$ret .= 'Actor upper limit: ' . $hash->{helper}{actorLimitUpper} . "\n"; $ret .= 'Actor upper limit: ' . $hash->{helper}{actorLimitUpper} . "\n";
return $ret; return $ret;
} }
default { return $usage; }; default { return $usage; }
} }
} }
######################################## ########################################
@@ -315,76 +298,66 @@ sub PID20_Set($@)
{ {
my ( $hash, @a ) = @_; my ( $hash, @a ) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $reFloat ='^([\\+,\\-]?\\d+\\.?\d*$)'; my $reFloat = '^([\\+,\\-]?\\d+\\.?\d*$)';
my $usage = my $usage =
"Unknown argument $a[1], choose one of stop:noArg start:noArg restart " "Unknown argument $a[1], choose one of stop:noArg start:noArg restart "
. AttrVal( $name, 'pidDesiredName', 'desired' ); . AttrVal( $name, 'pidDesiredName', 'desired' );
return $usage if ( @a < 2 ); return $usage if ( @a < 2 );
my $cmd = lc( $a[1] ); my $cmd = lc( $a[1] );
my $desiredName = lc(AttrVal( $name, 'pidDesiredName', 'desired' )); my $desiredName = lc( AttrVal( $name, 'pidDesiredName', 'desired' ) );
#PID20_Log $hash, 3, "name:$name cmd:$cmd $desired:$desired";
#PID20_Log $hash, 3, "name:$name cmd:$cmd $desired:$desired";
given ($cmd) given ($cmd)
{ {
when ("?") when ("?")
{ {
return $usage; return $usage;
} }
when ($desiredName)
when ( $desiredName )
{ {
return "Set " . AttrVal( $name, 'pidDesiredName', 'desired' ) . " needs a <value> parameter" return
"Set "
. AttrVal( $name, 'pidDesiredName', 'desired' )
. " needs a <value> parameter"
if ( @a != 3 ); if ( @a != 3 );
my $value = $a[2];
my $value=$a[2]; $value = ( $value =~ m/$reFloat/ ) ? $1 : undef;
$value=($value=~ m/$reFloat/) ? $1:undef; return "value " . $a[2] . " is not a number"
return "value ".$a[2]." is not a number" if ( !defined($value) );
if (!defined($value));
readingsSingleUpdate( $hash, $cmd, $value, 1 ); readingsSingleUpdate( $hash, $cmd, $value, 1 );
PID20_Log $hash, 3, "set $name $cmd $a[2]"; PID20_Log $hash, 3, "set $name $cmd $a[2]";
} }
when ("start") when ("start")
{ {
return "Set start needs a <value> parameter" return "Set start needs a <value> parameter"
if ( @a != 2 ); if ( @a != 2 );
$hash->{helper}{stopped} =0; $hash->{helper}{stopped} = 0;
} }
when ("stop") when ("stop")
{ {
return "Set stop needs a <value> parameter" return "Set stop needs a <value> parameter"
if ( @a != 2 ); if ( @a != 2 );
$hash->{helper}{stopped} =1; $hash->{helper}{stopped} = 1;
PID20_Calc($name); PID20_Calc($name);
} }
when ("restart") when ("restart")
{ {
return "Set restart needs a <value> parameter" return "Set restart needs a <value> parameter"
if ( @a != 3 ); if ( @a != 3 );
my $value = $a[2];
$value = ( $value =~ m/$reFloat/ ) ? $1 : undef;
my $value=$a[2];
$value=($value=~ m/$reFloat/) ? $1:undef;
#PID20_Log $hash, 1, "value:$value"; #PID20_Log $hash, 1, "value:$value";
return "value " . $a[2] . " is not a number"
return "value ".$a[2]." is not a number" if ( !defined($value) );
if (!defined($value)); $hash->{helper}{stopped} = 0;
$hash->{helper}{adjust} = $value;
$hash->{helper}{stopped} =0;
$hash->{helper}{adjust} =$value;
PID20_Log $hash, 3, "set $name $cmd $value"; PID20_Log $hash, 3, "set $name $cmd $value";
} }
when ("calc") # inofficial function, only for debugging purposes when ("calc") # inofficial function, only for debugging purposes
{ {
PID20_Calc($name); PID20_Calc($name);
} }
default default
{ {
return $usage; return $usage;
@@ -392,7 +365,6 @@ sub PID20_Set($@)
} }
return; return;
} }
######################################## ########################################
# disabled = 0 # disabled = 0
# idle = 1 # idle = 1
@@ -404,185 +376,185 @@ sub PID20_Calc($)
my $reUINT = '^([\\+]?\\d+)$'; # uint without whitespaces my $reUINT = '^([\\+]?\\d+)$'; # uint without whitespaces
my $re01 = '^([0,1])$'; # only 0,1 my $re01 = '^([0,1])$'; # only 0,1
my $reINT = '^([\\+,\\-]?\\d+$)'; # int my $reINT = '^([\\+,\\-]?\\d+$)'; # int
my $reFloatpos ='^([\\+]?\\d+\\.?\d*$)'; # gleitpunkt positiv my $reFloatpos = '^([\\+]?\\d+\\.?\d*$)'; # gleitpunkt positiv
my $reFloat ='^([\\+,\\-]?\\d+\\.?\d*$)'; # gleitpunkt my $reFloat = '^([\\+,\\-]?\\d+\\.?\d*$)'; # gleitpunkt
my ($name) = @_; my ($name) = @_;
my $hash = $defs{$name}; my $hash = $defs{$name};
my $sensor = $hash->{helper}{sensor}; my $sensor = $hash->{helper}{sensor};
my $reading = $hash->{helper}{reading}; my $reading = $hash->{helper}{reading};
my $regexp = $hash->{helper}{regexp}; my $regexp = $hash->{helper}{regexp};
my $DEBUG_Sensor = AttrVal( $name, 'pidDebugSensor', '0' ) eq '1';
my $DEBUG_Sensor = AttrVal($name, 'pidDebugSensor', '0' ) eq '1'; my $DEBUG_Actuation = AttrVal( $name, 'pidDebugActuation', '0' ) eq '1';
my $DEBUG_Actuation = AttrVal($name, 'pidDebugActuation', '0' ) eq '1'; my $DEBUG_Delta = AttrVal( $name, 'pidDebugDelta', '0' ) eq '1';
my $DEBUG_Delta = AttrVal($name, 'pidDebugDelta', '0' ) eq '1'; my $DEBUG_Calc = AttrVal( $name, 'pidDebugCalc', '0' ) eq '1';
my $DEBUG_Calc = AttrVal($name, 'pidDebugCalc', '0' ) eq '1'; my $DEBUG_Update = AttrVal( $name, 'pidDebugUpdate', '0' ) eq '1';
my $DEBUG_Update = AttrVal($name, 'pidDebugUpdate', '0' ) eq '1'; my $DEBUG = $DEBUG_Sensor || $DEBUG_Actuation || $DEBUG_Calc || $DEBUG_Delta || $DEBUG_Update;
my $DEBUG = $DEBUG_Sensor || $DEBUG_Actuation || $DEBUG_Calc || $DEBUG_Delta || $DEBUG_Update ;
my $actuation = ""; my $actuation = "";
my $actuationDone = ReadingsVal( $name, 'actuation', "" ); my $actuationDone = ReadingsVal( $name, 'actuation', "" );
my $actuationCalc = ReadingsVal( $name, 'actuationCalc', "" ); my $actuationCalc = ReadingsVal( $name, 'actuationCalc', "" );
my $actuationCalcOld = $actuationCalc; my $actuationCalcOld = $actuationCalc;
my $actorTimestamp = ($hash->{helper}{actorTimestamp}) my $actorTimestamp =
?$hash->{helper}{actorTimestamp}:FmtDateTime(gettimeofday()-3600*24); ( $hash->{helper}{actorTimestamp} )
? $hash->{helper}{actorTimestamp}
: FmtDateTime( gettimeofday() - 3600 * 24 );
my $sensorStr = ReadingsVal( $sensor, $reading, "" ); my $sensorStr = ReadingsVal( $sensor, $reading, "" );
my $sensorValue = ""; my $sensorValue = "";
my $sensorTS = ReadingsTimestamp( $sensor, $reading, undef ); my $sensorTS = ReadingsTimestamp( $sensor, $reading, undef );
my $sensorIsAlive = 0; my $sensorIsAlive = 0;
my $iPortion = ReadingsVal( $name, 'p_i', 0 ); my $iPortion = ReadingsVal( $name, 'p_i', 0 );
my $pPortion = ""; my $pPortion = "";
my $dPortion = ""; my $dPortion = "";
my $stateStr = ""; my $stateStr = "";
my $deltaOld = ReadingsVal( $name, 'delta', 0 ); my $deltaOld = ReadingsVal( $name, 'delta', 0 );
my $delta = ""; my $delta = "";
my $deltaGradient = ($hash->{helper}{deltaGradient})?$hash->{helper}{deltaGradient}:0; my $deltaGradient = ( $hash->{helper}{deltaGradient} ) ? $hash->{helper}{deltaGradient} : 0;
my $calcReq = 0; my $calcReq = 0;
# ---------------- check different conditions # ---------------- check different conditions
while (1) while (1)
{ {
# --------------- retrive values from attributes # --------------- retrive values from attributes
$hash->{helper}{actorInterval} =
$hash->{helper}{actorInterval} = (AttrVal($name, 'pidActorInterval', 180 ) =~ m/$reUINT/) ? $1:180; ( AttrVal( $name, 'pidActorInterval', 180 ) =~ m/$reUINT/ ) ? $1 : 180;
$hash->{helper}{actorThreshold} = (AttrVal($name, 'pidActorTreshold', 1 ) =~ m/$reUINT/) ? $1:1; $hash->{helper}{actorThreshold} =
$hash->{helper}{actorKeepAlive} = (AttrVal($name, 'pidActorKeepAlive', 1800 ) =~ m/$reUINT/) ? $1:1800; ( AttrVal( $name, 'pidActorTreshold', 1 ) =~ m/$reUINT/ ) ? $1 : 1;
$hash->{helper}{actorValueDecPlaces} = (AttrVal($name, 'pidActorValueDecPlaces', 0 ) =~ m/$reUINT/) ? $1:0; $hash->{helper}{actorKeepAlive} =
( AttrVal( $name, 'pidActorKeepAlive', 1800 ) =~ m/$reUINT/ ) ? $1 : 1800;
$hash->{helper}{actorErrorAction} = (AttrVal($name, 'pidActorErrorAction', 'freeze') eq 'errorPos') ?'errorPos':'freeze'; $hash->{helper}{actorValueDecPlaces} =
$hash->{helper}{actorErrorPos} = (AttrVal($name, 'pidActorErrorPos', 0 ) =~ m/$reINT/) ? $1:0; ( AttrVal( $name, 'pidActorValueDecPlaces', 0 ) =~ m/$reUINT/ ) ? $1 : 0;
$hash->{helper}{actorErrorAction} =
( AttrVal( $name, 'pidActorErrorAction', 'freeze' ) eq 'errorPos' ) ? 'errorPos' : 'freeze';
$hash->{helper}{calcInterval} = (AttrVal($name, 'pidCalcInterval', 60 ) =~ m/$reUINT/) ? $1:60; $hash->{helper}{actorErrorPos} =
$hash->{helper}{deltaTreshold} = (AttrVal($name, 'pidDeltaTreshold', 0 ) =~ m/$reFloatpos/) ? $1:0; ( AttrVal( $name, 'pidActorErrorPos', 0 ) =~ m/$reINT/ ) ? $1 : 0;
$hash->{helper}{disable} = (AttrVal($name, 'Disable', 0 ) =~ m/$re01/) ? $1:''; $hash->{helper}{calcInterval} =
( AttrVal( $name, 'pidCalcInterval', 60 ) =~ m/$reUINT/ ) ? $1 : 60;
$hash->{helper}{sensorTimeout} = (AttrVal($name, 'pidSensorTimeout', 3600 ) =~ m/$reUINT/) ? $1:3600; $hash->{helper}{deltaTreshold} =
$hash->{helper}{reverseAction} = (AttrVal($name, 'pidReverseAction', 0 ) =~ m/$re01/) ? $1:0; ( AttrVal( $name, 'pidDeltaTreshold', 0 ) =~ m/$reFloatpos/ ) ? $1 : 0;
$hash->{helper}{updateInterval} = (AttrVal($name, 'pidUpdateInterval', 600 ) =~ m/$reUINT/) ? $1:600; $hash->{helper}{disable} = ( AttrVal( $name, 'disable', 0 ) =~ m/$re01/ ) ? $1 : '';
$hash->{helper}{sensorTimeout} =
$hash->{helper}{measuredName} = AttrVal($name, 'pidMeasuredName', 'measured') ; ( AttrVal( $name, 'pidSensorTimeout', 3600 ) =~ m/$reUINT/ ) ? $1 : 3600;
$hash->{helper}{desiredName} = AttrVal($name, 'pidDesiredName', 'desired') ; $hash->{helper}{reverseAction} =
( AttrVal( $name, 'pidReverseAction', 0 ) =~ m/$re01/ ) ? $1 : 0;
$hash->{helper}{actorLimitLower} = (AttrVal($name, 'pidActorLimitLower', 0) =~ m/$reFloat/) ? $1:0; $hash->{helper}{updateInterval} =
( AttrVal( $name, 'pidUpdateInterval', 600 ) =~ m/$reUINT/ ) ? $1 : 600;
$hash->{helper}{measuredName} = AttrVal( $name, 'pidMeasuredName', 'measured' );
$hash->{helper}{desiredName} = AttrVal( $name, 'pidDesiredName', 'desired' );
$hash->{helper}{actorLimitLower} =
( AttrVal( $name, 'pidActorLimitLower', 0 ) =~ m/$reFloat/ ) ? $1 : 0;
my $actorLimitLower = $hash->{helper}{actorLimitLower}; my $actorLimitLower = $hash->{helper}{actorLimitLower};
$hash->{helper}{actorLimitUpper} =
$hash->{helper}{actorLimitUpper} = (AttrVal($name, 'pidActorLimitUpper', 100) =~ m/$reFloat/) ? $1:100; ( AttrVal( $name, 'pidActorLimitUpper', 100 ) =~ m/$reFloat/ ) ? $1 : 100;
my $actorLimitUpper = $hash->{helper}{actorLimitUpper}; my $actorLimitUpper = $hash->{helper}{actorLimitUpper};
$hash->{helper}{factor_P} =
( AttrVal( $name, 'pidFactor_P', 25 ) =~ m/$reFloatpos/ ) ? $1 : 25;
$hash->{helper}{factor_I} =
( AttrVal( $name, 'pidFactor_I', 0.25 ) =~ m/$reFloatpos/ ) ? $1 : 0.25;
$hash->{helper}{factor_D} = ( AttrVal( $name, 'pidFactor_D', 0 ) =~ m/$reFloatpos/ ) ? $1 : 0;
$hash->{helper}{factor_P} = (AttrVal($name, 'pidFactor_P', 25) =~ m/$reFloatpos/) ? $1:25; if ( $hash->{helper}{disable} )
$hash->{helper}{factor_I} = (AttrVal($name, 'pidFactor_I', 0.25) =~ m/$reFloatpos/) ? $1:0.25;
$hash->{helper}{factor_D} = (AttrVal($name, 'pidFactor_D', 0) =~ m/$reFloatpos/) ? $1:0;
if ($hash->{helper}{disable})
{ {
$stateStr="disabled"; $stateStr = "disabled";
last; last;
} }
if ( $hash->{helper}{stopped} )
if ($hash->{helper}{stopped})
{ {
$stateStr="stopped"; $stateStr = "stopped";
last; last;
} }
my $desired = ReadingsVal( $name, $hash->{helper}{desiredName}, "" );
my $desired = ReadingsVal( $name,$hash->{helper}{desiredName}, "" );
# sensor found # sensor found
PID20_Log $hash, 2, "--------------------------" if ($DEBUG); PID20_Log $hash, 2, "--------------------------" if ($DEBUG);
PID20_Log $hash, 2, "S1 sensorStr:$sensorStr sensorTS:$sensorTS" if ($DEBUG_Sensor); PID20_Log $hash, 2, "S1 sensorStr:$sensorStr sensorTS:$sensorTS" if ($DEBUG_Sensor);
$stateStr="alarm - no $reading yet for $sensor" if ( !$sensorStr && !$stateStr); $stateStr = "alarm - no $reading yet for $sensor" if ( !$sensorStr && !$stateStr );
# sensor alive # sensor alive
if ($sensorStr && $sensorTS) if ( $sensorStr && $sensorTS )
{ {
my $timeDiff = PID20_TimeDiff($sensorTS); my $timeDiff = PID20_TimeDiff($sensorTS);
$sensorIsAlive = 1 if ( $timeDiff <= $hash->{helper}{sensorTimeout} ); $sensorIsAlive = 1 if ( $timeDiff <= $hash->{helper}{sensorTimeout} );
$sensorStr =~ m/$regexp/; $sensorStr =~ m/$regexp/;
$sensorValue = $1; $sensorValue = $1;
$sensorValue="" if (!defined($sensorValue)); $sensorValue = "" if ( !defined($sensorValue) );
PID20_Log $hash, 2, "S2 timeOfDay:".gettimeofday() PID20_Log $hash, 2,
." timeDiff:$timeDiff sensorTimeout:".$hash->{helper}{sensorTimeout} "S2 timeOfDay:"
." --> sensorIsAlive:$sensorIsAlive" if ($DEBUG_Sensor); . gettimeofday()
. " timeDiff:$timeDiff sensorTimeout:"
. $hash->{helper}{sensorTimeout}
. " --> sensorIsAlive:$sensorIsAlive"
if ($DEBUG_Sensor);
} }
# sensor dead # sensor dead
$stateStr="alarm - dead sensor" if (!$sensorIsAlive && !$stateStr); $stateStr = "alarm - dead sensor" if ( !$sensorIsAlive && !$stateStr );
# missing desired # missing desired
$stateStr="alarm - missing desired" if ($desired eq "" && !$stateStr); $stateStr = "alarm - missing desired" if ( $desired eq "" && !$stateStr );
# check delta threshold # check delta threshold
$delta =($desired ne "" && $sensorValue ne "" ) ? $desired - $sensorValue : ""; $delta = ( $desired ne "" && $sensorValue ne "" ) ? $desired - $sensorValue : "";
$calcReq = 1
$calcReq = 1 if (!$stateStr && $delta ne "" && (abs($delta) >= abs( $hash->{helper}{deltaTreshold})) ); if ( !$stateStr
&& $delta ne ""
PID20_Log $hash, 2, "D1 desired[". ($desired ne "") ? sprintf( "%.1f", $desired) : "" && ( abs($delta) >= abs( $hash->{helper}{deltaTreshold} ) ) );
."] - sensorValue: [". ($sensorValue ne "") ? sprintf( "%.1f", $sensorValue) : "" PID20_Log $hash, 2,
."] = delta[". ($delta ne "") ? sprintf( "%.2f", $delta):"" "D1 desired[" . ( $desired ne "" ) ? sprintf( "%.1f", $desired )
."] calcReq:$calcReq" : "" . "] - sensorValue: [" . ( $sensorValue ne "" ) ? sprintf( "%.1f", $sensorValue )
: "" . "] = delta[" . ( $delta ne "" ) ? sprintf( "%.2f", $delta )
: "" . "] calcReq:$calcReq"
if ($DEBUG_Delta); if ($DEBUG_Delta);
#request for calculation #request for calculation
# ---------------- calculation request # ---------------- calculation request
if ($calcReq) if ($calcReq)
{ {
# reverse action requested # reverse action requested
my $workDelta = ( $hash->{helper}{reverseAction} ==1 ) ? -$delta: $delta; my $workDelta = ( $hash->{helper}{reverseAction} == 1 ) ? -$delta : $delta;
my $deltaOld = - $deltaOld if ($hash->{helper}{reverseAction} ==1 ); my $deltaOld = -$deltaOld if ( $hash->{helper}{reverseAction} == 1 );
# calc p-portion # calc p-portion
$pPortion = $workDelta * $hash->{helper}{factor_P}; $pPortion = $workDelta * $hash->{helper}{factor_P};
# calc d-Portion # calc d-Portion
$dPortion = ( $deltaGradient ) * $hash->{helper}{calcInterval} * $hash->{helper}{factor_D}; $dPortion = ($deltaGradient) * $hash->{helper}{calcInterval} * $hash->{helper}{factor_D};
# calc i-portion respecting windUp # calc i-portion respecting windUp
# freeze i-portion if windUp is active # freeze i-portion if windUp is active
my $isWindup = my $isWindup = $actuationCalcOld
$actuationCalcOld && && (( $workDelta > 0 && $actuationCalcOld > $actorLimitUpper )
( || ( $workDelta < 0 && $actuationCalcOld < $actorLimitLower ) );
( $workDelta > 0 && $actuationCalcOld > $actorLimitUpper ) if ( $hash->{helper}{adjust} ne "" )
|| ( $workDelta < 0 && $actuationCalcOld < $actorLimitLower )
);
if ($hash->{helper}{adjust} ne "")
{ {
$iPortion = $hash->{helper}{adjust} - ($pPortion + $dPortion); $iPortion = $hash->{helper}{adjust} - ( $pPortion + $dPortion );
$iPortion= $actorLimitUpper if($iPortion > $actorLimitUpper); $iPortion = $actorLimitUpper if ( $iPortion > $actorLimitUpper );
$iPortion= $actorLimitLower if($iPortion < $actorLimitLower); $iPortion = $actorLimitLower if ( $iPortion < $actorLimitLower );
PID20_Log $hash, 5, "adjust request with:".$hash->{helper}{adjust}." ==> p_i:$iPortion"; PID20_Log $hash, 5,
"adjust request with:" . $hash->{helper}{adjust} . " ==> p_i:$iPortion";
$hash->{helper}{adjust}=""; $hash->{helper}{adjust} = "";
} } elsif ( !$isWindup ) # integrate only if no windUp
elsif ( !$isWindup ) # integrate only if no windUp
{ {
# normalize the intervall to minute=60 seconds # normalize the intervall to minute=60 seconds
$iPortion = $iPortion + $workDelta * $hash->{helper}{factor_I}*$hash->{helper}{calcInterval}/60; $iPortion =
$iPortion +
$workDelta * $hash->{helper}{factor_I} * $hash->{helper}{calcInterval} / 60;
$hash->{helper}{isWindUP} = 0; $hash->{helper}{isWindUP} = 0;
} }
$hash->{helper}{isWindUP} = $isWindup; $hash->{helper}{isWindUP} = $isWindup;
# calc actuation # calc actuation
$actuationCalc = $pPortion + $iPortion + $dPortion; $actuationCalc = $pPortion + $iPortion + $dPortion;
PID20_Log $hash, 2, "P1 delta:".sprintf( "%.2f",$delta) PID20_Log $hash, 2, "P1 delta:" . sprintf( "%.2f", $delta ) . " isWindup:$isWindup"
." isWindup:$isWindup" if ($DEBUG_Calc);
PID20_Log $hash, 2,
"P2 pPortion:"
. sprintf( "%.2f", $pPortion )
. " iPortion:"
. sprintf( "%.2f", $iPortion )
. " dPortion:"
. sprintf( "%.2f", $dPortion )
. " actuationCalc:"
. sprintf( "%.2f", $actuationCalc )
if ($DEBUG_Calc); if ($DEBUG_Calc);
PID20_Log $hash, 2, "P2 pPortion:".sprintf( "%.2f",$pPortion)
." iPortion:".sprintf( "%.2f",$iPortion)
." dPortion:".sprintf( "%.2f",$dPortion)
." actuationCalc:".sprintf( "%.2f", $actuationCalc) if ($DEBUG_Calc);
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate( $hash, 'p_p', $pPortion ); readingsBulkUpdate( $hash, 'p_p', $pPortion );
readingsBulkUpdate( $hash, 'p_i', $iPortion ); readingsBulkUpdate( $hash, 'p_i', $iPortion );
@@ -590,127 +562,133 @@ sub PID20_Calc($)
readingsBulkUpdate( $hash, 'actuationCalc', $actuationCalc ); readingsBulkUpdate( $hash, 'actuationCalc', $actuationCalc );
readingsBulkUpdate( $hash, 'delta', $delta ); readingsBulkUpdate( $hash, 'delta', $delta );
readingsEndUpdate( $hash, 0 ); readingsEndUpdate( $hash, 0 );
#PID20_Log $hash, 3, "calculation done"; #PID20_Log $hash, 3, "calculation done";
} }
# ---------------- acutation request # ---------------- acutation request
my $noTrouble = ($desired ne "" && $sensorIsAlive); my $noTrouble = ( $desired ne "" && $sensorIsAlive );
# check actor fallback in case of sensor fault # check actor fallback in case of sensor fault
if (!$sensorIsAlive && ($hash->{helper}{actorErrorAction} eq "errorPos")) if ( !$sensorIsAlive && ( $hash->{helper}{actorErrorAction} eq "errorPos" ) )
{ {
$stateStr .= "- force pid-output to errorPos"; $stateStr .= "- force pid-output to errorPos";
$actuationCalc=$hash->{helper}{actorErrorPos}; $actuationCalc = $hash->{helper}{actorErrorPos};
$actuationCalc="" if (!defined($actuationCalc)); $actuationCalc = "" if ( !defined($actuationCalc) );
} }
# check acutation diff # check acutation diff
$actuation = $actuationCalc; $actuation = $actuationCalc;
# limit $actuation # limit $actuation
$actuation= $actorLimitUpper if($actuation ne "" && ($actuation > $actorLimitUpper)); $actuation = $actorLimitUpper if ( $actuation ne "" && ( $actuation > $actorLimitUpper ) );
$actuation= $actorLimitLower if($actuation ne "" && ($actuation < $actorLimitLower)); $actuation = $actorLimitLower if ( $actuation ne "" && ( $actuation < $actorLimitLower ) );
# check if round request # check if round request
my $fmt= "%.".$hash->{helper}{actorValueDecPlaces}."f"; my $fmt = "%." . $hash->{helper}{actorValueDecPlaces} . "f";
$actuation = sprintf( $fmt, $actuation) if ($actuation ne ""); $actuation = sprintf( $fmt, $actuation ) if ( $actuation ne "" );
my $actuationDiff = abs( $actuation - $actuationDone )
my $actuationDiff = abs( $actuation - $actuationDone) if ($actuation ne "" && $actuationDone ne ""); if ( $actuation ne "" && $actuationDone ne "" );
PID20_Log $hash, 2, "A1 act:$actuation actDone:$actuationDone " PID20_Log $hash, 2,
." actThreshold:".$hash->{helper}{actorThreshold} "A1 act:$actuation actDone:$actuationDone "
." actDiff:$actuationDiff" . " actThreshold:"
. $hash->{helper}{actorThreshold}
. " actDiff:$actuationDiff"
if ($DEBUG_Actuation); if ($DEBUG_Actuation);
# check threshold-condition for actuation # check threshold-condition for actuation
my $rsTS = $actuationDone ne "" # limit exceeded my $rsTS = $actuationDone ne "" # limit exceeded
&& $actuationDiff >= $hash->{helper}{actorThreshold}; && $actuationDiff >= $hash->{helper}{actorThreshold};
my $rsUp = $actuationDone ne "" # upper range my $rsUp = $actuationDone ne "" # upper range
&& $actuation>$actorLimitUpper-$hash->{helper}{actorThreshold} && $actuation > $actorLimitUpper - $hash->{helper}{actorThreshold}
&& $actuationDiff != 0 && $actuationDiff != 0
&& $actuation >=$actorLimitUpper; && $actuation >= $actorLimitUpper;
my $rsDown = $actuationDone ne "" # low range my $rsDown = $actuationDone ne "" # low range
&& $actuation<$actorLimitLower+$hash->{helper}{actorThreshold} && $actuation < $actorLimitLower + $hash->{helper}{actorThreshold}
&& $actuationDiff != 0 && $actuationDiff != 0
&& $actuation <=$actorLimitLower; && $actuation <= $actorLimitLower;
my $rsLimit = $actuationDone ne "" my $rsLimit = $actuationDone ne ""
&& ($actuationDone<$actorLimitLower || $actuationDone>$actorLimitUpper); && ( $actuationDone < $actorLimitLower || $actuationDone > $actorLimitUpper );
my $actuationByThreshold = ( ( $rsTS || $rsUp || $rsDown ) && $noTrouble );
my $actuationByThreshold = ( ($rsTS || $rsUp || $rsDown ) && $noTrouble); PID20_Log $hash, 2, "A2 rsTS:$rsTS rsUp:$rsUp rsDown:$rsDown noTrouble:$noTrouble"
if ($DEBUG_Actuation);
PID20_Log $hash, 2, "A2 rsTS:$rsTS rsUp:$rsUp rsDown:$rsDown noTrouble:$noTrouble" if ($DEBUG_Actuation);
# check time condition for actuation # check time condition for actuation
my $actTimeDiff = PID20_TimeDiff($actorTimestamp); # $actorTimestamp is valid in each case my $actTimeDiff = PID20_TimeDiff($actorTimestamp); # $actorTimestamp is valid in each case
my $actuationByTime = ($noTrouble) && ($actTimeDiff > $hash->{helper}{actorInterval}); my $actuationByTime = ($noTrouble) && ( $actTimeDiff > $hash->{helper}{actorInterval} );
PID20_Log $hash, 2,
PID20_Log $hash, 2, "A3 actTS:$actorTimestamp" "A3 actTS:$actorTimestamp"
." actTimeDiff:".sprintf( "%.2f",$actTimeDiff) . " actTimeDiff:"
." actInterval:".$hash->{helper}{actorInterval} . sprintf( "%.2f", $actTimeDiff )
."-->actByTime:$actuationByTime " if ($DEBUG_Actuation); . " actInterval:"
. $hash->{helper}{actorInterval}
. "-->actByTime:$actuationByTime "
if ($DEBUG_Actuation);
# check keep alive condition for actuation # check keep alive condition for actuation
my $actuationKeepAliveReq = ($actTimeDiff >= $hash->{helper}{actorKeepAlive}) my $actuationKeepAliveReq = ( $actTimeDiff >= $hash->{helper}{actorKeepAlive} )
if (defined($actTimeDiff) && $actuation ne ""); if ( defined($actTimeDiff) && $actuation ne "" );
# summary actuation reques # summary actuation reques
my $actuationReq = ( my $actuationReq = (
($actuationByThreshold && $actuationByTime) ( $actuationByThreshold && $actuationByTime )
|| $actuationKeepAliveReq || $actuationKeepAliveReq
|| $rsLimit || $rsLimit
|| $actuationDone eq "" # startup condition || $actuationDone eq "" # startup condition
) ) && $actuation ne "";
&& $actuation ne ""; PID20_Log $hash, 2,
"A4 (actByTh:$actuationByThreshold && actByTime:$actuationByTime)"
PID20_Log $hash, 2, "A4 (actByTh:$actuationByThreshold && actByTime:$actuationByTime)" . "||actKeepAlive:$actuationKeepAliveReq"
."||actKeepAlive:$actuationKeepAliveReq" . "||rsLimit:$rsLimit=actnReq:$actuationReq"
."||rsLimit:$rsLimit=actnReq:$actuationReq" if ($DEBUG_Actuation); if ($DEBUG_Actuation);
# perform output to actor # perform output to actor
if ($actuationReq) if ($actuationReq)
{ {
#build command for fhem #build command for fhem
PID20_Log $hash, 5, "actor:".$hash->{helper}{actor} PID20_Log $hash, 5,
." actorCommand:".$hash->{helper}{actorCommand} "actor:"
." actuation:".$actuation; . $hash->{helper}{actor}
. " actorCommand:"
my $cmd= sprintf("set %s %s %g", $hash->{helper}{actor}, $hash->{helper}{actorCommand},$actuation); . $hash->{helper}{actorCommand}
. " actuation:"
. $actuation;
my $cmd = sprintf( "set %s %s %g",
$hash->{helper}{actor},
$hash->{helper}{actorCommand}, $actuation );
# execute command # execute command
my $ret; my $ret;
$ret = fhem $cmd; $ret = fhem $cmd;
# note timestamp # note timestamp
$hash->{helper}{actorTimestamp}=TimeNow(); $hash->{helper}{actorTimestamp} = TimeNow();
$actuationDone=$actuation; $actuationDone = $actuation;
my $retStr=""; my $retStr = "";
$retStr = " with return-value:".$ret if (defined($ret) && ($ret ne '')); $retStr = " with return-value:" . $ret if ( defined($ret) && ( $ret ne '' ) );
PID20_Log $hash, 3, "<$cmd> ".$retStr; PID20_Log $hash, 3, "<$cmd> " . $retStr;
} }
my $updateAlive = ( $actuation ne "" )
my $updateAlive= ($actuation ne "") && PID20_TimeDiff( ReadingsTimestamp( $name, 'actuation', gettimeofday() ) ) >=
&& PID20_TimeDiff(ReadingsTimestamp( $name, 'actuation', gettimeofday()))>=$hash->{helper}{updateInterval}; $hash->{helper}{updateInterval};
my $updateReq = ( ( $actuationReq || $updateAlive ) && $actuation ne "" );
my $updateReq=(($actuationReq || $updateAlive) && $actuation ne ""); PID20_Log $hash, 2,
"U1 actReq:$actuationReq updateAlive:$updateAlive --> updateReq:$updateReq"
PID20_Log $hash, 2, "U1 actReq:$actuationReq updateAlive:$updateAlive --> updateReq:$updateReq"
if ($DEBUG_Update); if ($DEBUG_Update);
# ---------------- update request # ---------------- update request
if ($updateReq) if ($updateReq)
{ {
readingsBeginUpdate($hash); readingsBeginUpdate($hash);
readingsBulkUpdate( $hash, $hash->{helper}{desiredName}, $desired ) if ($desired ne ""); readingsBulkUpdate( $hash, $hash->{helper}{desiredName}, $desired ) if ( $desired ne "" );
readingsBulkUpdate( $hash, $hash->{helper}{measuredName}, $sensorValue ) if ($sensorValue ne ""); readingsBulkUpdate( $hash, $hash->{helper}{measuredName}, $sensorValue )
readingsBulkUpdate( $hash, 'p_p', $pPortion ) if ($pPortion ne""); if ( $sensorValue ne "" );
readingsBulkUpdate( $hash, 'p_d', $dPortion ) if ($dPortion ne ""); readingsBulkUpdate( $hash, 'p_p', $pPortion ) if ( $pPortion ne "" );
readingsBulkUpdate( $hash, 'p_i', $iPortion ) if ($iPortion ne ""); readingsBulkUpdate( $hash, 'p_d', $dPortion ) if ( $dPortion ne "" );
readingsBulkUpdate( $hash, 'actuation', $actuationDone ) if ($actuationDone ne ""); readingsBulkUpdate( $hash, 'p_i', $iPortion ) if ( $iPortion ne "" );
readingsBulkUpdate( $hash, 'actuationCalc', $actuationCalc ) if ($actuationCalc ne ""); readingsBulkUpdate( $hash, 'actuation', $actuationDone ) if ( $actuationDone ne "" );
readingsBulkUpdate( $hash, 'delta', $delta ) if ($delta ne ""); readingsBulkUpdate( $hash, 'actuationCalc', $actuationCalc ) if ( $actuationCalc ne "" );
readingsBulkUpdate( $hash, 'delta', $delta ) if ( $delta ne "" );
readingsEndUpdate( $hash, 1 ); readingsEndUpdate( $hash, 1 );
PID20_Log $hash, 5, "readings updated"; PID20_Log $hash, 5, "readings updated";
} }
@@ -718,10 +696,9 @@ sub PID20_Calc($)
} # end while } # end while
# update statePID. # update statePID.
$stateStr = "idle" if (!$stateStr && !$calcReq); $stateStr = "idle" if ( !$stateStr && !$calcReq );
$stateStr = "processing" if (!$stateStr && $calcReq); $stateStr = "processing" if ( !$stateStr && $calcReq );
readingsSingleUpdate( $hash, 'state', $stateStr , 0 ); readingsSingleUpdate( $hash, 'state', $stateStr, 0 );
PID20_Log $hash, 2, "C1 stateStr:$stateStr calcReq:$calcReq" if ($DEBUG_Calc); PID20_Log $hash, 2, "C1 stateStr:$stateStr calcReq:$calcReq" if ($DEBUG_Calc);
# timer setup # timer setup
@@ -729,12 +706,9 @@ sub PID20_Calc($)
RemoveInternalTimer($name); # prevent multiple timers for same hash RemoveInternalTimer($name); # prevent multiple timers for same hash
InternalTimer( $next, "PID20_Calc", $name, 1 ); InternalTimer( $next, "PID20_Calc", $name, 1 );
#PID20_Log $hash, 2, "InternalTimer next:".FmtDateTime($next)." PID20_Calc name:$name DEBUG_Calc:$DEBUG_Calc"; #PID20_Log $hash, 2, "InternalTimer next:".FmtDateTime($next)." PID20_Calc name:$name DEBUG_Calc:$DEBUG_Calc";
return; return;
} }
1; 1;
=pod =pod