PDA

Просмотр полной версии : Измерение и регулирование скорости нагрева



M'aik
26.11.2018, 20:47
Здравствуйте, изучаю codesys не так давно, пишу свою программу для управления печью. Запнулся на этапе скоростных параметров. Необходимо измерить скорость нагрева, и при необходимости её ограничить. Никак не могу реализовать данную функцию, может кто сталкивался?
Пробовал измерять скорость через массив, каждую единицу времени записывая показания температуры, а затем искать разницу, но что-то все равно не получается адекватный результат получить.
А в дальнейшем по ограничению скорости вообще идей нет...

Eugene.A
26.11.2018, 20:55
Зная две температуры и интервал времени между ними, можно разделить приращение температуры на время и получить скорость нагрева. Регулировать скорость можно, управляя мощностью нагревателя.

M'aik
26.11.2018, 21:04
То есть достаточно только двух показаний? Текущей температуры, и скажем, температуры секунду назад? То есть массивы ни к чему? И выборка из 10-20 значений бесполезна?
То, что нужно управлять мощностью регулятора, это понятно. Не понятно, как его ограничить, чтобы, к примеру он грел не более 1 град./мин на всем этапе нагрева.

Eugene.A
26.11.2018, 23:56
Частота выборок определяется тепловой инерционностью объекта регулирования. Если температура заметно меняется за секунду - значит нужно вычислять скорость ежесекундно и корректировать мощность соответственно. Для чего накапливать массив и как потом интерпретировать полученные данные - не совсем понятно. Что делать с мощностью во время накопления данных? Это лишь внесёт дополнительную задержку в процесс регулирования.
Мне представляется так: за заданный интервал времени вычисляем скорость изменения температуры и полученную величину подаём на вход ПИД-регулятора, на другой вход подаём задание скорости, ПИД регулирует мощность нагревателя.

ferret_maybe
27.11.2018, 15:31
Производная функции - скорость изменения физической величины. Вычисляя производную находите скорость изменения температуры. Блок Derivative вроде бы...

Crusash
28.11.2018, 18:03
Производная функции - скорость изменения физической величины. Вычисляя производную находите скорость изменения температуры. Блок Derivative вроде бы...

Попробовал для интересу этот блок Derivative, както странно он работает:
тенденцию изменений (нагрев\охлаждение\удержание) он отображает точно, а вот количественные показатели странные - чтобы привести к боле менее реальным показаниям, вызывая блок раз в секунду, параметр для TM получилось подобрать 20 (судя по документам миллисекунд).

Лучше как ТС предлагает, самому собирать массив и аппроксимируй как хочешь, на любой диапазон времени...

SBeaR
29.11.2018, 04:02
Попробовал для интересу этот блок Derivative, както странно он работает:
тенденцию изменений (нагрев\охлаждение\удержание) он отображает точно, а вот количественные показатели странные - чтобы привести к боле менее реальным показаниям, вызывая блок раз в секунду, параметр для TM получилось подобрать 20 (судя по документам миллисекунд).

Лучше как ТС предлагает, самому собирать массив и аппроксимируй как хочешь, на любой диапазон времени...

Попробуйте стандартную формулу дифференцирования:


OUT:=TD*(IN-OLD_IN)/CYCLE;
OLD_IN:=IN;

CYCLE - период вызова данной функции;
TD - время дифференцирования.
Размерности CYCLE и TD естественно должны совпадать.
То есть вы смотрите на сколько изменилась переменная за время CYCLE (например 100мс) и экстраполируя определяете на сколько она изменится за время TD (например 1 сек = 1000мс) при сохранении текущей скорости.

rwg
29.11.2018, 07:21
Когда вы вычисляете скорость изменения температуры, вы делите 0 на 0, микроизменение температуры на секундный интервал времени. Чтобы повысить точность, нужно увеличить время между измерениями и фильтровать результат. Но это приведёт к задержкам измерения, что снижает точность регулирования и может вызвать автоколебания регулятора. Проще настроить регулятор температуры и с заданной скоростью изменять его уставку, заданная скорость нагрева получится автоматически, а погрешности её вычисления не будут влиять на работу регулятора.

Crusash
29.11.2018, 12:58
Когда вы вычисляете скорость изменения температуры, вы делите 0 на 0, микроизменение температуры на секундный интервал времени. Чтобы повысить точность, нужно увеличить время между измерениями и фильтровать результат. Но это приведёт к задержкам измерения, что снижает точность регулирования и может вызвать автоколебания регулятора. Проще настроить регулятор температуры и с заданной скоростью изменять его уставку, заданная скорость нагрева получится автоматически, а погрешности её вычисления не будут влиять на работу регулятора.

