Neues Modul PID20 - Der PID-Regler

Begonnen von John, 02 Dezember 2013, 22:03:40

Vorheriges Thema - Nächstes Thema

John

actuationCalc wird sich am häufigsten ändern und wird in jedem Zyklus geschrieben.
John
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

AlterSchwede

Hallo,

ich habe heute das PID20 Modul ausprobiert und bin direkt in der define-Anweisung auf ein kleines Problem gestoßen. Meine Definition sollte so aussehen:

define PID.PID PID20 netatmo_D70:ee:50:04:cd:38:temperature MAX_1059f4:maxValveSetting

wobei "netatmo_D70:ee:50:04:cd:38" der Name meines Sensors ist. Ich erhalte als Fehlermeldung: "PID.PID: Unknown sensor device netatmo_D70 specified". Meine Vermutung ist, dass das Reading (also "temperature" in diesem Fall) direkt nach dem ersten auftretenden Doppelpunkt erwartet wird.
Ein Versuch, den Alias des Sensors zu verwenden hat leider nicht funktioniert. "Unknown Sensor..."

Ich hoffe, der Beitrag ist hier richtig.

Viele Grüße
Alter Schwede

mkninc

Das Problem hatte ich auch. Die Doppelpunkte im Namen der Netatmo sind das Problem. Benenne die Netatmo Module um, dann dann sollte das klappen.

John

@AlterSchwede
mkninc hat wohl recht.

Das Problem ist, daß der Doppelpunkt als Separator zwischen Device-Namen und Reading verwendet wird.
Das ist überall so in FHEM.

Der Name ist daher extrem ungünstig.

Umbemennen geht via "rename <alt> <neu>"
John
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

AlterSchwede

Hallo John, Hallo mkninc!

Die Netatmo ist umbenannt. Danach hat alles bestens funktioniert. Tolles Modul! Danke!
Der erste Thermostat läuft als Stellglied. Morgen sind die beiden anderen dran!

Viel Erfolg und ein Gesundes Neues Jahr!

Der Alte Schwede

Nick666

Hallöle,

ich habe eine Anwendung, bei der ich einen Heizstrahler mit einem FS20-Dimmer ansteuern möchte. Dazu verwende ich das PID20-Modul.
Problem war, dass der FS20-Dimmer nur in Stufen von 6,25 % dimmt und das im PID20-Modul nicht einstellbar war.

Ich habe deshalb eine kleine Änderung vorgenommen:
+ Zusätzlicher Parameter FS20Dim
+ Wenn dieser auf '1', wird der Actuator in 6.25er-Schritten angesteuert

Das diff dazu:

--- ./98_PID20.pm       2015-01-24 10:40:53.164577065 +0100
+++ /opt/fhem/FHEM/98_PID20.pm  2015-01-24 10:42:06.811027901 +0100
@@ -107,7 +107,7 @@
      . "pidDebugDelta:0,1 "
      . "pidDebugUpdate:0,1 "
      . "pidDebugNotify:0,1 "
-
+     . "FS20Dim:0,1 "
      . "disable:0,1 "
      . $readingFnAttributes;

