Forum: Mikrocontroller und Digitale Elektronik [PID] - D-Regler reagiert nicht


von Muzaffer S. (mzo)


Lesenswert?

Hallo Zusammen,

ich arbeite gerade an einem Projekt an der Hochschule. Die 
Aufgabenstellung ist einen PID-Temperaturregler für einen 
Lötbarkeitstester zu programmieren mit den Vorgaben (kurzgefasst):

 - Sollwert Lot: 240°
 - Maximale Heiztemperatur der Heizpatrone: 500°

Habe eigentlich schon alles soweit programmiert und getestet (inklusive 
Anti-Windup,PWM-Regelausgangsteuerung...). Ich habe eine 
Temperaturdifferenz von ungefähr +-2°C.

Hier ist mein Code:
1
// SystemTaskAbfrage, Umwandlung der Zykluszeit und Zuweisung der Zykluszeit in die Variable 'cycle_time'
2
fbGetCurTaskIdx();
3
udint_zclock := _TaskInfo[fbGetCurTaskIdx.index].CycleTime/10000;
4
int_zclock:= UDINT_TO_INT(udint_zclock);
5
real_zclock:= INT_TO_LREAL(int_zclock)*0.01;
6
cycle_time := real_zclock;          // = 0.1
7
8
// Nach Abfrage aktuelle Temperaturwerte von MAIN übernehmen
9
Solltemp   := MAIN.setpoint;
10
Akttemp    := MAIN.actual_value;
11
12
// Regeldifferenz berechnen (Solltemperatur - Isttemperatur)
13
error := (Solltemp - Akttemp);
14
15
// P-Regler beschreiben (Regeldifferenz * Verstärkung kP)
16
P_part := error * GVL_VAR.kP;
17
18
// I-Regler beschreiben
19
IF GVL_VAR.kI > 0  THEN
20
  I_Part_Zw_Summe := (delta_error_last_cycle * (cycle_time / GVL_VAR.kI));
21
  
22
  IF NOT limit_on_low AND (I_Part_Zw_Summe <0) THEN
23
  I_part :=  I_part + I_Part_Zw_Summe;
24
  ELSIF NOT limit_on_high AND (I_Part_Zw_Summe >0) THEN
25
  I_part :=  I_part + I_Part_Zw_Summe;
26
  END_IF;
27
  
28
  IF I_part > Out_max THEN
29
    I_part  := Out_max;
30
  ELSIF I_part < Out_min THEN
31
    I_part   := Out_min;
32
  END_IF;
33
    
34
ELSIF GVL_VAR.kI <= 0.0 THEN
35
  I_part := 0.0;
36
END_IF;
37
38
// Manuelles Zurücksetzen des Integrators
39
if I_Reset then
40
  I_part := 0.0;
41
END_IF;
42
43
// D-Regler beschreiben
44
diff_anteil := (error - delta_error_last_cycle) / cycle_time;
45
D_part := diff_anteil * GVL_VAR.kD;
46
47
// Regleroutput berechnen (P+I+D)
48
output_value := P_part + I_part; //+ D_part;
49
50
// Merkbits zur Anti-Windup-Maßnahme beim Integrator
51
limit_on_low     := FALSE;
52
limit_on_high   := FALSE;
53
54
// Reglerausgang zwischen den Werten Min und Max skallieren (wird benötigt für die PWM)
55
IF output_value > Out_max THEN
56
  output_value   := Out_max;
57
  limit_on_high  := TRUE;
58
ELSIF output_value < Out_min THEN
59
  output_value   := Out_min;
60
  limit_on_low   := TRUE;
61
END_IF;
62
63
// Skalierter Reglerausgang
64
PID_out := output_value;
65
66
// Regeldifferenz für nächsten Zyklus beschreiben
67
delta_error_last_cycle := error;


Mein Problem ist nun: In meiner Regelung bewirkt der D-Anteil garnichts, 
heisst, D ist bei mir immer 0, da sich (error - delta_error_last_cycle) 
nie ändert und immer 0 ist.

Ist mein Regler soweit richtig programmiert? Denn an sich komme ich ja 
auf die gewünschte Solltemperatur mit +-2°C. Was mich aber stört ist, 
dass der D-Regler nichts bewirkt..

Grüße
Muzaffer


PS.: Variablendeklaration habe ich jetzt erst mal nicht mit reingepackt.

: Bearbeitet durch User
von Sven B. (scummos)


