# PID Regler in Codesys wie einbinden



## edbal002 (29 Juni 2021)

Hallo allerseits,

über dieses Forum habe ich bereits wertevolle Hilfe in der Komponentenauswahl bekommen, deswegen wende ich mich wieder an euch.

Ich habe einen Widerstand, den ich einregeln möchte mittels PI bzw. PID Regler.
Meine verwendete SPS ist ein PiXtend und hat leider soetwas nicht eingebaut.

Deshalb habe ich mir folgendes Tutorial angesehen: PID Controller in CoDeSys - Maksym Levinskyi und abgetippt.

Über zwei Analogeingänge, berechne ich den Sensorwiderstand (R = U/I).
Um den Widerstand einzuregeln, muss ich einen Analogausgang ansteuern, der mein Netzteil regelt.
Ich habe vorerst nur meinen einfachen Code zum laufen bekommen:

Sensorwiderstand:=(((Analogeingang0-0.789)/0.182)/((Analogeingang1-2.43)/7.57));
//Versuch einer Regelung
IF Sensorwiderstand <= 20.986 THEN
    rAnalogOut0:=rAnalogOut0_Last-0.01;
;//rAnalogOut0-0.01; //Ausgangsspannung muss eingeregelt werden, nach Sensorwiderstandssollwert
ELSIF Sensorwiderstand >= 20.986 THEN
    rAnalogOut0:=rAnalogOut0_Last+0.01;
ELSIF Sensorwiderstand=20.986 THEN
    rAnalogOut0:=rAnalogOut0_Last;
END_IF

Jetzt Frage ich mich: Wo an welcher stelle füge ich meine Eingangsgröße in den PID Regler ein (Sensorwiderstand) und wie regele ich meine Ausgangsgröße (Spannung) ?
Das Projekt ist angehangen.

Vielen Dank!!


----------



## Blockmove (29 Juni 2021)

Irgendwie ist mir nicht klar, was du da Regeln willst.
Du misst deinen Sensorwiderstand ... Ok.
Und steuerst du abhängig vom Widerstandswert ein Netzteil.

Reicht da nicht eine simple Abhängigkeit?
U = R * x


----------



## edbal002 (29 Juni 2021)

Hallo Blockmove,

der Sensor hat ein Heizelement aufgedruckt. Dieses Heizelement, möchte ich auf einen festen Widerstandswert einregeln.

Der Heizerwiderstand verändert sich mit der Temperatur. D.h. wird der Sensor in einem heißeren Bereich betrieben, muss die Heizung entsprechend weniger heizen, oder umgekehrt. Dieser Widerstand entspricht einer Temperatur.

Der Sensorwiderstand (Heizung) wird beeinflusst durch die beaufschlagte Spannung. Diese soll ohne Überschwingen eingeregelt werden.
Deshalb dachte ich, verwende ich einen PID Regler.


Ich hoffe mein Problem wird nun klarer.


----------



## GLT (29 Juni 2021)

edbal002 schrieb:


> Ich habe einen Widerstand, den ich einregeln möchte mittels PI bzw. PID Regler.
> Meine verwendete SPS ist ein PiXtend und hat leider soetwas nicht eingebaut.


Wäre mir neu, dass in CoDeSys kein Regler in der Bibliothek wäre - aber selbst wenn, gibt es ja auch noch die OSCAT.lib.


----------



## Heinileini (29 Juni 2021)

Zwar off topic, aber zu Deiner IF-ELSIF-Konstruktion:


```
IF Sensorwiderstand <= 20.986 THEN

ELSIF Sensorwiderstand >= 20.986 THEN

ELSIF Sensorwiderstand=20.986 THEN // dieser Zweig wird nie durchlaufen

END_IF
// - - - - - - - - - -
// Alternative ohne Hysterese
IF Sensorwiderstand < 20.986 THEN

ELSIF Sensorwiderstand > 20.986 THEN

ELSE // wenn weder '<' noch '>', dann kann es nur '=' sein

END_IF
// - - - - - - - - - -
// Alternative mit Hysterese
IF Sensorwiderstand < 20.986 - Hysterese THEN

ELSIF Sensorwiderstand > 20.986 + Hysterese THEN

ELSE // Betrag der WiderstandsAbweichung nicht grösser als Hysterese

END_IF
```

PS:
Zu Deinem HeizElement: Kaltleiter oder Heissleiter?


