صنع محاكي تحكم جافا سكريبت يعمل على إيقاف التشغيل

يتضمن جوهر نظرية التحكم الآلي بناء مثل هذا النظام الذي يحافظ على معلمة معينة لكائن ما في حالة معينة ، على سبيل المثال ، درجة الحرارة في الفرن ، أو مستوى الماء في الخزان. لفهم العملية بشكل أفضل ، من المناسب التفكير على الفور في نموذج تحكم محدد ، على سبيل المثال ، التحكم في مستوى الماء في الخزان. بالمناسبة ، في الكتب المدرسية والمقالات حول TAU ، يتم ذكر هذه العملية في كثير من الأحيان كمرجع للتاريخ ، لأنه في عام 1763 البعيد المخترع الروسي I.I. طور نظام التحكم في مستوى المياه لمحركه البخاري. نوع من المنظم الكلاسيكي ، والذي ، بالمناسبة ، هو في الأساس منظم ثنائي الموضع كما في هذه الصورة (لا يوجد ماء - افتح الصمام ، يوجد ماء يغلق الصمام).







إنه ذو موقعين لأنه يحتوي على موقعين: مفتوح (مفتوح) ومغلق (مغلق) ، في أدب اللغة الإنجليزية على-إيقاف. هناك أيضًا ثلاثة منظمات موضعية أو أكثر ، أي أن صمام تجديد المياه مفتوح أو مغلق في المواضع الرئيسية ، ويتم إضافة الوضع "المفتوح قليلاً". بعد تصريف الماء في المرحاض ، تنخفض العوامة ، فتفتح الصمام تمامًا ويدخل الماء إلى الخزان بضغط كامل ، ولكن أقرب إلى الوصول إلى المستوى المحدد ، يرتفع العوامة ، ويغلق الصمام ويقلل من تدفق الماء. وبمجرد أن يرتفع مستوى المياه الحالي (باللغة الإنجليزية PV - قيمة العملية - القيمة الحالية ) إلى المجموعة (باللغة الإنجليزية SP - Set Point - Setpoint) ، يغلق الصمام ويتوقف مستوى الماء عن الارتفاع. في الحالة الموصوفة ، يكون المنظم أكثر شبهاً بالمنظم النسبي - يتناقص الإجراء التنظيمي مع تناقص عدم التطابق (الخطأ) ، أي الفرق بين المستوى المحدد والمستوى الحالي.



من خلال فتح الأنبوب السفلي قليلاً لتصريف المياه ، سيكون من الممكن تحقيق مثل هذه الحالة عندما يكون الصمام مفتوحًا بالكامل ، ولا ينخفض ​​مستوى الماء (أي أن تدفق المياه إلى الداخل يصبح مساوياً للمصدر) - يدخل النظام في حالة توازن. لكن المشكلة هي أن هذه الحالة محفوفة بالمخاطر - أي اضطراب خارجي يمكن أن يكسر هذا التوازن - دعنا نقول أنه يمكننا أخذ كمية معينة من الماء من الخزان ، وبعد ذلك قد يحدث أن كل الماء سوف يتدفق بعد ذلك من الخزان (بسبب تغير الضغط) ، أو سيصبح أنبوب الإمداد مسدودًا وسيقل التدفق ، أو ينكسر العوامة وتفيض المياه. هذا هو تعقيد أنظمة التحكم في المبنى - الأنظمة الحقيقية معقدة للغاية ولها العديد من الخصائص التي يجب أخذها في الاعتبار.هناك خاصية مثل القصور الذاتي للنظام - إذا قمت بإيقاف تشغيل اللوح المسخن ، فسيظل ساخنًا لفترة طويلة ، وهذا هو السبب في استخدام منظمات أكثر تعقيدًا للتحكم في درجة الحرارة ، أيPID - التفاضل النسبي المتكامل . كل مكون له خصائصه الخاصة - فجميعها تتصرف بشكل مختلف في ظل ظروف مختلفة ، ولكن عند استخدامها معًا ، فإنها تتيح تحقيق تنظيم واضح إلى حد ما. يتم حساب كل هذه الأنظمة وفقًا للصيغ ، ولكن في هذه الحالة من المهم فقط فهم كيفية تصرف النظام عندما تتغير معاملات وحدة التحكم PID: مع زيادة الارتباط النسبي ، يزداد التأثير الأولي وبالتالي سيكون النظام قادرًا على تحقيق المعلمات المطلوبة بسرعة. ولكن إذا تجاوزت الأمر ، فقد يظهر التجاوز ، والذي يمكن أن يكون أسوأ من السرعة المنخفضة للنظام.