@@ -672,6 +672,12 @@
      # perform output to actor
      if ($actuationReq)
      {
+       if (AttrVal($name, 'FS20Dim', '0') eq '1')
+       {
+               my $int = sprintf("%.0f", $actuation/6.25);
+               $actuation = int($int * 6.25);
+       }
+
         #build command for fhem
         PID20_Log $hash, 5, "actor:".$hash->{helper}{actor}
                    ." actorCommand:".$hash->{helper}{actorCommand}



Viele Grüße
Nick666

Joachim

Moin Nick666,
nette Idee, besser wäre, wenn man die Dimmschritte frei wählen könnte.
Ich habe z.B. das Problem, dass die Max-Thermostaten in meiner Konstellation im unteren Bereich Probleme mit 1% Schritten haben (die ersten 0-5%) danach ist es egal.

Gruß Joachim
FHEM aktuellste Version auf FB 7570 und 7390 mit Zebradem Toolbox Freetz
FHEM auf Raspberry
1-Wire mit LinkUSBi und Rs-Pi ds2482-800  1-Wire-9 Board; Max mit Cube, HMLAN
div. 1-Wire Sensoren; MAX-Thermostaten; Homematic-Komponenten, Zehnder KWL über RS-232

Nick666


Ich habe mittlerweile diese Lösung erfolgreich in Betrieb:


--- ./98_PID20.pm       2015-01-24 10:40:53.164577065 +0100
+++ /opt/fhem/FHEM/98_PID20.pm  2015-01-25 10:59:43.656551209 +0100
@@ -107,7 +107,7 @@
      . "pidDebugDelta:0,1 "
      . "pidDebugUpdate:0,1 "
      . "pidDebugNotify:0,1 "
-
+     . "pidActorStepWidth "
      . "disable:0,1 "
      . $readingFnAttributes;

@@ -672,6 +672,14 @@
      # perform output to actor
      if ($actuationReq)
      {
+       # Calc actor step width if 'pidActorStepWidth' is set
+       my $StepWidth = AttrVal($name, 'pidActorStepWidth', '0');
+       if ($StepWidth ne '0')
+       {
+               my $int = sprintf("%.0f", $actuation/$StepWidth);
+               $actuation = int($int * $StepWidth);
+       }
+
         #build command for fhem
         PID20_Log $hash, 5, "actor:".$hash->{helper}{actor}
                    ." actorCommand:".$hash->{helper}{actorCommand}


Mit 'pidActorStepWidth' kann man eine Schrittweite angeben, im Falle von FS20-Dimmern also 6.25.
Ist somit etwas flexibler gehalten.

Grüße
Nick

mkninc

Zitat von: Joachim am 24 Januar 2015, 14:34:07
Ich habe z.B. das Problem, dass die Max-Thermostaten in meiner Konstellation im unteren Bereich Probleme mit 1% Schritten haben (die ersten 0-5%) danach ist es egal.
Das, oder ein ähnliches Problem hatte ich auch. Unter 5-6% sind die Thermostaten noch komplett zu. Ich hatte anfangs mal mit dem Parameter pidActorLimitLower gespielt, allerdings schneidet der alle Regeländerungen unterhalb des Limits einfach ab. Was dann zum gleichen Ergebnis führt. Ist halt mehr als mechanisches Limit gedacht. Deshalb hab ich bei mir noch einen neuen Parameter eingeführt, der als Offset drauf gerechnet wird. Sodass auch Regeländerungen im unteren Bereich von 1-5 % schon eine Änderung bewirken.

--- FHEM/98_PID20.pm (revision 7702)
+++ FHEM/98_PID20.pm (working copy)
@@ -89,6 +89,7 @@
     . "pidActorKeepAlive "
     . "pidActorLimitLower "
     . "pidActorLimitUpper "
+    . "pidActorDeadZoneLower "
     . "pidCalcInterval "
     . "pidDeltaTreshold "
     . "pidDesiredName "
@@ -288,7 +289,8 @@
       $ret .= 'Factor I         : ' . $hash->{helper}{factor_I} . "\n";
       $ret .= 'Factor D         : ' . $hash->{helper}{factor_D} . "\n\n";
       $ret .= 'Actor lower limit: ' . $hash->{helper}{actorLimitLower} . "\n";
-      $ret .= 'Actor upper limit: ' . $hash->{helper}{actorLimitUpper} . "\n";
+      $ret .= 'Actor upper limit: ' . $hash->{helper}{actorLimitUpper} . "\n\n";
+      $ret .= 'Actor lower dead zone: ' . $hash->{helper}{actorDeadZoneLower} . "\n";
       return $ret;
     }
     default { return $usage; }
@@ -438,6 +440,8 @@
     my $actorLimitLower = $hash->{helper}{actorLimitLower};
     $hash->{helper}{actorLimitUpper} = ( AttrVal( $name, 'pidActorLimitUpper', 100 ) =~ m/$reFloat/ ) ? $1 : 100;
     my $actorLimitUpper = $hash->{helper}{actorLimitUpper};
+    $hash->{helper}{actorDeadZoneLower} = ( AttrVal( $name, 'pidActorDeadZoneLower', 0 ) =~ m/$reFloat/ ) ? $1 : 0;
+    my $actorDeadZoneLower = $hash->{helper}{actorDeadZoneLower};
     $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;
@@ -533,6 +537,12 @@

       # calc actuation
       $actuationCalc = $pPortion + $iPortion + $dPortion;
+     
+      # add dead zone offset
+      if ($actuationCalc > 0.1)
+      {
+ $actuationCalc = $actuationCalc + $actorDeadZoneLower;
+      }

       PID20_Log $hash, 2, "P1 delta:" . sprintf( "%.2f", $delta ) . " isWindup:$isWindup" if ($DEBUG_Calc);

John

Zu den vielfältigen Wünschen der letzten Einträge zum Thema Stellausgabe:

Ich schlage eine Callback-Funktion vor, in der der Anwender seine spezifische Implementierung für
die Wertvorgabe zum Stellwert realisieren kann.

Diese Methode würde immer unmittelbar vor der Ausgabe eines Stellwertes ausgeführt werden.

Damit könnte man alle beliebig exotischen Regeln implementieren ohne das Basis-Modul zu überfrachten.
John

CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

mkninc

#265
So exotisch find ich die Sachen gar nicht.
Das Runden auf 6,25% passt doch schon fast zum Parameter pidActorValueDecPlaces. Den könnte man erweitern. Ist doch egal, ob ich z.B. auf 2 Nachkommastellen, bzw. Vielfache von 0,01 Runde, oder eben auf Vielfache von 6,25. Das könnte man evtl. sogar abwärtskompatibel implementieren.

Und für meine Änderung fände ich eine Callbackfunktion auch eher ungünstig. Die Einstellung will ich ja individuell für jedes Thermostat machen. Vielleicht habe ich aber auch noch nicht die Funktion von pidActorLimitLower richtig verstanden. Oder wie ist der gedacht?

Nick666

Hallo,

ich habe folgendes Verhalten beobachtet:
Obwohl ich ActorErrorAction auf 'errorPos' und ActorErrorPos auf '0' gestellt habe, wird der Actor bei einem Fehler nicht auf 0 gesetzt, sondern auf der aktuellen Positionen eingefroren. Die Readings blieben auch auf den alten Werten (außer state, der den alarm entsprechend anzeigt) und es tauchen auch keine Events mehr auf. Ist das vielleicht ein Fehler im Modul und kann das jemand bestätigen (einen Fehler kann man recht leicht provozieren, indem man zB SensorTimeout auf '1' stellt)  oder muss ich bei mir noch an einer anderen Stelle weitersuchen?

und noch eine andere Sache:
Ich würde solch einen Fehlerfall gerne weiter mit notifies auswerten, jedoch taucht 'state' nicht in den Events auf und ich weiß nicht, wie ich das sonst auswerten könnte. Jemand eine Idee?


Viele Grüße
Nick666

John

Hallo Nick666,

ich habe das selbst probiert und es funktioniert.

Stell bitte ein die Ausgabe von "list <dein PID>" hier rein.

John
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP

Nick666

Seltsam, habs gerade nochmal auch mit einer "unbefummelten" 98_PID20.pm probiert. Der Wert friert ein aber wird nicht auf 0 (oder andere Werte in actorErrorPos) gesetzt. Bin mal gespannt, wechen Denkfehler ich diesmal wieder drin hab  :)


