г. Москва, ул. Азовская, 14
+7 (495) 310-97-15
Пн-пт: с 9.00 до 18.00
Заказать звонок
Обратный звонок
Ваше имя*
Ваш телефон*
Ваш Email*
Перезвоните мне
Линейно-нарастающая функция

Линейно-нарастающая функция

Линейно-нарастающие процессы чаще всего используются там, где есть задачи термостатирования. Когда температуру печи или любого другого устройства нельзя по технологии быстро нагревать или остужать. Использовал такие функции в работе тепличных комплексов, при сушке и обжиге кирпича, при закалке изделий из металла, системах дозаривания фруктов. Мы управляем не самой переменной объекта, а работаем с устанавливаем значением регулятора, который с помощью тенов, газа или других способов управления регулирует температуру объекта.
График температуры
В данной статье поделюсь способом программирования функции RAMP для линейно-инкрементированных технологических процессов. Когда нужно повышать или понижать установленное значение от начального значения до конечного за заданный интервал времени или с заданной скоростью, например 2С в час.
Тут важно отметить, что для корректной работы данной функции нам потребуется переменная, связанная с системным временем контроллера. Переменная постоянно меняется в коде данного блока. Сам процесс запуска основан на запоминании начального времени и расчета времени, до которого функция будет следовать.
Данный программный код взят из программы написанной для Codesys 2.3, но он с небольшими доработками будет работать и в других системах, где реализован в соответствии со стандартом язык ST(Structured Text).
Начинается блок с объявления. Обязательно комментируйте свой код. Это уменьшит защиту Вашего решения, но увеличит понятность и читабельность.
Линейно-временная функция RAMP
FUNCTION_BLOCK TE_CALC_SP
VAR_INPUT
    TE_SP_1:REAL;(*Значение с которого мы начали стартовать*)
    TE_SP_2:REAL;(*Значение к которому мы идем*)
    SPEED:REAL;(*Скорость с какой мы должны достичь установленного значения*)
END_VAR
VAR_IN_OUT
START:BOOL;
END_VAR
VAR_OUTPUT
    OUT:REAL; (*Выходная переменная, которая привязывается к уставке *)
    State:INT; (*Номер шага, на котором мы находимся*)
    Complite:BOOL;(*Выставляем флаг, что рамп закончил*)
    START_TIME:TIME;(*Время, когда ожидается завершение подсчета*)
    FINISH_TIME:TIME;(*Время, когда ожидается завершение подсчета*)
END_VAR

VAR
TIME_MAIN:TIME;(*Общее время прироста рамп-функции*)
First:REAL;(*Начальное значение интервала*)
Second:REAL;(*Конечное значение интервала*)
GRADUS:REAL;(*Считаем разницу в градусах*)
TON2:TON;(*Таймер от зависания в стадии перехода через 0*)
Cur_Timei:DWORD;(*Для расчета перехода через 00:00:00*)
AM:REAL;(*Разница между уставкой и переменной процесса*)
OS:REAL;(*Значение переменной процесса в начале функции*)
Err:REAL;(*Уменьшающаяся ошибка*)
tx:TIME;(*Текущее время ПЛК*)
tx1:TIME;(*Запоминаем время ПЛК в начале счета*)
txr_diff:REAL;(*Нарастающее время в формате REAL*)
fr:REAL;(*Расчитанный коэффициент приращения, угол наклона*)
R_TRIG:R_TRIG;(*Ловим переход, окончание RAMP*)
END_VAR

Теперь немного о коде этого функционального блока. Код выполнен на операторе CASE, что удобно для реализации конечного автомата. Это когда в каждый конкретный момент времени выполняется какая-то часть программного кода, причем весь остальной программный код находится в состоянии ожидания. Возможно делать различные гибкие комбинации подобно языку SFC. Управляется переход с шага на шаг при помощи целочисленной переменной State

CASE State OF
0:(*На этом шаге мы стоим и ждем, инициализируем переменные*)
OUT:=TE_SP_1; (*Присваиваем начальное значение выходу*)
START_TIME:=T#0m; (*Обнуляем начальное время*)
FINISH_TIME:=T#0m; (*Обнуляем конечное время*)
IF START THEN  State:=1; END_IF; (*Если нажата кнопка старт, то переходим на следующий уровень*)

1:(*Определяем время начала работы функции, высчитываем время и переходим дальше*)
Complite:=FALSE;(*Сбрасываем признак окончания*)
GRADUS:=ABS(TE_SP_2 - TE_SP_1);(*Посчитали сколько градусов разница*)
First:=TE_SP_1;(* Запомнили первое число*)
Second:=TE_SP_2;(*Запомнили второе число*)
txr_diff:=1;(*Присваиваем 1 переменной, которая отвечает за угол наклона функции*)
TIME_MAIN:=(REAL_TO_TIME(GRADUS/SPEED)*1000*60*60);(*Вычисляем, за сколько времени приращать функцию*)
fr:=txr_diff/DINT_TO_REAL(TIME_TO_DINT(TIME_MAIN));(*Время за которое должна нарастать или убывать функция. Высчитывает коэффициент приращения/убавления*)
tx:=T#0s;(*Обнулили инкремент по времени*)
Err:=0.0;(*Обнулили инкремент по рассогласованию*)
AM:=Second - First;(*Посчитали расстояние в градусах между двумя точками*)
OS:=First; (*Запомнили откуда мы идем*)
tx1:=PLC_TIME; (*Запоминаем время до начала работы рамп*)
START_TIME:=PLC_TIME;
FINISH_TIME:=PLC_TIME+TIME_MAIN;
State:=2;

2:(*Делаем RAMP от первой до второй точки*)
tx:=PLC_TIME;(*Время циклически накапливается*)
txr_diff:=DINT_TO_REAL(TIME_TO_DINT(tx)) - DINT_TO_REAL(TIME_TO_DINT(tx1));(*Разница между запомненным временем и текущим*)
fr:=txr_diff/DINT_TO_REAL(TIME_TO_DINT(TIME_MAIN));(*Время за которое должна нарастать или убывать функция. Высчитывает коэффициент приращения/убавления*)
IF First<Second THEN Err:=Second - OUT; END_IF;(*0-рост*)
IF First>Second THEN Err:=OUT - Second; END_IF;(*1-падение*)
OUT:=AM * fr + OS;(*Общая линейная зависимость*)
R_TRIG(CLK:=Err< 0);(*Ждем перехода через ноль*)
IF  R_TRIG.Q THEN State:=3; END_IF;
IF NOT START THEN  State:=3; END_IF;

3:(*Рамп отработал*)
OUT:=TE_SP_2;(*Оставляем второе значение на выходе*)
START_TIME:=T#0m;(*Делаем визуализацию переменных времени*)
FINISH_TIME:=TIME_MAIN;(*Делаем визуализацию переменных времени*)
Complite:=TRUE;(*Выставляем признак того, что завершилось*)

IF NOT START THEN State:=0; END_IF;(*Возвращаем, если кнопка START прекратила действовать, на 0 шаг*)
END_CASE;
END_FUNCTION_BLOCK

#RAMP, #Линейно-нарастающая функция, #Управление процессом нагрева

Оставьте первый комментарий

Ваш комментарий добавлен
Оставьте Вашу заявку и получите ответ в самые короткие сроки!