Erstellen eines JavaScript-Ein-Aus-Controller-Simulators

Die Essenz der Theorie der automatischen Steuerung impliziert den Aufbau eines solchen Systems, das einen bestimmten Parameter eines Objekts in einem bestimmten Zustand beibehält, beispielsweise die Temperatur in einem Ofen oder den Wasserstand in einem Tank. Für ein besseres Verständnis des Prozesses ist es zweckmäßig, sofort ein bestimmtes Steuerungsmodell in Betracht zu ziehen, beispielsweise die Steuerung des Wasserstandes in einem Tank. Übrigens wird dieser Prozess in Lehrbüchern und Artikeln über TAU ziemlich oft als Hinweis auf die Geschichte erwähnt, weil der russische Erfinder I.I. entwickelte ein Wasserstandsregelungssystem für seine Dampfmaschine. Eine Art klassischer Regler, der übrigens im Wesentlichen wie in diesem Bild ein Regler mit zwei Positionen ist (es gibt kein Wasser - öffnen Sie das Ventil, es gibt Wasser, schließen Sie das Ventil).







Es ist zwei Positionen, weil es zwei Positionen hat: offen (ein) und geschlossen (aus), in der englischsprachigen Literatur ein-aus. Es gibt auch drei oder mehr Positionsregler, dh das Wassernachfüllventil ist in den Hauptpositionen geöffnet oder geschlossen, und die Position "leicht geöffnet" wird hinzugefügt. Nach dem Ablassen des Wassers in der Toilette geht der Schwimmer nach unten, öffnet das Ventil vollständig und das Wasser tritt mit vollem Druck in den Tank ein. Näher am Erreichen des eingestellten Niveaus steigt der Schwimmer an, schließt das Ventil und verringert den Wasserfluss. Und sobald der aktuelle Wasserstand (auf Englisch PV - Prozesswert - Aktueller Wert ) auf den eingestellten Wert (auf Englisch SP - Sollwert - Sollwert ) ansteigt) schließt das Ventil und der Wasserstand steigt nicht mehr an. Im beschriebenen Fall ist die Steuerung der proportionalen noch ähnlicher - die Steueraktion nimmt mit abnehmender Fehlanpassung (Fehler) ab, dh der Differenz zwischen dem eingestellten und dem aktuellen Pegel.



Durch leichtes Öffnen des unteren Rohrs zum Ablassen des Wassers kann ein solcher Zustand erreicht werden, wenn das Ventil vollständig geöffnet ist und der Wasserstand nicht abnimmt (dh der Wasserzufluss wird gleich der Quelle) - das System befindet sich in einem Gleichgewichtszustand. Das Problem ist jedoch, dass dieser Zustand sehr prekär ist - jede äußere Störung kann dieses Gleichgewicht stören -, sagen wir, wir können etwas Wasser aus dem Tank schöpfen, und dann kann es vorkommen, dass das gesamte Wasser aus dem Tank fließt (aufgrund der Druckänderung), oder Das Nachfüllrohr wird verstopft und der Durchfluss nimmt ab, oder der Schwimmer bricht und das Wasser läuft über. Dies ist die Komplexität von Gebäudesteuerungssystemen - reale Systeme sind recht komplex und weisen viele Merkmale auf, die berücksichtigt werden müssen.Es gibt eine solche Eigenschaft wie die Trägheit des Systems - wenn Sie den beheizten Ofen ausschalten, bleibt er ziemlich lange heiß, weshalb komplexere Regler zur Steuerung der Temperatur verwendet werden, nämlichPID - Proportional Integral Differential . Jede der Komponenten hat ihre eigenen Eigenschaften - sie verhalten sich alle unter verschiedenen Bedingungen unterschiedlich, aber wenn sie zusammen verwendet werden, ermöglichen sie eine ziemlich klare Regulierung. Alle diese Systeme werden nach Formeln berechnet, aber in diesem Fall ist es nur wichtig zu verstehen, wie sich das System verhält, wenn sich die PID-Reglerkoeffizienten ändern: Mit einer Erhöhung der Proportionalverbindung steigt die anfängliche Auswirkung und somit kann das System die erforderlichen Parameter schnell erreichen. Wenn Sie es jedoch übertreiben, kann es zu einem Überschwingen kommen, das sogar noch schlimmer sein kann als die niedrige Geschwindigkeit des Systems.