Internals:
   DEF        TH.Terrarium:temperature HZ.Terrarium:dim
   NAME       PID.HZ.Terrarium
   NR         25
   NTFY_ORDER 50-PID.HZ.Terrarium
   STATE      processing - Soll: 24 °C
   TYPE       PID20
   Readings:
     2015-02-02 23:00:19   actuation       46
     2015-02-02 23:00:19   actuationCalc   45.7500000000001
     2015-02-02 23:00:19   delta           0.399999999999999
     2015-02-02 23:00:19   desired         24
     2015-02-02 23:00:19   measured        23.6
     2015-02-02 23:00:19   p_d             0
     2015-02-02 23:00:19   p_i             33.2500000000001
     2015-02-02 23:00:19   p_p             12.5
     2015-02-02 23:00:19   state           processing
   Helper:
     actor      HZ.Terrarium
     actorCommand dim
     actorErrorAction errorPos
     actorErrorPos 0
     actorInterval 1
     actorKeepAlive 1800
     actorLimitLower 0
     actorLimitUpper 100
     actorThreshold 1
     actorTimestamp 2015-02-02 23:00:19
     actorValueDecPlaces 0
     adjust
     calcInterval 60
     deltaGradient 0
     deltaOld   0.399999999999999
     deltaOldTS 2015-02-02 22:59:57
     deltaTreshold 0
     desiredName desired
     disable    0
     factor_D   0
     factor_I   1.25
     factor_P   31.25
     isWindUP
     measuredName measured
     reading    temperature
     regexp     ^([\+,\-]?\d+\.?\d*$)
     reverseAction 0
     sensor     TH.Terrarium
     sensorTimeout 180
     stopped    0
     updateInterval 600
Attributes:
   pidActorErrorAction errorPos
   pidActorErrorPos 0
   pidActorInterval 1
   pidFactor_I 1.25
   pidFactor_P 31.25
   pidSensorTimeout 180
   room       Terrarium.Technik
   stateFormat state - Soll: desired °C


John

Hi nick666

Zitat2015-02-02 23:00:19   state           processing

also der ist noch nicht eingefroren.

John
CubieTruck Docker Node-Red Tasmota Shelly Homematic-IP