ตัวอย่างการใช้งานและการประยุกต์ใช้ตัวควบคุม ตัวควบคุม PID - คำอธิบายแบบเต็ม แอปพลิเคชัน การประสานงานของอุปกรณ์เอาท์พุตของหน่วยงานกำกับดูแลอย่างต่อเนื่อง
ระบบควบคุมอัตโนมัติ (ACS)ได้รับการออกแบบมาเพื่อเปลี่ยนพารามิเตอร์หนึ่งหรือหลายพารามิเตอร์ของวัตถุควบคุมโดยอัตโนมัติเพื่อสร้างโหมดการทำงานที่ต้องการ ACS ช่วยให้มั่นใจได้ถึงการรักษาความสม่ำเสมอของค่าที่ระบุของพารามิเตอร์ที่ได้รับการควบคุมหรือการเปลี่ยนแปลงตามกฎหมายที่กำหนดหรือปรับเกณฑ์บางอย่างให้เหมาะสมสำหรับคุณภาพของการควบคุม ตัวอย่างเช่น ระบบดังกล่าวได้แก่:
- ระบบรักษาเสถียรภาพ,
- ระบบควบคุมโปรแกรม,
- ระบบติดตาม
นี่เป็นระบบประเภทที่ค่อนข้างกว้างซึ่งสามารถพบได้ทุกที่ แต่สิ่งนี้เกี่ยวอะไรกับ Unity3D และโดยเฉพาะเกม? โดยหลักการแล้ว มันตรงไปตรงมา: ในเกมใดก็ตามที่ใช้การจำลองเป็นองค์ประกอบของการเล่นเกม จะมีการนำปืนอัตตาจรมาใช้ เกมดังกล่าวได้แก่ Kerbal Space Programm, Digital Combat Simulator (เดิมชื่อ Lock On), Strike Suit Zero, ฯลฯ (ใครจะรู้ตัวอย่างเพิ่มเติม - เขียนในความคิดเห็น) โดยหลักการแล้ว เกมใดก็ตามที่จำลองกระบวนการทางกายภาพจริง รวมถึงจลนศาสตร์ที่มีไดนามิกของการเคลื่อนไหว สามารถใช้ปืนที่ขับเคลื่อนด้วยตัวเองได้ - แนวทางนี้ง่ายกว่า เป็นธรรมชาติมากกว่า และผู้พัฒนาก็มีชุดเครื่องมือสำเร็จรูปที่มอบให้โดย Vyshnegradskys, Lyapunovs, Kalmans , Chebyshevs และ Kolomogorovs อื่น ๆ ทุกประเภทดังนั้นคุณสามารถทำได้โดยไม่ต้องสร้างวงล้อใหม่เพราะ มันถูกคิดค้นขึ้นมากจนกลายเป็นวิทยาศาสตร์ที่แยกจากกัน: ทฤษฎีการควบคุมอัตโนมัติ สิ่งสำคัญที่นี่คืออย่าหักโหมจนเกินไป มีปัญหาเดียวคือพวกเขาไม่ได้พูดถึง TAU ทุกที่ ไม่ใช่กับทุกคน มักจะเล็กน้อยและไม่ชัดเจนนัก
ทฤษฎีเล็กน้อย
ระบบควบคุมอัตโนมัติแบบคลาสสิกแสดงในรูปต่อไปนี้:
องค์ประกอบสำคัญของปืนอัตตาจรคือ หน่วยงานกำกับดูแลซึ่งเป็นอุปกรณ์ที่ตรวจสอบสถานะของวัตถุควบคุมและจัดให้มีกฎหมายควบคุมที่จำเป็น กระบวนการควบคุมประกอบด้วย: การคำนวณข้อผิดพลาดในการควบคุมหรือสัญญาณข้อผิดพลาด จ(ที) อะไรคือความแตกต่างระหว่างสิ่งที่ต้องการ การตั้งค่า(จุดกำหนดหรือ เอสพี ) และค่าปัจจุบันของกระบวนการ (process val หรือ พีวี ) หลังจากนั้นตัวควบคุมจะสร้างสัญญาณควบคุม (ค่าที่ถูกจัดการหรือ เอ็มวี ).
ตัวควบคุมประเภทหนึ่งคือ ตัวควบคุมสัดส่วนปริพันธ์อนุพันธ์ (PID)ซึ่งสร้างสัญญาณควบคุมซึ่งเป็นผลรวมของคำศัพท์สามคำ: สัดส่วน อินทิกรัล และดิฟเฟอเรนเชียล
โดยที่ ข้อผิดพลาดที่ไม่ตรงกันรวมถึง - สัดส่วน - อินทิกรัล - ส่วนประกอบที่แตกต่าง (เงื่อนไข) ของกฎหมายควบคุมซึ่งอธิบายในรูปแบบสุดท้ายโดยสูตรต่อไปนี้
องค์ประกอบตามสัดส่วน P- รับผิดชอบในสิ่งที่เรียกว่า การควบคุมตามสัดส่วน ความหมายก็คือ สัญญาณเอาท์พุตของตัวควบคุมจะตอบโต้การเบี่ยงเบนของตัวแปรควบคุม (ข้อผิดพลาดที่ไม่ตรงกันหรือเรียกอีกอย่างว่าค่าตกค้าง) จากค่าที่ตั้งไว้ ยิ่งข้อผิดพลาดไม่ตรงกันมากเท่าใด การเบี่ยงเบนคำสั่งของคอนโทรลเลอร์ก็จะยิ่งมากขึ้นเท่านั้น นี่เป็นกฎหมายควบคุมที่ง่ายและชัดเจนที่สุด ตำหนิกฎการควบคุมตามสัดส่วนคือตัวควบคุมไม่เคยเสถียรที่ค่าที่กำหนด และการเพิ่มขึ้นของค่าสัมประสิทธิ์สัดส่วนจะนำไปสู่การผันผวนในตัวเองเสมอ นั่นคือเหตุผลที่นอกเหนือจากกฎหมายควบคุมตามสัดส่วนแล้วยังจำเป็นต้องใช้กฎอินทิกรัลและดิฟเฟอเรนเชียลอีกด้วย
ส่วนประกอบสำคัญ Iสะสม (รวม) ข้อผิดพลาดในการควบคุม ซึ่งช่วยให้ตัวควบคุม PID สามารถกำจัดข้อผิดพลาดคงที่ได้ (ข้อผิดพลาดคงที่ ข้อผิดพลาดตกค้าง) หรืออีกนัยหนึ่ง: ลิงค์อินทิกรัล มักจะนำเสนออคติบางอย่างเสมอและหากระบบมีข้อผิดพลาดถาวร ระบบจะชดเชยข้อผิดพลาดเหล่านั้น (เนื่องจากอคติ) แต่ถ้าไม่มีข้อผิดพลาดดังกล่าวหรือมีขนาดเล็กมาก ผลที่ได้จะตรงกันข้าม - ส่วนประกอบสำคัญจะทำให้เกิดข้อผิดพลาดในการเคลื่อนที่ ด้วยเหตุนี้จึงไม่มีการใช้ เช่น ในงานการวางตำแหน่งที่แม่นยำเป็นพิเศษ สำคัญ ข้อเสียเปรียบกฎหมายควบคุมแบบรวมเป็นผลจากความอิ่มตัวของตัวรวมระบบ (การสิ้นสุดของตัวรวมระบบ)
องค์ประกอบดิฟเฟอเรนเชียล Dเป็นสัดส่วนกับอัตราการเปลี่ยนแปลงของการเบี่ยงเบนของตัวแปรควบคุมและได้รับการออกแบบเพื่อต่อต้านการเบี่ยงเบนไปจากค่าเป้าหมายซึ่ง มีการคาดการณ์ไว้ในอนาคต. เป็นที่น่าสังเกตว่าส่วนประกอบส่วนต่างช่วยลดการสั่นแบบหน่วง การควบคุมส่วนต่างมีประสิทธิผลโดยเฉพาะอย่างยิ่งสำหรับกระบวนการที่มีความล่าช้ามาก ข้อเสียกฎหมายควบคุมส่วนต่างคือความไม่แน่นอนต่อผลกระทบของเสียงรบกวน (Differentiation Noise)
ดังนั้น ขึ้นอยู่กับสถานการณ์ สามารถใช้ตัวควบคุม P-, PD-, PI- และ PID ได้ แต่กฎหมายควบคุมหลักส่วนใหญ่เป็นสัดส่วน (แม้ว่าในงานเฉพาะบางอย่างสามารถใช้เฉพาะองค์ประกอบของตัวสร้างความแตกต่างและผู้รวมระบบเท่านั้น)
ดูเหมือนว่าปัญหาในการใช้ตัวควบคุม PID จะถูกแฮ็กมานานแล้ว และที่Habré มีบทความดีๆ สองสามบทความในหัวข้อนี้ รวมถึงใน Unity3D ยังมีบทความที่ดี PID Without a PhD (การแปล) และชุดของ บทความในวารสาร "Modern Automation Technologies" ในสองส่วน: ครั้งแรกและครั้งที่สอง นอกจากนี้ยังมีบทความเกี่ยวกับ Wikipedia พร้อมให้บริการคุณ (อ่านบทความที่สมบูรณ์ที่สุดในเวอร์ชันภาษาอังกฤษ) และในฟอรัมชุมชน Unity3D ไม่ ไม่ และคอนโทรลเลอร์ PID จะปรากฏขึ้นเหมือนกับใน gamedev.stackexchange
คำถามเกี่ยวกับการใช้งานคอนโทรลเลอร์ PID นั้นค่อนข้างลึกกว่าที่คิด มากเสียจนการค้นพบที่น่าอัศจรรย์มากมายรอคอยนัก DIYers รุ่นเยาว์ที่ตัดสินใจใช้แผนการกำกับดูแลดังกล่าวและหัวข้อนี้ก็เกี่ยวข้อง ฉันหวังว่าบทประพันธ์นี้จะเป็นประโยชน์กับใครบางคน เรามาเริ่มกันเลย
พยายามอันดับหนึ่ง
ตามตัวอย่าง เราจะพยายามใช้แผนการควบคุมโดยใช้ตัวอย่างการหมุนการควบคุมในเกมอาร์เคดอวกาศ 2D ง่ายๆ ทีละขั้นตอนโดยเริ่มจากจุดเริ่มต้น (คุณลืมไปแล้วหรือว่านี่คือบทช่วยสอน?)
ทำไมไม่สามมิติ? เนื่องจากการใช้งานจะไม่เปลี่ยนแปลง ยกเว้นว่าคุณจะต้องเปิดตัวควบคุม PID เพื่อควบคุมระดับเสียง การหันเห และการหมุน แม้ว่าปัญหาของการประยุกต์ใช้การควบคุม PID อย่างถูกต้องร่วมกับควอเทอร์เนียนจะน่าสนใจมาก แต่บางทีฉันจะหารือเกี่ยวกับเรื่องนี้ในอนาคต แต่แม้แต่ NASA ก็ชอบมุมออยเลอร์มากกว่าควอเทอร์เนียน ดังนั้นเราจะใช้แบบจำลองง่ายๆ ในสองมิติ เครื่องบิน.
ขั้นแรก เรามาสร้างวัตถุเกมยานอวกาศขึ้นมา ซึ่งจะประกอบด้วยวัตถุยานอวกาศจริง ๆ ที่ระดับบนสุดของลำดับชั้น และแนบวัตถุเครื่องยนต์ลูกเข้ากับมัน (เพื่อประโยชน์ของเอฟเฟกต์พิเศษเท่านั้น) นี่คือสิ่งที่ดูเหมือนสำหรับฉัน:
และเราก็โยนเข้าไปบนวัตถุยานอวกาศ สารวัตรส่วนประกอบทุกชนิด เมื่อมองไปข้างหน้า ฉันจะให้ภาพหน้าจอว่าตอนจบจะเป็นอย่างไร:
แต่นั่นไว้สำหรับทีหลัง และตอนนี้ยังไม่มีสคริปต์อยู่ในนั้น มีเพียงชุดสุภาพบุรุษมาตรฐานเท่านั้น: Sprite Render, RigidBody2D, Polygon Collider, Audio Source (ทำไม?)
ที่จริงแล้วฟิสิกส์เป็นสิ่งที่สำคัญที่สุดสำหรับเราในตอนนี้และการควบคุมจะดำเนินการผ่านฟิสิกส์นั้นโดยเฉพาะ มิฉะนั้น การใช้ตัวควบคุม PID จะสูญเสียความหมาย ปล่อยให้มวลยานอวกาศของเราอยู่ที่ 1 กิโลกรัมและค่าสัมประสิทธิ์แรงเสียดทานและแรงโน้มถ่วงทั้งหมดจะเท่ากับศูนย์ในอวกาศ
เพราะ นอกจากตัวยานอวกาศแล้ว ยังมีวัตถุอวกาศอื่นๆ ที่มีความฉลาดน้อยกว่าอีกมากมาย ดังนั้นก่อนอื่นเราจะอธิบายคลาสพาเรนต์ก่อน ฐานร่างกายซึ่งจะมีลิงก์ไปยังส่วนประกอบของเรา วิธีการเริ่มต้นและการทำลาย ตลอดจนฟิลด์และวิธีการเพิ่มเติมจำนวนหนึ่ง เช่น สำหรับการนำกลไกท้องฟ้าไปใช้:
BaseBody.cs
ใช้ UnityEngine; ใช้ System.Collections; ใช้ System.Collections.Generic; namespace Assets.Scripts.SpaceShooter.Bodies (คลาสสาธารณะ BaseBody: MonoBehaviour ( อ่านอย่างเดียว float _deafultTimeDelay = 0.05f; รายการคงที่สาธารณะ
ดูเหมือนว่าเราจะอธิบายทุกสิ่งที่จำเป็นมากกว่าที่จำเป็น (ภายในกรอบของบทความนี้) ตอนนี้เรามาสืบทอดคลาสเรือจากมันกันดีกว่า เรือซึ่งควรจะสามารถเคลื่อนที่และหมุนได้:
SpaceShip.cs
ใช้ UnityEngine; ใช้ System.Collections; ใช้ System.Collections.Generic; namespace Assets.Scripts.SpaceShooter.Bodies ( เรือคลาสสาธารณะ: BaseBody ( public Vector2 _movement = new Vector2(); public Vector2 _target = new Vector2(); public float _rotation = 0f; public void FixedUpdate() ( float Torque = ControlRotate( _rotation); Vector2 force = ControlForce(_movement); _rb2d.AddTorque(torque); _rb2d.AddRelativeForce(force); ) public float ControlRotate(Vector2 หมุน) ( float result = 0f; return result; ) สาธารณะ Vector2 ControlForce (การเคลื่อนที่ของ Vector2) ( ผลลัพธ์ Vector2 = Vector2 ใหม่ (); ส่งคืนผลลัพธ์; ) ) )
แม้ว่าจะไม่มีอะไรน่าสนใจ แต่ในขณะนี้มันเป็นเพียงคลาส Stub เท่านั้น
นอกจากนี้เรายังจะอธิบายคลาสฐาน (นามธรรม) สำหรับตัวควบคุมอินพุตทั้งหมด BaseInputController:
BaseInputController.cs
ใช้ UnityEngine; ใช้ Assets.Scripts.SpaceShooter.Bodies; namespace Assets.Scripts.SpaceShooter.InputController ( public enum eSpriteRotation ( Rigth = 0, Up = -90, Left = -180, Down = -270 ) คลาสนามธรรมสาธารณะ BaseInputController: MonoBehaviour ( public GameObject _agentObject; public Ship _agentBody; // Link ไปยังองค์ประกอบตรรกะของเรือ public eSpriteRotation _spriteOrientation = eSpriteRotation.Up; // นี่เป็นเพราะไม่ได้มาตรฐาน // การวางแนวของสไปรต์ "ขึ้น" แทนที่จะเป็น "ขวา" โมฆะสาธารณะนามธรรม ControlRotate (float dt); โมฆะสาธารณะนามธรรม ControlForce (float dt); โมฆะเสมือนสาธารณะเริ่มต้น () ( _agentObject = gameObject; _agentBody = gameObject.GetComponent
และสุดท้ายคือคลาสตัวควบคุมผู้เล่น ผู้เล่น FigtherInput:
PlayerInput.cs
ใช้ UnityEngine; ใช้ Assets.Scripts.SpaceShooter.Bodies; namespace Assets.Scripts.SpaceShooter.InputController ( public class PlayerFigtherInput: BaseInputController ( public override void ControlRotate(float dt) ( // กำหนดตำแหน่งของเมาส์ที่สัมพันธ์กับผู้เล่น Vector3 worldPos = Input.mousePosition; worldPos = Camera.main.ScreenToWorldPoint (worldPos); / / บันทึกพิกัดตัวชี้เมาส์ float dx = -this.transform.position.x + worldPos.x; float dy = -this.transform.position.y + worldPos.y; // ผ่านทิศทาง Vector2 เป้าหมาย = new Vector2(dx, dy ); _agentBody._target = target; //คำนวณการหมุนตามการกดแป้นพิมพ์ที่ลอย targetAngle = Mathf.Atan2(dy, dx) * Mathf.Rad2Deg; _agentBody._targetAngle = targetAngle + (float)_spriteOrientation ; ) public override void ControlForce( float dt) ( //ผ่านการเคลื่อนไหว _agentBody._movement = Input.GetAxis("Vertical") * Vector2.up + Input.GetAxis("Horizontal") * Vector2.right; ) ) )
ดูเหมือนว่าเราจะเสร็จสิ้นแล้ว ในที่สุดเราก็สามารถไปยังสิ่งที่เริ่มต้นทั้งหมดนี้ได้ในที่สุด นั่นคือ ตัวควบคุม PID (ฉันหวังว่าคุณจะไม่ลืมใช่ไหม) การใช้งานดูเหมือนง่ายราวกับนรก:
ใช้ระบบ; ใช้ System.Collections.Generic; ใช้ System.Linq; ใช้ System.Text; namespace Assets.Scripts.Regulator ( // คุณลักษณะนี้จำเป็นสำหรับฟิลด์ควบคุม // ที่จะแสดงในตัวตรวจสอบและคลาสสาธารณะแบบอนุกรม SimplePID ( public float Kp, Ki, Kd; private float LastError; private float P, I, D ; สาธารณะ SimplePID() ( Kp = 1f; Ki = 0; Kd = 0.2f; ) SimplePID สาธารณะ (float pFactor, float iFactor, float dFactor) ( this.Kp = pFactor; this.Ki = iFactor; this.Kd = dFactor ; ) การอัปเดตโฟลตสาธารณะ (ข้อผิดพลาดโฟลต, float dt) ( P = ข้อผิดพลาด; I += ข้อผิดพลาด * dt; D = (ข้อผิดพลาด - LastError) / dt; LastError = ข้อผิดพลาด; float CO = P * Kp + I * Ki + D * Kd ; กลับ CO; ) ) )
เราจะนำค่าเริ่มต้นของสัมประสิทธิ์ออกจากอากาศ: นี่จะเป็นค่าสัมประสิทธิ์เดียวเล็กน้อยของกฎการควบคุมสัดส่วน Kp = 1 ซึ่งเป็นค่าเล็กน้อยของสัมประสิทธิ์สำหรับกฎการควบคุมส่วนต่าง Kd = 0.2 ซึ่งควรกำจัด ความผันผวนที่คาดหวังและค่าศูนย์สำหรับ Ki ซึ่งได้รับการเลือกเนื่องจากในซอฟต์แวร์ของเรา โมเดลไม่มีข้อผิดพลาดคงที่ (แต่คุณสามารถแนะนำพวกเขาได้ตลอดเวลา จากนั้นต่อสู้อย่างกล้าหาญด้วยความช่วยเหลือจากผู้รวมระบบ)
ตอนนี้กลับไปที่คลาส SpaceShip ของเราแล้วลองใช้สิ่งที่เราสร้างเป็นตัวควบคุมการหมุนของยานอวกาศในเมธอด ControlRotate:
ControlRotate ลอยสาธารณะ (หมุนเวกเตอร์ 2) ( float MV = 0f; float dt = Time.fixedDeltaTime; // คำนวณข้อผิดพลาด float angleError = Mathf.DeltaAngle (_myTransform.eulerAngles.z, targetAngle); // รับการเร่งความเร็วแก้ไข MV = _angleController .Update (angleError, dt); กลับ MV; )
ตัวควบคุม PID จะทำการวางตำแหน่งเชิงมุมของยานอวกาศอย่างแม่นยำโดยใช้แรงบิดเพียงอย่างเดียว ทุกอย่างยุติธรรม ฟิสิกส์และปืนอัตตาจร เกือบจะเหมือนในชีวิตจริง
และหากไม่มี Quaternion.Lerp ของคุณ
ถ้า (!_rb2d.freezeRotation) rb2d.freezeRotation = จริง; float deltaAngle = Mathf.DeltaAngle(_myTransform.eulerAngles.z, targetAngle); float T = dt * Mathf.Abs(_rotationSpeed / deltaAngle); // แปลงมุมให้เป็นเวกเตอร์ Quaternion rot = Quaternion.Lerp(_myTransform.rotation, Quaternion.Euler(เวกเตอร์ใหม่3(0, 0, targetAngle)), T); // เปลี่ยนการหมุนของวัตถุ _myTransform.rotation = rot;
ซอร์สโค้ดผลลัพธ์ของ Ship.cs อยู่ภายใต้สปอยเลอร์
ใช้ UnityEngine; ใช้ Assets.Scripts.Regulator; namespace Assets.Scripts.SpaceShooter.Bodies ( เรือคลาสสาธารณะ: BaseBody ( public GameObject _flame; public Vector2 _movement = new Vector2(); public Vector2 _target = new Vector2(); public float _targetAngle = 0f; public float _angle = 0f; public SimplePID _angleController = new SimplePID(); โมฆะสาธารณะ FixUpdate() ( float Torque = ControlRotate(_targetAngle); Vector2 force = ControlForce(_movement); _rb2d.AddTorque(torque); _rb2d.AddRelativeForce(force); ) public float ControlRotate(ลอย หมุน) ( float MV = 0f; float dt = Time.fixedDeltaTime; _angle = _myTransform.eulerAngles.z; // คำนวณข้อผิดพลาด float angleError = Mathf.DeltaAngle (_angle, หมุน); // รับการเร่งความเร็วแก้ไข MV = _angleController อัปเดต ( angleError, dt); return MV; ) public Vector2 ControlForce(การเคลื่อนที่ของ Vector2) ( Vector2 MV = new Vector2(); // โค้ดส่วนหนึ่งสำหรับเอฟเฟกต์พิเศษของเอ็นจิ้นที่ทำงานอยู่เพื่อประโยชน์ของ if (การเคลื่อนไหว != Vector2.zero) ( ถ้า (_flame != null) ( _flame.SetActive(จริง); ) ) else ( if (_flame != null) ( _flame.SetActive(false); ) ) MV = การเคลื่อนไหว; ส่งคืนเอ็มวี; ) ) )
ทั้งหมด? เราจะกลับบ้านกันไหม?
ว้าว! เกิดอะไรขึ้น? ทำไมเรือถึงเลี้ยวแปลกๆ? แล้วเหตุใดมันจึงกระดอนกับวัตถุอื่นอย่างแรง? ตัวควบคุม PID โง่ ๆ นี้ไม่ทำงานใช่ไหม
อย่าตื่นตกใจ! เราลองหาคำตอบกันว่าเกิดอะไรขึ้น
ในขณะนี้ได้รับค่า SP ใหม่ มีการกระโดดอย่างรวดเร็ว (แบบขั้นตอน) ในข้อผิดพลาดที่ไม่ตรงกัน ซึ่งตามที่เราจำได้ คำนวณดังนี้: ดังนั้น มีการกระโดดอย่างรวดเร็วในข้อผิดพลาดอนุพันธ์ ซึ่งเราคำนวณเป็น รหัสบรรทัดนี้:
D = (ข้อผิดพลาด - ข้อผิดพลาดล่าสุด) / dt;
แน่นอนคุณสามารถลองใช้แผนการสร้างความแตกต่างอื่นๆ ได้ เช่น สามจุดหรือห้าจุด หรือ... แต่ก็ยังไม่ได้ช่วยอะไร พวกเขาไม่ชอบอนุพันธ์ของการกระโดดที่แหลมคม - ณ จุดดังกล่าวคือฟังก์ชัน ไม่สามารถหาความแตกต่างได้. อย่างไรก็ตาม การทดลองกับโครงร่างการสร้างความแตกต่างและการบูรณาการที่แตกต่างกันก็คุ้มค่าที่จะลองใช้ แต่ไม่ใช่ในบทความนี้
ฉันคิดว่าถึงเวลาแล้วที่จะสร้างกราฟของกระบวนการเปลี่ยนผ่าน: การกระทำแบบเป็นขั้นตอนจาก S(t) = 0 ถึง SP(t) = 90 องศาสำหรับร่างกายที่มีน้ำหนัก 1 กก. ความยาวแขนบังคับ 1 เมตร และขั้นตอนตารางหาความแตกต่าง 0.02 วินาที - เช่นเดียวกับในตัวอย่างของเราใน Unity3D (อันที่จริงไม่ใช่ทั้งหมด เมื่อสร้างกราฟเหล่านี้ ไม่ได้คำนึงถึงโมเมนต์ความเฉื่อยขึ้นอยู่กับเรขาคณิตของวัตถุแข็ง ดังนั้นกระบวนการชั่วคราวจะเล็กน้อย แตกต่างแต่ยังคงคล้ายกันเพียงพอสำหรับการสาธิต) ค่าทั้งหมดบนแผนภูมิจะแสดงเป็นค่าสัมบูรณ์:
อืม เกิดอะไรขึ้นที่นี่? การตอบสนองของคอนโทรลเลอร์ PID หายไปไหน
ยินดีด้วย เราเพิ่งเจอปรากฏการณ์แบบ "เตะ" นั่นเอง เห็นได้ชัดว่า ณ เวลาที่กระบวนการยังคงเป็น PV = 0 และค่าเซ็ตพอยต์อยู่ที่ SP = 90 จากนั้นด้วยการหาความแตกต่างเชิงตัวเลข เราจะได้ค่าอนุพันธ์ของลำดับที่ 4500 ซึ่งจะถูกคูณด้วย เคดี=0.2และเพิ่มด้วย therom ตามสัดส่วน เพื่อว่าที่เอาต์พุตเราจะได้ค่าความเร่งเชิงมุม 990 และนี่เป็นความชั่วร้ายอย่างสมบูรณ์ในแบบจำลองทางกายภาพของ Unity3D (ความเร็วเชิงมุมจะสูงถึง 18,000 องศา/วินาที... ฉันคิดว่านี่คือ ค่าจำกัดของความเร็วเชิงมุมสำหรับ RigidBody2D)
- บางทีอาจคุ้มค่าที่จะเลือกค่าสัมประสิทธิ์ด้วยตนเองเพื่อให้การกระโดดไม่แรงนัก?
- เลขที่! สิ่งที่ดีที่สุดที่เราสามารถทำได้ด้วยวิธีนี้คือแอมพลิจูดเล็กน้อยของการกระโดดแบบอนุพันธ์ แต่ตัวการกระโดดจะยังคงเหมือนเดิม และในกรณีนี้ องค์ประกอบดิฟเฟอเรนเชียลอาจไม่ได้ผลโดยสิ้นเชิง
อย่างไรก็ตาม คุณสามารถทดลองได้
พยายามหมายเลขสอง ความอิ่มตัว
มันสมเหตุสมผลแล้ว หน่วยไดรฟ์(ในกรณีของเราคือกลไกการหลบหลีกเสมือนจริงของ SpaceShip) ไม่สามารถจัดการกับค่าขนาดใหญ่ใด ๆ ที่ตัวควบคุมที่บ้าคลั่งของเราไม่สามารถผลิตได้ ดังนั้นสิ่งแรกที่เราจะทำคือทำให้เอาต์พุตของตัวควบคุมอิ่มตัว:
ControlRotate ลอยสาธารณะ (Vector2 หมุน, แรงผลักดันลอย) ( float CO = 0f; float MV = 0f; float dt = Time.fixedDeltaTime; // คำนวณข้อผิดพลาด float angleError = Mathf.DeltaAngle (_myTransform.eulerAngles.z, targetAngle); / / เราได้รับการเร่งความเร็วที่ถูกต้อง CO = _angleController.Update(angleError, dt); //Saturate MV = CO; if (MV > thrust) MV = thrust; if (MV< -thrust) MV = -thrust; return MV; }
และอีกครั้งที่คลาส Ship ที่เขียนใหม่มีลักษณะดังนี้:
namespace Assets.Scripts.SpaceShooter.Bodies ( เรือคลาสสาธารณะ: BaseBody ( public GameObject _flame; public Vector2 _movement = new Vector2(); public Vector2 _target = new Vector2(); public float _targetAngle = 0f; public float _angle = 0f; public float _thrust = 1f; Public SimplePID _angleController = new SimplePID (0.1f, 0f,0.05f); โมฆะสาธารณะ FixUpdate () ( _torque = ControlRotate (_targetAngle, _thrust); _force = ControlForce (_movement); _rb2d.AddTorque (_torque); _rb2d.AddRelativeForce(_force); ) public float ControlRotate (float targetAngle, float thrust) ( float CO = 0f; float MV = 0f; float dt = Time.fixedDeltaTime; // คำนวณข้อผิดพลาด float angleError = Mathf.DeltaAngle (_myTransform. eulerAngles .z, targetAngle); // รับการเร่งความเร็วที่ถูกต้อง CO = _angleController.Update (angleError, dt); // Saturate MV = CO; if (MV > thrust) MV = thrust; if (MV< -thrust) MV = -thrust; return MV; } public Vector2 ControlForce(Vector2 movement) { Vector2 MV = new Vector2(); if (movement != Vector2.zero) { if (_flame != null) { _flame.SetActive(true); } } else { if (_flame != null) { _flame.SetActive(false); } } MV = movement * _thrust; return MV; } public void Update() { } } }
รูปแบบสุดท้ายของปืนอัตตาจรของเราจะมีลักษณะเช่นนี้
ในขณะเดียวกันก็ชัดเจนว่าเอาต์พุตของคอนโทรลเลอร์ คาร์บอนไดออกไซด์(t)แตกต่างจากตัวแปรควบคุมของกระบวนการเล็กน้อย เอ็มวี(ที).
จริงๆ แล้ว จากที่นี่ คุณสามารถเพิ่มเอนทิตีเกมใหม่ได้แล้ว - หน่วยไดรฟ์ซึ่งกระบวนการจะถูกควบคุม ตรรกะที่อาจซับซ้อนกว่าแค่ Mathf.Clamp() เช่น คุณสามารถแนะนำการแยกค่าต่างๆ ได้ (เพื่อไม่ให้ฟิสิกส์ของเกมโอเวอร์โหลดด้วยค่าที่เข้ามา ในอันดับที่หกหลังจุดทศนิยม) โซนตาย (อีกครั้งไม่ใช่ มันสมเหตุสมผลแล้วที่จะโอเวอร์โหลดฟิสิกส์ด้วยปฏิกิริยาขนาดเล็กพิเศษ) ทำให้เกิดความล่าช้าในการควบคุมและไม่เชิงเส้น (เช่น sigmoid) ของไดรฟ์แล้วดู อะไรมาจากมัน
เมื่อเปิดตัวเกมแล้ว เราจะพบว่าในที่สุดยานอวกาศก็สามารถควบคุมได้:
หากคุณสร้างกราฟ คุณจะเห็นว่าการตอบสนองของคอนโทรลเลอร์เป็นดังนี้:
ที่นี่มีการใช้ค่าที่ทำให้เป็นมาตรฐานแล้ว มุมจะถูกหารด้วยค่า SP และเอาต์พุตของคอนโทรลเลอร์จะถูกทำให้เป็นมาตรฐานโดยสัมพันธ์กับค่าสูงสุดที่เกิดความอิ่มตัวแล้ว
ด้านล่างนี้เป็นตารางที่รู้จักกันดีเกี่ยวกับผลกระทบของการเพิ่มพารามิเตอร์ของคอนโทรลเลอร์ PID ( ฉันจะทำให้แบบอักษรเล็กลงได้อย่างไร ไม่เช่นนั้นตารางยัติภังค์เมอแรงค์จะไม่พอดี):
และอัลกอริธึมทั่วไปสำหรับการปรับคอนโทรลเลอร์ PID ด้วยตนเองมีดังนี้:
- เราเลือกค่าสัมประสิทธิ์ตามสัดส่วนโดยปิดการเชื่อมต่อดิฟเฟอเรนเชียลและอินทิกรัลจนกว่าการสั่นในตัวเองจะเริ่มต้นขึ้น
- การเพิ่มองค์ประกอบส่วนต่างอย่างค่อยเป็นค่อยไปทำให้เรากำจัดการสั่นในตัวเองออกไป
- หากมีข้อผิดพลาดในการควบคุมสารตกค้าง (การเคลื่อนตัว) เราจะกำจัดมันโดยใช้ส่วนประกอบที่เป็นส่วนประกอบ
ไม่มีค่าทั่วไปสำหรับพารามิเตอร์ของตัวควบคุม PID: ค่าเฉพาะขึ้นอยู่กับพารามิเตอร์ของกระบวนการเท่านั้น (ลักษณะการถ่ายโอน): ตัวควบคุม PID ที่ทำงานได้อย่างสมบูรณ์กับวัตถุควบคุมหนึ่งจะไม่ทำงานกับวัตถุควบคุมอื่น นอกจากนี้ ค่าสัมประสิทธิ์สำหรับส่วนประกอบตามสัดส่วน อินทิกรัล และส่วนต่างยังขึ้นอยู่กับกันและกันอีกด้วย
พยายามหมายเลขสาม อนุพันธ์อีกครั้งหนึ่ง
หลังจากติดไม้ยันรักแร้ในรูปแบบของการจำกัดค่าเอาต์พุตของคอนโทรลเลอร์แล้ว เรายังคงไม่สามารถแก้ไขปัญหาที่สำคัญที่สุดของคอนโทรลเลอร์ของเราได้ - ส่วนประกอบส่วนต่างทำงานได้ไม่ดีเมื่อข้อผิดพลาดที่อินพุตของคอนโทรลเลอร์เปลี่ยนไปตามขั้นตอน ในความเป็นจริงมีไม้ค้ำยันอื่น ๆ อีกมากมายเช่นในขณะที่มีการเปลี่ยนแปลง SP อย่างกะทันหัน "ปิด" ส่วนประกอบส่วนต่างหรือติดตั้งตัวกรองความถี่ต่ำผ่านระหว่าง เอสพี(ที)และการดำเนินการเนื่องจากข้อผิดพลาดจะค่อยๆ เพิ่มขึ้น หรือคุณสามารถพลิกกลับได้ทั้งหมดและใช้ตัวกรองคาลมานจริงเพื่อทำให้ข้อมูลอินพุตราบรื่น โดยทั่วไปมีไม้ค้ำยันจำนวนมากและเพิ่ม ผู้สังเกตการณ์แน่นอนว่าฉันต้องการ แต่ไม่ใช่ครั้งนี้
ดังนั้น ลองกลับไปที่อนุพันธ์ของข้อผิดพลาดที่ไม่ตรงกันแล้วดูอย่างละเอียด:
คุณสังเกตเห็นอะไรไหม? หากคุณมองอย่างใกล้ชิด คุณจะพบว่าโดยทั่วไป SP(t) จะไม่เปลี่ยนแปลงเมื่อเวลาผ่านไป (ยกเว้นช่วงเวลาของการเปลี่ยนแปลงขั้นตอนเมื่อตัวควบคุมได้รับคำสั่งใหม่) เช่น อนุพันธ์ของมันคือศูนย์:
กล่าวอีกนัยหนึ่ง แทนที่จะเป็นข้อผิดพลาดอนุพันธ์ที่สามารถหาอนุพันธ์ได้ ไม่ใช่ทุกที่เราสามารถใช้อนุพันธ์ของกระบวนการ ซึ่งในโลกของกลศาสตร์คลาสสิกมักจะมีความต่อเนื่องและแตกต่างไปทุกที่ และแผนภาพของระบบควบคุมอัตโนมัติของเราจะอยู่ในรูปแบบต่อไปนี้:
มาแก้ไขโค้ดคอนโทรลเลอร์กันเถอะ:
ใช้ระบบ; ใช้ System.Collections.Generic; ใช้ System.Linq; ใช้ System.Text; เนมสเปซ Assets.Scripts.Regulator ( SimplePID คลาสสาธารณะ ( public float Kp, Ki, Kd; private float P, I, D; private float LastPV = 0f; public SimplePID() ( Kp = 1f; Ki = 0f; Kd = 0.2f ; ) SimplePID สาธารณะ (float pFactor, float iFactor, float dFactor) ( this.Kp = pFactor; this.Ki = iFactor; this.Kd = dFactor; ) public float Update (ข้อผิดพลาดลอย, float PV, float dt) ( P = ข้อผิดพลาด; I += ข้อผิดพลาด * dt; D = -(PV - LastPV) / dt; LastPV = PV; float CO = Kp * P + Ki * I + Kd * D; กลับ CO; ) ) )
และมาเปลี่ยนวิธี ControlRotate กันสักหน่อย:
ControlRotate ลอยสาธารณะ (Vector2 หมุน, แรงผลักดันลอย) ( float CO = 0f; float MV = 0f; float dt = Time.fixedDeltaTime; // คำนวณข้อผิดพลาด float angleError = Mathf.DeltaAngle (_myTransform.eulerAngles.z, targetAngle); / / เราได้รับการเร่งความเร็วที่ถูกต้อง CO = _angleController.Update(angleError, _myTransform.eulerAngles.z, dt); //Saturate MV = CO; ถ้า (CO >< -thrust) MV = -thrust; return MV; }
และและและและและ... หากคุณเริ่มเกม คุณจะพบว่าในความเป็นจริงไม่มีอะไรเปลี่ยนแปลงไปนับตั้งแต่การลองครั้งล่าสุด ซึ่งเป็นสิ่งที่จำเป็นต้องได้รับการพิสูจน์ อย่างไรก็ตาม หากคุณลบความอิ่มตัว กราฟการตอบสนองของตัวควบคุมจะมีลักษณะดังนี้:
กระโดด คาร์บอนไดออกไซด์(t)ก็ยังมีอยู่แต่ก็ไม่ใหญ่เท่าเดิมอีกต่อไปแล้ว และที่สำคัญ เป็นที่คาดเดาได้เพราะ มีให้โดยองค์ประกอบตามสัดส่วนโดยเฉพาะ และถูกจำกัดด้วยข้อผิดพลาดที่ไม่ตรงกันสูงสุดที่เป็นไปได้และอัตราขยายตามสัดส่วนของตัวควบคุม PID (และนี่ก็บอกเป็นนัยแล้วว่า เคพีมันสมเหตุสมผลที่จะเลือกน้อยกว่าความสามัคคี เช่น 1/90f) แต่ไม่ได้ขึ้นอยู่กับขั้นตอนของเส้นตารางสร้างความแตกต่าง (เช่น dt). โดยทั่วไป ฉันขอแนะนำอย่างยิ่งให้ใช้อนุพันธ์ของกระบวนการมากกว่าข้อผิดพลาด
ฉันคิดว่าตอนนี้มันจะไม่ทำให้ใครแปลกใจ แต่ในลักษณะเดียวกับที่คุณสามารถแทนที่มันได้ แต่เราจะไม่อยู่กับสิ่งนี้คุณสามารถทดลองตัวเองและบอกในความคิดเห็นว่าอะไรออกมาจากมัน (สิ่งที่น่าสนใจที่สุด)
พยายามหมายเลขสี่ การใช้งานทางเลือกอื่นของคอนโทรลเลอร์ PID
นอกเหนือจากการแสดงตัวควบคุม PID ในอุดมคติที่อธิบายไว้ข้างต้นแล้ว ในทางปฏิบัติมักใช้รูปแบบมาตรฐานโดยไม่มีค่าสัมประสิทธิ์ กี้และ เคดีแทนที่จะใช้ค่าคงที่ชั่วคราว
วิธีการนี้เกิดจากการที่เทคนิคจำนวนหนึ่งสำหรับการปรับแต่งตัวควบคุม PID นั้นขึ้นอยู่กับลักษณะความถี่ของตัวควบคุม PID และกระบวนการ ที่จริงแล้ว TAU ทั้งหมดหมุนรอบลักษณะความถี่ของกระบวนการ ดังนั้นสำหรับผู้ที่ต้องการเจาะลึกและพบกับระบบการตั้งชื่อทางเลือกในทันใด ฉันจะยกตัวอย่างสิ่งที่เรียกว่า แบบฟอร์มมาตรฐานตัวควบคุมพีไอดี:
โดยที่ คือค่าคงที่ของความแตกต่างที่ส่งผลต่อการทำนายสถานะของระบบโดยหน่วยงานกำกับดูแล
- ค่าคงที่การรวมซึ่งส่งผลต่อช่วงเวลาเฉลี่ยข้อผิดพลาดโดยลิงก์อินทิกรัล
หลักการพื้นฐานสำหรับการปรับแต่งคอนโทรลเลอร์ PID ในรูปแบบมาตรฐานนั้นคล้ายคลึงกับคอนโทรลเลอร์ PID ในอุดมคติ:
- การเพิ่มค่าสัมประสิทธิ์ตามสัดส่วนจะเพิ่มประสิทธิภาพและลดส่วนต่างเสถียรภาพ
- เมื่อส่วนประกอบสำคัญลดลง ข้อผิดพลาดในการควบคุมจะลดลงเร็วขึ้นเมื่อเวลาผ่านไป
- การลดค่าคงที่การรวมจะลดส่วนต่างความเสถียร
- การเพิ่มขึ้นของส่วนประกอบส่วนต่างจะเพิ่มความเสถียรและประสิทธิภาพ
ซอร์สโค้ดของแบบฟอร์มมาตรฐานอยู่ใต้สปอยเลอร์
เนมสเปซ Assets.Scripts.Regulator ( StandartPID คลาสสาธารณะ ( public float Kp, Ti, Td; ข้อผิดพลาด float สาธารณะ, CO; public float P, I, D; โฟลตส่วนตัว LastPV = 0f; StandartPID สาธารณะ () ( Kp = 0.1f; Ti = 10000f; Td = 0.5f; bias = 0f; ) public StandardPID (float Kp, float Ti, float Td) ( this.Kp = Kp; this.Ti = Ti; this.Td = Td; ) public float อัปเดต (float ข้อผิดพลาด, float PV, float dt) ( this.error = error; P = error; I += (1 / Ti) * error * dt; D = -Td * (PV - LastPV) / dt; CO = Kp * ( P + I + D); LastPV = PV; กลับ CO; ) ) )
ค่าเริ่มต้นคือ Kp = 0.01, Ti = 10,000, Td = 0.5 - ด้วยค่าเหล่านี้เรือจะหมุนค่อนข้างเร็วและมีความเสถียรเล็กน้อย
นอกจากตัวควบคุม PID ในรูปแบบนี้แล้วยังเรียกอีกอย่างว่า แบบฟอร์มกำเริบ:
เราจะไม่ยึดติดกับมัน เพราะ... มันมีความเกี่ยวข้องเป็นหลักสำหรับโปรแกรมเมอร์ฮาร์ดแวร์ที่ทำงานกับ FPGA และไมโครคอนโทรลเลอร์ซึ่งการใช้งานดังกล่าวสะดวกและมีประสิทธิภาพมากกว่ามาก ในกรณีของเรา - มามอบบางอย่างให้กับกองบน Unity3D - นี่เป็นเพียงการใช้งานคอนโทรลเลอร์ PID อีกครั้งซึ่งไม่ได้ดีไปกว่าตัวอื่นและยังเข้าใจได้น้อยกว่าด้วยซ้ำ ดังนั้นขอให้ทุกคนชื่นชมยินดีอีกครั้งว่าการเขียนโปรแกรมใน C# ที่สะดวกสบายนั้นดีแค่ไหน และไม่ได้อยู่ใน VHDL ที่น่าขนลุกและแย่มาก
แทนที่จะได้ข้อสรุป คุณจะเพิ่มตัวควบคุม PID ที่ไหนอีก
ทีนี้ลองทำให้การควบคุมของเรือซับซ้อนขึ้นเล็กน้อยโดยใช้การควบคุมแบบดูอัลลูป: ตัวควบคุม PID หนึ่งตัวที่เราคุ้นเคย _angleController ยังคงรับผิดชอบในการวางตำแหน่งเชิงมุม แต่ตัวที่สอง - ใหม่ _angularVelocityController - ควบคุมความเร็วในการหมุน:
ControlRotate ลอยสาธารณะ (float targetAngle, float thrust) (float CO = 0f; float MV = 0f; float dt = Time.fixedDeltaTime; _angle = _myTransform.eulerAngles.z; // ตัวควบคุมมุมการหมุน float angleError = Mathf.DeltaAngle (_angle, targetAngle); float TorqueCorrectionForAngle = _angleController.Update (angleError, _angle, dt); // ตัวควบคุมเสถียรภาพความเร็ว float angularVelocityError = -_rb2d.angularVelocity; float TorrectionForAngularVelocity = _angularVelocityController.Update (เชิงมุมVelocityError, -angularVelocityError, dt); // รวม เอาต์พุตคอนโทรลเลอร์ CO = TorqueCorrectionForAngle + TorqueCorrectionForAngularVelocity; // ตัวอย่างในขั้นตอนที่ 100 CO = Mathf.Round (100f * CO) / 100f; // Saturate MV = CO; if (CO > thrust) MV = thrust; if (CO< -thrust) MV = -thrust; return MV; }
วัตถุประสงค์ของตัวควบคุมตัวที่สองคือเพื่อลดความเร็วเชิงมุมส่วนเกินโดยการเปลี่ยนแรงบิด - ซึ่งคล้ายกับการเสียดสีเชิงมุมซึ่งเราปิดไว้เมื่อสร้างวัตถุของเกม รูปแบบการควบคุมดังกล่าวจะ [อาจ] ทำให้สามารถรับพฤติกรรมที่เสถียรยิ่งขึ้นของเรือได้ และแม้กระทั่งได้รับโดยมีค่าสัมประสิทธิ์การควบคุมตามสัดส่วนเท่านั้น - ตัวควบคุมตัวที่สองจะรองรับความผันผวนทั้งหมด โดยทำหน้าที่คล้ายกับส่วนประกอบส่วนต่างของตัวควบคุมตัวแรก .
นอกจากนี้ เราจะเพิ่มคลาสอินพุตของผู้เล่นใหม่ - PlayerInputCorvette ซึ่งจะทำการผลัดกันโดยการกดปุ่มซ้ายขวา และเราจะทิ้งการกำหนดเป้าหมายไว้ด้วยเมาส์สำหรับสิ่งที่มีประโยชน์มากขึ้น เช่น สำหรับการควบคุมป้อมปืน . ในเวลาเดียวกัน ตอนนี้เรามีพารามิเตอร์เช่น _turnRate ซึ่งรับผิดชอบความเร็ว/การตอบสนองของการเลี้ยว (ยังไม่ชัดเจนว่าควรวางไว้ที่ใดใน InputCOntroller หรือยังคงจัดส่ง)
PlayerCorvetteInput ระดับสาธารณะ: BaseInputController ( public float _turnSpeed = 90f; public override void ControlRotate() ( // ค้นหาตัวชี้เมาส์ Vector3 worldPos = Input.mousePosition; worldPos = Camera.main.ScreenToWorldPoint(worldPos); // เก็บญาติ พิกัดของตัวชี้เมาส์ float dx = -this.transform.position.x + worldPos.x; float dy = -this.transform.position.y + worldPos.y; // ส่งผ่านทิศทางของตัวชี้เมาส์ Vector2 target = new Vector2( dx, dy); _agentBody. _target = target; //คำนวณการหมุนตามการกดแป้นพิมพ์ _agentBody._rotation -= Input.GetAxis("Horizontal") * _turnSpeed * Time.deltaTime; ) public override void ControlForce() ( //ผ่านการเคลื่อนไหว _agentBody._movement = Input .GetAxis("Vertical") * Vector2.up; ) )
นอกจากนี้ เพื่อความชัดเจน เราจะวางสคริปต์เพื่อแสดงข้อมูลการดีบัก
namespace Assets.Scripts.SpaceShooter.UI (ดีบักเกอร์คลาสสาธารณะ: MonoBehaviour ( Ship _ship; BaseInputController _controller; List
คลาส Ship ยังผ่านการกลายพันธุ์ที่ไม่สามารถย้อนกลับได้ และตอนนี้ควรมีลักษณะดังนี้:
namespace Assets.Scripts.SpaceShooter.Bodies ( เรือคลาสสาธารณะ: BaseBody ( public GameObject _flame; public Vector2 _movement = new Vector2(); public Vector2 _target = new Vector2(); public float _targetAngle = 0f; public float _angle = 0f; public float _thrust = 1f; SimplePID สาธารณะ _angleController = SimplePID ใหม่ (0.1f,0f,0.05f); SimplePID สาธารณะ _angularVelocityController = SimplePID ใหม่ (0f,0f,0f); float ส่วนตัว _torque = 0f; float สาธารณะ _Torque ( รับ ( return _torque; ) ) Vector2 ส่วนตัว _force = vector2 ใหม่ (); Vector2 สาธารณะ _Force ( รับ ( return _force; ) ) โมฆะสาธารณะ FixUpdate() ( _torque = ControlRotate(_targetAngle, _thrust); _force = ControlForce(_movement, _thrust); _rb2d.AddTorque( _torque); _rb2d.AddRelativeForce(_force); ) ControlRotate ลอยสาธารณะ (float targetAngle, float thrust) ( float CO = 0f; float MV = 0f; float dt = Time.fixedDeltaTime; _angle = _myTransform.eulerAngles.z; // ตัวควบคุม มุมการหมุน มุมลอย ข้อผิดพลาด = Mathf.DeltaAngle (_angle, targetAngle); แรงบิดลอย CorrectionForAngle = _angleController.Update (angleError, _angle, dt); //ตัวควบคุมเสถียรภาพความเร็ว float เชิงมุมVelocityError = -_rb2d.เชิงมุมVelocity; แรงบิดลอยตัว CorrectionForAngularVelocity = _angularVelocityController.Update (เชิงมุมVelocityError, -เชิงมุมVelocityError, dt); // เอาต์พุตคอนโทรลเลอร์ทั้งหมด CO = TorqueCorrectionForAngle + TorqueCorrectionForAngularVelocity; //แยกส่วนเป็นขั้นละ 100 CO = Mathf.Round(100f * CO) / 100f; //อิ่มตัว MV = CO; ถ้า (CO > แรงขับ) MV = แรงขับ; ถ้า(CO< -thrust) MV = -thrust; return MV; } public Vector2 ControlForce(Vector2 movement, float thrust) { Vector2 MV = new Vector2(); if (movement != Vector2.zero) { if (_flame != null) { _flame.SetActive(true); } } else { if (_flame != null) { _flame.SetActive(false); } } MV = movement * thrust; return MV; } public void Update() { } } }
ลิงค์เพิ่มเติมไปยังตัวอย่างอื่น ๆ
แถบสัดส่วน X p เช่นเดียวกับส่วนเบี่ยงเบน E จะแสดงเป็นหน่วยของพารามิเตอร์ควบคุม ยิ่งแถบสัดส่วน X p กว้างขึ้น สัญญาณเอาท์พุต Y ก็จะยิ่งน้อยลงสำหรับค่าเบี่ยงเบน E ที่เท่ากัน
ภายนอกแถบสัดส่วน เอาต์พุต Y จะเป็น 0 หรือ 100%
เมื่อกฎ P ทำงาน ตัวควบคุมจะสร้างพัลส์โดยมีเพียงส่วนประกอบตามสัดส่วนของค่าสัญญาณเอาท์พุตเท่านั้น
เมื่ออุปกรณ์ทำงานในโหมดคอนโทรลเลอร์ PD ขนาดของสัญญาณเอาต์พุต Yi ไม่เพียงขึ้นอยู่กับขนาดของส่วนเบี่ยงเบน Ei เท่านั้น แต่ยังขึ้นอยู่กับอัตราการเปลี่ยนแปลงด้วย:
การเปลี่ยนแปลงสัญญาณเอาต์พุตของคอนโทรลเลอร์โดยมีการเปลี่ยนแปลงส่วนเบี่ยงเบนแบบขั้นตอนจะแสดงในรูป ในช่วงแรกหลังจากการเปลี่ยนแปลงขั้นตอนใน E i ตัวควบคุมจะออกพัลส์ควบคุม ซึ่งนอกเหนือจากองค์ประกอบตามสัดส่วนที่เกิดจาก E i ที่ไม่ตรงกันแล้ว ยังมีการเพิ่มดิฟเฟอเรนเชียล (ส่วนที่แรเงา) ΔYd ซึ่งขึ้นอยู่กับค่า ของสัมประสิทธิ์ΔE i และ τ l ในพัลส์ต่อมาจะมีเพียงส่วนประกอบที่เป็นสัดส่วนเท่านั้น เนื่องจากไม่มีการเปลี่ยนแปลงใน E i
รูปแสดงให้เห็นว่าในช่วงเวลาแรก เมื่อไม่มีการเบี่ยงเบน (E i =0) จะไม่มีสัญญาณเอาท์พุต (Y i =0) เมื่อเกิดการเบี่ยงเบน E i พัลส์จะปรากฏขึ้น ระยะเวลาที่ค่อยๆ เพิ่มขึ้น พัลส์ประกอบด้วยส่วนประกอบที่เป็นสัดส่วน ซึ่งขึ้นอยู่กับค่าของ E (ส่วนที่ไม่มีแรเงาของพัลส์) และส่วนประกอบที่เป็นอินทิกรัล (ส่วนที่แรเงา) ระยะเวลาพัลส์ที่เพิ่มขึ้นเกิดขึ้นเนื่องจากส่วนประกอบสำคัญเพิ่มขึ้นซึ่งขึ้นอยู่กับความไม่ตรงกัน E i และค่าสัมประสิทธิ์ τ i
ตัวควบคุมปริพันธ์ตามสัดส่วนส่วนต่างคืออุปกรณ์ที่ติดตั้งในระบบอัตโนมัติเพื่อรักษาพารามิเตอร์ที่กำหนดซึ่งสามารถเปลี่ยนแปลงได้
เมื่อมองแวบแรก ทุกอย่างดูสับสน แต่การควบคุม PID สามารถอธิบายได้สำหรับหุ่นจำลอง เช่น ผู้ที่ไม่คุ้นเคยกับระบบและอุปกรณ์อิเล็กทรอนิกส์เลย
ตัวควบคุม PID คืออะไร?
ตัวควบคุม PID เป็นอุปกรณ์ที่ติดตั้งอยู่ในวงจรควบคุมพร้อมข้อเสนอแนะบังคับ ได้รับการออกแบบมาเพื่อรักษาระดับที่กำหนดไว้ของค่าที่ระบุ เช่น อุณหภูมิของอากาศ
อุปกรณ์จ่ายการควบคุมหรือสัญญาณเอาท์พุตไปยังอุปกรณ์ควบคุม โดยมีพื้นฐานอยู่บนข้อมูลที่ได้รับจากตัวตรวจรู้หรือตัวตรวจรู้ ตัวควบคุมมีความแม่นยำสูงของกระบวนการชั่วคราวและคุณภาพของการปฏิบัติงานที่ได้รับมอบหมาย
ค่าสัมประสิทธิ์ตัวควบคุม PID สามตัวและหลักการทำงาน
การทำงานของคอนโทรลเลอร์ PID คือการจัดเตรียมสัญญาณเอาท์พุตเกี่ยวกับพลังงานที่จำเป็นในการรักษาพารามิเตอร์ที่ถูกควบคุมในระดับที่กำหนด ในการคำนวณตัวบ่งชี้จะใช้สูตรทางคณิตศาสตร์ที่ซับซ้อนซึ่งมี 3 ค่าสัมประสิทธิ์ - สัดส่วน, อินทิกรัล, ส่วนต่าง
ให้เรานำภาชนะใส่น้ำมาเป็นวัตถุควบคุมซึ่งจำเป็นต้องรักษาอุณหภูมิในระดับที่กำหนดโดยการปรับระดับการเปิดวาล์วด้วยไอน้ำ
องค์ประกอบตามสัดส่วนจะปรากฏขึ้นในขณะที่ข้อมูลอินพุตไม่ตรงกัน พูดง่าย ๆ ดูเหมือนว่านี้ - นำความแตกต่างระหว่างอุณหภูมิจริงกับอุณหภูมิที่ต้องการคูณด้วยค่าสัมประสิทธิ์ที่ปรับได้และรับสัญญาณเอาต์พุตที่ควรจ่ายให้กับวาล์ว เหล่านั้น. ทันทีที่องศาลดลง กระบวนการทำความร้อนจะเริ่มขึ้น หากสูงกว่าระดับที่ต้องการ การปิดเครื่องหรือแม้แต่การระบายความร้อนจะเกิดขึ้น
ถัดมาคือส่วนประกอบสำคัญ ซึ่งออกแบบมาเพื่อชดเชยอิทธิพลของสภาพแวดล้อมหรืออิทธิพลรบกวนอื่นๆ ที่มีต่อการรักษาอุณหภูมิของเราในระดับที่กำหนด เนื่องจากมีปัจจัยเพิ่มเติมที่มีอิทธิพลต่ออุปกรณ์ควบคุมอยู่เสมอ ในขณะที่ข้อมูลมาถึงเพื่อคำนวณส่วนประกอบตามสัดส่วน ตัวเลขจึงเปลี่ยนแปลงไปแล้ว และยิ่งอิทธิพลภายนอกมากเท่าไร ความผันผวนของตัวบ่งชี้ก็จะยิ่งแข็งแกร่งขึ้นเท่านั้น มีไฟกระชากในกำลังไฟที่จ่าย
ส่วนประกอบสำคัญจะพยายามส่งกลับค่าหากมีการเปลี่ยนแปลง โดยอิงตามค่าอุณหภูมิที่ผ่านมา กระบวนการนี้อธิบายไว้ในรายละเอียดเพิ่มเติมในวิดีโอด้านล่าง
อินทิกรัลใช้เพื่อกำจัดข้อผิดพลาดโดยการคำนวณข้อผิดพลาดคงที่ สิ่งสำคัญในกระบวนการนี้คือการเลือกค่าสัมประสิทธิ์ที่ถูกต้อง มิฉะนั้นข้อผิดพลาด (ไม่ตรงกัน) จะส่งผลต่อส่วนประกอบสำคัญด้วย
องค์ประกอบที่สามของ PID กำลังสร้างความแตกต่าง ได้รับการออกแบบมาเพื่อชดเชยผลกระทบของความล่าช้าที่เกิดขึ้นระหว่างผลกระทบต่อระบบและผลตอบรับ ตัวควบคุมสัดส่วนจะจ่ายไฟจนกว่าอุณหภูมิจะถึงระดับที่ต้องการ แต่ข้อผิดพลาดมักเกิดขึ้นเมื่อข้อมูลส่งผ่านไปยังอุปกรณ์ โดยเฉพาะอย่างยิ่งที่ค่าสูง นี่อาจทำให้เกิดความร้อนสูงเกินไป ส่วนต่างทำนายความเบี่ยงเบนที่เกิดจากความล่าช้าหรืออิทธิพลของสิ่งแวดล้อม และลดกำลังไฟฟ้าที่จ่ายล่วงหน้า
การตั้งค่าตัวควบคุม PID
ตัวควบคุม PID ได้รับการกำหนดค่าโดยใช้ 2 วิธี:
- การสังเคราะห์เกี่ยวข้องกับการคำนวณพารามิเตอร์ตามแบบจำลองของระบบ การตั้งค่านี้แม่นยำ แต่ต้องใช้ความรู้เชิงลึกเกี่ยวกับทฤษฎีการควบคุมอัตโนมัติ เป็นเรื่องของวิศวกรและนักวิทยาศาสตร์เท่านั้น เนื่องจากจำเป็นต้องคำนึงถึงลักษณะการบริโภคและทำการคำนวณมากมาย
- วิธีการด้วยตนเองนั้นขึ้นอยู่กับการลองผิดลองถูก ในการทำเช่นนี้จะใช้ข้อมูลของระบบสำเร็จรูปเป็นพื้นฐานและมีการปรับเปลี่ยนค่าสัมประสิทธิ์การควบคุมอย่างน้อยหนึ่งค่า หลังจากเปิดเครื่องและสังเกตผลลัพธ์สุดท้ายแล้ว พารามิเตอร์จะเปลี่ยนไปในทิศทางที่ต้องการ และต่อๆ ไปจนได้ประสิทธิภาพตามที่ต้องการ
วิธีการวิเคราะห์และการปรับเปลี่ยนทางทฤษฎีนั้นไม่ค่อยได้ใช้ในทางปฏิบัติมากนัก ซึ่งเกิดจากการเพิกเฉยต่อลักษณะของวัตถุควบคุมและอิทธิพลที่รบกวนที่อาจเกิดขึ้นมากมาย โดยทั่วไปคือวิธีการทดลองโดยอาศัยการสังเกตระบบ
กระบวนการอัตโนมัติสมัยใหม่ถูกนำมาใช้เป็นโมดูลพิเศษที่ควบคุมโดยโปรแกรมเพื่อปรับค่าสัมประสิทธิ์ตัวควบคุม
วัตถุประสงค์ของตัวควบคุม PID
ตัวควบคุม PID ได้รับการออกแบบมาเพื่อรักษาค่าบางอย่างให้อยู่ในระดับที่ต้องการ เช่น อุณหภูมิ ความดัน ระดับในถัง อัตราการไหลในท่อ ความเข้มข้นของบางสิ่งบางอย่าง ฯลฯ โดยการเปลี่ยนการควบคุมบนแอคทูเอเตอร์ เช่น วาล์วควบคุมอัตโนมัติ โดยใช้สัดส่วน การอินทิเกรต และปริมาณที่ทำให้เกิดความแตกต่างในการตั้งค่า
วัตถุประสงค์การใช้งานคือการรับสัญญาณควบคุมที่แม่นยำซึ่งสามารถควบคุมอุตสาหกรรมขนาดใหญ่และแม้แต่เครื่องปฏิกรณ์ของโรงไฟฟ้าได้
ตัวอย่างวงจรควบคุมอุณหภูมิ
ตัวควบคุม PID มักใช้เพื่อควบคุมอุณหภูมิ ลองดูกระบวนการอัตโนมัตินี้โดยใช้ตัวอย่างง่ายๆ ของการทำความร้อนน้ำในภาชนะ
ภาชนะเต็มไปด้วยของเหลวซึ่งจะต้องได้รับความร้อนจนถึงอุณหภูมิที่ต้องการและรักษาในระดับที่กำหนด มีการติดตั้งเซ็นเซอร์วัดอุณหภูมิภายในถัง - หรือเชื่อมต่อโดยตรงกับตัวควบคุม PID
เพื่อให้ความร้อนแก่ของเหลว เราจะจ่ายไอน้ำพร้อมวาล์วควบคุมอัตโนมัติดังแสดงในรูปด้านล่าง ตัววาล์วรับสัญญาณจากตัวควบคุม ผู้ปฏิบัติงานป้อนค่าอุณหภูมิที่กำหนดในตัวควบคุม PID ที่ต้องคงไว้ในถัง
หากการตั้งค่าสัมประสิทธิ์ตัวควบคุมไม่ถูกต้อง อุณหภูมิของน้ำจะผันผวน โดยวาล์วเปิดจนสุดหรือปิดสนิท ในกรณีนี้ จำเป็นต้องคำนวณค่าสัมประสิทธิ์ตัวควบคุม PID แล้วป้อนอีกครั้ง หากทุกอย่างถูกต้อง หลังจากช่วงเวลาสั้นๆ ระบบจะปรับระดับกระบวนการและอุณหภูมิในภาชนะจะคงอยู่ที่จุดที่ตั้งไว้ ในขณะที่ระดับการเปิดของวาล์วควบคุมจะอยู่ในตำแหน่งตรงกลาง
คอนโทรลเลอร์ PID เป็นอุปกรณ์สำเร็จรูปที่จะอนุญาตให้ผู้ใช้ใช้อัลกอริธึมซอฟต์แวร์สำหรับควบคุมอุปกรณ์บางอย่างของระบบอัตโนมัติ การสร้างและกำหนดค่าระบบควบคุมจะง่ายขึ้นมากหากคุณใช้อุปกรณ์สำเร็จรูป เช่น ตัวควบคุม universal PID TRM148 สำหรับ 8 ช่องจากบริษัท Aries
สมมติว่าคุณต้องบำรุงรักษาสภาพภูมิอากาศที่ถูกต้องในเรือนกระจกโดยอัตโนมัติ: โดยคำนึงถึงอุณหภูมิของดินใกล้กับรากพืช ความกดอากาศ ความชื้นในอากาศและดิน และรักษาพารามิเตอร์ที่ตั้งไว้โดยการควบคุมพัดลม ไม่มีอะไรง่ายไปกว่านี้แล้ว เพียงแค่กำหนดค่าคอนโทรลเลอร์ PID
ก่อนอื่นมาจำกันก่อนว่าคอนโทรลเลอร์ PID คืออะไร? ตัวควบคุม PID เป็นอุปกรณ์พิเศษที่ดำเนินการปรับพารามิเตอร์เอาต์พุตอย่างแม่นยำอย่างต่อเนื่องในสามวิธี: ตามสัดส่วน บูรณาการและต่างกัน และพารามิเตอร์เริ่มต้นคือพารามิเตอร์อินพุตที่ได้รับจากเซ็นเซอร์ (ความดัน ความชื้น อุณหภูมิ แสง ฯลฯ)
พารามิเตอร์อินพุตจะถูกส่งไปยังอินพุตของตัวควบคุม PID จากเซ็นเซอร์ เช่น จากเซ็นเซอร์ความชื้น ตัวควบคุมจะได้รับค่าแรงดันหรือกระแส วัดค่า จากนั้นทำการคำนวณตามอัลกอริธึม และในที่สุดก็จะส่งสัญญาณไปยังเอาต์พุตที่เกี่ยวข้อง ซึ่งส่งผลให้ระบบอัตโนมัติได้รับการดำเนินการควบคุม ความชื้นในดินลดลง - เปิดการรดน้ำสักครู่
เป้าหมายคือเพื่อให้ได้ค่าความชื้นที่ผู้ใช้กำหนด หรือตัวอย่าง: การส่องสว่างลดลง - เปิดไฟโตแลมป์เหนือต้นไม้ เป็นต้น
การควบคุมพีไอดี
ในความเป็นจริง แม้ว่าทุกอย่างจะดูเรียบง่าย แต่ภายในตัวควบคุม คณิตศาสตร์นั้นซับซ้อนกว่า ทุกอย่างไม่ได้เกิดขึ้นในขั้นตอนเดียว หลังจากเปิดการชลประทาน ตัวควบคุม PID จะทำการวัดอีกครั้ง โดยวัดว่าค่าอินพุตเปลี่ยนแปลงไปมากน้อยเพียงใด - นี่คือวิธีที่พบข้อผิดพลาดในการควบคุม ผลกระทบถัดไปต่อผู้บริหารจะได้รับการปรับเปลี่ยนโดยคำนึงถึงข้อผิดพลาดด้านกฎระเบียบที่วัดได้ และต่อๆ ไปในแต่ละขั้นตอนการควบคุมจนกว่าจะบรรลุเป้าหมาย - พารามิเตอร์ที่ผู้ใช้ระบุ - บรรลุผล
องค์ประกอบสามประการที่เกี่ยวข้องกับการควบคุม ได้แก่ สัดส่วน อินทิกรัล และดิฟเฟอเรนเชียล แต่ละส่วนประกอบมีระดับความสำคัญของตัวเองในแต่ละระบบเฉพาะ และยิ่งการมีส่วนร่วมของส่วนประกอบหนึ่งหรือส่วนประกอบอื่นมากเท่าไร ก็ควรมีการเปลี่ยนแปลงในกระบวนการกำกับดูแลมากขึ้นเท่านั้น
องค์ประกอบตามสัดส่วนนั้นง่ายที่สุด ยิ่งมีการเปลี่ยนแปลงมาก ค่าสัมประสิทธิ์ก็จะยิ่งมากขึ้น (สัดส่วนในสูตร) และเพื่อลดผลกระทบ ก็เพียงพอแล้วที่จะลดค่าสัมประสิทธิ์ (ตัวคูณ)
สมมติว่าความชื้นในดินในเรือนกระจกต่ำกว่าค่าที่ตั้งไว้มาก - ดังนั้นเวลาในการรดน้ำควรนานขึ้นตามปริมาณที่เท่ากันเนื่องจากความชื้นในปัจจุบันต่ำกว่าค่าที่ตั้งไว้ นี่เป็นตัวอย่างคร่าวๆ แต่นี่คือหลักการทั่วไป
องค์ประกอบที่เป็นส่วนประกอบ - จำเป็นต้องเพิ่มความแม่นยำในการควบคุมตามเหตุการณ์การควบคุมก่อนหน้านี้: ข้อผิดพลาดก่อนหน้านี้จะถูกรวมเข้าด้วยกัน และจะมีการแก้ไขเพื่อให้ได้รับการเบี่ยงเบนเป็นศูนย์ในที่สุดเมื่อทำการควบคุมในอนาคต
สุดท้ายคือองค์ประกอบส่วนต่าง อัตราการเปลี่ยนแปลงของตัวแปรควบคุมจะถูกนำมาพิจารณาด้วย ไม่ว่าค่าที่ระบุจะเปลี่ยนแปลงอย่างราบรื่นหรือกะทันหันก็ตาม การดำเนินการตามกฎระเบียบไม่ควรนำไปสู่การเบี่ยงเบนค่ามากเกินไปในระหว่างการควบคุม
สิ่งที่เหลืออยู่คือการเลือกอุปกรณ์สำหรับการควบคุม PID วันนี้มีหลายรายการในตลาดมีหลายช่องที่ให้คุณเปลี่ยนพารามิเตอร์หลายรายการพร้อมกันดังในตัวอย่างข้างต้นพร้อมเรือนกระจก
มาดูการออกแบบคอนโทรลเลอร์โดยใช้ตัวอย่างคอนโทรลเลอร์ universal PID TRM148 จากบริษัท Aries กัน
เซ็นเซอร์อินพุตแปดตัวส่งสัญญาณไปยังอินพุตที่เกี่ยวข้อง สัญญาณจะถูกปรับขนาด, กรอง, แก้ไข, สามารถดูค่าได้บนจอแสดงผลโดยการสลับด้วยปุ่ม
เอาต์พุตของอุปกรณ์ได้รับการผลิตขึ้นโดยการดัดแปลงที่แตกต่างกันโดยต้องผสมผสานสิ่งต่อไปนี้:
รีเลย์ 4 A 220 V;
ออปโตคัปเปลอร์ของทรานซิสเตอร์ชนิด n–p–n 400 mA 60 V;
ออปโตคัปเปลอร์ triac 50 mA 300 V;
DAC “พารามิเตอร์กระแส 4...20 mA”;
DAC “แรงดันไฟฟ้าพารามิเตอร์ 0...10 V”;
เอาต์พุต 4...6 V 100 mA สำหรับควบคุมโซลิดสเตตรีเลย์
ดังนั้นการดำเนินการควบคุมอาจเป็นแบบอะนาล็อกหรือดิจิทัล - สิ่งเหล่านี้คือพัลส์ที่มีความกว้างแปรผันและอะนาล็อก - ในรูปแบบของแรงดันหรือกระแสที่เปลี่ยนแปลงได้อย่างราบรื่นในช่วงรวม: จาก 0 ถึง 10 V สำหรับแรงดันไฟฟ้าและจาก 4 ถึง 20 mA สำหรับสัญญาณปัจจุบัน
สัญญาณเอาท์พุตเหล่านี้ถูกใช้อย่างแม่นยำในการควบคุมแอคชูเอเตอร์ เช่น ปั๊มระบบชลประทาน หรือรีเลย์ที่เปลี่ยนองค์ประกอบความร้อนหรือมอเตอร์ควบคุมวาล์วเปิดและปิด มีตัวบ่งชี้สัญญาณบนแผงควบคุม
ในการโต้ตอบกับพีซี ตัวควบคุม TRM148 มีอินเทอร์เฟซ RS-485 ซึ่งช่วยให้:
- รับข้อมูลการดำเนินงานจากเครือข่ายเพื่อสร้างสัญญาณควบคุม
กำหนดค่าอุปกรณ์บนพีซี (มีโปรแกรมกำหนดค่าให้ฟรี)
ส่งค่าปัจจุบันของค่าที่วัดได้, กำลังเอาต์พุตของคอนโทรลเลอร์, รวมถึงพารามิเตอร์ที่ตั้งโปรแกรมได้ไปยังเครือข่าย
เป็นที่ถกเถียงกันอยู่ว่าประสิทธิภาพสูงสุดนั้นมาจาก ป-ลอว์, - ขึ้นอยู่กับอัตราส่วน tp / T d .
อย่างไรก็ตาม หากการได้รับ P-regulator Kr มีขนาดเล็ก (ส่วนใหญ่มักจะสังเกตได้ด้วยความล่าช้า) สิ่งนี้ไม่ได้ให้ความแม่นยำในการควบคุมสูงเพราะ ในกรณีนี้ค่าจะมีขนาดใหญ่
ถ้า Kp > 10 แสดงว่า P-regulator เป็นที่ยอมรับได้ และหาก Kp< 10, то требуется введение в закон управления составляющей.
กฎหมายควบคุม PI
ที่พบมากที่สุดในทางปฏิบัติคือ ตัวควบคุมพีไอ,ซึ่งมีข้อดีดังต่อไปนี้:
- ให้การควบคุมเป็นศูนย์
- ค่อนข้างง่ายในการตั้งค่าเพราะว่า... มีการปรับพารามิเตอร์เพียงสองตัวเท่านั้น ได้แก่ อัตราขยาย Kp และค่าคงที่เวลาการรวม Ti ในตัวควบคุมดังกล่าว สามารถปรับค่าอัตราส่วน Kp/Ti-min ให้เหมาะสมได้ ซึ่งรับประกันการควบคุมด้วยการควบคุมรูต-ค่าเฉลี่ย-กำลังสองขั้นต่ำที่เป็นไปได้
- ความไวต่อสัญญาณรบกวนต่ำในการวัด (ต่างจากตัวควบคุม PID)
กฎหมายควบคุมพีไอดี
สำหรับลูปควบคุมที่สำคัญที่สุด เราสามารถแนะนำให้ใช้ได้ , ให้ประสิทธิภาพสูงสุดในระบบ
อย่างไรก็ตาม โปรดทราบว่าการดำเนินการนี้ทำได้เฉพาะกับการตั้งค่าที่เหมาะสมที่สุดเท่านั้น (มีการกำหนดค่าพารามิเตอร์สามตัว)
ด้วยความล่าช้าที่เพิ่มขึ้นในระบบ การเปลี่ยนเฟสเชิงลบจะเพิ่มขึ้นอย่างรวดเร็ว ซึ่งจะช่วยลดผลกระทบของส่วนประกอบส่วนต่างของคอนโทรลเลอร์ ดังนั้นคุณภาพของตัวควบคุม PID สำหรับระบบที่มีความล่าช้ามากจึงเทียบได้กับคุณภาพของตัวควบคุม PI
นอกจากนี้ การมีอยู่ของสัญญาณรบกวนในช่องการวัดในระบบที่มีตัวควบคุม PID ทำให้เกิดความผันผวนแบบสุ่มอย่างมีนัยสำคัญในสัญญาณควบคุมของตัวควบคุม ซึ่งเพิ่มความแปรปรวนของข้อผิดพลาดในการควบคุมและการสึกหรอของกลไก
ดังนั้นควรเลือกตัวควบคุม PID สำหรับระบบควบคุมที่มีระดับเสียงค่อนข้างต่ำและความล่าช้าในการควบคุม ตัวอย่างของระบบดังกล่าว ได้แก่ ระบบควบคุมอุณหภูมิ