Pid регулятор на wb_rule

Коллеги, добрый день! Нашел тему по поводу PID. Не могу запустить. В виртуальное устройство ничего не прилетает, log пустой. Кто-нибудь сможет этот скрипт выложить готовым, чтобы скопировал-вставил и можно было поиграться с входом-выходом PID.
Pid регулятор - топик, скрипт с которого не могу запустить.
Спасибо!

Добрый день.
Опишите подробнее, что вы делаете.
Какие в итоге у вас созданы правила, виртуальные устройства. Что от низ ожидаете получить и что получаете. Не понятно, что из приведенной темы вы сделали.

Я создаю новое правило, вставляю туда код:



 // Виртуальное устройство для теста
defineVirtualDevice("DevTest", {
title: "Test",
cells: {
enabled: {
type: "range",
value: 27,
max: 34,
min: 26
},
log: {
type: "text",
value: false,
max: 100
},
kp1: {
type: "range",
value: 2,
min: 0,
max: 100,

},
}
});
// Начало кода PID регулятора
var Pid = function(opts) { //Конструктор объектов
opts = opts || {};
this._target = opts.target //|| 0;
this._kp = opts.kp || 0;
this._ki = opts.ki || 0;
this._kd = opts.kd || 0;
this._outputMin = opts.outputMin || 0;
this._outputMax = opts.outputMax === undefined ? 1 : opts.outputMax;
this._lastTime = null;
this._intervalId = null;
};

Pid.prototype.clip = function(x, min, max) { //Функция ограничения выходных значений регулирующего устройства
if (x < min){
return min;
} else if (x > max) {
return max;
} else {
return x;
}
};

Pid.prototype._clearErrors = function() { //Функция очистки накопленной ошибки PID регулятора
this._sumError = 0;
this._lastError = 0;
this._lastTime = null;
};

Pid.prototype.setup = function(opts) {
this._target = opts.target === undefined ? this._target : opts.target;
this._kp = opts.kp === undefined ? this._kp : opts.kp;
this._ki = opts.ki === undefined ? this._ki : opts.ki;
this._kd = opts.kd === undefined ? this._kd : opts.kd;
this._outputMin =
opts.outputMin === undefined ? this._outputMin : opts.outputMin;
this._outputMax =
opts.outputMax === undefined ? this._outputMax : opts.outputMax;
this._clearErrors();
};

Pid.prototype.tune = function(opts) {
this._kp += opts.kp || 0;
this._ki += opts.ki || 0;
this._kd += opts.kd || 0;
this._clearErrors();
};

Pid.prototype.update = function(input) { //Функция PID регулятора
var date = new Date();
var dt = date.getTime() - this._lastTime;
var error = this._target - input;
var dError = 0;
var integralNormalized = 0;
var differential = 0;

if (this._lastTime) {
dError = error - this._lastError;
this._sumError += error;
integralNormalized = this._ki * this._sumError * dt;
differential = (this._kd * dError) / dt;
integralNormalized = this.clip(
integralNormalized,
this._outputMin,
this._outputMax
);

} else {
this._clearErrors();
}

var output = this._kp * error + integralNormalized - differential;

output = this.clip(output, this._outputMin, this._outputMax);
this._lastError = error;
var date = new Date();
this._lastTime = date.getTime();
return output;
};

Pid.prototype.run = function(repeat, interval) {
if (!this._intervalID) {
this._intervalID = setInterval(repeat, interval * 1000);
this._clearErrors();
}
};

Pid.prototype.stop = function() {
if (this._intervalID) {
clearInterval(this._intervalID);
}
this._intervalID = null;
};
//Создаем объект с нужными параметрами PID регулятора

var myControl = new Pid({
target: 20, // требуемая величина выходного значения
kp: 0.5, // пропорциональная составляющая
ki: 5, // интегральная составляющая
kd: 0.1, // дифференциальная составляющая
outputMin: 0, // минимальное значение выхода
outputMax: 10 // максимальное значение выхода
});

myControl.run(function() {

var input = dev["DevTest"]["enabled"]; //Входное значение от виртуального устройства
var output = myControl.update(input); //Выходное значение
dev["DevTest"]["log"] = String(output); //Выходное значение передаем в виртуальное устройство
dev["TestAnalog"]["Channel 1"] = String(output);
myControl.kp = dev["DevTest/kp1"]; //Пример для подбора параметров PID
myControl.setup(myControl); //Пример для подбора параметров PID
}, 2); //Интервал запуска ПИД-регулятора каждые 200 мс

На сколько я понимаю в Log виртуального устройства должен увидеть значение пид (0-10В). При изменении значения Test (видимо температура) и уставке 20 должно меняться значение Log.
Лог стоит в 0.
Иными словами мне нужен этот код таким, чтобы я его вставил, и играясь крутилкой Test у меня хотябы значение Log менялось

// Виртуальное устройство для теста
defineVirtualDevice("DevTest", {
title: "Test",
cells: {
enabled: {
type: "range",
value: 27,
max: 34,
min: 26
},
setpoint: {
type: "range",
value: 20, // какое-то значение по умолчанию
min: -1, // минимальное значение уставки
max: 45 // максимальное значение уставки
},
log: {
type: "text",
value: false,
max: 100
},
kp1: {
type: "range",
value: 2,
min: 0,
max: 10,
}
},
});
// Начало кода PID регулятора
var Pid = function(opts) { //Конструктор объектов
opts = opts || {};
this._target = opts.target //|| 0;
this._kp = opts.kp || 0;
this._ki = opts.ki || 0;
this._kd = opts.kd || 0;
this._outputMin = opts.outputMin || 0;
this._outputMax = opts.outputMax === undefined ? 1 : opts.outputMax;
this._lastTime = null;
this._intervalId = null;
};

