# Tank PID-Controller



## sargan26 (28 September 2020)

Hallo, ich habe einen Tank mit folgenden Variablen:
Setpoint (0-10 liter)
Level meter (0-10 liter)
Discharge valve (lässt sich variabel öffnen, real, 0-10)
Fill valve (lässt sich variabel öffnen, real, 0-10)

Jetzt hätte ich einen PID_Compact im TIA Portal genommen und verschaltet.



Beim Output bekomme ich ja nur einen real Wert raus also muss ich ihn irgendwie auf die zwei Ventile umrechnen:



Wenn der Output kleiner als 5 ist soll sich der Discharge valve öffnen, größer als 5 soll sich Fill valve öffnen. Weil die Formeln kompliziert aussehen habe ich noch eine Excel Tabelle erstellt.



Kann es gerade nicht testen, macht der Ansatz Sinn? Oder gibt es PID-Bausteine um 2 real-Ausgänge anzusteuern?


----------



## sargan26 (28 September 2020)

Der Tank.


----------



## Onkel Dagobert (28 September 2020)

Ich nehme an, du willst den Füllstand regeln, bzw. konstant halten? Dann würde ich mit der ersten Sequenz das Befüllventil ansteuern. Wenn das nicht reicht, schließt die zweite Sequenz das Entnahmeventil. Also die Sequenzen genau anders.

Schöner ist es m.E. ohne IF-Anweisungen:

```
"Fill valve"      := 2.0 * (LIMIT(MN := 0.0, IN := #X, MX := 50.0));
"Discharge valve" := 2.0 * ((LIMIT(MN := 50.0, IN := #X, MX := 100.0)) - 50.0);
```


----------



## Heinileini (28 September 2020)

Ich kann mir nicht vorstellen, dass Dein Regler nur positive Werte ausgibt (z.B. 0 .. 10). Normal wäre z.B. -x .. 0 .. x.
Dann wird es minimal übersichtlicher:

```
rtPID := riPIDpos - 5.0 ; // 0..x

rtPID := riPID ; // -x..0..x

if rtPID > 0.0 then
    roValve1 := rtPID * 2.0 ; // Faktor 2 ggfs anpassen
    roValve2 := 0.0 ;
end_if ;
if rtPID < 0.0 then
    roValve1 := 0.0 ;
    roValve2 := rtPID * -2.0 ; // Faktor -2 ggfs anpassen
end_if ;
```
Besser mit ein Bisschen Hystere, z.B.:

```
rtPID := riPIDpos ; // -x..0..x

if rtPID > 0.1 then
    roValve1 := rtPID ;
    roValve2 := 0.0 ;
elseif rtPID < -0.1 then
    roValve1 := 0.0 ;
    roValve2 := -rtPID ;
else
    roValve1 := 0.0 ;
    roValve2 := 0.0 ;
end_if ;
```

PS:
Wenn schon mit Limit, Dagobert, fänd ich es so übersichtlicher:

```
#X := const1 * (riPIDpos - const2) ;
roValve1 := LIMIT(MN := 0.0, IN :=  #X, MX := 100.0) ;
roValve2 := LIMIT(MN := 0.0, IN := -#X, MX := 100.0) ;
```
Ggfs Faktor const1 und Offset const2 anpassen bzw. weglassen.


----------



## Onkel Dagobert (28 September 2020)

Heinileini schrieb:


