Pid и ручное управление

Здравствуйте. Знает кто-нибудь, или, может, есть у кого-то готовое решение: как сделать работающий ПИД-регулятор для насоса с тремя скоростями, да и с возможностью ручного управления? Отпишитесь, если есть какие-то идеи. Заранее благодарен.

есть простенький скрипт для 2-х каналов ПД регулирования. но в качестве управляющего сигнала используются 0…10В, доп.модули в WB, если надо - опубликую

Прошу, если несложно. Но хотелось бы еще и с ручным управлением видеть. У Вас оно случаем не предусмотрено?

Предусмотрено. Обратная связь с датчиков ds с конкретными адресами, что легко меняется.
Ниже содержимое rules.js:

(function(){

var pidTick=null;
var pidInterval=5000;
var temp1_prev=null;
var temp2_prev=null;

defineVirtualDevice("AOmanualTune", {
	title: "Ручное управление",
  	cells: {
    	ao1 : {
       		type : "range",
       		value : 50,
       		max : 100
    		},
    	ao2 : {
       		type : "range",
       		value : 50,
       		max : 100
    		},
    	enabled : {
       		type : "switch",
       		value : false
    		}
  		}
	});

defineRule("AO1set", {
	whenChanged: [ "AOmanualTune/ao1", "AOmanualTune/enabled" ],
	then: function () {
    	if ( dev["AOmanualTune"]["enabled"] ) {
   			dev["wb-dac"]["MOD1_O1"]=(dev["AOmanualTune"]["ao1"])*100;
  			}
  		}
	});

defineRule("AO2set", {
	whenChanged: [ "AOmanualTune/ao2", "AOmanualTune/enabled" ],
	then: function () {
	   	if ( dev["AOmanualTune"]["enabled"] ) {
    		dev["wb-dac"]["MOD1_O2"]=(dev["AOmanualTune"]["ao2"])*100;
   			}
  		}
	});


defineVirtualDevice("PID1_set", {
	title: "Уставки 1 регулятора",
  	cells: {
    	prop : {
       		type : "range",
       		value : 15,
       		max : 100
    		},
    	diff : {
       		type : "range",
       		value : 1500,
       		max : 5000
    		},
      	tset : {
          	type : "range",
          	value : 61,
          	max : 100
        	}
  		}
	});

defineVirtualDevice("PID2_set", {
	title: "Уставки 2 регулятора",
  	cells: {
    	prop : {
       		type : "range",
       		value : 20,
       		max : 100
    		},
    	diff : {
       		type : "range",
       		value : 1500,
       		max : 5000
    		},
      	tset : {
          	type : "range",
          	value : 68,
          	max : 100
        	}
  		}
	});


defineRule("PIDstart", {
  	asSoonAs: function(){
      	return ( (!dev["AOmanualTune"]["enabled"]) && (pidTick==null) );
    	},
  	then: function() {
      if(pidTick==null){
      	pidTick=setInterval(function(){
          	if(temp1_prev != null){
          		var t1_step = dev["wb-w1"]["28-000009314f47"] - temp1_prev;
            	var dt1 = dev["wb-w1"]["28-000009314f47"] - dev["PID1_set"]["tset"];
          		var dAO1= ( dt1 * dev["PID1_set"]["prop"] ) + (t1_step * (dev["PID1_set"]["diff"]) * 1000 / pidInterval);
          		var temp = dev["wb-dac"]["MOD1_O1"] - dAO1;
          		if( (temp >= 0) && (temp <=10000) ){
          			dev["wb-dac"]["MOD1_O1"] = temp;
                	}
          		else{
              		if( temp < 0 ){
                  		dev["wb-dac"]["MOD1_O1"]=0;
                    	}
          			else{
                  		if( temp > 10000 ){
                      		dev["wb-dac"]["MOD1_O1"]=10000;
                        	}
                    	}
                	}
            	}
          
          	if(temp2_prev != null){
            	var t2_step = dev["wb-w1"]["28-000009311e75"] - temp2_prev;
            	var dt2 = dev["wb-w1"]["28-000009311e75"] - dev["PID2_set"]["tset"];
            	var dAO2= ( dt2 * dev["PID2_set"]["prop"] ) + (t2_step * (dev["PID2_set"]["diff"]) * 1000 / pidInterval);
             	var temp = dev["wb-dac"]["MOD1_O2"] - dAO2;
          		if( (temp >= 0) && (temp <=10000) ){
                	dev["wb-dac"]["MOD1_O2"] = temp;  
                	}
          		else{
              		if( temp < 0 ){
                  		dev["wb-dac"]["MOD1_O2"]=0;
                    	}
          			else{
                  		if( temp > 10000 ){
                      		dev["wb-dac"]["MOD1_O2"]=10000;
                        	}
                    	}
                	}
            	}
  
          	temp1_prev=dev["wb-w1"]["28-000009314f47"]
         	temp2_prev=dev["wb-w1"]["28-000009311e75"]

        	},pidInterval)
      	  }
   		}
	});

defineRule("PIDstop", {
  	asSoonAs: function(){
      	return (dev.AOmanualTune.enabled && (pidTick != null) );
    	},
  	then: function() {
      	if( pidTick!=null ){
          	clearInterval(pidTick);
          	pidTick=null;
        	}
        temp1_prev=null;
      	temp2_prev=null;
  	
   		}
	});
  
setInterval(function(){
   	dev["AOmanualTune"]["enabled"] = dev["AOmanualTune"]["enabled"];
   	dev["AOmanualTune"]["ao1"] = dev["AOmanualTune"]["ao1"];
    dev["AOmanualTune"]["ao2"] = dev["AOmanualTune"]["ao2"];
  	dev["PID1_set"]["diff"] = dev["PID1_set"]["diff"];
  	dev["PID1_set"]["prop"] = dev["PID1_set"]["prop"];
  	dev["PID1_set"]["tset"] = dev["PID1_set"]["tset"];
  	dev["PID2_set"]["diff"] = dev["PID2_set"]["diff"];
  	dev["PID2_set"]["prop"] = dev["PID2_set"]["prop"];
  	dev["PID2_set"]["tset"] = dev["PID2_set"]["tset"];
   	},60000);

})();
2 лайка