Lesenswert?

Der Variablenname "delta_error_last_cycle" ist ziemlich verwirrend. Du 
meinst ja eigentlich "error_last_cycle". Das "delta" weist darauf hin, 
dass es sich um eine Differenz handelt, was ja nicht so ist.

Ansonsten muss das Problem ja irgendwie in der Zeile
> diff_anteil := (error - delta_error_last_cycle) / cycle_time;
sein. Gib doch mal die Operanden dieser Rechnung aus und das Ergebnis.

von A. Z. (donvido)


Lesenswert?

Spätestens wenn du die Solltemperatur sprunghaft änderst sollte sich das 
im D-Term bemerkbar machen. Ist delta_error_last_cycle eventuell keine 
statische Variable und bei jedem Funktionsaufruf auf 0 initialisiert? 
Dann würde aber auch dein I-Term nicht funktionieren.

von Muzaffer S. (mzo)


Lesenswert?

Danke für die schnellen Antworten erstmal,

Sven B. schrieb:
> Der Variablenname "delta_error_last_cycle" ist ziemlich verwirrend

Da hast du Recht, weis garnicht wie ich da auf "delta" noch gekommen bin 
:D

Sven B. schrieb:
> Ansonsten muss das Problem ja irgendwie in der Zeile
>> diff_anteil := (error - delta_error_last_cycle) / cycle_time;
> sein. Gib doch mal die Operanden dieser Rechnung aus und das Ergebnis.

Hmm, das Problem ist ich bekomme (error - delta_error_last_cycle) hier 
0, daher ist die komplette gleichung 0 und wird mit D-Anteil = 0 
initialisiert.

A. Z. schrieb:
> Spätestens wenn du die Solltemperatur sprunghaft änderst sollte sich das
> im D-Term bemerkbar machen.

Macht es, aber nur kurzfristig, also nur ein Zyklus und dann ist D 
gleich wieder 0

Also ich habe für den Regler Zykluszeit von 0,1s definiert, is das 
möglich das ich diese zu gering gewählt habe, sodass sich der Regler so 
schnell aufruft, dass er keine Regelfehlerdifferenz findet?

von A. Z. (donvido)


Lesenswert?

Muzaffer S. schrieb:
> Also ich habe für den Regler Zykluszeit von 0,1s definiert, is das
> möglich das ich diese zu gering gewählt habe, sodass sich der Regler so
> schnell aufruft, dass er keine Regelfehlerdifferenz findet?

Na klar, wenn die Temperatur sich so langsam ändert, dass zwischen zwei 
Aufrufen keine Änderung feststellbar ist, dann kann es nicht 
funktionieren.
Du könntest entweder die Zykluszeit verlängern oder aber, wie es sich 
für einen realen PID gehört, dem D-Term ein PT1 Filterglied spendieren.
Dann hättest du ein bisschen länger was vom Sollwertsprung.

von Muzaffer S. (mzo)


Lesenswert?

A. Z. schrieb:
> oder aber, wie es sich
> für einen realen PID gehört, dem D-Term ein PT1 Filterglied spendieren

Was ist damit genau gemeint?
Bzw. wie genau muss dass dann im Code umgesetzt werden damit der D-Term 
auch richtig funktioniert.

Sry wenn ich so genau bzw "dumm" Frage, aber das hier ist mein erstes 
Projekt in SPS-Programmierung, daher brauch ich ein bisschen Starthilfe 
damit ich das auch richtig verstehe und umsetzen kann.

von A. Z. (donvido)


Lesenswert?

Sorry vergiss das mit dem Filter.
Dein D-Term scheint schon richtig zu funktionieren.
Auf Sollwertsprünge kann er ja reagieren und die dauern nunmal nur einen 
Zyklus. Die Auflösung deines Temperatursignals ist vermutlich zu gering. 
Deshalb ist delta_error_last_cycle häufig 0 und ab und zu gibts mal 
einen kurzen Puls. Du könntest wie schon gesagt deine Zykluszeit 
verlängern oder den D-Term auch einfach weglassen.

von Muzaffer S. (mzo)


Lesenswert?

A. Z. schrieb:
> Deshalb ist delta_error_last_cycle häufig 0 und ab und zu gibts mal
> einen kurzen Puls.

genau so ist das gerade.

Alles klar, danke für die Antwort, ich werde mal versuchen die 
Zykluszeit zu verlängern.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.