> ..
> Wenn schon mit Limit, Dagobert, fänd ich es so übersichtlicher:
> 
> ```
> ...


Quatschkopf  !

Was ist denn daran bitte übersichtlicher? In meinem Fall erkennt man sofort, welcher Bereich des Stellsignals als Sequenz verwendet wird. Deine Version ist doch nur eine Verschleierung trivialen Codes. Nichtssagende Konstanten zu verwenden, macht es hier auch nicht gerade verständlicher. Warum muss man einfache Sachen immer verkomplizieren?


----------



## Heinileini (28 September 2020)

Ach Dagobert, anscheinend streiten wir uns hier um Geschmacksfragen.

Was die "nichtssagenden Konstanten" betrifft, dienen diese nur dazu, die AusgangswerteBereiche ggfs an den EingangswerteBeriech anzupassen und - oh Wunder - Du benutzt sie in Deinem Zweizeiler ja auch, nur dass sie dort anders heissen (Faktor: 2.0, Offset: 50.0). Bei Deiner Variante passt übrigens eines der beiden Ergebnisse "tendenziell" nicht zum anderen, verglichen mit der ExcelTabelle aus Beitrag #1. Es müsste sein:

```
Valve1 := 2 * ([B]50.0 [/B]- LIMIT(0.0 .. 50.0)) ;
Valve2 := 2 * (LIMIT(50.0 .. 100.0) - 50.0) ;
```
Der Offset müsste meiner Meinung nach ohnehin überflüssig sein. Den habe ich nur eingeführt, weil ich auf die Aufgabenstellung eingegangen bin, die ich für falsch halte.
Ich gehe nämlich davon aus, dass der Regler (so wie es üblich ist) am Ausgang den Wert 0 liefert, wenn "seiner Meinung nach nichts zu tun ist" und, dass das Vorzeichen schon erkennen lässt, ob z.B. geheizt oder gekühlt werden soll oder hier der Zufluss oder der Abfluss aktiviert werden muss.


----------



## Onkel Dagobert (28 September 2020)

Heinileini, ich habe nicht vor, sinnlose Diskussionen mit dir zu führen. Jedenfalls nicht jetzt.


----------



## Heinileini (28 September 2020)

Onkel Dagobert schrieb:


> Heinileini, ich habe nicht vor, sinnlose Diskussionen mit dir zu führen. Jedenfalls nicht jetzt.


Dann sind wir uns ja schon wieder einig! Sinnlose Diskussionen mag ich auch nicht führen. Mit allen und zu jeder Zeit.


----------



## Onkel Dagobert (28 September 2020)

Heinileini schrieb:


> .. dass das Vorzeichen schon erkennen lässt, ob ... der Zufluss oder der Abfluss aktiviert werden muss.


Wenn das Stellsignal sein Vorzeichen wechselt, dann müsste mehr drin sein, als hinein gelassen wurde. Das könnte z.Bsp. bei einem Löschwasserbecken der Fall sein, in dem auch Regenwasser gesammelt wird. Ich gehe hier aber von einem klassischen Tank aus, in dem ein Stoff zwischengespeichert wird. Hier kann nur bis zum Soll-Füllstand nachgefüllt werden. Reicht der Zufluss nicht aus, um den Pegel zu halten, kann in zweiter Sequenz der Abfluss gedrosselt werden. Das ist natürlich nur meine persönliche Interpretation, abweichend von der Tabelle, lieber Heinileini  . 

Sargan möge mir meiner Zweifel gnädig sein!


----------



## Heinileini (29 September 2020)

Moin Dagobert,
Dein Ansatz mit Limit wäre doch ein schöner Ansatz für den Thread Mehrsequenz Regler  erstellen. Bei einer Erweiterung auf mehr als zwei Zeilen punktet die Übersichtlichkeit umso mehr! 
Gruss, Heinileini


----------



## Onkel Dagobert (29 September 2020)

Heinileini schrieb:


> .. Dein Ansatz mit Limit wäre doch ein schöner Ansatz für den Thread Mehrsequenz Regler  erstellen. Bei einer Erweiterung auf mehr als zwei Zeilen punktet die Übersichtlichkeit umso mehr!  ..


Das ist wohl wahr, Heinileini. Wer jedoch Lüftungsanlagen programmiert oder programmieren möchte, der liest interessehalber auch einen Thread namens "Tank PID-Controller". Und wenn nicht, dann muss er halt mit Fallunterscheidungen zum Ziel kommen. 

@Sargan,
beteiligst du dich noch an deiner Problemlösung?


----------



## sargan26 (30 September 2020)

Hallo, danke für die vielen Vorschläge. Ich habe jetzt folgenden Code probiert:


```
IF "PID".Output < -0.1 THEN    
    "Discharge valve" := - "PID".Output / 10;
    "Fill valve" := 0;
ELSIF "PID".Output > 0.1 THEN
    "Fill valve" := "PID".Output / 10;
    "Discharge valve" := 0;
ELSE
    "Discharge valve" := 0;
    "Fill valve" := 0;
