[JavaScript] Делаем симулятор двухпозиционного регулятора на JavaScript
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Суть теории автоматического управления подразумевает построение такой системы, которая поддерживает определенный параметр некоторого объекта в заданном состоянии, например, температуру в печи, или уровень воды в баке. Для лучшего понимания процесса, удобно сразу рассмотреть конкретную модель управления, скажем, управление уровнем воды в баке. Кстати, в учебниках и статьях по ТАУ этот процесс упоминается довольно часто как отсылка к истории, потому что в далеком 1763 году русский изобретатель Ползунов И.И. разработал для своего парового двигателя систему контроля уровня воды. Своего рода классический регулятор, который, кстати, и является по сути двухпозиционным регулятором как на этой картинке (воды нет — клапан открыть, вода есть клапан закрыть)
Двухпозиционный он потому, что имеет 2 позиции: открыт (включен) и закрыт (выключен), в англоязычной литературе on-off. Бывают и трех и более позиционные регуляторы, то есть к основным положениям клапан пополнения воды открыт или закрыт, добавляется еще положение «приоткрыт». После слива воды в унитазе поплавок опускается, открывая полностью клапан и вода поступает в бак на полном напоре, но ближе к достижению заданного уровня, поплавок поднимается призакрывая клапан и уменьшая поступление воды. И как только текущий уровень воды ( в английском языке PV — Process Value — Текущее значение) поднимется до заданного (в английском языке SP — Set Point — Уставка), клапан закроется и уровень воды перестанет расти. В описанном случае регулятор даже более похож на пропорциональный — регулирующее воздействие уменьшается при уменьшении рассогласования (ошибка — error), то есть разницы между заданным уровнем и уровнем текущим.
Приоткрывая нижнюю трубу на слив воды, можно будет добиться такого состояния, когда клапан будет открыт полностью, а уровень воды не будет уменьшаться (то есть приток воды станет равным истоку) — система войдет в состояние равновесия. Но проблема в том, что это состояние очень шаткое — любой внешнее возмущающее воздействие может сломать это равновесие — скажем мы можем зачерпнуть из бака некоторое количество воды, и тогда может так получиться что вся вода после этого вытечет из бака (засчет изменения давления), либо труба пополнения забьется и поток уменьшится, либо поплавок сломается и вода перельется. В этом и заключается сложность построения систем управления — реальные системы довольно сложные и имеют много характеристик, которые нужно учитывать. Есть такая характеристика как инерционность системы — если отключить разогретую плиту то она будет оставаться горячей довольно продолжительное время, именно поэтому для управления температурой используют более сложные регуляторы, а именно ПИД — пропорционально интегрально дифференциальный. У каждой из составляющих есть свои особенности — они все по-разному себя ведут при разных условиях, но в совместном использовании позволяют добиться довольно четкого регулирования. Все эти системы просчитываются по формулам, но в данном случае просто важно понимать, как поведет себя система при изменении коэффициентов ПИД регулятора: при увеличении пропорционального звена — начальное воздействие увеличивается и таким образом система сможет быстрее достичь необходимых параметров. Но если переборщить с этим, то возможно появится перерегулирование, что может быть еще хуже чем малое быстродействие системы.
За время существования ТАУ были найдены математические описания многих процессов и теперь мы можем предугадать как поведет себя система при определенных обстоятельствах. Существует множество программ-симуляторов, где можно задать параметры системы, задать параметры регулятора и примерно увидеть что из этого выйдет. Гуляя по просторам интернета наткнулся на сайт Excel для инженеров, и там есть несколько симуляторов регуляторов, благодаря которым можно посмотреть на изменение в процессе при изменении коэффициентов регулирования. Наиболее простой для повторения был, естественно, регулятор ON-OFF, то есть по-русски двухпозиционный регулятор. Напоминаю принцип работы: если текущая величина процесса (Process value = PV) -температура, например — ниже уставки (SP), то регулятор включается (OP) — запускаются тэны на полную мощность. Как только температура достигает уставки — регулятор отключает подачу напряжения на тэны.
Делаем симулятор на JavaScript
Для построения графика буду использовать библиотеку ZingChart — пользоваться ей оказалось довольно просто и легко. Есть много примеров в документации по которым можно построить вообще все что угодно. Принцип построения довольно простой — есть массив значений, которые автоматически ложатся на график по порядку, и таким образом из пары сотен точек появляется непрерывный график процесса. Кстати в оригинале в экселе все делается точно так же — генерируется 300 значений и строится график.
Собственно именно генерация значений и является самым сложным, а именно сложность правильно описать процесс, который правильно реагирует на наши управляющие воздействия — включение тэнов — температура растет, выключение — падает, плюс сюда же нужно заложить инерционность системы. Кроме того среда нагрева может быть разная и некоторые среды быстрее нагреваются и остывают, а некоторые наоборот, а если регулируем уровень, то при одинаковом потоке сверху, уровень подниматься будет выше в том баке, где площадь дна меньше. Это все я веду к тому, что процесс будет зависеть и от коэффициента передачи (усиления). В оригинале в процесс введен еще параметр задержки (ну типа система не сразу реагирует на управляющий сигнал), но я решил от него отказаться — достаточно и двух. Зато добавил изменение уставки, хотя по сути получилось что уставка может меняться от нуля до 100, свыше 100 процесс начинает вести себя не так, и судя по всему причина в том что формула процесса универсальная и не описывает частный случай. В общем приступаем:
Создаем 5 полей для ввода параметров, все это помещаем в таблицу, которую выше в css окрашиваем в красивый цвет и помещаем по центру:
<table align="center" oninput="setvalues ();">
<tr>
<td>
Process parameters <br>
Gain: <input id="gain" type="number" value ="1" ><br>
Time Constant: <input id="time" type="number" value ="100" ><br>
</td>
<td>
Control parameters <br>
SetPoint(0-100): <input id="sp" type="number" value ="50"><br>
Hysteresis: <input id="hyst" type="number" value ="1">%<br>
</td>
<td>
Plot parameters <br>
Points: <input id="points" type="number" value ="200"><br>
</td>
</tr>
</table>
Как видно при каждом изменении значения полей внутри таблицы будет вызываться функция setvalues(). В ней мы считываем данные из каждого поля в специальные переменные
let gain = document.getElementById('gain').value;
let time = document.getElementById('time').value;
let sp = document.getElementById('sp').value;
let points = document.getElementById('points').value;
let hyst = document.getElementById('hyst').value;
Как уже говорилось для построения графика нужны массивы с данными на основании которых и будет строиться график, поэтому создаем кучку массивов:
let pv = []; // массив данных процесса
let pv100 = []; //то же но *100
let op = []; // управляющий сигнал 1 вкл, 0 выкл
let pvp = 0; //предыдущее значение процесса
let low = sp-sp*hyst/100;//нижняя граница гистерезиса
let high = +sp+(sp*hyst/100); // верхняя граница гистерезиса
let st=true; // старт нагрева
Немного поясню за гистерезис. Ситуация такая: когда температура достигает заданного значения, тэны отключаются и сразу же (на самом деле не сразу, т.к. есть инерция) начинается процесс остывания. И остыв на один градус а то и некоторую долю градуса — система понимает что уже снова вышла за рамки задания и нужно снова включать тэны. В таком режиме тэны будут включаться и выключаться очень часто, может быть и такое что несколько раз за минуту — для оборудования такой режим не очень хороший, и поэтому чтобы исключить такие колебания вводят так называемый гистерезис — deadband — зона нечувствительности — скажем 1 градус выше и ниже уставки мы не будем реагировать, и тогда количество переключений можно значительно сократить. Поэтому в переменной low находится нижняя граница уставки, а в high верхняя. Переменная st отслеживает достижение верхнего уровня и позволяет снизиться процессу до нижнего. Логика всего процесса находится в цикле:
for (var i=0;i<points;i++) {
if (pvp<=(low/100)) {
st=true;
op[i]=1;
}//
else if (pvp<=(high/100)&& st) op[i] = 1;
else { st=false; op[i]=0;}
let a = Math.pow(2.71828182845904, -1/time);
let b = gain*(1 -a);
pv[i] = op[i]*b+pvp*a;
pv100[i] = pv[i]*100;
pvp = pv[i];
}
По итогу мы получаем массив с заданным количеством точек, который отправляем скрипту построения графиков.
scaleX: {
zooming: true
},
series: [
{ values: op , text: 'OP' },
{ values: pv100 , text: 'PV'}
]
};
Полный код под спойлером
SPL
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>График</title>
<script src="https://cdn.zingchart.com/zingchart.min.js"></script>
<style>
html,
body,
#myChart {
width: 100%;
height: 100%;
}
input {
width: 25%;
text-align:center;
}
td {
background-color: peachpuff;
text-align: center;
}
</style>
</head>
<body>
<table align="center" oninput="setvalues ();">
<tr>
<td>
Process parameters <br>
Gain: <input id="gain" type="number" value ="1" ><br>
Time Constant: <input id="time" type="number" value ="100" ><br>
</td>
<td>
Control parameters <br>
SetPoint(0-100): <input id="sp" type="number" value ="50"><br>
Hysteresis: <input id="hyst" type="number" value ="2">%<br>
</td>
<td>
Plot parameters <br>
Points: <input id="points" type="number" value ="250"><br>
Animation: <input type="checkbox" id="animation">
</td>
</tr>
</table>
<script>
setTimeout('setvalues ()', 0);
function setvalues (){
let gain = document.getElementById('gain').value;
let time = document.getElementById('time').value;
let sp = document.getElementById('sp').value;
let points = document.getElementById('points').value;
let hyst = document.getElementById('hyst').value;
let anim = document.getElementById('animation').checked ? +1 : 0;
let pv = []; // массив данных процесса
let pv100 = []; //то же но *100
let op = []; // управляющий сигнал 1 вкл, 0 выкл
let pvp = 0; //предыдущее значение процесса
let low = sp-sp*hyst/100; //нижняя граница гистерезиса
let high = +sp+(sp*hyst/100); //верхняя граница гистерезиса
let st=true; // старт нагрева
for (var i=0;i<points;i++) {
if (pvp<=(low/100)) {
st=true;
op[i]=1;
}
else if (pvp<=(high/100)&& st) op[i] = 1;
else { st=false; op[i]=0;}
let a = Math.pow(2.71828182845904, -1/time);
let b = gain*(1 -a);
pv[i] = op[i]*b+pvp*a;
pv100[i] = pv[i]*100;
pvp = pv[i];
}
ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"];
var myConfig = {
type: "line",
"plot": {
"animation": {
"effect": anim,
"sequence": 2,
"speed": 200,
}
},
legend: {
layout: "1x2", //row x column
x: "20%",
y: "5%",
},
crosshairX:{
plotLabel:{
text: "%v"
}
},
"scale-y": {
item: {
fontColor: "#7CA82B"
},
markers: [
{
type: "area",
range: [low, high],
backgroundColor: "#d89108",
alpha: 0.7
},
{
type: "line",
range: [sp],
lineColor: "#7CA82B",
lineWidth: 2,
label: { //define label within marker
text: "SP = "+sp,
backgroundColor: "white",
alpha: 0.7,
textAlpha: 1,
offsetX: 60,
offsetY: -5
}
}]
},
scaleX: {
zooming: true
},
'scale-y-2': {
values: "0:1"
},
series: [
{ scales: "scale-x,scale-y-2", values: op , 'legend-text': 'OP' },
{ values: pv100 , text: 'PV'}
]
};
zingchart.render({
id: 'myChart',
data: myConfig,
height: "90%",
width: "100%"
});
}
</script>
<div id='myChart'></div>
</body>
</html>
Ну а поскольку симулятор готов, самое время заценить как он работает.
Стандартная настройка: усилительное звено 1, постоянная времени 100 секунд, гистерезис 2%
Теперь если задать уставку побольше, например 92, то внезапно процесс сильно замедляется, хотя при этом уставку 50 он набирает за те же 71 секунды, но уже потом кривая начинает приближаться к заданию медленнее по экспоненциальной зависимости, и доходит до уставки лишь за 278 секунд, из-за чего пришлось расширить диапазон построения графика до 300 точек
Данный пример очень показательный, переводя ситуацию на модель с температурой можно сделать такой вывод, что не хватает мощности нагревателя: нагреватель загружен на 100% но при этом температура перестает расти после определенного момента. Решений может быть несколько: поставить второй такой же нагревательный элемент, или подавать напряжение на него в 2 раза больше (но это может повредить тэн), либо поставить нагреватель в 2 раза большей мощности, либо залить в систему более теплопроводящую жидкость если речь идет о нагреве жидкости. Довольно интересно то, что если нужно поддерживать температуру в районе 95-100 градусов, то не нужно даже ставить регулятор — поставил такой маломощный нагреватель, врубил его на полную катушку и все — через 300 секунд (условные 300 секунд) можно получить желаемые 100 градусов. Проблема такой системы в том что если открыть окно зимой в минус 40, то температура тут же просядет и довольно существенно, да и быстродействие такой системы очень малое.
Давайте увеличим усилительное звено gain в 2 раза — это как будто поставить второй такой же нагревательный элемент, или добавить еще одну трубу на пополнение бака.
График получился тоже довольно показательный — температура до 51 градуса реально добралась в 2 раза быстрее, а вот до 92 добралось раза в 4 быстрее. Не знаю насколько такой симулятор приближен к реальным процессам, но поскольку заданная в нем зависимость экспоненциальная, то это вполне ожидаемое поведение системы, но вот объяснить с позиции добавления второй трубы и увеличение скорости заполнения в 4 раза я даже не могу предположить. Реакция линейной функции была бы более предсказуемой на увеличение коэффициента, но реальные системы в жизни редко бывают линейными
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, JavaScript, Node.JS, ООП, TypeScript] Внедрение зависимостей (dependency injection) через свойства-функции в JavaScript
- [Разработка веб-сайтов, JavaScript, Программирование] JavaScript: что нас ждет в следующем году
- [Разработка веб-сайтов, JavaScript, HTML, Расширения для браузеров] Растянуть видео в браузере
- [JavaScript, Google Chrome, Расширения для браузеров, Браузеры] Расширения для Google Chrome, без которых вы уже не сможете представить свою работу
- [Firefox, Браузеры] В Firefox 83 внедрили режим «только HTTPS»
- [Разработка веб-сайтов, CSS, JavaScript, Программирование, HTML] Современный стартовый HTML-шаблон
- [JavaScript, VueJS] CSR vs SSR для одностраничных приложений на VueJS
- [Тестирование IT-систем, JavaScript, Google Chrome] Автотесты на базе playwright и jest
- [C#, Промышленное программирование] Как я при помощи Google сделал OPC2WEB клиент
- [JavaScript, Qt, Интерфейсы, Графический дизайн] Разработка круговых интерфейсов. Часть 2. Перенос библиотеки с JavaScript на QML
Теги для поиска: #_javascript, #_javascript, #_promyshlennaja_avtomatizatsija (промышленная автоматизация), #_javascript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:57
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Суть теории автоматического управления подразумевает построение такой системы, которая поддерживает определенный параметр некоторого объекта в заданном состоянии, например, температуру в печи, или уровень воды в баке. Для лучшего понимания процесса, удобно сразу рассмотреть конкретную модель управления, скажем, управление уровнем воды в баке. Кстати, в учебниках и статьях по ТАУ этот процесс упоминается довольно часто как отсылка к истории, потому что в далеком 1763 году русский изобретатель Ползунов И.И. разработал для своего парового двигателя систему контроля уровня воды. Своего рода классический регулятор, который, кстати, и является по сути двухпозиционным регулятором как на этой картинке (воды нет — клапан открыть, вода есть клапан закрыть) Двухпозиционный он потому, что имеет 2 позиции: открыт (включен) и закрыт (выключен), в англоязычной литературе on-off. Бывают и трех и более позиционные регуляторы, то есть к основным положениям клапан пополнения воды открыт или закрыт, добавляется еще положение «приоткрыт». После слива воды в унитазе поплавок опускается, открывая полностью клапан и вода поступает в бак на полном напоре, но ближе к достижению заданного уровня, поплавок поднимается призакрывая клапан и уменьшая поступление воды. И как только текущий уровень воды ( в английском языке PV — Process Value — Текущее значение) поднимется до заданного (в английском языке SP — Set Point — Уставка), клапан закроется и уровень воды перестанет расти. В описанном случае регулятор даже более похож на пропорциональный — регулирующее воздействие уменьшается при уменьшении рассогласования (ошибка — error), то есть разницы между заданным уровнем и уровнем текущим. Приоткрывая нижнюю трубу на слив воды, можно будет добиться такого состояния, когда клапан будет открыт полностью, а уровень воды не будет уменьшаться (то есть приток воды станет равным истоку) — система войдет в состояние равновесия. Но проблема в том, что это состояние очень шаткое — любой внешнее возмущающее воздействие может сломать это равновесие — скажем мы можем зачерпнуть из бака некоторое количество воды, и тогда может так получиться что вся вода после этого вытечет из бака (засчет изменения давления), либо труба пополнения забьется и поток уменьшится, либо поплавок сломается и вода перельется. В этом и заключается сложность построения систем управления — реальные системы довольно сложные и имеют много характеристик, которые нужно учитывать. Есть такая характеристика как инерционность системы — если отключить разогретую плиту то она будет оставаться горячей довольно продолжительное время, именно поэтому для управления температурой используют более сложные регуляторы, а именно ПИД — пропорционально интегрально дифференциальный. У каждой из составляющих есть свои особенности — они все по-разному себя ведут при разных условиях, но в совместном использовании позволяют добиться довольно четкого регулирования. Все эти системы просчитываются по формулам, но в данном случае просто важно понимать, как поведет себя система при изменении коэффициентов ПИД регулятора: при увеличении пропорционального звена — начальное воздействие увеличивается и таким образом система сможет быстрее достичь необходимых параметров. Но если переборщить с этим, то возможно появится перерегулирование, что может быть еще хуже чем малое быстродействие системы. За время существования ТАУ были найдены математические описания многих процессов и теперь мы можем предугадать как поведет себя система при определенных обстоятельствах. Существует множество программ-симуляторов, где можно задать параметры системы, задать параметры регулятора и примерно увидеть что из этого выйдет. Гуляя по просторам интернета наткнулся на сайт Excel для инженеров, и там есть несколько симуляторов регуляторов, благодаря которым можно посмотреть на изменение в процессе при изменении коэффициентов регулирования. Наиболее простой для повторения был, естественно, регулятор ON-OFF, то есть по-русски двухпозиционный регулятор. Напоминаю принцип работы: если текущая величина процесса (Process value = PV) -температура, например — ниже уставки (SP), то регулятор включается (OP) — запускаются тэны на полную мощность. Как только температура достигает уставки — регулятор отключает подачу напряжения на тэны. Делаем симулятор на JavaScript Для построения графика буду использовать библиотеку ZingChart — пользоваться ей оказалось довольно просто и легко. Есть много примеров в документации по которым можно построить вообще все что угодно. Принцип построения довольно простой — есть массив значений, которые автоматически ложатся на график по порядку, и таким образом из пары сотен точек появляется непрерывный график процесса. Кстати в оригинале в экселе все делается точно так же — генерируется 300 значений и строится график. Собственно именно генерация значений и является самым сложным, а именно сложность правильно описать процесс, который правильно реагирует на наши управляющие воздействия — включение тэнов — температура растет, выключение — падает, плюс сюда же нужно заложить инерционность системы. Кроме того среда нагрева может быть разная и некоторые среды быстрее нагреваются и остывают, а некоторые наоборот, а если регулируем уровень, то при одинаковом потоке сверху, уровень подниматься будет выше в том баке, где площадь дна меньше. Это все я веду к тому, что процесс будет зависеть и от коэффициента передачи (усиления). В оригинале в процесс введен еще параметр задержки (ну типа система не сразу реагирует на управляющий сигнал), но я решил от него отказаться — достаточно и двух. Зато добавил изменение уставки, хотя по сути получилось что уставка может меняться от нуля до 100, свыше 100 процесс начинает вести себя не так, и судя по всему причина в том что формула процесса универсальная и не описывает частный случай. В общем приступаем: Создаем 5 полей для ввода параметров, все это помещаем в таблицу, которую выше в css окрашиваем в красивый цвет и помещаем по центру: <table align="center" oninput="setvalues ();">
<tr> <td> Process parameters <br> Gain: <input id="gain" type="number" value ="1" ><br> Time Constant: <input id="time" type="number" value ="100" ><br> </td> <td> Control parameters <br> SetPoint(0-100): <input id="sp" type="number" value ="50"><br> Hysteresis: <input id="hyst" type="number" value ="1">%<br> </td> <td> Plot parameters <br> Points: <input id="points" type="number" value ="200"><br> </td> </tr> </table> Как видно при каждом изменении значения полей внутри таблицы будет вызываться функция setvalues(). В ней мы считываем данные из каждого поля в специальные переменные let gain = document.getElementById('gain').value;
let time = document.getElementById('time').value; let sp = document.getElementById('sp').value; let points = document.getElementById('points').value; let hyst = document.getElementById('hyst').value; Как уже говорилось для построения графика нужны массивы с данными на основании которых и будет строиться график, поэтому создаем кучку массивов: let pv = []; // массив данных процесса
let pv100 = []; //то же но *100 let op = []; // управляющий сигнал 1 вкл, 0 выкл let pvp = 0; //предыдущее значение процесса let low = sp-sp*hyst/100;//нижняя граница гистерезиса let high = +sp+(sp*hyst/100); // верхняя граница гистерезиса let st=true; // старт нагрева Немного поясню за гистерезис. Ситуация такая: когда температура достигает заданного значения, тэны отключаются и сразу же (на самом деле не сразу, т.к. есть инерция) начинается процесс остывания. И остыв на один градус а то и некоторую долю градуса — система понимает что уже снова вышла за рамки задания и нужно снова включать тэны. В таком режиме тэны будут включаться и выключаться очень часто, может быть и такое что несколько раз за минуту — для оборудования такой режим не очень хороший, и поэтому чтобы исключить такие колебания вводят так называемый гистерезис — deadband — зона нечувствительности — скажем 1 градус выше и ниже уставки мы не будем реагировать, и тогда количество переключений можно значительно сократить. Поэтому в переменной low находится нижняя граница уставки, а в high верхняя. Переменная st отслеживает достижение верхнего уровня и позволяет снизиться процессу до нижнего. Логика всего процесса находится в цикле: for (var i=0;i<points;i++) {
if (pvp<=(low/100)) { st=true; op[i]=1; }// else if (pvp<=(high/100)&& st) op[i] = 1; else { st=false; op[i]=0;} let a = Math.pow(2.71828182845904, -1/time); let b = gain*(1 -a); pv[i] = op[i]*b+pvp*a; pv100[i] = pv[i]*100; pvp = pv[i]; } По итогу мы получаем массив с заданным количеством точек, который отправляем скрипту построения графиков. scaleX: {
zooming: true }, series: [ { values: op , text: 'OP' }, { values: pv100 , text: 'PV'} ] }; Полный код под спойлеромSPL<!DOCTYPE html>
<html> <head> <meta charset="utf-8"> <title>График</title> <script src="https://cdn.zingchart.com/zingchart.min.js"></script> <style> html, body, #myChart { width: 100%; height: 100%; } input { width: 25%; text-align:center; } td { background-color: peachpuff; text-align: center; } </style> </head> <body> <table align="center" oninput="setvalues ();"> <tr> <td> Process parameters <br> Gain: <input id="gain" type="number" value ="1" ><br> Time Constant: <input id="time" type="number" value ="100" ><br> </td> <td> Control parameters <br> SetPoint(0-100): <input id="sp" type="number" value ="50"><br> Hysteresis: <input id="hyst" type="number" value ="2">%<br> </td> <td> Plot parameters <br> Points: <input id="points" type="number" value ="250"><br> Animation: <input type="checkbox" id="animation"> </td> </tr> </table> <script> setTimeout('setvalues ()', 0); function setvalues (){ let gain = document.getElementById('gain').value; let time = document.getElementById('time').value; let sp = document.getElementById('sp').value; let points = document.getElementById('points').value; let hyst = document.getElementById('hyst').value; let anim = document.getElementById('animation').checked ? +1 : 0; let pv = []; // массив данных процесса let pv100 = []; //то же но *100 let op = []; // управляющий сигнал 1 вкл, 0 выкл let pvp = 0; //предыдущее значение процесса let low = sp-sp*hyst/100; //нижняя граница гистерезиса let high = +sp+(sp*hyst/100); //верхняя граница гистерезиса let st=true; // старт нагрева for (var i=0;i<points;i++) { if (pvp<=(low/100)) { st=true; op[i]=1; } else if (pvp<=(high/100)&& st) op[i] = 1; else { st=false; op[i]=0;} let a = Math.pow(2.71828182845904, -1/time); let b = gain*(1 -a); pv[i] = op[i]*b+pvp*a; pv100[i] = pv[i]*100; pvp = pv[i]; } ZC.LICENSE = ["569d52cefae586f634c54f86dc99e6a9", "b55b025e438fa8a98e32482b5f768ff5"]; var myConfig = { type: "line", "plot": { "animation": { "effect": anim, "sequence": 2, "speed": 200, } }, legend: { layout: "1x2", //row x column x: "20%", y: "5%", }, crosshairX:{ plotLabel:{ text: "%v" } }, "scale-y": { item: { fontColor: "#7CA82B" }, markers: [ { type: "area", range: [low, high], backgroundColor: "#d89108", alpha: 0.7 }, { type: "line", range: [sp], lineColor: "#7CA82B", lineWidth: 2, label: { //define label within marker text: "SP = "+sp, backgroundColor: "white", alpha: 0.7, textAlpha: 1, offsetX: 60, offsetY: -5 } }] }, scaleX: { zooming: true }, 'scale-y-2': { values: "0:1" }, series: [ { scales: "scale-x,scale-y-2", values: op , 'legend-text': 'OP' }, { values: pv100 , text: 'PV'} ] }; zingchart.render({ id: 'myChart', data: myConfig, height: "90%", width: "100%" }); } </script> <div id='myChart'></div> </body> </html> Ну а поскольку симулятор готов, самое время заценить как он работает. Стандартная настройка: усилительное звено 1, постоянная времени 100 секунд, гистерезис 2% Теперь если задать уставку побольше, например 92, то внезапно процесс сильно замедляется, хотя при этом уставку 50 он набирает за те же 71 секунды, но уже потом кривая начинает приближаться к заданию медленнее по экспоненциальной зависимости, и доходит до уставки лишь за 278 секунд, из-за чего пришлось расширить диапазон построения графика до 300 точек Данный пример очень показательный, переводя ситуацию на модель с температурой можно сделать такой вывод, что не хватает мощности нагревателя: нагреватель загружен на 100% но при этом температура перестает расти после определенного момента. Решений может быть несколько: поставить второй такой же нагревательный элемент, или подавать напряжение на него в 2 раза больше (но это может повредить тэн), либо поставить нагреватель в 2 раза большей мощности, либо залить в систему более теплопроводящую жидкость если речь идет о нагреве жидкости. Довольно интересно то, что если нужно поддерживать температуру в районе 95-100 градусов, то не нужно даже ставить регулятор — поставил такой маломощный нагреватель, врубил его на полную катушку и все — через 300 секунд (условные 300 секунд) можно получить желаемые 100 градусов. Проблема такой системы в том что если открыть окно зимой в минус 40, то температура тут же просядет и довольно существенно, да и быстродействие такой системы очень малое. Давайте увеличим усилительное звено gain в 2 раза — это как будто поставить второй такой же нагревательный элемент, или добавить еще одну трубу на пополнение бака. График получился тоже довольно показательный — температура до 51 градуса реально добралась в 2 раза быстрее, а вот до 92 добралось раза в 4 быстрее. Не знаю насколько такой симулятор приближен к реальным процессам, но поскольку заданная в нем зависимость экспоненциальная, то это вполне ожидаемое поведение системы, но вот объяснить с позиции добавления второй трубы и увеличение скорости заполнения в 4 раза я даже не могу предположить. Реакция линейной функции была бы более предсказуемой на увеличение коэффициента, но реальные системы в жизни редко бывают линейными =========== Источник: habr.com =========== Похожие новости:
|
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 13:57
Часовой пояс: UTC + 5