PDA

Просмотр полной версии : Время цикла ПР205 и ПР225



igorlisin
03.02.2026, 10:52
Здравствуйте. Хотел узнать, как рассчитывается время цикла на ПР205 и ПР225. По личным наблюдениям время цикла фиксируется как максимальное время цикла за все время работы интеллектуального реле после перезагрузки. Например, в моей программе на первом цикле реализован алгоритм инициализации, который занимает достаточно продолжительное время (55 мс). Все последующие циклы алгоритм инициализации не работает, соответственно время «рабочих» циклов должно быть меньше, а оно такое же (55мс). Если это так, то можно ли как-то убрать фиксацию времени цикла по максимальному значению, хотя бы опционально в настройках среды?

kondor3000
03.02.2026, 11:43
Здравствуйте. Хотел узнать, как рассчитывается время цикла на ПР205 и ПР225. По личным наблюдениям время цикла фиксируется как максимальное время цикла за все время работы интеллектуального реле после перезагрузки. Например, в моей программе на первом цикле реализован алгоритм инициализации, который занимает достаточно продолжительное время (55 мс). Все последующие циклы алгоритм инициализации не работает, соответственно время «рабочих» циклов должно быть меньше, а оно такое же (55мс). Если это так, то можно ли как-то убрать фиксацию времени цикла по максимальному значению, хотя бы опционально в настройках среды?

Время цикла зависит от загруженности проекта, а не от инициализации.
Например можно поставить 100 таймеров, а можно один, без потери функционала. Зависит от программиста.
Более конкретно, надо обсуждать на примере, выкладывайте проект.

FPavel
03.02.2026, 12:22
Здравствуйте. Хотел узнать, как рассчитывается время цикла на ПР205 и ПР225. По личным наблюдениям время цикла фиксируется как максимальное время цикла за все время работы интеллектуального реле после перезагрузки. Например, в моей программе на первом цикле реализован алгоритм инициализации, который занимает достаточно продолжительное время (55 мс). Все последующие циклы алгоритм инициализации не работает, соответственно время «рабочих» циклов должно быть меньше, а оно такое же (55мс). Если это так, то можно ли как-то убрать фиксацию времени цикла по максимальному значению, хотя бы опционально в настройках среды?
Не совсем понятно, как может инициализация так долго выполняться.

Если для признака инициализации в Вашей программе применён таймер - пусть он и взводит переменную bInitDone:bool, которая будет являться разрешением работы другим частям программы через вход bEnable.

Наверное, есть смысл рассказать, почему машинный цикл инициализации столь длителен.

FPavel
03.02.2026, 12:32
Недавно делал проект на ПР205 с длительностью машинного цикла 25 мс.
Характеристика:
- ПРМ - 2 шт
- AI - 7 шт
- DI - 10 шт
- AO - 0 шт
- DO - 7 шт
- переменные сетевые Master (обмен с 2 ПЧВ RS-485) - 2*7=14
- переменные сетевые Slave (обмен с панелью RS-485) - 130 шт в 180 регистрах
- экраны не используют графики - самый нагруженный компонент - только ввод/вывод текста и фигур

Думаю, что 25 мс - за счёт большого количества сетевых переменных, т.к. ранее для подобных проектов доходило всего до 15 мс.

igorlisin
03.02.2026, 17:43
Недавно делал проект на ПР205 с длительностью машинного цикла 25 мс.
Характеристика:
- ПРМ - 2 шт
- AI - 7 шт
- DI - 10 шт
- AO - 0 шт
- DO - 7 шт
- переменные сетевые Master (обмен с 2 ПЧВ RS-485) - 2*7=14
- переменные сетевые Slave (обмен с панелью RS-485) - 130 шт в 180 регистрах
- экраны не используют графики - самый нагруженный компонент - только ввод/вывод текста и фигур

Думаю, что 25 мс - за счёт большого количества сетевых переменных, т.к. ранее для подобных проектов доходило всего до 15 мс.

function_block FB_CycleTimeTest
var_input
i_x_Input : bool;
end_var

var_output
o_x_Init : bool := false;
o_x_Not_Init : bool := true;
o_udi_Value : udint := 0;
o_udi_Counter : udint := 0;

end_var

o_x_Not_Init := not o_x_Init;

if (o_x_Not_Init) then
for o_udi_Counter := 0 to 1800 do
o_udi_Value := o_udi_Value + 1;
end_for

// o_x_Init := true;
else
o_udi_Value:= 10000;
end_if;
end_function_block

54мс

igorlisin
03.02.2026, 17:47
Время цикла зависит от загруженности проекта, а не от инициализации.
Например можно поставить 100 таймеров, а можно один, без потери функционала. Зависит от программиста.
Более конкретно, надо обсуждать на примере, выкладывайте проект.

После Ваших замечаний перепроверил код. Похоже, что все-таки основной код достаточно сложный для данного реле (т.е. дело не в инициализации, а в основном коде). Буду менять реле на ПЛК. Оптимизировать уже нечего. Проект выложить не могу

FPavel
03.02.2026, 18:04
Не совсем понятен замысел кода

function_block FB_CycleTimeTest
var_input
i_x_Input : bool;
end_var

var_output
o_x_Init : bool := false;
o_x_Not_Init : bool := true;
o_udi_Value : udint := 0;
o_udi_Counter : udint := 0;

end_var

o_x_Not_Init := not o_x_Init;

if (o_x_Not_Init) then
for o_udi_Counter := 0 to 1800 do
o_udi_Value := o_udi_Value + 1;
end_for

// o_x_Init := true;
else
o_udi_Value:= 10000;
end_if;
end_function_block

При каждом вызове этого ФБ инвертируется o_x_Not_Init и цикл выполняется каждый второй вызов.

Основное отличие ПЛК (ПР) от компьютера - сознательный отказ от циклов - всех циклов.
Поэтому желательно применять только короткие циклы или пользоваться тем, что программа не теряет контекст между машинными циклами, т.е. цикл будет выполняться не единым блоком, а с цикличностью программы.

А так, лучше скажите, какую задачу решали столь неприлично длинным (в 1800 итераций) циклом?

igorlisin
03.02.2026, 18:51
При каждом вызове этого ФБ инвертируется o_x_Not_Init и цикл выполняется каждый второй вызов.

Основное отличие ПЛК (ПР) от компьютера - сознательный отказ от циклов - всех циклов.
Поэтому желательно применять только короткие циклы или пользоваться тем, что программа не теряет контекст между машинными циклами, т.е. цикл будет выполняться не единым блоком, а с цикличностью программы.

А так, лучше скажите, какую задачу решали столь неприлично длинным (в 1800 итераций) циклом?

Это просто пример. Хотел показать, что нагрузить ПР очень несложно.
Уже разобрался в основном коде программы, оказалось, что слишком много условных переходов и вызовов ФБ. Реле будем менять на ПЛК.
Кстати никогда не было проблем с циклами на ПЛК. И o_x_Not_Init не инвертируется, потому что o_x_Init := true закомментировано

kondor3000
03.02.2026, 19:21
После Ваших замечаний перепроверил код. Похоже, что все-таки основной код достаточно сложный для данного реле (т.е. дело не в инициализации, а в основном коде). Буду менять реле на ПЛК. Оптимизировать уже нечего. Проект выложить не могу

Тогда проверьте пример, вычисление ArcTg (арк тангенса), в функции 1000 итераций, а у меня в проекте ещё и ArcSin и ArcCos имеется и везде по 1000 итераций. И это только 1 строка проекта, да у меня по вашему цикл ПР просто вечность займёт.

FUNCTION Arctg : REAL; // Автор
VAR_INPUT
x: REAL; (* Аргумент: x ∈ ℝ *)
END_VAR

VAR
eps: REAL := 1E-6; (* Точность вычисления *)
maxIter: UDINT := 1000; (* Макс. число итераций, тип UDINT *)
x_abs: REAL; (* |x| для проверки области сходимости *)
arg: REAL; (* Рабочий аргумент: x или 1/x *)
n: UDINT := 0; (* Номер итерации: n = 0, 1, 2, ... *)
term: REAL; (* Текущий член ряда *)
sum: REAL := 0.0; (* Накопленная сумма ряда *)
pi: REAL := 3.14159265358979323846; (* Число π *)
correction: REAL := 0.0; (* Поправка для |x| > 1 *)
END_VAR

(* 1. Проверка области сходимости *)
x_abs := ABS(x);

IF x_abs > 1.0 THEN
(* Для |x| > 1: используем тождество *)
arg := 1.0 / x;
IF x > 0.0 THEN
correction := pi / 2.0;
ELSIF x < 0.0 THEN
correction := - pi / 2.0;
ELSE correction := 0;
END_IF
ELSE
(* Для |x| ≤ 1: вычисляем напрямую *)
arg := - x;
END_IF
(* 2. Вычисление ряда Тейлора *)
WHILE n < maxIter DO
(* Вычисляем текущий член ряда: (-1)^n * arg^(2n+1) / (2n+1) *)
term:= POW(-1.0, udint_to_real(n)) * POW(arg, udint_to_real(2*n + 1)) / udint_to_real(2*n + 1);

sum := sum + term;
(* Проверяем достижение точности *)
IF ABS(term) < eps THEN
EXIT;
END_IF

(* Переход к следующей итерации *)
n := n + 1;
END_WHILE

(* 3. Формируем итоговый результат *)
Arctg := correction - sum;
end_function

А то может и ссылку на все функции удалить надо https://owen.ru/forum/showthread.php?t=35489&p=397789&viewfull=1#post397789

FPavel
03.02.2026, 19:59
Не делайте так больше :D
При виде этого где-то плачет котик и грустит розовый пони ;)

term:= POW(-1.0, udint_to_real(n)) * POW(arg, udint_to_real(2*n + 1)) / udint_to_real(2*n + 1);