Pid.prototype.clip = function(x, min, max) { //Функция ограничения выходных значений регулирующего устройства
if (x < min){
return min;
} else if (x > max) {
return max;
} else {
return x;
}
};

Pid.prototype._clearErrors = function() { //Функция очистки накопленной ошибки PID регулятора
this._sumError = 0;
this._lastError = 0;
this._lastTime = null;
};

Pid.prototype.setup = function(opts) {
this._target = opts.target === undefined ? this._target : opts.target;
this._kp = opts.kp === undefined ? this._kp : opts.kp;
this._ki = opts.ki === undefined ? this._ki : opts.ki;
this._kd = opts.kd === undefined ? this._kd : opts.kd;
this._outputMin =
opts.outputMin === undefined ? this._outputMin : opts.outputMin;
this._outputMax =
opts.outputMax === undefined ? this._outputMax : opts.outputMax;
this._clearErrors();
};

Pid.prototype.tune = function(opts) {
this._kp += opts.kp || 0;
this._ki += opts.ki || 0;
this._kd += opts.kd || 0;
this._clearErrors();
};

Pid.prototype.update = function(input) { //Функция PID регулятора
var date = new Date();
var dt = date.getTime() - this._lastTime;
var error = this._target - input;
var dError = 0;
var integralNormalized = 0;
var differential = 0;

if (this._lastTime) {
dError = error - this._lastError;
this._sumError += error;
integralNormalized = this._ki * this._sumError * dt;
differential = (this._kd * dError) / dt;
integralNormalized = this.clip(
integralNormalized,
this._outputMin,
this._outputMax
);

} else {
this._clearErrors();
}

var output = this._kp * error + integralNormalized - differential;

output = this.clip(output, this._outputMin, this._outputMax);
this._lastError = error;
var date = new Date();
this._lastTime = date.getTime();
return output;
};

Pid.prototype.run = function(repeat, interval) {
if (!this._intervalID) {
this._intervalID = setInterval(repeat, interval * 1000);
this._clearErrors();
}
};

Pid.prototype.stop = function() {
if (this._intervalID) {
clearInterval(this._intervalID);
}
this._intervalID = null;
};
//Создаем объект с нужными параметрами PID регулятора

var myControl = new Pid({
target: 20, // требуемая величина выходного значения
kp: 0.5, // пропорциональная составляющая
ki: 5, // интегральная составляющая
kd: 0.1, // дифференциальная составляющая
outputMin: 0, // минимальное значение выхода
outputMax: 10 // максимальное значение выхода
});

myControl.run(function() {

var input = dev["DevTest"]["enabled"]; //Входное значение от виртуального устройства
var output = myControl.update(input); //Выходное значение
var output = Math.round(output *100);
myControl.target = dev["DevTest"]["setpoint"];
dev["DevTest"]["log"] = String(output * 10); //Выходное значение будет писаться в лог
dev["wb-mao4_202"]["Channel 1"] = Number(output * 10); //Выходное значение будет записываться в модуль выхода 0-10в
myControl.kp = dev["DevTest/kp1"]; //Пример для подбора параметров PID
myControl.setup(myControl); //Пример для подбора параметров PID
}, 2); //Интервал запуска ПИД-регулятора каждые 200 мс

Здесь dev[“DevTest”][“setpoint”] - уставка
dev[“DevTest”][“enabled”] - то с чем уставка сравнивается

1 лайк

Где у вас описано? И какого типа?

Спасибо! В лог пишутся данные. Подскажите пожалуйста, как выяснить работает ПИД на оброгрев или охлаждение? Какой параметр отвечает за это? Судя по всему текущий конфиг ПИДа работает на обогрев.

Он работает так, как настроите) в данном случае кран открывается при понижении температуры относительно уставки

А как настроить на охлаждение? Подскажите пожалуйста новичку-юзеру)

На приводе всегда есть переключатель, в какую сторону крутить при 10в на входе)
ПИД работает на уравнивание параметров, у него нет обогрева или охлаждения

1 лайк

ПИД1
ПИД2
Если температура ниже установки - идет регулироваание, если выше - то не идет
Мне нужно наоборот. Если температура выше - чтобы шло регулирование, ниже- прекращалось

Коллеги, подскажите пожалуйста, как доработать этот код, чтобы выходное значение увеличивалось при увеличении температуры (ПИД работал на охлаждение).

Как вам писали выше, ПИД-регулятор - это не утюг. Это я про разные принципы регулирования.
ПИД-регулятор стремится удержать регулируемую величину в нужном (заданном) значении за счет изменения изменения регулирующего параметра.
Опишите, что вы пытаетесь регулировать и каким параметром.

В данном примере Enabled- температура с импровизированного датчика, setpoint -уставка текущей температуры. Если enabled<Setpoint, происходит регулирование, если enabled>setpoint, то выходное значение ПИД=0, регулирования не происходит.
Мне нужно наоборот, чтобы происходило регулирование, когда температура с импровизированного датчика (enabled) больше температуры установки (Setpoint)

Ну так знак ошибки смените, не вижу проблемы, собственно.

В упор не могу сообразить где этот знак ошибки… Ткните пожалуйста пальцем.

Спасибо, вроде разобрался :slight_smile:

Вопрос немного не по теме, но где можно почитать про наследуемые методы, такие как: clip, tune, update, run и т.д? Не получается найти.
В коде они не вызываются явно, хотелось бы изучить этот скрытый механизм.

1 лайк

Вопрос, собственно, не очень понятен. Эти методы и свойства для объекта прямо в коде автор ведь описывает.

Более конкретно - не вижу вызовов методов tune() и stop()

Значит тут они не используются. Я очень плохой программист, к сожалению.

1 лайк