Просмотр полной версии : Измерение и регулирование скорости нагрева
Здравствуйте, изучаю codesys не так давно, пишу свою программу для управления печью. Запнулся на этапе скоростных параметров. Необходимо измерить скорость нагрева, и при необходимости её ограничить. Никак не могу реализовать данную функцию, может кто сталкивался?
Пробовал измерять скорость через массив, каждую единицу времени записывая показания температуры, а затем искать разницу, но что-то все равно не получается адекватный результат получить.
А в дальнейшем по ограничению скорости вообще идей нет...
Eugene.A
26.11.2018, 20:55
Зная две температуры и интервал времени между ними, можно разделить приращение температуры на время и получить скорость нагрева. Регулировать скорость можно, управляя мощностью нагревателя.
То есть достаточно только двух показаний? Текущей температуры, и скажем, температуры секунду назад? То есть массивы ни к чему? И выборка из 10-20 значений бесполезна?
То, что нужно управлять мощностью регулятора, это понятно. Не понятно, как его ограничить, чтобы, к примеру он грел не более 1 град./мин на всем этапе нагрева.
Eugene.A
26.11.2018, 23:56
Частота выборок определяется тепловой инерционностью объекта регулирования. Если температура заметно меняется за секунду - значит нужно вычислять скорость ежесекундно и корректировать мощность соответственно. Для чего накапливать массив и как потом интерпретировать полученные данные - не совсем понятно. Что делать с мощностью во время накопления данных? Это лишь внесёт дополнительную задержку в процесс регулирования.
Мне представляется так: за заданный интервал времени вычисляем скорость изменения температуры и полученную величину подаём на вход ПИД-регулятора, на другой вход подаём задание скорости, ПИД регулирует мощность нагревателя.
ferret_maybe
27.11.2018, 15:31
Производная функции - скорость изменения физической величины. Вычисляя производную находите скорость изменения температуры. Блок Derivative вроде бы...
Производная функции - скорость изменения физической величины. Вычисляя производную находите скорость изменения температуры. Блок Derivative вроде бы...
Попробовал для интересу этот блок Derivative, както странно он работает:
тенденцию изменений (нагрев\охлаждение\удержание) он отображает точно, а вот количественные показатели странные - чтобы привести к боле менее реальным показаниям, вызывая блок раз в секунду, параметр для TM получилось подобрать 20 (судя по документам миллисекунд).
Лучше как ТС предлагает, самому собирать массив и аппроксимируй как хочешь, на любой диапазон времени...
Попробовал для интересу этот блок Derivative, както странно он работает:
тенденцию изменений (нагрев\охлаждение\удержание) он отображает точно, а вот количественные показатели странные - чтобы привести к боле менее реальным показаниям, вызывая блок раз в секунду, параметр для TM получилось подобрать 20 (судя по документам миллисекунд).
Лучше как ТС предлагает, самому собирать массив и аппроксимируй как хочешь, на любой диапазон времени...
Попробуйте стандартную формулу дифференцирования:
OUT:=TD*(IN-OLD_IN)/CYCLE;
OLD_IN:=IN;
CYCLE - период вызова данной функции;
TD - время дифференцирования.
Размерности CYCLE и TD естественно должны совпадать.
То есть вы смотрите на сколько изменилась переменная за время CYCLE (например 100мс) и экстраполируя определяете на сколько она изменится за время TD (например 1 сек = 1000мс) при сохранении текущей скорости.
Когда вы вычисляете скорость изменения температуры, вы делите 0 на 0, микроизменение температуры на секундный интервал времени. Чтобы повысить точность, нужно увеличить время между измерениями и фильтровать результат. Но это приведёт к задержкам измерения, что снижает точность регулирования и может вызвать автоколебания регулятора. Проще настроить регулятор температуры и с заданной скоростью изменять его уставку, заданная скорость нагрева получится автоматически, а погрешности её вычисления не будут влиять на работу регулятора.
Когда вы вычисляете скорость изменения температуры, вы делите 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
Спасибо! Помогло! А не подскажете, как регулировку скорости делаете?
Спасибо! Помогло! А не подскажете, как регулировку скорости делаете?
Можно подавать на пид текущую скорость и требуемую скорость, пусть регулирует...
Или стандартно, подавать на пид текущую температуру и менять уставку с требуемой скоростью, как предлагалось выше.
Александр 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. А значения так же откуда и какие брать?
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 ?
нужно с определенной периодичностью в переменную 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
Совсем запутался, не могу запустить измерение скорости. Пробовал с таймером но, что то не то. На короткое время запускается но скорость показывает не реальную. Подскажите кто знает, как запустить измерение.
... Подскажите кто знает, как запустить измерение.
Для начала уберите весь ненужный мусор из проекта. Вы к стоматологу в кресло бухаетесь в сапогах с налипшим гуаном ?
Александр SPB
22.05.2022, 22:41
Для начала уберите весь ненужный мусор из проекта. Вы к стоматологу в кресло бухаетесь в сапогах с налипшим гуаном ?
Почистил. Извините.
Замените тип
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 и т.д
Не понял только про 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 в этом варианте счет не работает. Показывает с - и значения идут по нарастающей.
Возможно из за этого когда значение температуры не изменяется,
На планете эльфов существуют неименяемые результаты измерений, а их графики преставляют собой непрерывные графики.
На Земле измерения, например, температур в 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
Инициализация в вашем варианте запускается по отдельному таймеру или как?
Инициализация у меня присваивает значения температуры и времени в момент запуска программы.
Как сделать инициализацию, вам уже выкладывали.
Powered by vBulletin® Version 4.2.3 Copyright © 2024 vBulletin Solutions, Inc. All rights reserved. Перевод: zCarot