Подтверждаю, регулировку скорости много проще делать изменением уставки, но и подсчет скорости не помешает. Я это делаю накапливая массив:



TYPE mnt_temp_time :
STRUCT
temp:REAL;
mt_time:DWORD;
END_STRUCT
END_TYPE

VAR
(*переменные подсчета скорости температуры*)
arr_tt:ARRAY [0..20] OF mnt_temp_time;(*массив меток времени и температур для расчёта скорости*)
j:INT:=0;
j2:INT:=0;
n:INT:=20;
END_VAR

(*подсчет скорости изменения температуры*)
IF NOT(arr_tt[j].temp=mashina.tek_t) AND (timer.dw_time_ms-arr_tt[j].mt_time)>1000 THEN
IF j=n THEN j:=0;
ELSE j:=j+1; END_IF
arr_tt[j].temp:=mashina.tek_t;
arr_tt[j].mt_time:=timer.dw_time_ms;
IF j=n THEN j2:=0;
ELSE j2:=j+1;END_IF
mashina.spid_temp2:=((arr_tt[j].temp - arr_tt[j2].temp)/
(DWORD_TO_REAL(arr_tt[j].mt_time)-DWORD_TO_REAL(arr_tt[j2].mt_time)))*60000;
END_IF

M'aik
10.12.2018, 21:56
Спасибо! Помогло! А не подскажете, как регулировку скорости делаете?

Crusash
17.12.2018, 19:54
Спасибо! Помогло! А не подскажете, как регулировку скорости делаете?

Можно подавать на пид текущую скорость и требуемую скорость, пусть регулирует...
Или стандартно, подавать на пид текущую температуру и менять уставку с требуемой скоростью, как предлагалось выше.

Александр SPB
20.05.2022, 23:59
Подтверждаю, регулировку скорости много проще делать изменением уставки, но и подсчет скорости не помешает. Я это делаю накапливая массив:



TYPE mnt_temp_time :
STRUCT
temp:REAL;
mt_time:DWORD;
END_STRUCT
END_TYPE

VAR
(*переменные подсчета скорости температуры*)
arr_tt:ARRAY [0..20] OF mnt_temp_time;(*массив меток времени и температур для расчёта скорости*)
j:INT:=0;
j2:INT:=0;
n:INT:=20;
END_VAR

(*подсчет скорости изменения температуры*)
IF NOT(arr_tt[j].temp=mashina.tek_t) AND (timer.dw_time_ms-arr_tt[j].mt_time)>1000 THEN
IF j=n THEN j:=0;
ELSE j:=j+1; END_IF
arr_tt[j].temp:=mashina.tek_t;
arr_tt[j].mt_time:=timer.dw_time_ms;
IF j=n THEN j2:=0;
ELSE j2:=j+1;END_IF
mashina.spid_temp2:=((arr_tt[j].temp - arr_tt[j2].temp)/
(DWORD_TO_REAL(arr_tt[j].mt_time)-DWORD_TO_REAL(arr_tt[j2].mt_time)))*60000;
END_IF



Добрый день. Подскажите mt_time откуда брать и какие значения? И dw_time_ms я так понимаю создается так же STRUCT как и mt_time и так же DWORD. А значения так же откуда и какие брать?

Валенок
21.05.2022, 20:26
dword_to_time(time()) - обе см. справка КДС

Александр SPB
21.05.2022, 22:08
С этим все ясно. DWORD 1000 =T#1s для TIME. Я не могу понять как записать значения в timer.dw_time_ms. Понимаю что нужно с определенной периодичностью в переменную dw_time_ms записывать число больше 1000 (1 сек). Как можно это сделать? Использовать таймер, например TP ?

Валенок
21.05.2022, 22:36
нужно с определенной периодичностью в переменную dw_time_ms записывать число больше 1000 (1 сек). Как можно это сделать?
ton(in := not ton.q, pt := определенной_периодичностью);
dw_time_ms := sel(ton.q, dw_time_ms, 1001); //1001 > 1000

Чотко как просили.

Александр SPB
22.05.2022, 09:16
ton(in := not ton.q, pt := определенной_периодичностью);
dw_time_ms := sel(ton.q, dw_time_ms, 1001); //1001 > 1000

Чотко как просили.
Спасибо!
dw_time_ms := sel(ton.q, 1000, 1001); (*1001 > 1000*)