Это заменяется на менее затратное по времени и вычислениям, нужно только правильно инициировать переменные

arg := -arg*arg;
n := n+2;
term := term+arg / udint_to_real(n)

Пример в последнем сообщении темы
https://www.cyberforum.ru/pascalabc-net/thread3024183.html
и здесь
https://www.cyberforum.ru/pascalabc/thread2879815.html
и здесь
https://www.cyberforum.ru/turbo-pascal/thread2757806.html

kondor3000
03.02.2026, 21:01
Не делайте так больше :D
При виде этого где-то плачет котик и грустит розовый пони ;)

term:= POW(-1.0, udint_to_real(n)) * POW(arg, udint_to_real(2*n + 1)) / udint_to_real(2*n + 1);
Это заменяется на менее затратное по времени и вычислениям, нужно только правильно инициировать переменные

arg := -arg*arg;
n := n+2;
term := term+arg / udint_to_real(n)

Покажите мне, где я просил код исправить? Тем более я взял его на форуме как есть, а проверить успел только в симуляции.
https://owen.ru/forum/showthread.php?t=35489&p=475284&viewfull=1#post475284
Я просил ТС проверить код на время цикла, а вы в своём репертуаре, пофиг что пишут, буду гнуть свою линию.

Как и сравнивать Лоджик с Codesys3.5, просто мания какая то.

FPavel
03.02.2026, 21:46
Покажите мне, где я просил код исправить? Тем более я взял его на форуме как есть, а проверить успел только в симуляции.
https://owen.ru/forum/showthread.php?t=35489&p=475284&viewfull=1#post475284
Я просил ТС проверить код на время цикла, а вы в своём репертуаре, пофиг что пишут, буду гнуть свою линию.
Прошу прошения. Больше не повторится.

Как и сравнивать Лоджик с Codesys3.5, просто мания какая то.
Не с CODESYS, а со стандартом (и ГОСТ и IEC) на язык ST.
Прошу прощения. Больше не повторится.

igorlisin
03.02.2026, 22:48
1. dat_x_Enable= false и dat_x_Enable_For= false - время цикла - 1мс
2. dat_x_Enable=true и dat_x_Enable_For= true - время цикла - 14мс
3. dat_x_Enable=false и dat_x_Enable_For= false - время цикла все еще - 14 мс
87865
Я вот что хотел понять

igorlisin
03.02.2026, 22:58
Тогда проверьте пример, вычисление ArcTg (арк тангенса), в функции 1000 итераций, а у меня в проекте ещё и ArcSin и ArcCos имеется и везде по 1000 итераций. И это только 1 строка проекта, да у меня по вашему цикл ПР просто вечность займёт.

FUNCTION Arctg : REAL; // Автор
VAR_INPUT
x: REAL; (* Аргумент: x ∈ ℝ *)
END_VAR

VAR
eps: REAL := 1E-6; (* Точность вычисления *)
maxIter: UDINT := 1000; (* Макс. число итераций, тип UDINT *)
x_abs: REAL; (* |x| для проверки области сходимости *)
arg: REAL; (* Рабочий аргумент: x или 1/x *)
n: UDINT := 0; (* Номер итерации: n = 0, 1, 2, ... *)
term: REAL; (* Текущий член ряда *)
sum: REAL := 0.0; (* Накопленная сумма ряда *)
pi: REAL := 3.14159265358979323846; (* Число π *)
correction: REAL := 0.0; (* Поправка для |x| > 1 *)
END_VAR

(* 1. Проверка области сходимости *)
x_abs := ABS(x);

IF x_abs > 1.0 THEN
(* Для |x| > 1: используем тождество *)
arg := 1.0 / x;
IF x > 0.0 THEN
correction := pi / 2.0;
ELSIF x < 0.0 THEN
correction := - pi / 2.0;
ELSE correction := 0;
END_IF
ELSE
(* Для |x| ≤ 1: вычисляем напрямую *)
arg := - x;
END_IF
(* 2. Вычисление ряда Тейлора *)
WHILE n < maxIter DO
(* Вычисляем текущий член ряда: (-1)^n * arg^(2n+1) / (2n+1) *)
term:= POW(-1.0, udint_to_real(n)) * POW(arg, udint_to_real(2*n + 1)) / udint_to_real(2*n + 1);

sum := sum + term;
(* Проверяем достижение точности *)
IF ABS(term) < eps THEN
EXIT;
END_IF

(* Переход к следующей итерации *)
n := n + 1;
END_WHILE

(* 3. Формируем итоговый результат *)
Arctg := correction - sum;
end_function

А то может и ссылку на все функции удалить надо https://owen.ru/forum/showthread.php?t=35489&p=397789&viewfull=1#post397789

На ПР205 при x=1.0 время цикла 72 мс

kondor3000
03.02.2026, 23:12
На ПР205 при x=1.0 время цикла 72 мс

Офигеть, значит эти функции нельзя использовать, надо будет проверить на другой ПР.