forked from komatic1/SCL_modular_PID
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPID.scl
251 lines (251 loc) · 10.7 KB
/
PID.scl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
FUNCTION_BLOCK FB119
TITLE =" output PID-algorithm"
AUTHOR : AUT_1
FAMILY : MODCONT
NAME : PID
VERSION : " 1.2"
// reverse by komatic
(*
Блок PID содержит ПИД-алгоритмы и используется для создания
регуляторов следующих типов:
• ПИД-регулятор непрерывного управления:
Блоки: PID + LMNGEN_C
• Импульсный ПИД-регулятор для пропорциональных приводов:
Блоки: PID + LMNGEN_C + PULSEGEN
• ПИД-регулятор пошагового управления для пропорциональных
приводов:
Блоки: PID + LMNGEN_S
Блок осуществляет PID алгоритм обработки входного сигнала.
Блок конструктивно и функционально представляет собой
параллельную структуру и функционирует исключительно как
алгоритм позиционирования. Компоненты П-, И- и Д-,
предназначенные для обработки входного сигнала, могут быть
активизированы или выключены в индивидуальном порядке. Это
позволяет конфигурировать П-, ПИ-, ПД- и ПИД- регуляторы на
основе программного продукта Modular Control (Модульное
управление).
Компоненты П- и Д- могут быть также введены в цепь обратной
связи. Помещая компоненты П- и Д- в цепи обратной связи
регулятора, можно предотвратить скачкообразные изменения
сигнала. При этом обычно нет необходимости использовать
интегратор в цепи уставки (setpoint), чтобы избежать ступенчатых
изменений уровня сигнала.
В то время как блок PID вызывается в приоритетном классе
циклических прерываний, период которого привязан к
доминирующей постоянной времени системы, блоки обработки
сигналов для привода (LMNGEN_C и LMNGEN_S) могут
вызываться в приоритетном классе циклических прерываний с
меньшим периодом.
*)
VAR_INPUT
ER : REAL ; //сигнал ошибки
PV : REAL ; //входная переменная
GAIN : REAL := 1.000000e+000; //кфт пропорциональности
TI : TIME := T#20S; //вримя интегрирования
I_ITLVAL : REAL ; //значение инициализации для интегральной составляющей
TD : TIME := T#10S; //время диференцирования
TM_LAG : TIME := T#2S; //время задержки диференциальной составляющей
DISV : REAL ; //сигнал рассогласования
P_SEL : BOOL := TRUE; //выбор пропорциональной составляющей
PFDB_SEL : BOOL ; //proportional action in feedback path selected
DFDB_SEL : BOOL ; //derivative action in feedback path on
I_SEL : BOOL := TRUE; //выбор интегральной составляющей
INT_HOLD : BOOL ; //удерживание интегральной составляющей
I_ITL_ON : BOOL ; //инициализировать интегральную составляющую
D_SEL : BOOL ; //выбор диференциальной составляющей
DISV_SEL : BOOL := TRUE; //выбор переменной рассогласования
COM_RST : BOOL ; //полный рестарт
CYCLE : TIME := T#1S; //время выполнения
LMNG_PID : STRUCT
LMN : REAL ; //выходное значение
LMN_HLM : REAL ; //верхняя граница для выхода
LMN_LLM : REAL ; //нижняя граница для выхода
R_MTR_TM : REAL ; //motor manipulated value
ARWHL_ON : BOOL ; //anti reset wind-up in high limit on
ARWLL_ON : BOOL ; //anti reset wind-up in low limit on
MAN_ON : BOOL ; //manual mode on
LMNGS_ON : BOOL ; //PID-algorithm for step controller on
LMNR_ON : BOOL ; //repeated manipulated value on
END_STRUCT ;
END_VAR
VAR_OUTPUT
LMN_P : REAL ; //пропорциональная составляющая
LMN_I : REAL ; //интегральная составляющая
LMN_D : REAL ; //диференциальная составляющая
PID_LMNG : STRUCT
PID_OUTV : REAL ; //PID output variable
PID_SCTR : REAL ; //PID output variable for step controller
END_STRUCT ;
END_VAR
VAR
sInvAlt : REAL ;
sIanteilAlt : REAL ;
sRestInt : REAL ;
sRestDif : REAL ;
sRueck : REAL ;
sbILimOn : BOOL := TRUE;
END_VAR
VAR_TEMP
Hvar : REAL ; //Hilfsvariable
ErKp : REAL ; //Variable ER*GAIN
rTi : REAL ; //Integrationszeit in real
rTd : REAL ; //Differentiationszeit in real
rTmLag : REAL ; //Verzцgerungszeit in real
rCycle : REAL ; //Abtastzeit in real
Panteil : REAL ; //P-Anteil
Ianteil : REAL ; //I-Anteil
Diff : REAL ; //Дnderungswert
Danteil : REAL ; //D-Anteil
Verstaerk : REAL ; //Verstдrkung
RueckDiff : REAL ; //Differenz des Rьckkopplungswertes
RueckAlt : REAL ; //Alter Rьckkopplungswert
dDisv : REAL ; //disturbance variable
dLmn : REAL ; //Stellwert
PidOutv : REAL ; //PID-Ausgangswert
PidSctr : REAL ; //PID-Ausgangswert fьr Schrittregler
rLmnHlm : REAL ; //Obere Begrenzung
rLmnLlm : REAL ; //Untere Begrenzung
rMtrTm : REAL ; //Motorstellzeit
bArwhlOn : BOOL ; //anti reset wind-up in high limit on
bArwllOn : BOOL ; //anti reset wind-up in low LIMIT on
bManOn : BOOL ; //manual mode on
bLmngsOn : BOOL ; //PID-algorithm for step controller
bLmnrOn : BOOL ; //step controller with repeated manipulated value
END_VAR
BEGIN
IF COM_RST
THEN
ErKp:=0.0;
Panteil:=0.0;
Ianteil:=0.0;
sRestInt:=0.0;
Danteil:=0.0;
sRueck:=0.0;
sRestDif:=0.0;
sInvAlt:=0.0;
sIanteilAlt:=0.0;
sRestInt:=0.0;
sRestDif:=0.0;
PidOutv:=0.0;
PidSctr:=0.0;
ELSE
bManOn:=LMNG_PID.MAN_ON;
bLmngsOn:=LMNG_PID.LMNGS_ON;
bLmnrOn:=LMNG_PID.LMNR_ON;
dLmn:=LMNG_PID.LMN;
rLmnHlm:=LMNG_PID.LMN_HLM;
rLmnLlm:=LMNG_PID.LMN_LLM;
rMtrTm:=LMNG_PID.R_MTR_TM;
bArwhlOn:=LMNG_PID.ARWHL_ON;
bArwllOn:=LMNG_PID.ARWLL_ON;
ErKp:=ER*GAIN;
rTi:=DINT_TO_REAL(TIME_TO_DINT(TI))/1000.0;
rTd:=DINT_TO_REAL(TIME_TO_DINT(TD))/1000.0;
rTmLag:=DINT_TO_REAL(TIME_TO_DINT(TM_LAG))/1000.0;
rCycle:=DINT_TO_REAL(TIME_TO_DINT(CYCLE))/1000.0;
IF rTi < (rCycle * 0.5)
THEN
rTi:=rCycle * 0.5;
END_IF;
IF rTd < rCycle
THEN
rTd:=rCycle;
END_IF;
IF rTmLag < (rCycle * 0.5)
THEN
rTmLag:=rCycle * 0.5;
END_IF;
IF DISV_SEL
THEN
dDisv:=DISV;
ELSE
dDisv:=0.0;
END_IF;
IF P_SEL
THEN
IF PFDB_SEL
THEN
Panteil:=(-PV)*GAIN;
ELSE
Panteil:=ErKp;
END_IF;
ELSE
Panteil:=0.0;
END_IF;
//====================================================
IF bLmngsOn
THEN
Hvar:=rTi-ABS(0.01*ErKp*rMtrTm);
IF Hvar < (0.1*rTi)
THEN
rTi:=0.1*rTi;
ELSE
rTi:=Hvar;
END_IF;
END_IF;
//=====================================================
IF ((NOT bLmngsOn) AND I_SEL) OR (I_SEL AND bLmngsOn AND bLmnrOn)
THEN
IF I_ITL_ON
THEN
Ianteil:=I_ITLVAL;
sRestInt:=0.0;
ELSE
IF bManOn
THEN
IF bLmngsOn
THEN
Ianteil:=dLmn;
ELSE
Ianteil:=dLmn-Panteil-dDisv;
END_IF;
sRestInt:=0.0;
ELSE
Diff:=rCycle/rTi*(ErKp+sInvAlt)*0.5+sRestInt;
IF (Diff > 0.0 AND bArwhlOn OR INT_HOLD) OR (Diff < 0.0 AND bArwllOn)
THEN
Diff:=0.0;
END_IF;
Ianteil:=sIanteilAlt+Diff;
sRestInt:=sIanteilAlt-Ianteil+Diff;
END_IF;
END_IF;
ELSE
Ianteil:=0.0;
sRestInt:=0.0;
END_IF;
IF (NOT bLmnrOn) AND bLmngsOn
THEN
PidSctr:=ErKp/rTi;
ELSE
PidSctr:=Ianteil;
END_IF;
IF DFDB_SEL
THEN
Diff:=(-PV)*GAIN;
ELSE
Diff:=ErKp;
END_IF;
IF (NOT LMNG_PID.MAN_ON) AND D_SEL
THEN
Verstaerk:=rTd/(rCycle*0.5+rTmLag);
Danteil:=(Diff-sRueck)*Verstaerk;
RueckAlt:=sRueck;
RueckDiff:=rCycle/rTd*Danteil+sRestDif;
sRueck:=RueckDiff+RueckAlt;
sRestDif:=RueckAlt-sRueck+RueckDiff;
ELSE
Danteil:=0.0;
sRestDif:=0.0;
sRueck:=Diff;
END_IF;
PidOutv:=Panteil+Ianteil+Danteil+dDisv;
END_IF;
LMN_P:=Panteil;
LMN_I:=Ianteil;
LMN_D:=Danteil;
sInvAlt:=ErKp;
sIanteilAlt:=Ianteil;
PID_LMNG.PID_OUTV:=PidOutv;
PID_LMNG.PID_SCTR:=PidSctr;
END_FUNCTION_BLOCK