keysansa
22.05.2022, 13:03
Реализовать рампу через таймеры - это жуть какая-то. Таймеры не работают, когда время вызова программы длительнее, чем, уставка таймера.
Необходимо использовать таймер контроллера
Каждый контроллер, отсчитывает время в мкс, от своего запуска. Это время можно получить с помощью системных процедур.
Далее, dA/dt, вне зависимости от периода работы управляющей программы.

В библиотеке oscat есть блок RAMP
Библиотека с открытым исходным кодом, можно посмотреть реализацию. Но лучше использовать.

Александр SPB
22.05.2022, 21:25
Совсем запутался, не могу запустить измерение скорости. Пробовал с таймером но, что то не то. На короткое время запускается но скорость показывает не реальную. Подскажите кто знает, как запустить измерение.

Валенок
22.05.2022, 22:18
... Подскажите кто знает, как запустить измерение.
Для начала уберите весь ненужный мусор из проекта. Вы к стоматологу в кресло бухаетесь в сапогах с налипшим гуаном ?

Александр SPB
22.05.2022, 22:41
Для начала уберите весь ненужный мусор из проекта. Вы к стоматологу в кресло бухаетесь в сапогах с налипшим гуаном ?

Почистил. Извините.

Валенок
22.05.2022, 23:16
Замените тип
mt_time: DWORD; на TIME;
или просто
mt : TIME;
На кой лишний dword и буквы ?

и тогда замените
timer.dw_time_ms
на TIME()
arr_tt[j].mt:=TIME();

Упростите счетчик
IF j=n THEN
j:=0;
ELSE
j:=j+1;
END_IF
на классический циклический
j := (j + 1) mod (n + 1);


Вычитаете
..[j] - ..[j2]
dt - это из текущего вычесть прошлое, но
j2 := j + 1; это будущее

логичней было бы не j2 а j0 (или j_) Да и определить проще :
j0 := j;
j := (j + 1) mod (n + 1);

сложное и странное dt
((...) / (DWORD_TO_REAL(arr_tt[j].mt_time)-DWORD_TO_REAL(arr_tt[j2].mt_time)))*60000
60000 - тута не СИ ?