----------



## edbal002 (29 Juni 2021)

Heinileini schrieb:


> Zwar off topic, aber zu Deiner IF-ELSIF-Konstruktion:
> 
> 
> ```
> ...


Danke für deinen Kommentar. Das stimmt.

Wie kann ich sinnvoll ein Über/Unterschwingen mit meiner Regelung vermeiden?
Ist ein PI Regler überhaupt sinnvoll bei meinem Vorhaben?

Ich habe folgenden Codeanteil mit beigefügt: macht das sinn?


```
IF rAnalogOut0 < 0.75 THEN //
                rAnalogOut0 := 0.75; //Ausgangsspannung 40V
ELSIF rAnalogOut0 > 2.5 THEN
                rAnalogOut0:=2.5;    //Ausgangsspannung 3V
```

Hiermit probiere ich ein Über/Unterschwingen meiner Spannung zu vermeiden, indem ich die Ausgansspannung limitiere.


----------



## Frohnius (29 Juni 2021)

wirf mal einen blick in die bibliotheken (suchfunktion) ....
da findest du sicher einen pid regler ...
dieser benötigt einen istwert, sollwert und die entsprechenden regelparameter ...
deinen istwert wandelst du sauber in einen temperaturwert als REAL um (LIN_TRAFO bei schneider), gibst deinen sollwert vor und gut  
über pid-regler und deren parameter sind schon bücher geschrieben worden - 
gut eingestellt sollte man das über/unterschwingen in den griff bekommen ...


----------



## Heinileini (29 Juni 2021)

edbal002 schrieb:


> Wie kann ich sinnvoll ein Über/Unterschwingen mit meiner Regelung vermeiden?
> Ist ein PI Regler überhaupt sinnvoll bei meinem Vorhaben?


Erstmal den "RegelSinn" klären: ist der TemperaturKoeffizient des HeizElements positiv oder negativ?
Vorsicht bei einem HeizElement mit negativem TemperaturKoeffizienten (NTC, Heissleiter). Den Strom im Auge behalten und begrenzen.

Dann I-Anteil und D-Anteil des PID unwirksam machen und den P-Anteil ermitteln, d.h. die Verstärkung schrittweise anheben, bis der Regelkreis anfängt zu schwingen. Die PeriodenDauer der Schwingung notieren. Dann Verstärkung sachte verringern bis das Schwingen aufhört.
Entsprechend der PeriodenDauer den D-Anteil ermitteln.
Die Verstärkung sollte sich jetzt geringfügig erhöhen lassen, ohne dass der Regelkreis anfängt zu schwingen.
Und ein Überschwingen sollte auch nicht auftreten.
Auf den I-Anteil würde ich möglichst ganz verzichten, denn er erhöht die Neigung zum Überschwingen. 
Ist die verbleibende RegelAbweichung zu gross (die Regelung zu "ungenau"), nur dann "FineTuning" mit dem I-Anteil versuchen.
PI-Regler ist m.E. nicht sinnvoll. PID bzw. PD ja.

Die Begrenzung der Spannung nach oben dürfte durchaus sinnvoll sein, um ein "Verbraten" des HeizElementes zu vermeiden.
Eine Begrenzung der Spannung nach unten ist vermutlich hilfreich bei einem NTC.

Irgendwie überkommen mich Zweifel, ob Du mit der WiderstandsErmittlung überhaupt ans Ziel kommst. Ich vermute, dass Du über die Leistung besser in den gewünschten Bereich gelangst. Und dann ggfs noch den Widerstand zu Hilfe nimmst, die "Feinheiten" nachzuregeln.
Wie genau kannst Du mit den ADUs überhaupt den Widerstand messen? Die Granularität (durch die Darstellung der AnalogWerte als INT-Zahlen - auch wenn sie dann noch in REAL gewandelt werden) dürfte bei dieser Anwendung recht störend sein.


----------



## holgermaik (29 Juni 2021)

Zu deiner eigentlichen Frage
Yzad wäre der Sollwert und Y der Istwert.

meiner Meinung nach
Ein PID Regler ist für dein Vorhaben schon geignet.
Der P Anteil hängt davon ab wie schnell dein Element mit einer Temperaturänderung auf Veränderung der Heizung reagiert. Sowohl bein Heizen als auch beim Abkühlen. (Größe, Material, Umgebung, Heizleistung usw..)
Auf den I Anteil würde ich verstärktes Augenmerk legen.
Der D Anteil ist ähnlich dem P Anteil zu werten.

Mit deinem Code schneidest du ja nur die Amplitude deines Ausgangs ab. Kann man als Sicherheitsmaßnahme einfügen um die Heizung zu schützen sollte aber bei einem vernünftig eingestellten Regler nicht dazu kommen.


----------



## wollvieh (29 Juni 2021)

Hallo, anbei ein einfacher PI Regler, der sollte es tun...






```
FUNCTION_BLOCK SimplePIControllerFB
VAR_INPUT
  Setpoint       : REAL;           // Setpoint
  Actual         : REAL;           // actual value
  feedforeward   : REAL;           // feed foreward value
  P_Gain         : REAL := 0.1;    // P Gain
  I_Time         : REAL := 1.0;    // integral time
  I_Reset        : BOOL;           // reset integrator
  Out_min        : REAL := 0.0;    // minimum of the output
  Out_max        : REAL := 100.0;  // maximum of the output
  hold           : BOOL;           // hold the regulator, no more calculations
  cycle_time     : REAL := 0.010;  // cycle time of the PLC task