Огромное спасибо! Буду разбираться)

нужен совет) почему при нажатий на кнопку М1 щёлкают все 4 реле? Нужно, чтобы в зависимости от значения (1…3) щёлкали только определённые.

defineRule(“M1set”, {
whenChanged: [“create_nasos/M1”],
then: function(newValue, devName, cellName) {
if (M1 = 1) {
dev[“wb-gpio”][“EXT2_R3A1”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
}
if (M1 = 2) {
dev[“wb-gpio”][“EXT2_R3A2”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
}
if (M1 = 3) {
dev[“wb-gpio”][“EXT2_R3A3”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
}
return M1;
}
});

Потому что M1 = 1 устанавливает значение переменной в 1, а не сравнивает с ним. Для сравнения нужно использовать ==. И заодно не помешает else if, если у вас взаимоисключающие друг-друга условия.

Спасибо, попробую) а ещё параллельный вопрос: почему так не срабатывает, интересно?
defineRule(“M1set”, {
whenChanged: [“create_nasos/M1”],
then: function(newValue, devName, cellName) {
switch (M1) {
case 1:
dev[“wb-gpio”][“EXT2_R3A1”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
break;
case 2:
dev[“wb-gpio”][“EXT2_R3A2”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
break;
case 3:
dev[“wb-gpio”][“EXT2_R3A3”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
break;
case 0:
dev[“wb-gpio”][“EXT2_R3A1”] = newValue;
dev[“wb-gpio”][“EXT2_R3A2”] = newValue;
dev[“wb-gpio”][“EXT2_R3A3”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
break;

я и с else if пробовал, и с ==. Видимо, что-то делаю неверно…

А где у вас объявлена переменная M1?

defineVirtualDevice(“create_nasos”, {
title: “NASOSbI”,
cells: {
M1: {
type: “range”,
value:0,
max:3
},
M2: {
type: “range”,
value:0,
max:3
},
M3: {
type: “range”,
value:0,
max:3
},

Это не объявление переменной M1. Вы создали девайс create_nasos с 3 контролами-слайдерами. Используйте dev["create_nasos/M1"], чтобы получить значение контрола.

Буду знать. Как мне тогда создать и переменную М1, и контрол-слайдер? Мне нужна будет эта переменная для привязки её к функции в другом блоке.

Таким раскладом ничего не происходит:
defineRule(“M1set”, {
whenChanged: [“create_nasos/M1”],
then: function(newValue, devName, cellName) {
if (dev[“create_nasos/M1”] == 1) {
dev[“wb-gpio”][“EXT2_R3A1”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
}
else if (dev[“create_nasos/M1”] == 2) {
dev[“wb-gpio”][“EXT2_R3A2”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;
}
else if (dev[“create_nasos/M1”] == 3) {
dev[“wb-gpio”][“EXT2_R3A3”] = newValue;
dev[“wb-gpio”][“EXT2_R3A4”] = newValue;

Спасибо!