أثناء وجود TAU ، تم العثور على أوصاف رياضية للعديد من العمليات ، والآن يمكننا التنبؤ بكيفية تصرف النظام في ظل ظروف معينة. هناك العديد من برامج المحاكاة حيث يمكنك تعيين معلمات النظام ، وتعيين معلمات المنظم ومعرفة ما سيأتي منه تقريبًا. بالمشي عبر الإنترنت ، صادفت موقع Excel للمهندسين ، وهناك العديد من محاكيات المنظمين ، وبفضل ذلك يمكنك النظر إلى التغيير في العملية عند تغيير عوامل التحكم. أسهل طريقة للتكرار كانت ، بالطبع ، التحكم ON-OFF.، وهذا هو ، باللغة الروسية ، منظم ذو موقعين. دعني أذكرك بمبدأ التشغيل: إذا كانت قيمة العملية الحالية (قيمة العملية = PV) هي درجة الحرارة ، على سبيل المثال ، أقل من نقطة الضبط (SP) ، يتم تشغيل المنظم (OP) - تبدأ عناصر التسخين بكامل طاقتها. بمجرد أن تصل درجة الحرارة إلى نقطة الضبط ، يقوم المنظم بإيقاف تشغيل مصدر الجهد لعناصر التسخين.



صنع محاكي جافا سكريبت



لإنشاء مخطط ، سأستخدم مكتبة ZingChart - اتضح أنها بسيطة للغاية وسهلة الاستخدام. هناك العديد من الأمثلة في الوثائق التي يمكنك بناء أي شيء عليها على الإطلاق. مبدأ الرسم بسيط للغاية - هناك مجموعة من القيم التي يتم وضعها تلقائيًا على الرسم البياني بالترتيب ، وبالتالي يظهر الرسم البياني للعملية المستمرة من بضع مئات من النقاط. بالمناسبة ، في الأصل في Excel ، يتم كل شيء بنفس الطريقة - يتم إنشاء 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 - deadband - قل درجة واحدة أعلى و أسفل نقطة الضبط ، لن نتفاعل ، ومن ثم يمكن تقليل عدد المحولات بشكل كبير. لذلك ، فإن القاع المتغير هو الحد الأدنى لنقطة الضبط ، والارتفاع المتغير هو الحد العلوي.المتغير 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="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٪ ، لكن درجة الحرارة تتوقف عن الارتفاع بعد لحظة معينة. قد يكون هناك عدة حلول: لوضع عنصر تسخين ثانٍ من نفس الشيء ، أو تطبيق الجهد عليه مرتين أكثر (ولكن هذا يمكن أن يضر بعنصر التسخين) ، أو لوضع سخان بقوة مرتين أكثر ، أو صب سائل أكثر توصيلًا للحرارة في النظام عندما يتعلق الأمر بالتسخين السوائل. من المثير للاهتمام أنه إذا كنت بحاجة إلى الحفاظ على درجة الحرارة في منطقة 95-100 درجة ، فلن تحتاج حتى إلى وضع المنظم - ضع مثل هذا السخان منخفض الطاقة ، وقم بتشغيله على أكمل وجه وهذا كل شيء - بعد 300 ثانية (300 ثانية شرطية) يمكنك الحصول على 100 درجة المطلوبة.تكمن مشكلة مثل هذا النظام في أنه إذا فتحت النافذة في الشتاء عند سالب 40 ، فسوف تنخفض درجة الحرارة على الفور وبشكل كبير جدًا ، ويكون أداء هذا النظام منخفضًا جدًا.



دعنا نزيد قسم الكسب مرتين - إنه مثل تثبيت عنصر تسخين ثان من نفس النوع ، أو إضافة أنبوب آخر لتجديد الخزان.







تبين أن الرسم البياني أيضًا دلالة تمامًا - وصلت درجة الحرارة إلى 51 درجة في الواقع أسرع مرتين ، لكنها وصلت 92 درجة 4 مرات أسرع. لا أعرف مدى قرب مثل هذا المحاكي من العمليات الحقيقية ، ولكن نظرًا لأن الاعتماد المحدد فيه أسي ، فهذا سلوك متوقع تمامًا للنظام ، لكن لا يمكنني حتى أن أتخيل الشرح من منظور إضافة أنبوب ثانٍ وزيادة معدل التعبئة بمقدار 4 مرات. ستكون استجابة دالة خطية أكثر قابلية للتنبؤ بزيادة المعامل ، لكن الأنظمة الحقيقية في الحياة نادرًا ما تكون خطية.



All Articles