((...) / (TIME_TO_REAL(arr_tt[j].mt - arr_tt[j0].mt)) * 1000
это *С /сек

Ну и есть смысл какой нить init для вычисления dT/dt т.к. при 1-ом измерении еще нет прошлого

if init then
..dT/dt;
end_if
init := true;

Александр SPB
23.05.2022, 11:54
Спасибо! Работает. Не понял только про if init then ..dT/dt; end_if init := true; Скорость и без этого показывает, но замер очень точный за мс. Как теперь можно реализовать замер изменения скорости за 1 сек, 2 и т.д

Валенок
23.05.2022, 14:46
Не понял только про if init
Какое dt на 1-ом измерении ?


Как теперь можно реализовать замер изменения скорости за 1 сек, 2 и т.д
a = (v - v')/dt, //*С/cек^2, видимо ускорение темп-ры
dt - уже есть
v - mashina.spid_temp2
..

ps
А что это выложено выше ? Вы хоть удаляйте ненужное - j0 j2
И куда ушло сравнение на изменение ?
Что такое init_1 : UINT ?

Александр SPB
24.05.2022, 22:58
А что это выложено выше ? Вы хоть удаляйте ненужное - j0 j2
И куда ушло сравнение на изменение ?
Что такое init_1 : UINT ?
init_1 : UINT это мусор, от проб и ошибок. Так же как и не удаленные j0 и т.д. Сравнение убрал чтоб проверить как работает этот код дальше в программе. Если оставить сравнение не могу запустить код целиком. Разбираюсь...:confused:

kondor3000
25.05.2022, 00:53
init_1 : UINT это мусор, от проб и ошибок. Так же как и не удаленные j0 и т.д. Сравнение убрал чтоб проверить как работает этот код дальше в программе. Если оставить сравнение не могу запустить код целиком. Разбираюсь...:confused:

Вы потеряли условия сравнения


Timer.dw_time_ms:=TIME();

IF NOT(arr_tt[j].temp=mashina.tek_t) AND (Timer.dw_time_ms-arr_tt[j].mt)>T#1000ms THEN
IF j=n THEN j:=0;
ELSE j:=j+1;
END_IF
arr_tt[j].temp:=mashina.tek_t;
arr_tt[j].mt:=Timer.dw_time_ms;
IF j=n THEN j2:=0;
ELSE j2:=j+1;
END_IF
mashina.spid_temp2:=((arr_tt[j].temp - arr_tt[j2].temp) / (TIME_TO_REAL(arr_tt[j].mt - arr_tt[j0].mt))) * 1000 ;
END_IF

Александр SPB
25.05.2022, 22:56
Более менее получилось. Первый вариант сделан по рекомендации Валенок . Не совсем понял как работает Timer.dw_time_ms, в переменной dw_time_ms присваивал значение T#1000ms что так измерение идет, что без присвоения измерение одинаково идет. Возможно из за этого когда значение температуры не изменяется, скорость изменения все равно показывает. Пусть это и 0.00 значение но все же. Можно поставить преобразование и количество знаков после запятой ставить исходя из требований. T#1000ms это я так понимаю период измерения температуры? Так и не понял с dt это (arr_tt[j].mt - arr_tt[j0].mt), а ..dT. что подставить?
Второй вариант сделал по варианту kondor3000 в этом варианте счет не работает. Показывает с - и значения идут по нарастающей.

Валенок
26.05.2022, 08:21
Возможно из за этого когда значение температуры не изменяется,

На планете эльфов существуют неименяемые результаты измерений, а их графики преставляют собой непрерывные графики.
На Земле измерения, например, температур в 99.9% случаях будут шевелится, если канешна измерение не производится 1-битным АЦП в виде термостата или производится странно ухудшение точности типа

количество знаков после запятой ставить исходя из требований.
а графики представляют собой набор точек которые образуются в момент оцифровки.
(соединение их в якобы реальный график также реально как достраивание картинки мозгом в районе слепого пятна в глазу)
ЛЮБЫЕ действия с данными измерения (вычисления скорости, пид-регулировани и т. п.) есть смысл производить ТОЛЬКО в момент оцифровки. В иное время - этот подвид онанизма.
Т. к. получить момент оцифровки непосредствено (особенно при работе с модулями расш.) обычно не представляется возможным, то наиболее простое решение - сравнить на изменение. При работе с модулями это будет момент ПОЛУЧЕНИЯ данных ПОСЛЕ реальной оцифровки. Нормальное добавочное решение для снятия проблем с оставшимися от вышеуказанного 0.1% добавить условие "но не реже 2..3х циклов реальной оцифровки", а в случаях принудительного торможения (как у Вас изначально) - "но не чаще чем...".
Вычисления подобные Вашим на планете Земля начинают с изучения характеристик планируемого измерителя. Он может удивить в некоторых случаях (плк 63,73, 2А, 8А -" не чаще.." может не потребоватся, а "не реже.." может быть аж до 10сек как ни чесались бы ладошки), поэтому

T#1000ms это я так понимаю период измерения температуры?
вообще никто кроме Вас не понимает.
"не чаще .." нужно только с измерителями данные с которых получаются реально чаще требуемой задачи (из местного - плк160, 2AC, 8AC)

Странный вопрос про dT, он у Вас же вычисляется в исходном проекте, правда со знаком

kondor3000
26.05.2022, 09:06
Более менее получилось. Первый вариант сделан по рекомендации Валенок . Не совсем понял как работает Timer.dw_time_ms, в переменной dw_time_ms присваивал значение T#1000ms что так измерение идет, что без присвоения измерение одинаково идет. Возможно из за этого когда значение температуры не изменяется, скорость изменения все равно показывает. Пусть это и 0.00 значение но все же. Можно поставить преобразование и количество знаков после запятой ставить исходя из требований. T#1000ms это я так понимаю период измерения температуры? Так и не понял с dt это (arr_tt[j].mt - arr_tt[j0].mt), а ..dT. что подставить?
Второй вариант сделал по варианту kondor3000 в этом варианте счет не работает. Показывает с - и значения идут по нарастающей.
Выложил кусок кода, без начальной инициализации, только для примера.
У вас в обоих вариантах сравнение температуры начинает работать только после прохождения 20 записей (Температура должна меняться).
Нет начальной инициализации первой температуры arr_tt[j2].temp, в моём варианте.
В первом варианте показания всегда стремятся к нулю. За какое время измерения не понятно, 1 вариант полная лажа ( при изменениина 0,4 градуса, скачет до 20, а потом снижается до нуля).
В моём варианте показания стоят пока идут 20 записей, измерение происходит каждую секунду, разницу показывает за время 1 сек. ( у меня с инициализацией сделано, в коде этого нет)

Александр SPB
27.05.2022, 10:58
Инициализация в вашем варианте запускается по отдельному таймеру или как?

kondor3000
28.05.2022, 14:32
Инициализация в вашем варианте запускается по отдельному таймеру или как?
Инициализация у меня присваивает значения температуры и времени в момент запуска программы.
Как сделать инициализацию, вам уже выкладывали.