Русский
Русский
English
Статистика
Реклама

Делаем симулятор двухпозиционного регулятора на JavaScript

Суть теории автоматического управления подразумевает построение такой системы, которая поддерживает определенный параметр некоторого объекта в заданном состоянии, например, температуру в печи, или уровень воды в баке. Для лучшего понимания процесса, удобно сразу рассмотреть конкретную модель управления, скажем, управление уровнем воды в баке. Кстати, в учебниках и статьях по ТАУ этот процесс упоминается довольно часто как отсылка к истории, потому что в далеком 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 = []; //то же но *100let 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'}      ]    };

Полный код под спойлером
<!DOCTYPE html><html> <head>  <meta charset="utf-8">  <title>График</title>   <script src="http://personeltest.ru/aways/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 = []; //то же но *100let 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
К списку статей
Опубликовано: 19.11.2020 16:18:00
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Javascript

Промышленная автоматизация

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru