ตอนที่ 23: Cascade Control ควบคุมแบบลูปซ้อนลูป สยบทุกการรบกวน

1. 🎯 ตอนที่ 23: Cascade Control ควบคุมแบบลูปซ้อนลูป สยบทุกการรบกวน
2. 📖 เปิดฉาก (The Hook)
สวัสดีครับน้องๆ และนักพัฒนาทุกท่าน! ยินดีต้อนรับกลับสู่ซีรีส์ เจาะลึกวิศวกรรมระบบควบคุม (Control Systems) จาก 101 ถึง Advance สไตล์วิศวกรรุ่นพี่ครับ
ลองจินตนาการว่าน้องเป็น “ประธานบริษัท (CEO)” ที่ต้องการให้บริษัทมีกำไร 100 ล้านบาทต่อปี (นี่คือ Setpoint ของน้อง) ถ้าน้องใช้ระบบควบคุมแบบลูปเดี่ยว (Single-loop Control) น้องจะต้องลงไปสั่งงานพนักงานระดับปฏิบัติการด้วยตัวเองทั้งหมด แต่ปัญหาก็คือ กว่าที่น้องจะรู้ตัวว่ายอดขายตกเพราะราคาวัตถุดิบแพงขึ้น (Disturbance) เวลาก็ผ่านไปจนถึงสิ้นไตรมาสแล้ว! การแก้ไขจึงล่าช้าและบริษัทก็ขาดทุนไปแล้ว
ในโลกความเป็นจริง CEO ที่เก่งจะจ้าง “ผู้จัดการแผนก (Manager)” มาคอยคุมงานย่อยๆ อีกที CEO มีหน้าที่แค่มองภาพรวมแล้วสั่งเป้าหมายยอดขายไปให้ผู้จัดการ ส่วนผู้จัดการจะคอยมอนิเตอร์และแก้ปัญหาราคาวัตถุดิบรายวันแบบเรียลไทม์ ทำให้ผลกระทบแทบจะไม่กระเทือนถึงภาพรวมของบริษัทเลย!
แนวคิดการแบ่งการทำงานเป็นลำดับชั้นแบบนี้ ในโลกของวิศวกรรมระบบควบคุมเราเรียกว่า Cascade Control (การควบคุมแบบคาสเคด หรือ ลูปซ้อนลูป) ซึ่งเป็นเทคนิคที่ใช้กันอย่างแพร่หลายมากที่สุดวิธีหนึ่งในอุตสาหกรรม วันนี้พี่จะพาไปเจาะลึกสถาปัตยกรรมนี้กันครับ ว่ามันเอาชนะข้อจำกัดของ PID ลูปเดียวได้อย่างไร!
3. 🧠 แก่นวิชา (Core Concepts)
Cascade Control คือสถาปัตยกรรมที่นำระบบควบคุม (มักจะเป็น PID) มาต่อกันแบบ “ซ้อนลูป (Nested loops)” โดยแบ่งออกเป็น 2 ลูปหลักๆ:
- Primary Loop (ลูปหลัก หรือ Outer Loop): เปรียบเสมือน CEO ทำหน้าที่ควบคุมตัวแปรหลักที่เราสนใจจริงๆ (เช่น ตำแหน่งของแขนกล หรือ อุณหภูมิของเตาเผา) เอาต์พุตของลูปนี้ ไม่ใช่ สัญญาณที่ส่งไปขับฮาร์ดแวร์โดยตรง แต่จะถูกส่งไปเป็น “ค่าเป้าหมาย (Setpoint)” ให้กับลูปรอง
- Secondary Loop (ลูปรอง หรือ Inner Loop): เปรียบเสมือนผู้จัดการ ทำหน้าที่ควบคุมตัวแปรภายในที่ตอบสนองได้รวดเร็วกว่า (เช่น กระแสไฟฟ้าของมอเตอร์ หรือ อัตราการไหลของเชื้อเพลิง) เอาต์พุตของลูปนี้ถึงจะเป็นสัญญาณที่ส่งไปขับ Actuator (วาล์ว หรือ มอเตอร์) จริงๆ
ทำไมถึงต้องซ้อนลูป? (The Magic of Disturbance Rejection) จุดประสงค์หลักของการทำ Cascade Control คือการ ขจัดการรบกวน (Disturbance Rejection) ให้รวดเร็วที่สุด หากมีสัญญาณรบกวนเข้ามากระแทกที่ระบบย่อย (เช่น โหลดทางกลเปลี่ยนกะทันหัน หรือแรงดันน้ำมันตก) ตัวเซ็นเซอร์ใน Inner Loop จะตรวจจับและสั่งตัวควบคุม Inner PID ให้แก้ไขปัญหานี้ทันที ก่อนที่ผลกระทบนั้นจะลามออกไปถึงตัวแปรใน Outer Loop!
นอกจากนี้ Inner Loop ยังช่วย “ปรับให้ระบบเป็นเชิงเส้น (Linearization)” เช่น วาล์วที่มีความฝืด (Stiction) หรือมอเตอร์ที่มี Deadband ตัว Inner Loop จะช่วยชดเชยความเพี้ยนเหล่านี้ ทำให้ Outer Loop มองเห็นฮาร์ดแวร์เบื้องล่างเป็นระบบที่สมบูรณ์แบบและสั่งงานได้ง่ายขึ้นมากครับ

4. 🧮 ร่ายมนต์สมการและโค้ดควบคุม (The Math & Implementation)
ในเชิงคณิตศาสตร์ เราสามารถพิสูจน์ความเจ๋งของมันได้จากการยุบบล็อกไดอะแกรมครับ สมมติให้:
- $C_1(s)$ คือ Primary Controller, $G_1(s)$ คือ Primary Plant
- $C_2(s)$ คือ Secondary Controller, $G_2(s)$ คือ Secondary Plant
ฟังก์ชันถ่ายโอนของ Inner Loop (ระบบปิด) คือ: $$ T_2(s) = \frac{C_2(s)G_2(s)}{1 + C_2(s)G_2(s)} $$
และฟังก์ชันถ่ายโอนของ Outer Loop (ระบบปิดทั้งหมด) จาก Setpoint ($R$) ไปยัง Output ($Y_1$) จะกลายเป็น: $$ T_{total}(s) = \frac{C_1(s) T_2(s) G_1(s)}{1 + C_1(s) T_2(s) G_1(s)} $$
ความลับอยู่ที่เทอม $T_2(s)$ ครับ! ถ้าเราจูน Inner Loop ให้มีอัตราขยาย (Gain) สูงๆ เราจะได้ $T_2(s) \approx 1$ ในย่านความถี่ต่ำถึงปานกลาง นั่นแปลว่าพลวัตที่ซับซ้อนและเชื่องช้าของ $G_2(s)$ ได้ถูก “ลบหายไป” จากมุมมองของ $C_1(s)$ ทำให้เราสามารถจูน Outer Loop ให้ตอบสนองได้เร็วและดุดันขึ้นกว่าเดิมมาก!
ตัวอย่างโค้ด C/C++: การควบคุมตำแหน่งมอเตอร์ (Position & Current Cascade) ในงานหุ่นยนต์ เรามักใช้ Cascade 3 ชั้น: Position (Outer) $\rightarrow$ Velocity (Middle) $\rightarrow$ Current (Inner) แต่นี่คือตัวอย่างแบบ 2 ชั้นที่เห็นภาพง่ายที่สุดครับ:
// อัตราการทำงานของแต่ละลูป (สำคัญมาก!)
#define DT_INNER 0.001 // Inner Loop ทำงานทุก 1 ms (เร็วมาก)
#define DT_OUTER 0.01 // Outer Loop ทำงานทุก 10 ms (ช้ากว่า)
// ตัวแปรโกลบอล
float position_setpoint = 90.0; // เป้าหมายคือหมุนมอเตอร์ไปที่ 90 องศา
float current_setpoint = 0.0; // เป้าหมายกระแส (ถูกสั่งจาก Outer Loop)
// --- 1. ฟังก์ชัน Secondary Loop (คุมกระแส) ทำงานด้วยความถี่ 1000 Hz ---
void Timer1_ISR_1kHz() {
float actual_current = read_current_sensor();
// คุมกระแสไฟฟ้าให้ได้ตามที่ Outer Loop สั่ง (เปรียบเหมือนคุมแรงบิด)
// นิยมใช้ PI Controller ธรรมดาก็เพียงพอ
float pwm_output = PID_Current(current_setpoint, actual_current, DT_INNER);
set_motor_pwm(pwm_output);
}
// --- 2. ฟังก์ชัน Primary Loop (คุมตำแหน่ง) ทำงานด้วยความถี่ 100 Hz ---
void Timer2_ISR_100Hz() {
float actual_position = read_encoder();
// คุมตำแหน่งมอเตอร์ เอาต์พุตที่ได้คือ "ความพยายาม"
// ซึ่งเราจะแปลงมันเป็น "เป้าหมายกระแสไฟฟ้า" ส่งให้ Inner Loop
current_setpoint = PID_Position(position_setpoint, actual_position, DT_OUTER);
// สังเกตว่าเราป้องกันค่าเกิน (Saturation) ของกระแสตรงนี้ได้เลย
if(current_setpoint > MAX_CURRENT) current_setpoint = MAX_CURRENT;
if(current_setpoint < -MAX_CURRENT) current_setpoint = -MAX_CURRENT;
}5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)
การทำ Cascade Control ดูเหมือนจะมีแต่ข้อดี แต่ถ้าออกแบบไม่เป็น มันคือการหาเรื่องใส่ตัวชัดๆ ครับ นี่คือ 3 กฎเหล็กที่วิศวกรหน้างานต้องรู้:
- กฎของเวลา (Time Scale Separation): จำไว้เสมอว่า “Inner Loop ต้องเร็วกว่า Outer Loop เสมอ!” กฎหัวแม่มือ (Rule of thumb) ในระดับสากลคือ แบนด์วิดท์ (Bandwidth) หรือเวลาตอบสนองของ Inner Loop ควรจะเร็วกว่า Outer Loop อย่างน้อย 5 เท่า (Ratio of residence times $\ge 5$) ถ้าน้องตั้งให้สองลูปทำงานเร็วเท่าๆ กัน มันจะตีกันเอง (Interference) จนระบบแกว่งและพังในที่สุด!
- ลำดับการจูน (Tuning Sequence):
ห้ามจูนสองลูปพร้อมกันเด็ดขาด! ลำดับที่ถูกต้องคือ:
- ปลด Outer Loop ออก (เปลี่ยนเป็น Manual Mode)
- จูน Inner Loop ก่อน ให้ตอบสนองเร็วที่สุดและมี Overshoot น้อยที่สุด (มักใช้แค่ P หรือ PI)
- เมื่อ Inner Loop นิ่งแล้ว ค่อยสับสวิตช์ Inner ให้เป็น Auto แล้วจึงเริ่ม จูน Outer Loop ตามปกติ
- ปัญหา Integral Windup ที่ซับซ้อนขึ้น: ถ้าน้องใช้ PI Controller ทั้งสองลูป เมื่อมอเตอร์จ่ายไฟเต็ม 100% แล้ว (Inner Loop Saturate) ตัว Outer Loop จะยังคงคำนวณสะสมค่า I-term ไปเรื่อยๆ (เพราะไม่รู้ว่าลูกน้องทำงานสุดกำลังแล้ว) วิธีแก้ระดับโปรคือ น้องต้องส่งสัญญาณสถานะจาก Inner Loop กลับไปบอก Outer Loop ว่า “ตอนนี้ชนเพดานแล้วนะ หยุดบวกค่า Error ซะที!” ซึ่งเรียกว่าการทำ Tracking หรือ Anti-windup feedback ครับ
6. 🏁 บทสรุป (To be continued…)
Cascade Control คือศิลปะในการแบ่งแยกและปกครอง (Divide and Conquer) โดยการใช้ตัวเซ็นเซอร์ที่อยู่ใกล้กับจุดกำเนิดการรบกวน (Disturbance) มากที่สุด มาสร้างลูปป้องกันชั้นใน (Inner Loop) เพื่อรับแรงกระแทกแทนลูปหลัก (Outer Loop) ทำให้ระบบทั้งหมดมีความเสถียร รวดเร็ว และทนทานต่อสภาพแวดล้อมที่โหดร้ายได้ดีกว่าการใช้ PID ตัวเดียวอย่างเทียบไม่ติด
แต่ถ้าเราเจอระบบที่มีเซ็นเซอร์หลายตัว และมอเตอร์หลายตัวที่ต้องทำงานสอดประสานกัน (MIMO - Multi-Input Multi-Output) การซ้อนลูปแบบ Cascade อาจจะเริ่มเอาไม่อยู่แล้วครับ ในตอนต่อไป พี่จะพาก้าวข้ามขีดจำกัดของ PID แบบคลาสสิก เข้าสู่โลกของ Modern Control ด้วยพระเอกที่ชื่อว่า State-Space Representation ซึ่งเป็นพื้นฐานของการสร้างหุ่นยนต์และระบบนำทางอากาศยาน! รอติดตามกันนะครับ
ต้องการที่ปรึกษาด้านการออกแบบระบบควบคุม (Control Systems), หุ่นยนต์อัตโนมัติ (Robotics) หรือพัฒนาระบบ Automation ขั้นสูงให้กับโรงงานของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p