END_IF;
```

Er regelt auch gut auf den Sollwert hin allerdings schaltet er noch viel zu schnell zwischen -100% und 100%. Der Füllstand vom Tank schwappt auch ziemlich, heißt der Istwert ist nicht konstant und das Wasser müsste sich erst beruhigen.


----------



## Heinileini (30 September 2020)

```
[COLOR=#0000cd]// mal die "Hysterese" vergrössern[/COLOR]
IF "PID".Output < [COLOR=#ff0000]-0.1[/COLOR] THEN [COLOR=#0000cd]// -0.1 verkleinern, z.B. -0.5 oder -1 oder -5 ... [/COLOR] 
    "Discharge valve" := - "PID".Output / 10;
    "Fill valve" := 0;
ELSIF "PID".Output > [COLOR=#ff0000]0.1[/COLOR] THEN [COLOR=#0000cd]// 0.1 vergrössern, z.B. 0.5 oder 1 oder 5 ...[/COLOR]
    "Fill valve" := "PID".Output / 10;
    "Discharge valve" := 0;
ELSE
    "Discharge valve" := 0;
    "Fill valve" := 0;
END_IF;
```
oder den Istwert glätten, z.B.:

```
rioIstWert := (9 * rioIstWert + [COLOR=#ff0000]riIstWert)[/COLOR] / 10.0 ; // riIstWert ist der aktuell gemessene IstWert
```

PS:
Die ProportionalVerstärkung scheint zu gross zu sein. Entweder am Regler verringern oder probeweise '... "PID".Output / 10;' z.B. in '... "PID".Output / 100.0 ;' ändern


----------



## sargan26 (30 September 2020)

Hallo Heinileini,
danke für die Tipps. Habe die Hysteres auf 5 gestellt und die Istwerte über 5 Sekunden geglättet (10 Messwerte, Abtastzeit 0,5s).

Sieht jetzt so aus:



Schon ganz gut denk ich. Der Output gibt mit -100% bis +100% da müsste /10 schon passen. Dann entspricht +100% fill valve ganz auf und -100% discharge valve ganz aus. Wenn du dir die Kurven ansiehst, denkst du da kann man noch was verbessern? 

EDIT: Stimmt mit niedrigeren ProportionalVerstärker siehts noch besser aus, Kurve folgt gleich.

LG, Daniel


----------



## sargan26 (30 September 2020)

Aktuelle Kurve 




Habe auch noch eine nützliche Kurzhilfe gefunden:
https://www.belektronig.de/web/content/1292?unique=dce691b6283fa7a3c9bce3b0347aeab35a8f4049


----------



## Heinileini (30 September 2020)

Die Reihenfoge der Schritte in Deinem Link gefällt mir nicht. Ich weiss, dass ich mit meiner Meinung ziemlich allein dastehe, hier im Forum. 
Schritt 1: D- und I-Anteil unwirksam machen.
Schritt 2: P-Anteil erhöhen, bis das System schwingt und die PeriodenDauer der Schwingung ermitteln.
Schritt 3: P-Anteil verringern, bis die Schwingung nachlässt.
Schritt 4: I-Anteil unwirksam lassen und zunächst nur den D-Anteil entsprechend der SchwingungsDauer laut 2. einstellen. Sollte nun schneller einschwingen und weniger bis gar nicht mehr überschwingen.
Schritt 5: P-Anteil vorsichtig erhöhen. Schwingung sollte jetzt erst bei einem höheren P-Anteil auftreten, als bei 2. bzw. 3. ermittelt. P-Anteil ggfs wieder verringern, bis Schwingung nachlässt.
Schritt 6: I-Anteil erst nach Ermittlung des D-Anteils einstellen. Anfangen mit Wert, der sich aus der PeriodenDauer der Schwingung laut 2. ergibt. Beim I-Anteil bedenken, dass ein kleiner Wert für die ZeitKonstante eine schnellere, heftigere Reaktion bewirkt, als ein grosser Wert für die ZeitKonstante!

PS:
Ich weiss nicht, warum alle meinen, nach dem P- müsste zuerst der I- und dann erst der D-Anteil in Angriff genommen werden.
Der I-Anteil dient dazu, die letzten Feinheiten herauszukitzeln. Darum ist die Aktion sinnlos, solange P- und D-Anteil noch weit davon entfernt sind, gut zu arbeiten!
Liegt es vielleicht nur an der Reihenfolge der drei Buchstaben in 'PID'?
Dann sollte man vielleicht den PID-Regler besser in PDI-Regler umbenennen. 

PPS:
Im Link steht "Die Vorhaltezeit t_V (differentieller Anteil, D-Anteil) dient zur Ausregelung von Temperaturschwankungen bei thermischschnellen System".
Hmmm. Ausregeln tut der D-Anteil überhaupt nichts und schnellen Systemen ist er nicht vorbehalten. Es geht darum, die Tendenz der RegelAbweichung möglichst frühzeitig zu erkennen und wenn sie noch so langsam erfolgt.
Es geht zwar auch darum, auf einen Sprung des Sollwertes möglichst schnell zu reagieren, aber das ist nur die halbe Miete. In die RegelAbweichung geht ausser dem Sollwert auch der Istwert ein und diesen Aspekt darf man nicht so schändlich unterbewerten. Nähert sich der Istwert zu schnell dem Sollwert, so dass ein Überschwingen unvermeidbar wird, so ist der D-Anteil der einzige, der dies frühzeitig genug erkennen und dementsprechend gegensteuern kann! Der I-Anteil ist sozusagen am anderen Ende der Skala wirksam und kann hierbei überhaupt nicht helfen.
Der I-Anteil wirkt sich umso stärker aus (mit all seinen meistens unerwünschten "Nebenwirkungen"), je grösser die RegelAbweichung ist und je länger sie bestehen bleibt.
Darum ist eine gute "Vorlage" durch P- und D-Anteil ganz wichtig, damit der I-Anteil nicht hoffnungslos mit einer Aufgabe beschäftigt und überfordert wird, die er zu erfüllen gar nicht imstande ist.
Seine "VerzweiflungsTaten" sind eher störend als zielführend. 
Bei digitalen Reglern reagiert allerdings der D-Anteil auch "überempfindlich" auf sprunghafte Wertänderungen, wie sie durch die Digitalisierung ("Granularität") der Messwerte und durch das Abtasten dieser Werte in grösseren ZeitAbständen entstehen. 

PPPS:
Sind das stehende Wellen, die an Deiner FlüssigkeitsOberfläche entstehen? 
Kann man die PegelMessung beruhigen, indem man den Ort der Messung verschiebt oder eine Trennwand (kleine Öffnung ganz unten) einfügt, so dass in einer "kommunizierenden Röhre" gemessen wird, die gegenüber dem restlichen Tank gedämpft auf die Schwingungen reagiert?


----------



## Onkel Dagobert (30 September 2020)

Meiner bescheidenen Meinung nach wäre hier ein P-Regler angebracht. Ach so, und dann möchte ich noch mal freundlichst auf meinen Beitrag 3# hin weisen. Vielleicht liege ich mit meiner gewagten Vermutung, die Sequenzen zu ändern, gar nicht so falsch. Ich habe die Kurven jetzt allerdings nur mit einem Auge betrachtet, bin noch auf Arbeit.


----------



## sargan26 (7 Oktober 2020)

Hätte ein Video mit dem Ergebnis gemacht:

https://www.youtube.com/watch?v=tmocnY_0ZNY


----------



## Onkel Dagobert (7 Oktober 2020)

sargan26 schrieb:


> .. ein Video ..


Grandios gemacht! Ich rätsle allerdings immer wieder über den eigentlichen Sinn des Behälters. Das ganze ist nur eine Übung, oder? Ich meine, gewöhnlich wird so ein Tank durch den Regler nachgefüllt. Du entleerst aber auch aktiv, wenn zu viel hineingefüllt wurde?

Womit hast du den Tank simuliert?


----------



## sargan26 (7 Oktober 2020)

War für eine Übung, Factory I/O hat ein paar typische Industrie Szenarien zum programmieren lernen (und ne Trial Version).

https://factoryio.com/


----------



## Ph3niX (8 Oktober 2020)

Spannend wird es meines Erachtens erst, wenn man versucht den Pegel zu halten bei unterschiedlicher, dynamischer Entnahme.

So hat das in meinen Augen wenig Reiz.


----------



## sargan26 (9 Oktober 2020)

Danke für den Vorschlag, werds mir anschauen!


----------



## Onkel Dagobert (9 Oktober 2020)

Ph3niX schrieb:


> Spannend wird es meines Erachtens erst, wenn man versucht den Pegel zu halten bei unterschiedlicher, dynamischer Entnahme....


Das ist in etwas so interessant wie eine Klospülung  , mit dem Unterschied, dass bei einer Klospülung relativ langsam gefüllt wird.


----------