END_VAR

VAR_OUTPUT
   out      : REAL;                // regulator output
END_VAR

VAR
  P_part                  : REAL ;
  I_part                  : REAL;
  I_Part_Zw_Summe         : REAL;
  delta_input             : REAL;
  delta_input_last_cycle  : REAL;
  output_value            : REAL;
  output_value_ramp       : REAL;
  limit_on_low            : BOOL;
  limit_on_high           : BOOL;
  END_VAR



// ################################################################
// CODE
//Regeldifferenz berechnen

delta_input := (Setpoint - Actual);

IF NOT hold
THEN
  //P-Regler beschreiben
  P_part := delta_input * P_Gain;
 
 
  //I_Regler beschreiben
  if I_Time > 0  then
    I_Part_Zw_Summe := ((((delta_input * P_Gain) + (delta_input_last_cycle
  * P_Gain)) / 2.0) * (cycle_time / I_Time));
    if not limit_on_low and (I_Part_Zw_Summe <0) then
      I_part :=  I_part + I_Part_Zw_Summe;
    elsif not limit_on_high and (I_Part_Zw_Summe >0) then
      I_part :=  I_part + I_Part_Zw_Summe;
    end_IF;
  elsif I_Time <= 0.0 then
    I_part := 0.0;
  end_if;
 
  //I_Regler zurück setzen
  if I_Reset then
    I_part := 0.0;
  end_if;
 
  output_value := P_part + I_part + feedforeward;
 
  limit_on_low   := 0;
  limit_on_high   := 0;
 
  if output_value > Out_max then
    output_value   := Out_max;
    limit_on_high     := 1;
  elsif output_value < Out_min then
    output_value   := Out_min;
    limit_on_low     := 1;
  end_if;

  //Regeldifferenz für nächsten Zyklus beschreiben
  delta_input_last_cycle := delta_input;
 
 END_IF
 
  out := output_value;
```



Gruß, Wollvieh


----------



## edbal002 (29 Juni 2021)

Hallo Wollvieh,

ich habe deinen Regler als Funktionsbaustein implementiert.

Ich habe einen actual wert --> der gemessene Sensorwiderstand
ich habe einen setpoint --> der gewünschte Wert

Wie zur Hölle mache ich jetzt eine Art Schleife daraus ?

D.h. wenn der gemessene Widerstand zu hoch ist, dann regele Analogausgang 1 zurück.

Wie verwerte ich denn nun Out ?

Ich erhalte da einen Widerstandswert, der durch P I beeinflusst wird, korrekt?

Ich muss nun diesen modifizierten Widerstandswert verarbeiten?
Muss ich da noch einen neuen Funktionsblock für erstellen?

Ps. Ich hatte noch keine SPS Erfahrung bisher. Das ist mein erstes Projekt.


----------



## wollvieh (29 Juni 2021)

Naja, den Ausgang Out skalieren und auf den Analogausgang legen.

... etwa so :

Der Regler in Verbindung mit dem Stellglied ist das, was Du "Schleife" nennst !








```
// Umrechnung OUT 0..100% nach 0..10 Volt
    AusgangsspannunginVolt :=  (10.0 / 100.0) * YOUT;
```


... und lass die Hölle aus dem Spiel ...


----------

