From 03bbac7f89d30a5e344ea1d6bacb540b785d304c Mon Sep 17 00:00:00 2001 From: jamesgo Date: Wed, 14 Dec 2016 21:03:26 +0000 Subject: [PATCH] 93_PWMR.pm : use DBuffer for usePID=2, implement get previousTemps git-svn-id: https://svn.fhem.de/fhem/trunk@12778 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/93_PWMR.pm | 79 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 15 deletions(-) diff --git a/fhem/FHEM/93_PWMR.pm b/fhem/FHEM/93_PWMR.pm index 0e8a7d35f..b506678de 100644 --- a/fhem/FHEM/93_PWMR.pm +++ b/fhem/FHEM/93_PWMR.pm @@ -42,6 +42,8 @@ # 17.11.16 GA add internals for configuration parameters: p_factor, p_tsensor, p_actor, p_window, p_pid # 11.12.16 GA add alternative PID calculation, selectable by usePID=2, implementation from user Albatros_ # 14.12.16 GA fix adjust rounding of PVal and newpulsePID +# 14.12.16 GA fix supply DBuffer with delta temps for usePID=2 calculation +# 14.12.16 GA add implement get previousTemps # module for PWM (Pulse Width Modulation) calculation @@ -355,9 +357,19 @@ PWMR_Get($@) { my ($hash, @a) = @_; + my $u = "Unknown argument $a[1], choose one of previousTemps"; + return $u if ($a[1] eq "?"); + return "argument is missing" if(int(@a) != 2); - my $msg; + if ($a[1] eq "previousTemps") { + my $msg = ""; + $msg .= "IBuffer: ".join (" ", @{$hash->{helper}{PID_I_previousTemps}})."\n" if (defined ($hash->{helper}{PID_I_previousTemps})); + $msg .= "DBuffer: ".join (" ", @{$hash->{helper}{PID_D_previousTemps}})."\n" if (defined ($hash->{helper}{PID_D_previousTemps})); + + return $msg + } + if($a[1] ne "status") { return "unknown get value, valid is status"; @@ -508,7 +520,7 @@ PWMR_Define($$) return "syntax: define PWMR [:] [[,][:]] ". "[]|". "[::[,]:[,]]|". - "[:::]" + "[:::[,]]" if(int(@a) < 6 || int(@a) > 9); my $iodevname = $a[2]; @@ -687,6 +699,8 @@ PWMR_Define($$) } else { + # usePID >= 2 + delete ($hash->{READINGS}{PWMPulse}) if (defined($hash->{READINGS}{PWMPulse})); delete ($hash->{READINGS}{PWMOnTime}) if (defined($hash->{READINGS}{PWMOnTime})); @@ -700,17 +714,34 @@ PWMR_Define($$) $hash->{c_PID_IFactor} = !defined($IFactor) ? 0.01 : $IFactor; $hash->{c_PID_DFactor} = !defined($DFactor) ? 0 : $DFactor; - delete ($hash->{helper}{PID_I_previousTemps}) if (defined (($hash->{helper}{PID_I_previousTemps}))); - delete ($hash->{helper}{PID_D_previousTemps}) if (defined (($hash->{helper}{PID_D_previousTemps}))); + $hash->{c_PID_DLookBackCnt} = !defined($DLookBackCnt) ? 10 : $DLookBackCnt; - delete ($hash->{h_PID_I_previousTemps}) if (defined (($hash->{h_PID_I_previousTemps}))); - delete ($hash->{h_PID_D_previousTemps}) if (defined (($hash->{h_PID_D_previousTemps}))); + delete ($hash->{helper}{PID_I_previousTemps}) if (defined (($hash->{helper}{PID_I_previousTemps}))); + #delete ($hash->{helper}{PID_D_previousTemps}) if (defined (($hash->{helper}{PID_D_previousTemps}))); delete ($hash->{c_PID_ILookBackCnt}) if (defined ($hash->{c_PID_ILookBackCnt})); - delete ($hash->{c_PID_DLookBackCnt}) if (defined ($hash->{c_PID_DLookBackCnt})); + #delete ($hash->{c_PID_DLookBackCnt}) if (defined ($hash->{c_PID_DLookBackCnt})); - delete ($hash->{h_deltaTemp}) if (defined ($hash->{h_deltaTemp})); - delete ($hash->{h_deltaTemp_D}) if (defined ($hash->{h_deltaTemp_D})); + #delete ($hash->{h_deltaTemp}) if (defined ($hash->{h_deltaTemp})); + #delete ($hash->{h_deltaTemp_D}) if (defined ($hash->{h_deltaTemp_D})); + + ### D-Factor + + # initialize if not yet done + $hash->{helper}{PID_D_previousTemps} = [] unless defined (($hash->{helper}{PID_D_previousTemps})); + + # shorter reference to array + my $DBuffer = $hash->{helper}{PID_D_previousTemps}; + my $Dcnt = ( @{$DBuffer} ); # or scalar @{$DBuffer} + + # reference + #Log3 ($hash, 3, "org reference DBuffer is $hash->{helper}{PID_D_previousTemps} short is $DBuffer, cnt is ". scalar @{$DBuffer}." (starting from 0)"); + Log3 ($hash, 4, "content of DBuffer is @{$DBuffer}"); + + # cut Buffer if it is too large + while (scalar @{$DBuffer} > $hash->{c_PID_DLookBackCnt}) { + my $v = shift @{$DBuffer}; + } } @@ -1084,12 +1115,23 @@ PWMR_ReadRoom(@) } elsif($room->{c_PID_useit} >= 2) { + my $DBuffer = $room->{helper}{PID_D_previousTemps}; + push @{$DBuffer}, $temperaturV; + + # cut D-Buffer if it is too large + while (scalar @{$DBuffer} > $room->{c_PID_DLookBackCnt}) { + my $v = shift @{$DBuffer}; + #Log3 ($room, 3, "shift $v from DBuffer"); + } + #Log3 ($room, 3, "DBuffer contains ".scalar @{$DBuffer}." elements"); + my $deltaTempPID = $desiredTemp - $temperaturV; $room->{h_deltaTemp} = sprintf ("%.1f", -1 * $deltaTempPID); + $room->{h_deltaTemp_D} = sprintf ("%.1f", -1 * ($desiredTemp - $DBuffer->[0])); #calculate IValue my $ISum = $room->{READINGS}{"PID_IVal"}{VAL}; - $ISum = $ISum + ($deltaTempPID*$room->{c_PID_IFactor}); + $ISum = $ISum + ($deltaTempPID * $room->{c_PID_IFactor}); my $PVal = $room->{c_PID_PFactor} * $deltaTempPID; my $IVal = $ISum; @@ -1642,7 +1684,7 @@ PWMR_valueFormat(@) Define
    - define <name> PWMR <IODev> <factor[,offset]> <tsensor[:reading:[t_regexp]]> <actor>[:<a_regexp_on>] [<window|dummy>[,<window>[:<w_regexp>]] [ <usePID=0> | <usePID=1>:<PFactor>:<IFactor>[,<ILookBackCnt>]:<DFactor>[,<DLookBackCnt>] | <usePID=2>:<PFactor>:<IFactor>:<DFactor> ]
    + define <name> PWMR <IODev> <factor[,offset]> <tsensor[:reading:[t_regexp]]> <actor>[:<a_regexp_on>] [<window|dummy>[,<window>[:<w_regexp>]] [ <usePID=0> | <usePID=1>:<PFactor>:<IFactor>[,<ILookBackCnt>]:<DFactor>[,<DLookBackCnt>] | <usePID=2>:<PFactor>:<IFactor>:<DFactor>[,<DLookBackCnt>] ]

    Define a calculation object with the following parameters:
    @@ -1692,11 +1734,12 @@ PWMR_valueFormat(@) Readings PID_DVal, PID_IVal, PID_PVal, PID_PWMOnTime and PID_PWMPulse will reflect the actual calculated PID values and Pulse.
  • - <usePID=2>:<PFactor>:<IFactor>:<DFactor>
    + <usePID=2>:<PFactor>:<IFactor>:<DFactor>[,<DLookBackCnt>]
    PFactor: Konstant for P. Default is 0.8.
    IFactor: Konstant for I. Default is 0.01
    DFactor: Konstant for D. Default is 0
    - Internals c_PID_PFactor, c_PID_IFactor, c_PID_DFactor and c_PID_useit will reflect the above configuration values.
    + DLookBackCnt: Buffer size to store previous temperatures. For D calculation actual and oldest temperature will be used. Default is 10.
    + Internals c_PID_PFactor, c_PID_IFactor, c_PID_DFactor, c_PID_DLookBackCnt and c_PID_useit will reflect the above configuration values.
    Readings PID_DVal, PID_IVal, PID_PVal, PID_PWMOnTime and PID_PWMPulse will reflect the actual calculated PID values and Pulse.
  • @@ -1712,7 +1755,8 @@ PWMR_valueFormat(@) define roomKitchen PWMR fh 1,0.11 tempKitchen relaisKitchen dummy 0
    define roomKitchen PWMR fh 0 tempKitchen relaisKitchen dummy 1:0.8:0.3:0.5
    define roomKitchen PWMR fh 0 tempKitchen relaisKitchen dummy 1:0.8:0.3,5:0.5,10
    - define roomKitchen PWMR fh 0 tempKitchen relaisKitchen dummy 2:0.8:0.01:0
    + define roomKitchen PWMR fh 0 tempKitchen relaisKitchen dummy 2:0.8:0.01:00
    + define roomKitchen PWMR fh 0 tempKitchen relaisKitchen dummy 2:0.8:0.01:0.1,10

    @@ -1750,7 +1794,12 @@ PWMR_valueFormat(@)
-
+ Get +
    +
  • previousTemps
    + Get conent of buffers defined by ILookBackCnt and DLookBackCnt. +

  • +
Attributes