Поправил скрипт, поправил неточности в библиотеке
This commit is contained in:
+2
-1
@@ -6,4 +6,5 @@
|
|||||||
# directories
|
# directories
|
||||||
|
|
||||||
# build results
|
# build results
|
||||||
*.opt
|
*.opt
|
||||||
|
*.~u
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,25 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Structs
|
||||||
|
Name : AnalogValueState
|
||||||
|
Type : DUT
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
{attribute 'qualified_only'}
|
||||||
|
{attribute 'strict'}
|
||||||
|
TYPE AnalogValueState:
|
||||||
|
(
|
||||||
|
undefined := INT#0, (* 0 - не определено *)
|
||||||
|
fail_hi := INT#5, (* 5 - аварийный по верхнему уровню *)
|
||||||
|
warn_hi := INT#4, (* 4 - предупредительный по верхнему уровню, *)
|
||||||
|
normal := INT#1, (* 1 - норма *)
|
||||||
|
warn_low := INT#2, (* 2 - предупредительный по нижнему уровню *)
|
||||||
|
fail_low := INT#3, (* 3 - аварийный по нижнему уровню *)
|
||||||
|
no_signal := - INT#1 (* -1 - нет связи с датчиком *)
|
||||||
|
) := undefined;
|
||||||
|
END_TYPE
|
||||||
|
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM721_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM721_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM721 из единиц АЦП в 0..20 мА
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC: DINT;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
AIM721_AI := DINT_TO_REAL(ADC)*REAL#2.40802793E-006;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM722_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM722_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM722 из единиц АЦП в 0..20 мА
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC: DINT;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
AIM722_AI := DINT_TO_REAL(ADC)*REAL#2.384185791015625E-006;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM723_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM723_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM723 из единиц АЦП в 4..20 мА
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC: DINT;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
AIM723_AI := REAL#4.0 + DINT_TO_REAL(ADC)*REAL#1.93119072E-006;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM725_Status
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK AIM725_Status
|
||||||
|
(*
|
||||||
|
Модуль формирования статуса
|
||||||
|
Гистерезис по отключению и задержка по включению
|
||||||
|
-1 - нет связи с датчиком
|
||||||
|
0 - не определено
|
||||||
|
1 - норма
|
||||||
|
2 - предупредительный по нижнему уровню
|
||||||
|
3 - аварийный по нижнему уровню
|
||||||
|
4 - предупредительный по верхнему уровню,
|
||||||
|
5 - аварийный по верхнему уровню
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
Input: REAL;
|
||||||
|
fail_hi: REAL:=3.402823466E+38;
|
||||||
|
delta_fail_hi: REAL := 0;
|
||||||
|
time_fail_hi: TIME :=t#0s;
|
||||||
|
warn_hi: REAL:=3.402823466E+38;
|
||||||
|
delta_warn_hi: REAL := 0;
|
||||||
|
time_warn_hi: TIME :=t#0s;
|
||||||
|
warn_low: REAL:=-3.402823466E+38;
|
||||||
|
delta_warn_low: REAL := 0;
|
||||||
|
time_warn_low: TIME :=t#0s;
|
||||||
|
fail_low: REAL:=-3.402823466E+38;
|
||||||
|
delta_fail_low: REAL := 0;
|
||||||
|
time_fail_low: TIME :=t#0s;
|
||||||
|
Modul_status: BYTE;
|
||||||
|
Chanel_num: BYTE;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Status: INT;
|
||||||
|
T_mod: INT;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
(* !!! ВНУТРЕННИЕ НЕВЫХОДНЫЕ ПЕРЕМЕННЫЕ!!! *)
|
||||||
|
TON_fail_hi: TON;
|
||||||
|
TON_warn_hi: TON;
|
||||||
|
TON_warn_low: TON;
|
||||||
|
TON_fail_low: TON;
|
||||||
|
(* !!! ВНУТРЕННИЕ ВЫХОДНЫЕ ПЕРЕМЕННЫЕ!!! *)
|
||||||
|
fail_hi_st: BOOL;
|
||||||
|
warn_hi_st: BOOL;
|
||||||
|
normal_st: BOOL;
|
||||||
|
warn_low_st: BOOL;
|
||||||
|
fail_low_st: BOOL;
|
||||||
|
no_signal_st: BOOL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
no_signal_st := (Input <= - REAL#200 OR ((Modul_status.0 OR Modul_status.4 OR Modul_status.5) AND Chanel_num = 1) OR ((Modul_status.1 OR Modul_status.6 OR Modul_status.7) AND Chanel_num = 2) OR Modul_status.2 OR Modul_status.3);
|
||||||
|
IF no_signal_st THEN T_mod := - INT#500; ELSE T_mod := REAL_TO_INT(Input); END_IF;
|
||||||
|
|
||||||
|
TON_fail_low(IN := ((Input <= fail_low) AND NOT(no_signal_st)), PT := time_fail_low);
|
||||||
|
IF TON_fail_low.Q THEN fail_low_st := TRUE; ELSIF (Input > fail_low + delta_fail_low) THEN fail_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_low(IN := ((Input <= warn_low) AND NOT(no_signal_st) AND NOT(TON_fail_low.Q)), PT := time_warn_low);
|
||||||
|
IF TON_warn_low.Q THEN warn_low_st := TRUE; ELSIF (Input > warn_low + delta_warn_low) THEN warn_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_fail_hi(IN := ((Input >= fail_hi) AND NOT(no_signal_st)), PT := time_fail_hi);
|
||||||
|
IF TON_fail_hi.Q THEN fail_hi_st := TRUE; ELSIF (Input < fail_hi - delta_fail_hi) THEN fail_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_hi(IN := ((Input >= warn_hi) AND NOT(no_signal_st) AND NOT(TON_fail_hi.Q)), PT := time_warn_hi);
|
||||||
|
IF TON_warn_hi.Q THEN warn_hi_st := TRUE; ELSIF (Input < warn_hi - delta_warn_hi) THEN warn_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
normal_st := (NOT(no_signal_st) AND NOT(fail_low_st) AND NOT(warn_low_st) AND NOT(warn_hi_st) AND NOT(fail_hi_st));
|
||||||
|
|
||||||
|
IF no_signal_st THEN
|
||||||
|
Status := - INT#1;
|
||||||
|
ELSIF fail_hi_st THEN
|
||||||
|
Status := INT#5;
|
||||||
|
ELSIF fail_low_st THEN
|
||||||
|
Status := INT#3;
|
||||||
|
ELSIF warn_hi_st THEN
|
||||||
|
Status := INT#4;
|
||||||
|
ELSIF warn_low_st THEN
|
||||||
|
Status := INT#2;
|
||||||
|
ELSIF normal_st THEN
|
||||||
|
Status := INT#1;
|
||||||
|
ELSE
|
||||||
|
Status := INT#0;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM726_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM726_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM726 из единиц АЦП в 0..40 В
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC : DWORD; (*Единицы АЦП*)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
AIM726_AI := DWORD_TO_REAL(ADC) * REAL#4.768372E-006;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM727_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM727_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM727 из единиц АЦП в 0..40 V
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC: DINT; (*Единицы АЦП*)
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
AIM727_AI := DINT_TO_REAL(ADC)*REAL#4.768372E-006;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM730_AO
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM730_AO : WORD
|
||||||
|
(*
|
||||||
|
Перевод значений 0..20 мА или 4..20 мА в единицы АЦП выходов модуля AIM730
|
||||||
|
Диапазон:
|
||||||
|
RANGE = 0 - 0..20 мА
|
||||||
|
RANGE = 1 - 4..20 мА
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
DAC : REAL; (*Миллиамперы*)
|
||||||
|
RANGE : BYTE; (*Диапазон: 0..20 мА - 0; 4..20 мА - 1 *)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF (RANGE = 1) AND (DAC < 4) THEN AIM730_AO := WORD#4; RETURN;END_IF;
|
||||||
|
CASE RANGE OF
|
||||||
|
0 : AIM730_AO := REAL_TO_WORD(DAC/REAL#0.00030518);
|
||||||
|
1 : AIM730_AO := REAL_TO_WORD((DAC - REAL#4)/REAL#0.00024414435);
|
||||||
|
ELSE
|
||||||
|
AIM730_AO := WORD#0;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM731_AO
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM731_AO : WORD
|
||||||
|
(*
|
||||||
|
Перевод значений -10..+10 В или 0..+10 В в единицы АЦП выходов модуля AIM731
|
||||||
|
Диапазон:
|
||||||
|
RANGE = 0 - -10..+10 В
|
||||||
|
RANGE = 1 - 0..+10 В
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
DAC : REAL; (*Вольты*)
|
||||||
|
RANGE : BYTE; (*Диапазон -10..+10 В - 0; 0..+10 В - 1 *)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
CASE RANGE OF
|
||||||
|
0 : AIM731_AO := REAL_TO_WORD((DAC + REAL#10.0)/REAL#0.00030518);
|
||||||
|
1 : AIM731_AO := REAL_TO_WORD(DAC/REAL#0.00015259);
|
||||||
|
ELSE
|
||||||
|
AIM731_AO := 0;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : AIM791_AI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION AIM791_AI : REAL
|
||||||
|
(*
|
||||||
|
Перевод значений входов модуля AIM791 из единиц АЦП в 0..5 мА / 0..20 мА / 4..20 мА
|
||||||
|
Диапазон:
|
||||||
|
RANGE = 0 - 0..5 мА
|
||||||
|
RANGE = 1 - 0..20 мА
|
||||||
|
RANGE = 2 - 4..20 мА
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
ADC: WORD;
|
||||||
|
RANGE: BYTE := 0;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
CASE RANGE OF
|
||||||
|
0 : AIM791_AI := WORD_TO_REAL(ADC) * REAL#7.820248722E-005;
|
||||||
|
1 : AIM791_AI := WORD_TO_REAL(ADC) * REAL#3.128099488E-004;
|
||||||
|
2 : AIM791_AI := (WORD_TO_REAL(ADC) * REAL#3.128099488E-004) - REAL#4.0;
|
||||||
|
ELSE
|
||||||
|
AIM791_AI := REAL#0.0;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Fastwel
|
||||||
|
Name : DIM764_DI
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION DIM764_DI : REAL
|
||||||
|
(*На выходе - Частота в Гц*)
|
||||||
|
VAR_INPUT
|
||||||
|
IN: DWORD;
|
||||||
|
RANGE: BYTE; (* 0-Period; 1-Interval; *)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
CASE RANGE OF
|
||||||
|
0 : IF(IN=0) THEN DIM764_DI:=0; ELSE DIM764_DI := 50000000.0/DWORD_TO_REAL(IN); END_IF;
|
||||||
|
1 : DIM764_DI:=DWORD_TO_REAL(IN)/50.0;
|
||||||
|
ELSE
|
||||||
|
DIM764_DI:=0;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Filters
|
||||||
|
Name : ExpRunAverage
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION ExpRunAverage : REAL
|
||||||
|
(* Экспоненциальное скользящее среднее (экспоненциальное сглаживание)*)
|
||||||
|
VAR_INPUT
|
||||||
|
In : REAL; (* Входное значение *)
|
||||||
|
Old : REAL; (* Значение экспоненциального скользящего среднего на прошлом шаге *)
|
||||||
|
K : REAL; (* Весовой коэффициент в интервале от 0 до 1, отражающий скорость старения прошлых данных: чем выше его значение, тем больший удельный вес имеют новые наблюдения величины *)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
ExpRunAverage := (1.0 - K) * Old + K * In;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Filters
|
||||||
|
Name : ExpRunAverageAdaptive
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION ExpRunAverageAdaptive : REAL
|
||||||
|
(* Экспоненциальное скользящее среднее c адаптивным коэффициентом*)
|
||||||
|
VAR_INPUT
|
||||||
|
In : REAL; (* Входное значение *)
|
||||||
|
Old : REAL; (* Значение экспоненциального скользящего среднего на прошлом шаге *)
|
||||||
|
K1 : REAL; (* Весовой коэффициент в интервале от 0 до 1, отражающий скорость старения прошлых данных: чем выше его значение, тем больший удельный вес имеют новые наблюдения величины *)
|
||||||
|
Delta : REAL; (* Разница для изменения коэффициента *)
|
||||||
|
K2 : REAL; (* Измененный весовой коэффициент в интервале от 0 до 1 (больший чем K1) *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
K: REAL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF ABS(In - Old) > Delta THEN K := K2; ELSE K := K1; END_IF;
|
||||||
|
ExpRunAverageAdaptive := (1.0 - K) * Old + K * In;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Filters
|
||||||
|
Name : MultipleClick
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK MultipleClick
|
||||||
|
VAR_INPUT
|
||||||
|
In: BOOL;(* Вход кнопки *)
|
||||||
|
TimeToWait: TIME:=T#500MS; (* Максимальное время между нажатиями *)
|
||||||
|
TimeRelease: TIME:=T#0S; (* Время удержания выхода*)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Click1: BOOL;(* Было сделано 1 нажатие *)
|
||||||
|
Click2: BOOL;(* Было сделано 2 нажатия *)
|
||||||
|
Click3: BOOL;(* Было сделано 3 нажатия *)
|
||||||
|
Click: WORD;(* Количество нажатий *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
R_TRIG_BTN: R_TRIG;
|
||||||
|
TOF_Click: TOF;
|
||||||
|
CurrentClick: WORD := 0;
|
||||||
|
TP_Release: TP;
|
||||||
|
F_TRIG_Click: F_TRIG;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
R_TRIG_BTN(CLK:=In);
|
||||||
|
TOF_Click(IN:=R_TRIG_BTN.Q, PT:=TimeToWait);
|
||||||
|
|
||||||
|
IF TOF_Click.Q AND R_TRIG_BTN.Q THEN
|
||||||
|
CurrentClick:=CurrentClick+1;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
F_TRIG_Click(CLK:=TOF_Click.Q);
|
||||||
|
TP_Release(IN:=F_TRIG_Click.Q, PT:=TimeRelease);
|
||||||
|
|
||||||
|
IF F_TRIG_Click.Q THEN
|
||||||
|
Click:=CurrentClick;
|
||||||
|
CurrentClick:=0;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
IF TP_Release.Q THEN
|
||||||
|
Click1 := (Click = 1);
|
||||||
|
Click2 := (Click = 2);
|
||||||
|
Click3 := (Click = 3);
|
||||||
|
ELSE
|
||||||
|
Click:=0;
|
||||||
|
Click1 := 0;
|
||||||
|
Click2 := 0;
|
||||||
|
Click3 := 0;
|
||||||
|
END_IF
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Filters
|
||||||
|
Name : RunMiddleArifm
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK RunMiddleArifm
|
||||||
|
(* Скользящая средняя *)
|
||||||
|
VAR_INPUT
|
||||||
|
In : REAL;
|
||||||
|
N : INT:=32; (* Размер выборки 0...32 *)
|
||||||
|
RST : BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Y : REAL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
init: BOOL;
|
||||||
|
buffer : ARRAY[0..31] OF REAL;
|
||||||
|
i: INT;
|
||||||
|
nEff: INT;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
nEff := LIMIT(0, N, 32);
|
||||||
|
|
||||||
|
IF NOT init OR RST OR nEff = 0 THEN
|
||||||
|
init := TRUE;
|
||||||
|
FOR i := 0 TO nEff - 1 DO
|
||||||
|
buffer[i] := In;
|
||||||
|
END_FOR;
|
||||||
|
Y := In;
|
||||||
|
ELSE
|
||||||
|
IF i >= nEff - 1 THEN i := 0; ELSE i := i + 1; END_IF;
|
||||||
|
Y := Y + (In - buffer[i]) / INT_TO_REAL(nEff);
|
||||||
|
buffer[i] := In;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Иное
|
||||||
|
Name : DFS
|
||||||
|
Type : PROGRAM
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
PROGRAM DFS
|
||||||
|
(* Алгоритм поиска в глубину *)
|
||||||
|
(* Копировать в свою программу *)
|
||||||
|
VAR_INPUT
|
||||||
|
graph: POINTER TO ARRAY[1..n, 1..n] OF BOOL; // Граф связности (редактируется извне программы через DFS.graph[i,j])
|
||||||
|
connected: POINTER TO ARRAY[1..n] OF INT; //подключенные вершины
|
||||||
|
Start: INT := 1; // Вершина из которой начинается поиск
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
STACK: STACK_I16;
|
||||||
|
v: INT;
|
||||||
|
i: INT;
|
||||||
|
visited: ARRAY[1..n] OF BOOL; // посещенные вершины
|
||||||
|
k: INT := 1; // номер посещенной вершины
|
||||||
|
END_VAR
|
||||||
|
VAR CONSTANT
|
||||||
|
n : INT := 12; // Количество вершин графа
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
FOR i:=1 TO n DO
|
||||||
|
visited[i]:=0;
|
||||||
|
connected^[i]:=0;
|
||||||
|
END_FOR
|
||||||
|
k:=1;
|
||||||
|
|
||||||
|
STACK(Din:= Start, PUSH:= 1);
|
||||||
|
visited[Start]:= 1;
|
||||||
|
WHILE NOT STACK.EMPTY DO
|
||||||
|
STACK(pop:= 1, Dout=>v);
|
||||||
|
FOR i:=1 TO n DO
|
||||||
|
IF (graph^[v,i] AND NOT(visited[i])) THEN
|
||||||
|
visited[i]:= 1;
|
||||||
|
STACK(Din:= i, PUSH:= 1);
|
||||||
|
connected^[k]:=i;k:=k+1;
|
||||||
|
END_IF
|
||||||
|
END_FOR
|
||||||
|
END_WHILE
|
||||||
|
END_PROGRAM
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : ALARM_1
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK ALARM_1
|
||||||
|
(* Функциональный блок проверяет входное значение X на принадлежность [LO_1…HI_1]*)
|
||||||
|
VAR_INPUT
|
||||||
|
X : REAL; (* Контролируемое значение. *)
|
||||||
|
LO_1 : REAL; (* Нижний предел 1. *)
|
||||||
|
HI_1 : REAL; (* Верхний предел 1. *)
|
||||||
|
HYS : REAL; (* Значение гистерезиса (берется как HYS/2 отностительно середины) *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q1_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 1». *)
|
||||||
|
Q1_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 1». *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
tmp: REAL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
tmp := X - HYS * 0.5;
|
||||||
|
IF tmp > LO_1 THEN Q1_LO := FALSE; END_IF;
|
||||||
|
IF tmp > HI_1 THEN Q1_HI := TRUE; END_IF;
|
||||||
|
tmp := tmp + HYS;
|
||||||
|
IF tmp < LO_1 THEN Q1_LO := TRUE; END_IF;
|
||||||
|
IF tmp < HI_1 THEN Q1_HI := FALSE; END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : ALARM_2
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK ALARM_2
|
||||||
|
(* Функциональный блок проверяет входное значение X на принадлежность [LO_1…HI_1] [LO_2…HI_2] *)
|
||||||
|
VAR_INPUT
|
||||||
|
X : REAL; (* Контролируемое значение. *)
|
||||||
|
LO_1 : REAL; (* Нижний предел 1. *)
|
||||||
|
HI_1 : REAL; (* Верхний предел 1. *)
|
||||||
|
LO_2 : REAL; (* Нижний предел 2. *)
|
||||||
|
HI_2 : REAL; (* Верхний предел 2. *)
|
||||||
|
HYS : REAL; (* Значение гистерезиса (берется как HYS/2 отностительно середины) *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q1_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 1». *)
|
||||||
|
Q1_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 1». *)
|
||||||
|
Q2_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 2». *)
|
||||||
|
Q2_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 2». *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
tmp: REAL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
tmp := X - HYS * 0.5;
|
||||||
|
IF tmp > LO_1 THEN Q1_LO := FALSE; END_IF;
|
||||||
|
IF tmp > LO_2 THEN Q2_LO := FALSE; END_IF;
|
||||||
|
IF tmp > HI_1 THEN Q1_HI := TRUE; END_IF;
|
||||||
|
IF tmp > HI_2 THEN Q2_HI := TRUE; END_IF;
|
||||||
|
tmp := tmp + HYS;
|
||||||
|
IF tmp < LO_1 THEN Q1_LO := TRUE; END_IF;
|
||||||
|
IF tmp < LO_2 THEN Q2_LO := TRUE; END_IF;
|
||||||
|
IF tmp < HI_1 THEN Q1_HI := FALSE; END_IF;
|
||||||
|
IF tmp < HI_2 THEN Q2_HI := FALSE; END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : ALARM_3
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK ALARM_3
|
||||||
|
(* Функциональный блок проверяет входное значение X на принадлежность [LO_1…HI_1] [LO_2…HI_2] [LO_3…HI_3] *)
|
||||||
|
VAR_INPUT
|
||||||
|
X : REAL; (* Контролируемое значение. *)
|
||||||
|
LO_1 : REAL; (* Нижний предел 1. *)
|
||||||
|
HI_1 : REAL; (* Верхний предел 1. *)
|
||||||
|
LO_2 : REAL; (* Нижний предел 2. *)
|
||||||
|
HI_2 : REAL; (* Верхний предел 2. *)
|
||||||
|
LO_3 : REAL; (* Нижний предел 3. *)
|
||||||
|
HI_3 : REAL; (* Верхний предел 3. *)
|
||||||
|
HYS : REAL; (* Значение гистерезиса (берется как HYS/2 отностительно середины) *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q1_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 1». *)
|
||||||
|
Q1_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 1». *)
|
||||||
|
Q2_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 2». *)
|
||||||
|
Q2_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 2». *)
|
||||||
|
Q3_LO : BOOL := FALSE; (* Флаг «значение меньше нижнего предела 3». *)
|
||||||
|
Q3_HI : BOOL := FALSE; (* Флаг «значение больше верхнего предела 3». *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
tmp: REAL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
tmp := X - HYS * 0.5;
|
||||||
|
IF tmp > LO_1 THEN Q1_LO := FALSE; END_IF;
|
||||||
|
IF tmp > LO_2 THEN Q2_LO := FALSE; END_IF;
|
||||||
|
IF tmp > LO_3 THEN Q3_LO := FALSE; END_IF;
|
||||||
|
IF tmp > HI_1 THEN Q1_HI := TRUE; END_IF;
|
||||||
|
IF tmp > HI_2 THEN Q2_HI := TRUE; END_IF;
|
||||||
|
IF tmp > HI_3 THEN Q3_HI := TRUE; END_IF;
|
||||||
|
tmp := tmp + HYS;
|
||||||
|
IF tmp < LO_1 THEN Q1_LO := TRUE; END_IF;
|
||||||
|
IF tmp < LO_2 THEN Q2_LO := TRUE; END_IF;
|
||||||
|
IF tmp < LO_3 THEN Q3_LO := TRUE; END_IF;
|
||||||
|
IF tmp < HI_1 THEN Q1_HI := FALSE; END_IF;
|
||||||
|
IF tmp < HI_2 THEN Q2_HI := FALSE; END_IF;
|
||||||
|
IF tmp < HI_3 THEN Q3_HI := FALSE; END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : BLINK_LMP
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK BLINK_LMP
|
||||||
|
(*
|
||||||
|
Мигание лампами в завистмости от статуса
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
State: WORD:=0; (* 0 - выключено; 1 - включено; 2 - мигание с частотой 1; 3 - мигание с частотой 2; 4 - мигание с частотой 3; *)
|
||||||
|
Inp_BL_1: BOOL := FALSE; (* Пульсар миганич с частотой 1 *)
|
||||||
|
Inp_BL_2: BOOL := FALSE; (* Пульсар миганич с частотой 2 *)
|
||||||
|
Inp_BL_3: BOOL := FALSE; (* Пульсар миганич с частотой 3 *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
LMP: BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
CASE State OF
|
||||||
|
0: LMP:=FALSE;
|
||||||
|
1: LMP:=TRUE;
|
||||||
|
2: LMP:=Inp_BL_1;
|
||||||
|
3: LMP:=Inp_BL_2;
|
||||||
|
4: LMP:=Inp_BL_3;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : BUZZER_CTRL
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK BUZZER_CTRL
|
||||||
|
(*
|
||||||
|
Звучание звонком лампами в завистмости от статуса с возможностью отключения звука
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
State: WORD:=0; (* 0 - выключено; 1 - включено; 2 - мигание с частотой 1; 3 - мигание с частотой 2; 4 - мигание с частотой 3; *)
|
||||||
|
Sound_off: BOOL; (* Отключение звука *)
|
||||||
|
Inp_BL_1: BOOL := FALSE; (* Пульсар миганич с частотой 1 *)
|
||||||
|
Inp_BL_2: BOOL := FALSE; (* Пульсар миганич с частотой 2 *)
|
||||||
|
Inp_BL_3: BOOL := FALSE; (* Пульсар миганич с частотой 3 *)
|
||||||
|
PermanentOFF_Enable: BOOL := FALSE; (*Включение возможности отключить звук перманентно *)
|
||||||
|
T_PermanentOFF: TIME := T#10S; (* Время удержания кнопки отключения звука для перманентного отключения *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
BUZZER: BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
R_TRIG_0: R_TRIG;
|
||||||
|
R_TRIG_1: R_TRIG;
|
||||||
|
R_TRIG_2: R_TRIG;
|
||||||
|
R_TRIG_3: R_TRIG;
|
||||||
|
R_TRIG_4: R_TRIG;
|
||||||
|
B_ctrl: WORD;
|
||||||
|
|
||||||
|
T_S_OFF: TON;
|
||||||
|
R_TRIG_S_OFF: R_TRIG;
|
||||||
|
AlltimeOff: BOOL;
|
||||||
|
TP1: TP:=(PT:=T#100MS);
|
||||||
|
R_TRIG1: R_TRIG;
|
||||||
|
F_TRIG1: F_TRIG;
|
||||||
|
F_TRIG2: F_TRIG;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
R_TRIG_0(CLK:=(State=0)); IF R_TRIG_0.Q THEN B_ctrl:=0; END_IF;
|
||||||
|
R_TRIG_1(CLK:=(State=1)); IF R_TRIG_1.Q THEN B_ctrl:=1; END_IF;
|
||||||
|
R_TRIG_2(CLK:=(State=2)); IF R_TRIG_2.Q THEN B_ctrl:=2; END_IF;
|
||||||
|
R_TRIG_3(CLK:=(State=3)); IF R_TRIG_3.Q THEN B_ctrl:=3; END_IF;
|
||||||
|
R_TRIG_4(CLK:=(State=4)); IF R_TRIG_4.Q THEN B_ctrl:=4; END_IF;
|
||||||
|
|
||||||
|
T_S_OFF(IN:=Sound_off, PT:=T_PermanentOFF);
|
||||||
|
R_TRIG_S_OFF(CLK:=Sound_off AND PermanentOFF_Enable);
|
||||||
|
R_TRIG1(CLK:=AlltimeOff);
|
||||||
|
F_TRIG1(CLK:=AlltimeOff);
|
||||||
|
TP1(IN:=R_TRIG1.Q OR F_TRIG1.Q);
|
||||||
|
F_TRIG2(CLK:=TP1.Q);
|
||||||
|
IF R_TRIG_S_OFF.Q THEN B_ctrl:=0; AlltimeOff:=0; END_IF
|
||||||
|
IF T_S_OFF.Q THEN AlltimeOff:=1; END_IF
|
||||||
|
IF AlltimeOff THEN B_ctrl:=0; END_IF;
|
||||||
|
IF TP1.Q THEN B_ctrl:=1; END_IF;
|
||||||
|
IF (F_TRIG2.Q OR F_TRIG1.Q) THEN B_ctrl:=0; END_IF;
|
||||||
|
|
||||||
|
|
||||||
|
CASE B_ctrl OF
|
||||||
|
0: BUZZER:=FALSE;
|
||||||
|
1: BUZZER:=TRUE;
|
||||||
|
2: BUZZER:=Inp_BL_1;
|
||||||
|
3: BUZZER:=Inp_BL_2;
|
||||||
|
4: BUZZER:=Inp_BL_3;
|
||||||
|
END_CASE;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : Button_acceleration
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK Button_acceleration
|
||||||
|
(* Ускорение изменения значения при нажатой кнопке *)
|
||||||
|
VAR_INPUT
|
||||||
|
Button: BOOL;
|
||||||
|
D_0: REAL := 0; (* Прирост при одиночном нажатии *)
|
||||||
|
T_W_1: TIME := T#0s; (* Время кратковременного удержания *)
|
||||||
|
T_D_1: TIME := T#200ms; (* Шаг времени прироста при кратковременном удержании *)
|
||||||
|
D_1: REAL := 0; (* Прирост при кратковременном удержании *)
|
||||||
|
T_W_2: TIME := T#0S; (* Время длительного удержания *)
|
||||||
|
T_D_2: TIME := T#200MS; (* Шаг времени прироста при длительном удержании *)
|
||||||
|
D_2: REAL := 0; (* Прирост при длительном удержании *)
|
||||||
|
Zeroes : BOOL := false; (* При этом флаге происходит сброс в 0 при дадании -D_0 << D_0 *)
|
||||||
|
END_VAR
|
||||||
|
VAR_IN_OUT
|
||||||
|
Out: REAL; (* Вход-выход который изменяется *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
Ton_1: TON;
|
||||||
|
Ton_2: TON;
|
||||||
|
TOF_1: TOF;
|
||||||
|
TOF_2: TOF;
|
||||||
|
R_TRIG_0: R_TRIG;
|
||||||
|
R_TRIG_1: R_TRIG;
|
||||||
|
R_TRIG_2: R_TRIG;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
Ton_1(PT := T_W_1,IN:=Button);
|
||||||
|
Ton_2(PT := T_W_2,IN:=Button);
|
||||||
|
TOF_1(PT := T_D_1,IN:=Ton_1.Q AND NOT(TOF_1.Q) AND NOT(Ton_2.Q));
|
||||||
|
TOF_2(PT := T_D_2,IN:=Ton_2.Q AND NOT(TOF_2.Q));
|
||||||
|
R_TRIG_0(CLK:=Button AND NOT(Ton_1.Q) AND NOT(Ton_2.Q));
|
||||||
|
R_TRIG_1(CLK:=TOF_1.Q);
|
||||||
|
R_TRIG_2(CLK:=TOF_2.Q);
|
||||||
|
IF R_TRIG_0.Q THEN
|
||||||
|
Out:=Out+D_0;
|
||||||
|
END_IF
|
||||||
|
IF R_TRIG_1.Q THEN
|
||||||
|
Out:=Out+D_1;
|
||||||
|
END_IF
|
||||||
|
IF R_TRIG_2.Q THEN
|
||||||
|
Out:=Out+D_2;
|
||||||
|
END_IF
|
||||||
|
IF Zeroes AND ABS(Out) < ABS(D_0) THEN
|
||||||
|
Out:=0;
|
||||||
|
END_IF
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : CONFIRMATION
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK CONFIRMATION
|
||||||
|
(*
|
||||||
|
Квитирование
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
Alarm: BOOL; // Авария
|
||||||
|
ControlState_On: BOOL; // Управление с текущего поста
|
||||||
|
Sound_Off: BOOL; // Сигнал снятия звука
|
||||||
|
Confirmation: BOOL; // Сигнал квитирования
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Lamp_Alarm_C: WORD; // Лампа аварии
|
||||||
|
Lamp_Confirmation_C: WORD; // Лампа квитирования
|
||||||
|
Buzzer_C: WORD; // Управление звонком
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
Alarm_Not_Sound_Off: BOOL;
|
||||||
|
Alarm_Not_Confirm: BOOL;
|
||||||
|
R_TR1: R_TRIG;
|
||||||
|
R_TR2: R_TRIG;
|
||||||
|
R_TR3: R_TRIG;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
R_TR1(CLK:=Confirmation); IF R_TR1.Q THEN Alarm_Not_Confirm:=0; END_IF;
|
||||||
|
R_TR2(CLK:=Sound_Off); IF R_TR2.Q THEN Alarm_Not_Sound_Off:=0; END_IF;
|
||||||
|
R_TR3(CLK:=Alarm); IF R_TR3.Q AND ControlState_On THEN Alarm_Not_Confirm:=1; Alarm_Not_Sound_Off:=1; END_IF;
|
||||||
|
IF NOT ControlState_On THEN Alarm_Not_Confirm:=0; Alarm_Not_Sound_Off:=0; END_IF;
|
||||||
|
|
||||||
|
IF NOT Alarm AND NOT Alarm_Not_Confirm THEN Lamp_Alarm_C:=0; Lamp_Confirmation_C:=0; END_IF;
|
||||||
|
IF Alarm AND NOT Alarm_Not_Confirm THEN Lamp_Alarm_C:=1; Lamp_Confirmation_C:=0; END_IF;
|
||||||
|
IF Alarm_Not_Confirm THEN Lamp_Alarm_C:=2; Lamp_Confirmation_C:=1; END_IF;
|
||||||
|
|
||||||
|
IF Alarm_Not_Sound_Off THEN Buzzer_C:=2; ELSE Buzzer_C:=0; END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : HYST
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK HYST
|
||||||
|
VAR_INPUT
|
||||||
|
In : REAL;
|
||||||
|
ON : REAL;
|
||||||
|
OFF : REAL;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q : BOOL;
|
||||||
|
win : BOOL;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF ON >= OFF THEN
|
||||||
|
IF IN < OFF THEN
|
||||||
|
Q := FALSE;
|
||||||
|
WIN := FALSE;
|
||||||
|
ELSIF IN > ON THEN
|
||||||
|
Q := TRUE;
|
||||||
|
WIN := FALSE;
|
||||||
|
ELSE
|
||||||
|
WIN := TRUE;
|
||||||
|
END_IF;
|
||||||
|
ELSE
|
||||||
|
IF IN > OFF THEN
|
||||||
|
Q := FALSE;
|
||||||
|
WIN := FALSE;
|
||||||
|
ELSIF IN < ON THEN
|
||||||
|
Q := TRUE;
|
||||||
|
WIN := FALSE;
|
||||||
|
ELSE
|
||||||
|
WIN := TRUE;
|
||||||
|
END_IF;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : Norm_real
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION Norm_real : REAL
|
||||||
|
(*
|
||||||
|
Нормирует значение аналогового входа X по двум заданным граничным точкам нормировки (X1,Y1) (X2,Y2)
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
X: REAL;
|
||||||
|
X1: REAL;
|
||||||
|
Y1: REAL;
|
||||||
|
X2: REAL;
|
||||||
|
Y2: REAL;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF (X2-X1 = 0) THEN Norm_real:=Y1; RETURN; END_IF;
|
||||||
|
Norm_real:=(X-X1)*(Y2-Y1)/(X2-X1)+Y1;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,125 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : PIDcontrol
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK PIDcontrol (* ПИД-регулятор. *)
|
||||||
|
VAR_INPUT
|
||||||
|
ProcessVariable: REAL := 0.0; (* Измеренное значение параметра *)
|
||||||
|
Setpoint: REAL := 0.0; (* Заданное значение *)
|
||||||
|
Kp: REAL := 0.001; (* Пропорциональный коэффициент *)
|
||||||
|
Ki: REAL := 0.001; (* Интегральный коэффициент *)
|
||||||
|
Kd: REAL := 0.0; (* Дифференциальный коэффициент *)
|
||||||
|
Kdf: REAL := 1.0; (* Коэффициент фильтрации (1/Tdf) *)
|
||||||
|
DBmax: REAL := 0.01; (* Верхняя граница зоны нечувствительности *)
|
||||||
|
DBmin: REAL := - 0.01; (* Нижняя граница зоны нечувствительности *)
|
||||||
|
OutMax: REAL := 100.0; (* Максимальный выход *)
|
||||||
|
OutMin: REAL := 0.0; (* Минимальный выход *)
|
||||||
|
Ts: REAL := 0.1; (* Время дискретизации [с] *)
|
||||||
|
Manual: REAL := 25.0; (* Значение в ручном режиме *)
|
||||||
|
ManOn: BOOL := FALSE; (* Флаг ручного режима *)
|
||||||
|
Reset: BOOL := FALSE; (* Сброс интегратора *)
|
||||||
|
AntiWindup: BOOL := TRUE; (* Включить антивиндап *)
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
VAR_OUTPUT
|
||||||
|
Out: REAL := 0.0; (* Выходной сигнал *)
|
||||||
|
Err: REAL := 0.0; (* Ошибка регулирования *)
|
||||||
|
OutLimited: BOOL := FALSE; (* Флаг ограничения выхода *)
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
VAR (* Внутренние переменные, сохраняемые. *)
|
||||||
|
Er: REAL := 0.0; (* Текущая ошибка *)
|
||||||
|
Ppart: REAL := 0.0; (* Пропорциональная часть *)
|
||||||
|
Ipart: REAL := 0.0; (* Интегральная часть *)
|
||||||
|
Dpart: REAL := 0.0; (* Дифференциальная часть *)
|
||||||
|
PrevEr: REAL := 0.0; (* Ошибка на предыдущем шаге (для дифференциатора). *)
|
||||||
|
FirstScan: BOOL := TRUE; (* Флаг первого сканирования. *)
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
VAR_TEMP
|
||||||
|
Auto: REAL; (* Выход ПИД *)
|
||||||
|
Sw: REAL; (* Промежуточное значение *)
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
(* === ИНИЦИАЛИЗАЦИЯ И СБРОС === *)
|
||||||
|
IF Reset OR FirstScan THEN
|
||||||
|
Ipart := 0.0;
|
||||||
|
Dpart := 0.0;
|
||||||
|
PrevEr := 0.0;
|
||||||
|
FirstScan := FALSE;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === ПРОВЕРКА ВХОДНЫХ ПАРАМЕТРОВ === *)
|
||||||
|
IF (OutMin >= OutMax) OR (DBmin >= DBmax) OR (Ts <= 0) THEN
|
||||||
|
Out := 0.0;
|
||||||
|
OutLimited := TRUE;
|
||||||
|
RETURN;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === РАСЧЕТ ОШИБКИ === *)
|
||||||
|
Er := Setpoint - ProcessVariable;
|
||||||
|
Err := Er;
|
||||||
|
|
||||||
|
(* ЗОНА НЕЧУВСТВИТЕЛЬНОСТИ *)
|
||||||
|
IF (DBmin < Er) AND (Er < DBmax) THEN
|
||||||
|
Er := 0.0;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === ПРОПОРЦИОНАЛЬНАЯ ЧАСТЬ === *)
|
||||||
|
Ppart := Kp * Er;
|
||||||
|
|
||||||
|
(* === ИНТЕГРАЛЬНАЯ ЧАСТЬ === *)
|
||||||
|
IF Ki <> 0.0 THEN
|
||||||
|
Ipart := Ipart + (Ki * Er * Ts);
|
||||||
|
Ipart := LIMIT(OutMin, Ipart, OutMax);
|
||||||
|
ELSE
|
||||||
|
Ipart := 0.0;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === ДИФФЕРЕНЦИАЛЬНАЯ ЧАСТЬ (фильтрованная) === *)
|
||||||
|
IF Kd <> 0.0 THEN
|
||||||
|
Dpart := Kd * Kdf * (Er - PrevEr) - Kdf * Dpart * Ts;
|
||||||
|
PrevEr := Er; (* Сохраняем ошибку для следующего шага *)
|
||||||
|
ELSE
|
||||||
|
Dpart := 0.0;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === ВЫЧИСЛЕНИЕ ВЫХОДА === *)
|
||||||
|
Auto := Ppart + Ipart + Dpart;
|
||||||
|
|
||||||
|
(* === РЕЖИМ РУЧНОЙ/АВТОМАТИЧЕСКИЙ === *)
|
||||||
|
IF ManOn THEN
|
||||||
|
Sw := Manual;
|
||||||
|
(* Сброс интегратора при переходе в ручной режим *)
|
||||||
|
IF AntiWindup THEN
|
||||||
|
Ipart := Sw - (Ppart + Dpart);
|
||||||
|
END_IF;
|
||||||
|
ELSE
|
||||||
|
Sw := Auto;
|
||||||
|
END_IF;
|
||||||
|
|
||||||
|
(* === ОГРАНИЧЕНИЕ ВЫХОДА И АНТИВИНДАП === *)
|
||||||
|
IF Sw >= OutMax THEN
|
||||||
|
Out := OutMax;
|
||||||
|
OutLimited := TRUE;
|
||||||
|
IF AntiWindup AND NOT ManOn THEN
|
||||||
|
Ipart := OutMax - (Ppart + Dpart);
|
||||||
|
END_IF;
|
||||||
|
ELSIF Sw <= OutMin THEN
|
||||||
|
Out := OutMin;
|
||||||
|
OutLimited := TRUE;
|
||||||
|
IF AntiWindup AND NOT ManOn THEN
|
||||||
|
Ipart := OutMin - (Ppart + Dpart);
|
||||||
|
END_IF;
|
||||||
|
ELSE
|
||||||
|
Out := Sw;
|
||||||
|
OutLimited := FALSE;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : Pulse_Switch
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK Pulse_Switch
|
||||||
|
VAR
|
||||||
|
R_tr_1: R_TRIG;
|
||||||
|
F_tr_1: F_TRIG;
|
||||||
|
tp_on: TP:=(PT:=t#500ms);
|
||||||
|
tp_off: TP:=(PT:=t#500ms);
|
||||||
|
END_VAR
|
||||||
|
VAR_INPUT
|
||||||
|
Switch_ctrl: BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Switch_on: BOOL;
|
||||||
|
Switch_off: BOOL;
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
R_tr_1(CLK:=Switch_ctrl);
|
||||||
|
tp_on(IN:=R_tr_1.Q, Q=>Switch_on);
|
||||||
|
|
||||||
|
F_tr_1(CLK:=Switch_ctrl);
|
||||||
|
tp_off(IN:=F_tr_1.Q, Q=>Switch_off);
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : STACK_I16
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK STACK_I16
|
||||||
|
(* стек на 16 элементов типа INT*)
|
||||||
|
VAR_INPUT
|
||||||
|
Din : INT; (* Переменная для записи в стек *)
|
||||||
|
E : BOOL := TRUE;(* Включение стека *)
|
||||||
|
POP : BOOL; (* Извлечение из стека *)
|
||||||
|
PUSH : BOOL; (* Запись в стек *)
|
||||||
|
RST : BOOL; (* Обнуление стека *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Dout : INT;
|
||||||
|
EMPTY : BOOL := TRUE;
|
||||||
|
FULL : BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
stack: ARRAY[0..n] OF INT;
|
||||||
|
pt : INT;
|
||||||
|
END_VAR
|
||||||
|
VAR CONSTANT
|
||||||
|
n : INT := 15; (* changing this value will chage the number of stored elements in the fifo *)
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF RST THEN
|
||||||
|
(* asynchronous reset for the fifo *)
|
||||||
|
pt := 0;
|
||||||
|
EMPTY := TRUE;
|
||||||
|
FULL := FALSE;
|
||||||
|
Dout := 0;
|
||||||
|
ELSIF E THEN
|
||||||
|
IF NOT EMPTY AND POP THEN
|
||||||
|
pt := pt - 1;
|
||||||
|
Dout := stack[pt];
|
||||||
|
EMPTY := pt = 0;
|
||||||
|
FULL := FALSE;
|
||||||
|
END_IF;
|
||||||
|
IF NOT FULL AND PUSH THEN
|
||||||
|
stack[pt] := Din;
|
||||||
|
pt := pt + 1;
|
||||||
|
FULL := pt > n;
|
||||||
|
EMPTY := FALSE;
|
||||||
|
END_IF;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : STATUS_ANALOG_M
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK STATUS_ANALOG_M
|
||||||
|
(*
|
||||||
|
Модуль формирования статуса
|
||||||
|
Гистерезис по отключению и задержка по включению, вход типа REAL
|
||||||
|
|
||||||
|
-1 - нет связи с датчиком
|
||||||
|
0 - не определено
|
||||||
|
1 - норма
|
||||||
|
2 - предупредительный по нижнему уровню
|
||||||
|
3 - аварийный по нижнему уровню
|
||||||
|
4 - предупредительный по верхнему уровню,
|
||||||
|
5 - аварийный по верхнему уровню
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
Input: REAL;
|
||||||
|
fail_hi: REAL:=3.402823466E+38;
|
||||||
|
delta_fail_hi: REAL := 0;
|
||||||
|
time_fail_hi: TIME :=t#0s;
|
||||||
|
warn_hi: REAL:=3.402823466E+38;
|
||||||
|
delta_warn_hi: REAL := 0;
|
||||||
|
time_warn_hi: TIME :=t#0s;
|
||||||
|
warn_low: REAL:=-3.402823466E+38;
|
||||||
|
delta_warn_low: REAL := 0;
|
||||||
|
time_warn_low: TIME :=t#0s;
|
||||||
|
fail_low: REAL:=-3.402823466E+38;
|
||||||
|
delta_fail_low: REAL := 0;
|
||||||
|
time_fail_low: TIME :=t#0s;
|
||||||
|
no_signal: REAL:=-3.402823466E+38;
|
||||||
|
delta_no_signal: REAL := 0;
|
||||||
|
time_no_signal: TIME :=T#0S;
|
||||||
|
|
||||||
|
In_fail_hi: BOOL := FALSE;
|
||||||
|
In_warn_hi: BOOL := FALSE;
|
||||||
|
In_warn_low: BOOL := FALSE;
|
||||||
|
In_fail_low: BOOL := FALSE;
|
||||||
|
In_no_signal: BOOL := FALSE;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Status: AnalogValueState;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
fail_hi_st: BOOL;
|
||||||
|
warn_hi_st: BOOL;
|
||||||
|
normal_st: BOOL;
|
||||||
|
warn_low_st: BOOL;
|
||||||
|
fail_low_st: BOOL;
|
||||||
|
no_signal_st: BOOL;
|
||||||
|
TON_fail_hi: TON;
|
||||||
|
TON_warn_hi: TON;
|
||||||
|
TON_warn_low: TON;
|
||||||
|
TON_fail_low: TON;
|
||||||
|
TON_no_signal: TON;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
TON_no_signal(IN := (Input <= no_signal) OR In_no_signal, PT := time_no_signal);
|
||||||
|
IF TON_no_signal.Q THEN no_signal_st := TRUE; ELSIF (Input > no_signal + delta_no_signal) THEN no_signal_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_fail_low(IN := ((Input <= fail_low) AND NOT(no_signal_st)) OR In_fail_low, PT := time_fail_low);
|
||||||
|
IF TON_fail_low.Q THEN fail_low_st := TRUE; ELSIF (Input > fail_low + delta_fail_low) THEN fail_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_low(IN := ((Input <= warn_low) AND NOT(no_signal_st) AND NOT(TON_fail_low.Q)) OR In_warn_low, PT := time_warn_low);
|
||||||
|
IF TON_warn_low.Q THEN warn_low_st := TRUE; ELSIF (Input > warn_low + delta_warn_low) THEN warn_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_fail_hi(IN := ((Input >= fail_hi) AND NOT(no_signal_st)) OR In_fail_hi, PT := time_fail_hi);
|
||||||
|
IF TON_fail_hi.Q THEN fail_hi_st := TRUE; ELSIF (Input < fail_hi - delta_fail_hi) THEN fail_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_hi(IN := ((Input >= warn_hi) AND NOT(no_signal_st) AND NOT(TON_fail_hi.Q)) OR In_warn_hi, PT := time_warn_hi);
|
||||||
|
IF TON_warn_hi.Q THEN warn_hi_st := TRUE; ELSIF (Input < warn_hi - delta_warn_hi) THEN warn_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
normal_st := (NOT(no_signal_st) AND NOT(fail_low_st) AND NOT(warn_low_st) AND NOT(warn_hi_st) AND NOT(fail_hi_st));
|
||||||
|
|
||||||
|
IF no_signal_st THEN
|
||||||
|
Status := AnalogValueState.no_signal;
|
||||||
|
ELSIF fail_hi_st THEN
|
||||||
|
Status := AnalogValueState.fail_hi;
|
||||||
|
ELSIF fail_low_st THEN
|
||||||
|
Status := AnalogValueState.fail_low;
|
||||||
|
ELSIF warn_hi_st THEN
|
||||||
|
Status := AnalogValueState.warn_hi;
|
||||||
|
ELSIF warn_low_st THEN
|
||||||
|
Status := AnalogValueState.warn_low;
|
||||||
|
ELSIF normal_st THEN
|
||||||
|
Status := AnalogValueState.normal;
|
||||||
|
ELSE
|
||||||
|
Status := AnalogValueState.undefined;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : STATUS_ANALOG_M_I
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK STATUS_ANALOG_M_I
|
||||||
|
(*
|
||||||
|
Модуль формирования статуса
|
||||||
|
Гистерезис по отключению и задержка по включению, вход типа INT
|
||||||
|
|
||||||
|
-1 - нет связи с датчиком
|
||||||
|
0 - не определено
|
||||||
|
1 - норма
|
||||||
|
2 - предупредительный по нижнему уровню
|
||||||
|
3 - аварийный по нижнему уровню
|
||||||
|
4 - предупредительный по верхнему уровню,
|
||||||
|
5 - аварийный по верхнему уровню
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
Input: INT;
|
||||||
|
fail_hi: INT:=32767;
|
||||||
|
delta_fail_hi: INT := 0;
|
||||||
|
time_fail_hi: TIME :=t#0s;
|
||||||
|
warn_hi: INT:=32767;
|
||||||
|
delta_warn_hi: INT := 0;
|
||||||
|
time_warn_hi: TIME :=t#0s;
|
||||||
|
warn_low: INT:=-32768;
|
||||||
|
delta_warn_low: INT := 0;
|
||||||
|
time_warn_low: TIME :=t#0s;
|
||||||
|
fail_low: INT:=-32768;
|
||||||
|
delta_fail_low: INT := 0;
|
||||||
|
time_fail_low: TIME :=t#0s;
|
||||||
|
no_signal: INT:=-32768;
|
||||||
|
delta_no_signal: INT := 0;
|
||||||
|
time_no_signal: TIME :=T#0S;
|
||||||
|
|
||||||
|
In_fail_hi: BOOL := FALSE;
|
||||||
|
In_warn_hi: BOOL := FALSE;
|
||||||
|
In_warn_low: BOOL := FALSE;
|
||||||
|
In_fail_low: BOOL := FALSE;
|
||||||
|
In_no_signal: BOOL := FALSE;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Status: AnalogValueState;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
(* !!! ВНУТРЕННИЕ ВЫХОДНЫЕ ПЕРЕМЕННЫЕ!!! *)
|
||||||
|
fail_hi_st: BOOL;
|
||||||
|
warn_hi_st: BOOL;
|
||||||
|
normal_st: BOOL;
|
||||||
|
warn_low_st: BOOL;
|
||||||
|
fail_low_st: BOOL;
|
||||||
|
no_signal_st: BOOL;
|
||||||
|
|
||||||
|
(* !!! ВНУТРЕННИЕ НЕВЫХОДНЫЕ ПЕРЕМЕННЫЕ!!! *)
|
||||||
|
TON_fail_hi: TON;
|
||||||
|
TON_warn_hi: TON;
|
||||||
|
TON_warn_low: TON;
|
||||||
|
TON_fail_low: TON;
|
||||||
|
TON_no_signal: TON;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
TON_no_signal(IN := (Input <= no_signal) OR In_no_signal, PT := time_no_signal);
|
||||||
|
IF TON_no_signal.Q THEN no_signal_st := TRUE; ELSIF (Input > no_signal + delta_no_signal) THEN no_signal_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_fail_low(IN := ((Input <= fail_low) AND NOT(no_signal_st)) OR In_fail_low, PT := time_fail_low);
|
||||||
|
IF TON_fail_low.Q THEN fail_low_st := TRUE; ELSIF (Input > fail_low + delta_fail_low) THEN fail_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_low(IN := ((Input <= warn_low) AND NOT(no_signal_st) AND NOT(TON_fail_low.Q)) OR In_warn_low, PT := time_warn_low);
|
||||||
|
IF TON_warn_low.Q THEN warn_low_st := TRUE; ELSIF (Input > warn_low + delta_warn_low) THEN warn_low_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_fail_hi(IN := ((Input >= fail_hi) AND NOT(no_signal_st)) OR In_fail_hi, PT := time_fail_hi);
|
||||||
|
IF TON_fail_hi.Q THEN fail_hi_st := TRUE; ELSIF (Input < fail_hi - delta_fail_hi) THEN fail_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
TON_warn_hi(IN := ((Input >= warn_hi) AND NOT(no_signal_st) AND NOT(TON_fail_hi.Q)) OR In_warn_hi, PT := time_warn_hi);
|
||||||
|
IF TON_warn_hi.Q THEN warn_hi_st := TRUE; ELSIF (Input < warn_hi - delta_warn_hi) THEN warn_hi_st := FALSE; END_IF;
|
||||||
|
|
||||||
|
normal_st := (NOT(no_signal_st) AND NOT(fail_low_st) AND NOT(warn_low_st) AND NOT(warn_hi_st) AND NOT(fail_hi_st));
|
||||||
|
|
||||||
|
IF no_signal_st THEN
|
||||||
|
Status := AnalogValueState.no_signal;
|
||||||
|
ELSIF fail_hi_st THEN
|
||||||
|
Status := AnalogValueState.fail_hi;
|
||||||
|
ELSIF fail_low_st THEN
|
||||||
|
Status := AnalogValueState.fail_low;
|
||||||
|
ELSIF warn_hi_st THEN
|
||||||
|
Status := AnalogValueState.warn_hi;
|
||||||
|
ELSIF warn_low_st THEN
|
||||||
|
Status := AnalogValueState.warn_low;
|
||||||
|
ELSIF normal_st THEN
|
||||||
|
Status := AnalogValueState.normal;
|
||||||
|
ELSE
|
||||||
|
Status := AnalogValueState.undefined;
|
||||||
|
END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : Status_Connect_Counter
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK Status_Connect_Counter
|
||||||
|
(* Статус связи с СВУ по счетчику*)
|
||||||
|
VAR_INPUT
|
||||||
|
Counter: WORD;
|
||||||
|
T_Error: TIME; (* время для диагностирования ошибки*)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
CounterIsChanged: BOOL;
|
||||||
|
ERROR_CONNECT: BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
CounterOld: WORD;
|
||||||
|
TON_SU: TON;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
TON_SU(IN:=(Counter = CounterOld), PT:=T_Error);
|
||||||
|
ERROR_CONNECT:=TON_SU.Q;
|
||||||
|
|
||||||
|
IF(Counter <> CounterOld) THEN
|
||||||
|
CounterIsChanged:=TRUE;
|
||||||
|
ELSE
|
||||||
|
CounterIsChanged:=FALSE;
|
||||||
|
END_IF
|
||||||
|
CounterOld:=Counter;
|
||||||
|
|
||||||
|
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : Status_SU_Connect
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK Status_SU_Connect
|
||||||
|
(* Статус связи с СВУ по серцебиению*)
|
||||||
|
VAR_INPUT
|
||||||
|
HeartBit: BOOL;
|
||||||
|
T_Pulse: TIME;
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
ERROR_CONNECT: BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
TON_SU_1: TON;
|
||||||
|
TON_SU_2: TON;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
TON_SU_1(IN:=HeartBit, PT:=T_Pulse);
|
||||||
|
TON_SU_2(IN:=NOT HeartBit, PT:=T_Pulse);
|
||||||
|
ERROR_CONNECT:=TON_SU_1.Q OR TON_SU_2.Q;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : TOF_RST
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK TOF_RST
|
||||||
|
VAR_INPUT
|
||||||
|
IN: BOOL; // Управляющий сигнал
|
||||||
|
PT: TIME; // Время задержки выключения
|
||||||
|
RST: BOOL; // Принудительный сброс
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q: BOOL; // Выход
|
||||||
|
ET: TIME; // Время работы таймера
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
_ton: TON;
|
||||||
|
prevIN: BOOL; // предыдущее состояние IN для детектирования фронта
|
||||||
|
timerRunning: BOOL; // TRUE — идёт отсчёт задержки
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
// Принудительный сброс — наивысший приоритет
|
||||||
|
IF RST THEN
|
||||||
|
Q := FALSE;
|
||||||
|
timerRunning := FALSE;
|
||||||
|
prevIN := FALSE; // после RST не ловим задний фронт
|
||||||
|
_ton(IN := FALSE, PT := PT);
|
||||||
|
ET := _ton.ET;
|
||||||
|
RETURN;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Передний фронт IN — отменяем задержку
|
||||||
|
IF IN AND NOT prevIN THEN
|
||||||
|
timerRunning := FALSE;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Задний фронт IN — запускаем задержку
|
||||||
|
IF NOT IN AND prevIN THEN
|
||||||
|
timerRunning := TRUE;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
prevIN := IN;
|
||||||
|
|
||||||
|
// Запуск/работа таймера
|
||||||
|
_ton(IN := timerRunning, PT := PT);
|
||||||
|
ET := _ton.ET;
|
||||||
|
|
||||||
|
// Логика выхода
|
||||||
|
IF IN THEN
|
||||||
|
Q := TRUE;
|
||||||
|
timerRunning := FALSE;
|
||||||
|
ELSIF timerRunning THEN
|
||||||
|
IF _ton.Q THEN
|
||||||
|
Q := FALSE;
|
||||||
|
timerRunning := FALSE;
|
||||||
|
ELSE
|
||||||
|
Q := TRUE;
|
||||||
|
END_IF
|
||||||
|
ELSE
|
||||||
|
Q := FALSE;
|
||||||
|
END_IF
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : TONOF
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK TONOF
|
||||||
|
(*
|
||||||
|
TONOF генерирует TON и TOF задержки для переменной IN
|
||||||
|
Задержка на вход T_ON, задержка на выход T_OFF
|
||||||
|
*)
|
||||||
|
VAR_INPUT
|
||||||
|
IN : BOOL;
|
||||||
|
T_ON : TIME := T#0s; (* Задержка на вход *)
|
||||||
|
T_OFF : TIME := T#0s; (* Задержка на выход *)
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q : BOOL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
X : TON;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
X(IN := IN XOR Q, PT := SEL(IN,T_OFF,T_ON));
|
||||||
|
IF X.Q THEN Q := IN; END_IF;
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Общие
|
||||||
|
Name : TP_RST
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION_BLOCK TP_RST
|
||||||
|
VAR_INPUT
|
||||||
|
IN: BOOL; // Управляющий сигнал
|
||||||
|
PT: TIME; // Длительность импульса
|
||||||
|
RST: BOOL; // Принудительный сброс
|
||||||
|
END_VAR
|
||||||
|
VAR_OUTPUT
|
||||||
|
Q: BOOL; // Выход
|
||||||
|
ET: TIME; // Прошедшее время импульса
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
_ton: TON;
|
||||||
|
prevIN: BOOL; // Предыдущее состояние IN
|
||||||
|
timerRunning: BOOL; // TRUE — идёт отсчёт импульса
|
||||||
|
END_VAR
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
// Принудительный сброс — наивысший приоритет
|
||||||
|
IF RST THEN
|
||||||
|
Q := FALSE;
|
||||||
|
timerRunning := FALSE;
|
||||||
|
prevIN := FALSE;
|
||||||
|
_ton(IN := FALSE, PT := PT);
|
||||||
|
ET := _ton.ET;
|
||||||
|
RETURN;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
// Передний фронт IN — запускаем импульс (только если не идёт уже)
|
||||||
|
IF IN AND NOT prevIN AND NOT timerRunning THEN
|
||||||
|
timerRunning := TRUE;
|
||||||
|
END_IF
|
||||||
|
|
||||||
|
prevIN := IN;
|
||||||
|
|
||||||
|
// Таймер вызывается каждый цикл
|
||||||
|
_ton(IN := timerRunning, PT := PT);
|
||||||
|
ET := _ton.ET;
|
||||||
|
|
||||||
|
// Логика выхода
|
||||||
|
IF timerRunning THEN
|
||||||
|
IF _ton.Q THEN
|
||||||
|
Q := FALSE;
|
||||||
|
timerRunning := FALSE;
|
||||||
|
ELSE
|
||||||
|
Q := TRUE;
|
||||||
|
END_IF
|
||||||
|
ELSE
|
||||||
|
Q := FALSE;
|
||||||
|
END_IF
|
||||||
|
END_FUNCTION_BLOCK
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Преобразование значений
|
||||||
|
Name : DWORD_OF_2WORD
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION DWORD_OF_2WORD : DWORD
|
||||||
|
VAR_INPUT
|
||||||
|
W1 : WORD;
|
||||||
|
W0 : WORD;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
DWORD_OF_2WORD := SHL(WORD_TO_DWORD(W1),16) OR WORD_TO_DWORD(W0);
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Преобразование значений
|
||||||
|
Name : DW_TO_REAL
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION DW_TO_REAL : REAL
|
||||||
|
VAR_INPUT
|
||||||
|
X : DWORD;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
pt : POINTER TO REAL;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
pt := ADR(X);
|
||||||
|
DW_TO_REAL := pt^;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Преобразование значений
|
||||||
|
Name : NTC_termistor_T
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION NTC_termistor_T : REAL
|
||||||
|
(* Перевод сопротивдления в температуру для NTC-type термистолров *)
|
||||||
|
VAR_INPUT
|
||||||
|
Res: REAL; (* Значение сопротивления *)
|
||||||
|
R0: REAL; (* Сопротивление при T0 *)
|
||||||
|
T0: REAL; (* T0 *)
|
||||||
|
b: REAL; (* Beta *)
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
IF (Res <= REAL#0.0) OR (R0 <= REAL#0.0) OR (b = REAL#0.0) THEN
|
||||||
|
NTC_termistor_T := REAL#0.0;
|
||||||
|
RETURN;
|
||||||
|
END_IF;
|
||||||
|
NTC_termistor_T := (1.0 / ((1.0 / (T0 + 273.15)) + (1.0 / b) * LN(Res / R0))) - 273.15;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Преобразование значений
|
||||||
|
Name : REAL_TO_DW
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION REAL_TO_DW : DWORD
|
||||||
|
VAR_INPUT
|
||||||
|
X : REAL;
|
||||||
|
END_VAR
|
||||||
|
VAR
|
||||||
|
pt : POINTER TO DWORD;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
pt := ADR(X);
|
||||||
|
REAL_TO_DW := pt^;
|
||||||
|
END_FUNCTION
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : PLC_Library
|
||||||
|
Device : -
|
||||||
|
Path : Преобразование значений
|
||||||
|
Name : WORD_OF_DWORD
|
||||||
|
Type : FUNCTION
|
||||||
|
Exported : 2026-07-31 11:16:16
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
|
||||||
|
FUNCTION WORD_OF_DWORD : WORD
|
||||||
|
VAR_INPUT
|
||||||
|
in : DWORD;
|
||||||
|
N : BYTE;
|
||||||
|
END_VAR
|
||||||
|
|
||||||
|
(*----- IMPLEMENTATION -----*)
|
||||||
|
WORD_OF_DWORD := DWORD_TO_WORD(SHR(in,SHL(n,4)));
|
||||||
|
END_FUNCTION
|
||||||
+244
-50
@@ -1,7 +1,22 @@
|
|||||||
# encoding:utf-8
|
# encoding:utf-8
|
||||||
# export_plc_src.py
|
# export_plc_src.py
|
||||||
# Экспорт POU / GVL / DUT из открытого проекта CODESYS в текстовые файлы
|
# Экспорт POU / GVL / DUT из открытого проекта CODESYS в текстовые файлы
|
||||||
# для хранения в git и работы с Claude Code.
|
# plc_src/
|
||||||
|
# ├── PLC1/
|
||||||
|
# │ ├── POU/...
|
||||||
|
# │ ├── GVL/...
|
||||||
|
# │ └── DUT/...
|
||||||
|
# ├── PLC2/
|
||||||
|
# │ ├── POU/...
|
||||||
|
# │ ├── GVL/...
|
||||||
|
# │ └── DUT/...
|
||||||
|
# └── _common/
|
||||||
|
# │ ├── POU/...
|
||||||
|
# │ ├── GVL/...
|
||||||
|
# │ └── DUT/..
|
||||||
|
#
|
||||||
|
# Методы (METHOD) и действия (ACTION) не создают отдельных файлов --
|
||||||
|
# они дописываются в конец файла того POU/FB, в котором были созданы
|
||||||
#
|
#
|
||||||
# Запуск:
|
# Запуск:
|
||||||
# 1) Внутри CODESYS: Tools -> Scripting -> Execute Script File -> выбрать этот файл
|
# 1) Внутри CODESYS: Tools -> Scripting -> Execute Script File -> выбрать этот файл
|
||||||
@@ -10,8 +25,6 @@
|
|||||||
# --Profile="CODESYS V3.5 SP17 Patch 3" --runscript="export_plc_src.py" ^
|
# --Profile="CODESYS V3.5 SP17 Patch 3" --runscript="export_plc_src.py" ^
|
||||||
# --project="D:\path\to\ТвойПроект.project"
|
# --project="D:\path\to\ТвойПроект.project"
|
||||||
#
|
#
|
||||||
# Проверено для установки: CODESYS V3.5 SP17 Patch 3 (32-bit)
|
|
||||||
#
|
|
||||||
# По умолчанию папка plc_src создаётся автоматически рядом с файлом .project.
|
# По умолчанию папка plc_src создаётся автоматически рядом с файлом .project.
|
||||||
# Если авто-определение не сработает, впиши путь вручную в MANUAL_OUTPUT_ROOT ниже.
|
# Если авто-определение не сработает, впиши путь вручную в MANUAL_OUTPUT_ROOT ниже.
|
||||||
|
|
||||||
@@ -19,9 +32,31 @@ from __future__ import print_function
|
|||||||
import os
|
import os
|
||||||
import codecs
|
import codecs
|
||||||
import re
|
import re
|
||||||
|
import datetime
|
||||||
|
|
||||||
PRAGMA_RE = re.compile(r"^\s*\{[^}]*\}\s*")
|
PRAGMA_RE = re.compile(r"^\s*\{[^}]*\}\s*")
|
||||||
|
|
||||||
|
# Единая метка времени на весь запуск экспорта (одинаковая во всех файлах).
|
||||||
|
EXPORT_TIMESTAMP = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
|
|
||||||
|
# Имена служебных узлов дерева, которые не нужно показывать в поле Path
|
||||||
|
# (сравнение без учёта регистра). Сами узлы всё равно обходятся -- пропускаются
|
||||||
|
# только их имена при формировании пути.
|
||||||
|
EXCLUDED_PATH_NAMES = set(["application", "plc logic"])
|
||||||
|
|
||||||
|
# Закрывающие ключевые слова, которые CODESYS не включает ни в textual_declaration,
|
||||||
|
# ни в textual_implementation -- их нужно дописывать вручную, чтобы файл был
|
||||||
|
# синтаксически полным ST-блоком.
|
||||||
|
END_KEYWORDS = {
|
||||||
|
"PROGRAM": "END_PROGRAM",
|
||||||
|
"FUNCTION_BLOCK": "END_FUNCTION_BLOCK",
|
||||||
|
"FUNCTION": "END_FUNCTION",
|
||||||
|
"INTERFACE": "END_INTERFACE",
|
||||||
|
"METHOD": "END_METHOD",
|
||||||
|
"PROPERTY": "END_PROPERTY",
|
||||||
|
"ACTION": "END_ACTION",
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def strip_leading_pragmas(text):
|
def strip_leading_pragmas(text):
|
||||||
"""Убирает ведущие блоки вида {attribute 'qualified_only'} перед проверкой ключевого слова."""
|
"""Убирает ведущие блоки вида {attribute 'qualified_only'} перед проверкой ключевого слова."""
|
||||||
@@ -43,8 +78,6 @@ def get_project_file_path(proj):
|
|||||||
return val
|
return val
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
# Фолбэк: вытащить путь из текстового представления объекта,
|
|
||||||
# например "Project(Project=0, stPath=C:\...\*.project)"
|
|
||||||
try:
|
try:
|
||||||
s = str(proj)
|
s = str(proj)
|
||||||
m = re.search(r"stPath=(.*?)\)", s)
|
m = re.search(r"stPath=(.*?)\)", s)
|
||||||
@@ -71,37 +104,148 @@ def get_declaration_text(obj):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_text(obj, declaration_text):
|
def has_implementation(obj):
|
||||||
"""Собирает декларацию + реализацию (если есть) в единый текст."""
|
|
||||||
text = declaration_text or ""
|
|
||||||
try:
|
try:
|
||||||
if hasattr(obj, "has_textual_implementation") and obj.has_textual_implementation:
|
return bool(getattr(obj, "has_textual_implementation", False))
|
||||||
text += "\r\n(*----- IMPLEMENTATION -----*)\r\n"
|
except Exception:
|
||||||
text += obj.textual_implementation.text
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def get_implementation_text(obj):
|
||||||
|
try:
|
||||||
|
return obj.textual_implementation.text
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
text += "(* ошибка чтения implementation: %s *)\r\n" % e
|
return "(* ошибка чтения implementation: %s *)\r\n" % e
|
||||||
return text
|
|
||||||
|
|
||||||
|
|
||||||
def classify(declaration_text):
|
def classify(obj, declaration_text):
|
||||||
"""Определяет тип объекта по первому ключевому слову декларации."""
|
"""Определяет тип объекта.
|
||||||
if not declaration_text:
|
Если есть декларация -- смотрим по ключевому слову (POU/GVL/DUT/METHOD/ACTION).
|
||||||
|
Если декларации нет, но есть implementation -- это ACTION (у него нет декларации в API)."""
|
||||||
|
if declaration_text:
|
||||||
|
stripped = strip_leading_pragmas(declaration_text.strip()).strip().upper()
|
||||||
|
if stripped.startswith(("PROGRAM", "FUNCTION_BLOCK", "FUNCTION", "INTERFACE")):
|
||||||
|
return "pou"
|
||||||
|
if stripped.startswith(("METHOD", "PROPERTY")):
|
||||||
|
return "method"
|
||||||
|
if stripped.startswith("VAR_GLOBAL"):
|
||||||
|
return "gvl"
|
||||||
|
if stripped.startswith("TYPE"):
|
||||||
|
return "dut"
|
||||||
return None
|
return None
|
||||||
stripped = strip_leading_pragmas(declaration_text.strip()).strip().upper()
|
|
||||||
if stripped.startswith(("PROGRAM", "FUNCTION_BLOCK", "FUNCTION", "INTERFACE", "METHOD", "ACTION", "PROPERTY")):
|
if has_implementation(obj):
|
||||||
return "pou"
|
return "action"
|
||||||
if stripped.startswith("VAR_GLOBAL"):
|
|
||||||
return "gvl"
|
|
||||||
if stripped.startswith("TYPE"):
|
|
||||||
return "dut"
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def write_file(folder, name, text):
|
def get_type_label(kind, declaration_text):
|
||||||
path = os.path.join(folder, name + ".st")
|
"""Возвращает читаемое название типа объекта, например 'FUNCTION_BLOCK', 'METHOD', 'ACTION'."""
|
||||||
|
if kind == "action":
|
||||||
|
return "ACTION"
|
||||||
|
if declaration_text:
|
||||||
|
stripped = strip_leading_pragmas(declaration_text.strip()).strip().upper()
|
||||||
|
for kw in ("FUNCTION_BLOCK", "PROGRAM", "FUNCTION", "INTERFACE", "METHOD", "PROPERTY"):
|
||||||
|
if stripped.startswith(kw):
|
||||||
|
return kw
|
||||||
|
if stripped.startswith("VAR_GLOBAL"):
|
||||||
|
return "GVL"
|
||||||
|
if stripped.startswith("TYPE"):
|
||||||
|
return "DUT"
|
||||||
|
return kind.upper() if kind else "UNKNOWN"
|
||||||
|
|
||||||
|
|
||||||
|
def close_block(text, type_label):
|
||||||
|
"""Дописывает END_PROGRAM / END_FUNCTION_BLOCK / END_METHOD / END_ACTION и т.п.,
|
||||||
|
если это применимо к данному типу объекта."""
|
||||||
|
kw = END_KEYWORDS.get(type_label)
|
||||||
|
if not kw:
|
||||||
|
return text
|
||||||
|
if not text.endswith("\n"):
|
||||||
|
text += "\r\n"
|
||||||
|
text += kw + "\r\n"
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def build_pou_text(obj, declaration_text, type_label):
|
||||||
|
"""Декларация + implementation (если есть) + закрывающее END_*."""
|
||||||
|
text = declaration_text or ""
|
||||||
|
if has_implementation(obj):
|
||||||
|
text += "\r\n(*----- IMPLEMENTATION -----*)\r\n"
|
||||||
|
text += get_implementation_text(obj)
|
||||||
|
text = close_block(text, type_label)
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def build_action_text(obj, name):
|
||||||
|
"""У Action нет declaration в API -- собираем заголовок 'ACTION Имя :' вручную,
|
||||||
|
затем тело и закрывающее END_ACTION."""
|
||||||
|
text = "ACTION %s :\r\n" % name
|
||||||
|
text += get_implementation_text(obj)
|
||||||
|
text = close_block(text, "ACTION")
|
||||||
|
return text
|
||||||
|
|
||||||
|
|
||||||
|
def build_header(project_name, device_name, path_parts, obj_name, type_label):
|
||||||
|
"""Заголовок-паспорт файла:
|
||||||
|
|
||||||
|
(*
|
||||||
|
===============================================================================
|
||||||
|
Project : MyProject
|
||||||
|
Device : PLC
|
||||||
|
Path : Application/Logic/Motion
|
||||||
|
Name : FB_Axis
|
||||||
|
Type : FUNCTION_BLOCK
|
||||||
|
Exported : 2026-07-30 14:32:18
|
||||||
|
===============================================================================
|
||||||
|
*)
|
||||||
|
"""
|
||||||
|
rel_path = "/".join(path_parts) if path_parts else "-"
|
||||||
|
sep = "=" * 79
|
||||||
|
lines = [
|
||||||
|
"(*",
|
||||||
|
sep,
|
||||||
|
" Project : %s" % project_name,
|
||||||
|
" Device : %s" % device_name,
|
||||||
|
" Path : %s" % rel_path,
|
||||||
|
" Name : %s" % obj_name,
|
||||||
|
" Type : %s" % type_label,
|
||||||
|
" Exported : %s" % EXPORT_TIMESTAMP,
|
||||||
|
sep,
|
||||||
|
"*)",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
]
|
||||||
|
return "\r\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
def write_new_file(folder, path_parts, obj_name, text, project_name, device_name, type_label):
|
||||||
|
"""path_parts -- путь БЕЗ имени самого объекта (папки родителей).
|
||||||
|
Создаёт вложенные папки и записывает файл с заголовком-паспортом."""
|
||||||
|
sub_parts = [sanitize_folder_name(p) for p in path_parts]
|
||||||
|
sub_folder = os.path.join(folder, *sub_parts) if sub_parts else folder
|
||||||
|
if not os.path.exists(sub_folder):
|
||||||
|
os.makedirs(sub_folder)
|
||||||
|
file_name = sanitize_folder_name(obj_name)
|
||||||
|
path = os.path.join(sub_folder, file_name + ".st")
|
||||||
with codecs.open(path, "w", encoding="utf-8") as f:
|
with codecs.open(path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(build_header(project_name, device_name, path_parts, obj_name, type_label))
|
||||||
f.write(text)
|
f.write(text)
|
||||||
print(" -> %s" % path)
|
print(" -> %s" % path)
|
||||||
|
return path
|
||||||
|
|
||||||
|
|
||||||
|
def append_to_file(path, path_parts, obj_name, text, project_name, device_name, type_label):
|
||||||
|
"""path_parts здесь включает имя родительского POU (т.к. метод/action лежит "внутри" него)."""
|
||||||
|
if not path or not os.path.exists(path):
|
||||||
|
return False
|
||||||
|
with codecs.open(path, "a", encoding="utf-8") as f:
|
||||||
|
f.write("\r\n")
|
||||||
|
f.write(build_header(project_name, device_name, path_parts, obj_name, type_label))
|
||||||
|
f.write(text)
|
||||||
|
print(" -> дописано в %s (%s: %s)" % (path, type_label, obj_name))
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def sanitize_folder_name(name):
|
def sanitize_folder_name(name):
|
||||||
@@ -132,34 +276,78 @@ def is_device_node(obj):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def walk(node, dirs, exported):
|
def walk(node, dirs, exported, project_name, device_name, current_path=None, parent_pou_path=None):
|
||||||
|
"""current_path -- список имён родителей от корня устройства (без учёта device_name самого),
|
||||||
|
накапливается по мере рекурсивного спуска по реальному дереву проекта -- поэтому Path
|
||||||
|
строится из фактической структуры, а не из строки, которую отдаёт CODESYS API."""
|
||||||
|
if current_path is None:
|
||||||
|
current_path = []
|
||||||
|
|
||||||
for child in node.get_children(False):
|
for child in node.get_children(False):
|
||||||
name = safe_name(child)
|
name = safe_name(child)
|
||||||
decl = get_declaration_text(child)
|
decl = get_declaration_text(child)
|
||||||
kind = classify(decl)
|
kind = classify(child, decl)
|
||||||
|
type_label = get_type_label(kind, decl)
|
||||||
|
|
||||||
|
next_parent_path = parent_pou_path
|
||||||
|
if name.strip().lower() in EXCLUDED_PATH_NAMES:
|
||||||
|
child_path = current_path # не добавляем служебное имя в путь
|
||||||
|
else:
|
||||||
|
child_path = current_path + [name] # путь для рекурсии в детей ЭТОГО child'а
|
||||||
|
|
||||||
if kind == "pou":
|
if kind == "pou":
|
||||||
print("POU: %s" % name)
|
print("POU: %s/%s" % ("/".join(current_path), name))
|
||||||
write_file(dirs["pou"], name, get_text(child, decl))
|
text = build_pou_text(child, decl, type_label)
|
||||||
|
path = write_new_file(dirs["pou"], current_path, name, text,
|
||||||
|
project_name, device_name, type_label)
|
||||||
exported["pou"] += 1
|
exported["pou"] += 1
|
||||||
|
next_parent_path = path
|
||||||
|
|
||||||
|
elif kind == "method":
|
||||||
|
print("METHOD: %s/%s" % ("/".join(current_path), name))
|
||||||
|
text = build_pou_text(child, decl, type_label)
|
||||||
|
if parent_pou_path and append_to_file(parent_pou_path, current_path, name, text,
|
||||||
|
project_name, device_name, type_label):
|
||||||
|
exported["method"] += 1
|
||||||
|
else:
|
||||||
|
write_new_file(dirs["pou"], current_path, name, text,
|
||||||
|
project_name, device_name, type_label)
|
||||||
|
exported["method"] += 1
|
||||||
|
|
||||||
|
elif kind == "action":
|
||||||
|
print("ACTION: %s/%s" % ("/".join(current_path), name))
|
||||||
|
text = build_action_text(child, name)
|
||||||
|
if parent_pou_path and append_to_file(parent_pou_path, current_path, name, text,
|
||||||
|
project_name, device_name, type_label):
|
||||||
|
exported["action"] += 1
|
||||||
|
else:
|
||||||
|
write_new_file(dirs["pou"], current_path, name, text,
|
||||||
|
project_name, device_name, type_label)
|
||||||
|
exported["action"] += 1
|
||||||
|
|
||||||
elif kind == "gvl":
|
elif kind == "gvl":
|
||||||
print("GVL: %s" % name)
|
print("GVL: %s/%s" % ("/".join(current_path), name))
|
||||||
write_file(dirs["gvl"], name, get_text(child, decl))
|
write_new_file(dirs["gvl"], current_path, name, decl or "",
|
||||||
|
project_name, device_name, type_label)
|
||||||
exported["gvl"] += 1
|
exported["gvl"] += 1
|
||||||
|
|
||||||
elif kind == "dut":
|
elif kind == "dut":
|
||||||
print("DUT: %s" % name)
|
print("DUT: %s/%s" % ("/".join(current_path), name))
|
||||||
write_file(dirs["dut"], name, get_text(child, decl))
|
write_new_file(dirs["dut"], current_path, name, decl or "",
|
||||||
|
project_name, device_name, type_label)
|
||||||
exported["dut"] += 1
|
exported["dut"] += 1
|
||||||
|
|
||||||
else:
|
else:
|
||||||
exported["skipped"] += 1
|
exported["skipped"] += 1
|
||||||
|
|
||||||
# рекурсивно обходим детей (для FB с методами, папок и т.д.)
|
# рекурсивно обходим детей (методы/actions FB, вложенные папки и т.д.),
|
||||||
walk(child, dirs, exported)
|
# передавая накопленный путь и (если только что создан POU) новый parent_pou_path
|
||||||
|
walk(child, dirs, exported, project_name, device_name, child_path, next_parent_path)
|
||||||
|
|
||||||
|
|
||||||
# ==== НАСТРОЙКА ====
|
# ==== НАСТРОЙКА ====
|
||||||
# Оставь пустой строкой "" чтобы папка plc_src создавалась автоматически
|
# Оставить пустой строкой "" чтобы папка plc_src создавалась автоматически
|
||||||
# рядом с файлом .project. Укажи путь вручную только если авто-определение
|
# рядом с файлом .project. Указать путь вручную только если авто-определение
|
||||||
# не сработает (см. вывод скрипта при запуске).
|
# не сработает (см. вывод скрипта при запуске).
|
||||||
MANUAL_OUTPUT_ROOT = r""
|
MANUAL_OUTPUT_ROOT = r""
|
||||||
# =====================================================
|
# =====================================================
|
||||||
@@ -169,11 +357,17 @@ proj = projects.primary
|
|||||||
if proj is None:
|
if proj is None:
|
||||||
print("ОШИБКА: нет открытого проекта. Открой .project перед запуском скрипта.")
|
print("ОШИБКА: нет открытого проекта. Открой .project перед запуском скрипта.")
|
||||||
else:
|
else:
|
||||||
|
project_file = get_project_file_path(proj)
|
||||||
|
|
||||||
|
if project_file:
|
||||||
|
project_name = os.path.splitext(os.path.basename(project_file))[0]
|
||||||
|
else:
|
||||||
|
project_name = "UnknownProject"
|
||||||
|
|
||||||
if MANUAL_OUTPUT_ROOT:
|
if MANUAL_OUTPUT_ROOT:
|
||||||
OUTPUT_ROOT = MANUAL_OUTPUT_ROOT
|
OUTPUT_ROOT = MANUAL_OUTPUT_ROOT
|
||||||
print("Папка вывода задана вручную: %s" % OUTPUT_ROOT)
|
print("Папка вывода задана вручную: %s" % OUTPUT_ROOT)
|
||||||
else:
|
else:
|
||||||
project_file = get_project_file_path(proj)
|
|
||||||
if project_file:
|
if project_file:
|
||||||
project_dir = os.path.dirname(project_file)
|
project_dir = os.path.dirname(project_file)
|
||||||
OUTPUT_ROOT = os.path.join(project_dir, "plc_src")
|
OUTPUT_ROOT = os.path.join(project_dir, "plc_src")
|
||||||
@@ -185,31 +379,31 @@ else:
|
|||||||
print("Задай путь вручную в переменной MANUAL_OUTPUT_ROOT и запусти снова.")
|
print("Задай путь вручную в переменной MANUAL_OUTPUT_ROOT и запусти снова.")
|
||||||
|
|
||||||
if OUTPUT_ROOT:
|
if OUTPUT_ROOT:
|
||||||
exported = {"pou": 0, "gvl": 0, "dut": 0, "skipped": 0}
|
exported = {"pou": 0, "gvl": 0, "dut": 0, "method": 0, "action": 0, "skipped": 0}
|
||||||
|
|
||||||
print("--- Экспорт в %s ---" % OUTPUT_ROOT)
|
print("--- Экспорт проекта '%s' в %s ---" % (project_name, OUTPUT_ROOT))
|
||||||
|
|
||||||
top_children = proj.get_children(False)
|
top_children = proj.get_children(False)
|
||||||
device_nodes = [c for c in top_children if is_device_node(c)]
|
device_nodes = [c for c in top_children if is_device_node(c)]
|
||||||
|
|
||||||
if device_nodes:
|
if device_nodes:
|
||||||
for device in device_nodes:
|
for device in device_nodes:
|
||||||
dev_name = sanitize_folder_name(safe_name(device))
|
device_name = safe_name(device)
|
||||||
print("=== Устройство: %s ===" % dev_name)
|
dev_folder = sanitize_folder_name(device_name)
|
||||||
dev_dirs = make_dirs(os.path.join(OUTPUT_ROOT, dev_name))
|
print("=== Устройство: %s ===" % device_name)
|
||||||
walk(device, dev_dirs, exported)
|
dev_dirs = make_dirs(os.path.join(OUTPUT_ROOT, dev_folder))
|
||||||
|
walk(device, dev_dirs, exported, project_name, device_name)
|
||||||
|
|
||||||
# на случай текстовых объектов вне дерева устройств (редко, но на всякий случай)
|
|
||||||
other_dirs = make_dirs(os.path.join(OUTPUT_ROOT, "_common"))
|
other_dirs = make_dirs(os.path.join(OUTPUT_ROOT, "_common"))
|
||||||
for child in top_children:
|
for child in top_children:
|
||||||
if not is_device_node(child):
|
if not is_device_node(child):
|
||||||
walk(child, other_dirs, exported)
|
walk(child, other_dirs, exported, project_name, "-")
|
||||||
else:
|
else:
|
||||||
# устройств не нашлось (или is_device не сработал) -- работаем как раньше, без разбивки
|
|
||||||
print("Устройства верхнего уровня не найдены, экспорт без разбивки по папкам.")
|
print("Устройства верхнего уровня не найдены, экспорт без разбивки по папкам.")
|
||||||
dirs = make_dirs(OUTPUT_ROOT)
|
dirs = make_dirs(OUTPUT_ROOT)
|
||||||
walk(proj, dirs, exported)
|
walk(proj, dirs, exported, project_name, "-")
|
||||||
|
|
||||||
print("--- Готово: POU=%d, GVL=%d, DUT=%d, пропущено=%d ---" % (
|
print("--- Готово: POU=%d, METHOD=%d, ACTION=%d, GVL=%d, DUT=%d, пропущено=%d ---" % (
|
||||||
exported["pou"], exported["gvl"], exported["dut"], exported["skipped"]
|
exported["pou"], exported["method"], exported["action"],
|
||||||
|
exported["gvl"], exported["dut"], exported["skipped"]
|
||||||
))
|
))
|
||||||
|
|||||||
Reference in New Issue
Block a user