Während der Existenz von TAU wurden mathematische Beschreibungen vieler Prozesse gefunden, und jetzt können wir vorhersagen, wie sich das System unter bestimmten Umständen verhalten wird. Es gibt viele Simulationsprogramme, in denen Sie die Parameter des Systems einstellen, die Parameter des Reglers einstellen und grob sehen können, was daraus werden wird. Als ich im Internet herumging, stieß ich auf eine Excel-Site für Ingenieure, und es gibt mehrere Simulatoren für Regulierungsbehörden, dank derer Sie die Änderung des Prozesses beim Ändern der Kontrollfaktoren betrachten können. Am einfachsten zu wiederholen war natürlich die EIN-AUS-Steuerung., das heißt auf Russisch, ein Regler mit zwei Positionen. Ich möchte Sie an das Funktionsprinzip erinnern: Wenn der aktuelle Prozesswert (Prozesswert = PV) die Temperatur ist, die beispielsweise unter dem Sollwert (SP) liegt, schaltet sich der Regler ein (OP) - die Heizelemente werden mit voller Leistung gestartet. Sobald die Temperatur den Sollwert erreicht, schaltet der Regler die Spannungsversorgung der Heizelemente ab.



Erstellen eines JavaScript-Simulators



Um ein Diagramm zu erstellen, werde ich die ZingChart-Bibliothek verwenden - es stellte sich heraus, dass sie recht einfach und benutzerfreundlich ist. Es gibt viele Beispiele in der Dokumentation, für die Sie überhaupt etwas erstellen können. Das Darstellungsprinzip ist recht einfach: Es gibt eine Reihe von Werten, die automatisch in der angegebenen Reihenfolge in das Diagramm eingefügt werden. Daher wird aus einigen hundert Punkten ein kontinuierliches Prozessdiagramm angezeigt. Übrigens wird im Original in Excel alles auf die gleiche Weise gemacht - 300 Werte werden generiert und ein Diagramm erstellt.



Tatsächlich ist die Generierung von Werten am schwierigsten, nämlich die Schwierigkeit, einen Prozess korrekt zu beschreiben, der korrekt auf unsere Steuerungsmaßnahmen reagiert - Einschalten der Heizelemente - Temperatur steigt, Ausschalten - fällt, und die Trägheit des Systems muss hier angegeben werden. Darüber hinaus kann die Heizumgebung unterschiedlich sein und einige Medien erwärmen und kühlen schneller ab und andere umgekehrt. Wenn wir den Füllstand einstellen, steigt der Füllstand bei gleichem Durchfluss von oben in dem Tank, in dem der Bodenbereich kleiner ist, höher an. All dies führe dazu, dass der Prozess auch von der Übertragung (Verstärkung) abhängt. Im Original wurde auch ein Verzögerungsparameter in den Prozess eingeführt (nun, da das System nicht sofort auf das Steuersignal reagiert), aber ich habe beschlossen, es aufzugeben - zwei sind genug. Aber ich habe eine Änderung in der Einstellung hinzugefügt,Obwohl sich herausstellte, dass sich der Sollwert von Null auf 100 ändern kann, beginnt sich der Prozess über 100 anders zu verhalten, und anscheinend liegt der Grund darin, dass die Prozessformel universell ist und keinen bestimmten Fall beschreibt. Beginnen wir im Allgemeinen:



Wir erstellen 5 Felder für die Eingabe von Parametern, fügen all dies in eine Tabelle ein, die wir oben in CSS in einer schönen Farbe malen, und platzieren sie in der Mitte:



<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>


Wie Sie sehen, wird jedes Mal, wenn sich der Wert der Felder in der Tabelle ändert, die Funktion setvalues ​​() aufgerufen. Darin lesen wir Daten aus jedem Feld in spezielle Variablen.



	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;


Wie bereits erwähnt, benötigen Sie zum Erstellen eines Diagramms Arrays mit Daten, auf deren Grundlage das Diagramm erstellt wird. Daher erstellen wir eine Reihe von Arrays:



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; //  


Lassen Sie mich ein wenig über die Hysterese erklären. Die Situation ist folgende: Wenn die Temperatur den eingestellten Wert erreicht, werden die Heizelemente ausgeschaltet und sofort (tatsächlich nicht sofort, weil Trägheit vorliegt) beginnt der Kühlprozess. Und nachdem das System um ein Grad oder sogar einen Bruchteil eines Grads abgekühlt ist, stellt es fest, dass es bereits wieder über den Aufgabenbereich hinausgegangen ist und die Heizelemente wieder eingeschaltet werden müssen. In diesem Modus schalten sich die Heizelemente sehr oft ein und aus, vielleicht sogar mehrmals pro Minute - für Geräte ist dieser Modus nicht sehr gut, und um solche Schwankungen auszuschließen, wird die sogenannte Hysterese eingeführt - Totband - Totband - sagen wir 1 Grad höher und Unterhalb des Sollwerts werden wir nicht reagieren, und dann kann die Anzahl der Schaltvorgänge erheblich reduziert werden. Daher ist die Variable low die untere Grenze des Sollwerts und die Variable high die obere.Die Variable st verfolgt das Erreichen der obersten Ebene und lässt den Prozess nach unten fallen. Die Logik des gesamten Prozesses ist in einer Schleife:



	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];
	}


Als Ergebnis erhalten wir ein Array mit einer bestimmten Anzahl von Punkten, das wir an das Diagrammskript senden.



scaleX: {
 	zooming: true
  },
      series: [
		{ values: op , text: 'OP' },
        { values: pv100 , text: 'PV'}
      ]
    };


Vollständiger Code unter dem Spoiler
<!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>




Nun, da der Simulator bereit ist, ist es Zeit zu überprüfen, wie es funktioniert. Sie können hier den gleichen Code testen, jedoch auf dem Github: Ein -Aus-Steuersimulator



Standardeinstellung: Verstärkerverbindung 1, Zeitkonstante 100 Sekunden, Hysterese 2%







Wenn Sie nun eine größere Einstellung einstellen, z. B. 92, verlangsamt sich der Prozess plötzlich erheblich, obwohl die Einstellung 50 ist es gewinnt in den gleichen 71 Sekunden, aber erst dann nähert sich die Kurve der Aufgabe langsamer exponentiell und erreicht den Sollwert in nur 278 Sekunden, weshalb der Plotbereich auf 300 Punkte erweitert werden musste







Dieses Beispiel ist sehr anschaulich und übersetzt die Situation in ein Modell mit Temperatur. Wir können daraus schließen, dass nicht genügend Heizleistung vorhanden ist: Die Heizung ist zu 100% ausgelastet, aber die Temperatur steigt nach einem bestimmten Moment nicht mehr an. Es kann mehrere Lösungen geben: Legen Sie ein zweites Heizelement desselben an oder legen Sie 2-mal mehr Spannung an (dies kann jedoch das Heizelement beschädigen), oder stellen Sie eine Heizung mit 2-mal mehr Leistung ein oder gießen Sie beim Heizen eine wärmeleitende Flüssigkeit in das System Flüssigkeiten. Es ist sehr interessant, dass Sie, wenn Sie die Temperatur im Bereich von 95 bis 100 Grad halten müssen, nicht einmal den Regler aufstellen müssen - setzen Sie eine so stromsparende Heizung ein, schneiden Sie sie in vollen Zügen und das wars - nach 300 Sekunden (bedingte 300 Sekunden) können Sie die gewünschten 100 Grad erreichen.Das Problem bei einem solchen System ist, dass, wenn Sie im Winter ein Fenster bei minus 40 öffnen, die Temperatur sofort und erheblich sinkt und die Leistung eines solchen Systems sehr gering ist.



Erhöhen wir den Verstärkungsbereich um das Zweifache - es ist so, als würden Sie ein zweites Heizelement des gleichen Typs installieren oder ein weiteres Rohr hinzufügen, um den Tank wieder aufzufüllen.







Die Grafik erwies sich auch als ziemlich bezeichnend - die Temperatur erreichte 51 Grad, erreichte tatsächlich 2-mal schneller, erreichte aber 92 Grad 4-mal schneller. Ich weiß nicht, wie nahe ein solcher Simulator an realen Prozessen liegt, aber da die darin angegebene Abhängigkeit exponentiell ist, ist dies ein vollständig erwartetes Verhalten des Systems, aber ich kann mir nicht einmal vorstellen, es aus der Perspektive des Hinzufügens eines zweiten Rohrs und des Erhöhens der Füllrate um das Vierfache zu erklären. Die Reaktion einer linearen Funktion wäre für eine Erhöhung des Koeffizienten vorhersehbarer, aber reale Systeme im Leben sind selten linear.



All Articles