-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathFbIntegrator.SCL
More file actions
200 lines (178 loc) · 6.22 KB
/
Copy pathFbIntegrator.SCL
File metadata and controls
200 lines (178 loc) · 6.22 KB
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
FUNCTION_BLOCK "FbIntegrator"
TITLE = 'Интегратор W(s)=1/s.'
{ S7_read_back := 'true' ;
S7_blockview := 'big' }
AUTHOR : VA
FAMILY : LIB_PLC
VERSION : '2.2'
VAR_INPUT // Входные переменные, сохраняемые.
In :REAL := 0.0 ; // Входной сигнал интегратора.
OutMax :REAL := 1000000.0; // Максимальное значение выхода.
OutMin :REAL := -1000000.0; // Минимальное значение выхода.
InitValue :REAL := 0.0 ; // Начальные условия интегрирования для Reset
Trapezoid :BOOL := FALSE ; // Интегрирование методом: 1-трапеций 0-прямоугольников.
Ts :REAL := 0.1 ; // Шаг дискретизации по времени [с].
Reset :BOOL := FALSE ; // Сброс при перезагрузке.
END_VAR
VAR_OUTPUT // Выходные переменные, сохраняемые.
Out :REAL := 0.0; // Выходной сигнал интегратора.
END_VAR
VAR // Внутренние переменные, сохраняемые.
InPrevious : REAL := 0.0; // Предидущее значение входа только для трапециидального интегратора.
END_VAR
BEGIN
// Интегратор W(s)=1/s.
// DbIntegrator
// +--------------+
// | FbIntegrator |
// ->-|In Out|->-
// -|OutMax |
// -|OutMin |
// -|InitValue |
// -|Trapezoid |
// -|Ts |
// -|Reset |
// +--------------+
IF (Trapezoid) THEN
// При шаге дискретизации Ts>=1s есть смысл включить более точный алгоритм.
// Или если мы точно понимаем, что делаем и зачем.
// Все же не траекторию ракеты в космомосе считаем.
Out := Out + (In + InPrevious) * 0.5 * Ts; // Трапецеидальный интегратор.
ELSE
// По умолчанию простой алгоритм.
// Используем прямоугольный интегратор т.к. его обычно достаточно.
Out := Out + In * Ts; // Прямоугольный интегратор
END_IF;
InPrevious := In;
IF (Reset) THEN // Начальные условия интегрирования применяются при сбросе.
Out := InitValue;
END_IF;
IF (Out >= OutMax) THEN // Ограничение верх.
Out := OutMax;
END_IF;
IF (Out <= OutMin) THEN // Ограничение низ.
Out := OutMin;
END_IF;
// Условное графическое обозначение (точное).
//
// +----------+
// | Ts * z |
// ->-| -------- |->-
// | z - 1 |
// +----------+
// Условное графическое обозначение (приближенное).
//
// +-----+
// | 1 |
// X(s)->-| --- |->-Y(s)
// | s |
// +-----+
//
// W(s) = Y(s) / X(s).
// Временная характеристика.
//
// ^ Out
// |
// 3 *
// | *
// 2 *
// | *
// 1 *
// | *
// 0---1---2---3---> t[s]
//
// ^ In
// |
// 1************
// |
// 0---1---2---3---> t[s]
// Подаем на вход константу на выходе получаем линейную функцию.
// Подаем на вход линейную функцию на выходе получаем параболу.
// Подаем на вход функцию sin(t) на выходе получаем cos(t).
// Подаем на вход функцию e(t) на выходе получаем e(t).
// Передаточная функция интегратора в изображении по Лапласу:
// 1
// W(s) = ---
// s
// W(s) = Y(s) / X(s)
// X(s) = L( X(t) )
// Y(s) = L( Y(t) )
// Например подали на вход константу 2:
// X(t) = 2
// Изображение константы 2:
// L( X(t) ) = L( 2 ) = 2/s
// На выходе получили линейную функцию 2t:
// Y(t) = 2t
// Изображение линейной функции 2t:
// L( Y(t) ) = L( 2t ) = 2/(s*s)
// Тогда по определению передаточной функции получаем для интегратора:
// W(s) = Y(s) / X(s) = 2/(s*s) / 2/s = 1/s
// W(s) = 1/s
// Преобразование Лапласа грубо говоря это преобразование Фурье в котором:
// Исходную функцию умножили на затухающую экспоненту чтобы результирующая площадь (интеграл) была конечной.
// Предел интегрирования не от -inf до +inf а 0 до +inf с той же целью чтобы площадь (интеграл) была конечной и проще было считать интеграл.
// Если вы не знаете что такое интеграл смотрите и вам откроется:)
// История математики ВВС: The Story of Maths (4 серии)
// Механическая Вселенная The Mechanical Universe… And Beyond (52 серии)
// Вывод разностного уравнения из дифференциального уравнения:
// 1
// W(p) = ---
// p
// W(p) = Y(t) / X(t)
// p = d/dt
// Y(t) / X(t) = 1 / p
// Y(t) * p = X(t)
// Y(t) * d/dt = X(t)
// d(Y(t)) / dt = X(t)
// (Y(t) - Y(t-dt)) / dt = X(t)
// Y(t) - Y(t-dt) = X(t) * dt
// Y(t) = Y(t-dt) + X(t) * dt
// Y = Y + X * Ts
// Прямоугольный интегратор (Integrator Backward Euler).
// Алгебраический порядок точности численного метода = 0 (ODE0)
// Вывод разностного уравнения из дискретной передаточной функции:
// Ts * z
// W(z) = --------
// z - 1
// W(z) = (Ts * z) / (z - 1)
// Y(z) / X(z) = (Ts * z) / (z - 1)
// Y(z) * (z - 1) = Ts * X(z) * z
// Y(z) * z - Y(z) = Ts * X(z) * z
// Y(z) * z = Y(z) + Ts * X(z) * z
// Y(z) = Y(z) * (z^-1) + Ts * X(z)
// Y[n] = Y[n-1] + Ts * X[n]
// Y = Y + X * Ts
// Практика применения в АСУТП показывает
// что достаточно нулевой алгебраической точности интегратора
// и шага дискретизации по времени Ts = 0.1s.
// Трапецеидальный интегратор (Integrator Trapezoidal).
// Алгебраический порядок точности численного метода = 1 (ODE1)
// Вывод разностного уравнения из дискретной передаточной функции:
// Ts * (z + 1)
// W(z) = --------------
// 2 * (z - 1)
// W(z) = Ts * (z + 1) / 2 * (z - 1)
// Y(z) / X(z) = Ts * (z + 1) / 2 * (z - 1)
// Y(z) * 2 * (z - 1) = X(z) * Ts * (z + 1)
// Y(z) * z * 2 - Y(z) * 2 = X(z) * z * Ts + X(z) * Ts
// Y(z) * 2 - Y(z) * (z^-1) * 2 = X(z) * Ts + X(z) * (z^-1) * Ts
// Y(z) * 2 = Y(z) * (z^-1) * 2 + X(z) * Ts + X(z) * (z^-1) * Ts
// Y(z) = Y(z) * (z^-1) + (X(z) * Ts + X(z) * (z^-1) * Ts) / 2
// Y(z) = Y(z) * (z^-1) + (X(z) + X(z) * (z^-1)) * 0.5 * Ts
// Y[n] = Y[n-1] + (X[n] + X[n-1]) * 0.5 * Ts
// Y = Y + (X + Xprevious) * 0.5 * Ts
// Xprevious = X
// @COPYLEFT ALL WRONGS RESERVED :)
// Author: VA
// Contacts: DIY.PLC.314@gmail.com
// Date start LIB_PLC: 2014
// License: GNU GPL-2.0-or-later
// https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
// https://www.youtube.com/watch?v=n1F_MfLRlX0
// https://www.youtube.com/@DIY_PLC
// https://github.com/DIYPLC/LIB_PLC
// https://oshwlab.com/diy.plc.314/PLC_HW1_SW1
// https://3dtoday.ru/3d-models/mechanical-parts/body/korpus-na-din-reiku
// https://t.me/DIY_PLC
// https://drive.google.com/drive/folders/16GDX0i07rwDrl_oPzL-lQAqMiAz3ouJV?usp=sharing
END_FUNCTION_BLOCK