รูปปกบทความ

1. 🎯 ตอนที่ 11: รวมพลัง P, I, D: เมื่อ 3 พลังประสานกัน สยบทุกความแกว่ง

2. 📖 เปิดฉาก (The Hook)

สวัสดีครับน้องๆ และนักพัฒนาทุกท่าน! ยินดีต้อนรับกลับสู่ซีรีส์ เจาะลึกวิศวกรรมระบบควบคุม (Control Systems) จาก 101 ถึง Advance กับพี่วิศวกรคนเดิมครับ

ตลอด 3 ตอนที่ผ่านมา เราได้ชำแหละสมองกลแต่ละส่วนกันไปแล้ว ไม่ว่าจะเป็น P (Proportional) ที่รวดเร็วแต่ชอบทิ้งรอยด่างพร้อย (Steady-state error), I (Integral) นักสะสมความผิดพลาดที่กัดไม่ปล่อยแต่แอบทำให้ระบบแกว่ง (Overshoot), และ D (Derivative) นักพยากรณ์อนาคตที่คอยแตะเบรกแต่ก็แพ้ทางสัญญาณรบกวน (Noise)

ลองจินตนาการดูสิครับว่า ถ้าเราให้ฮีโร่ทั้งสามคนนี้ทำงานแยกกัน เครื่องจักรของเราก็คงมีจุดอ่อนอยู่เสมอ แต่ถ้าเรานำทั้งสามมา “ฟิวชั่น” รวมร่างกันล่ะ? ความมหัศจรรย์ทางคณิตศาสตร์จะเกิดขึ้นทันทีครับ! วันนี้เราจะมาดูการรวมพลังของ PID Controller อัลกอริทึมคลาสสิกที่ถูกคิดค้นมาเกือบร้อยปี แต่ยังคงครองแชมป์ถูกใช้งานในระบบ Automation และหุ่นยนต์อุตสาหกรรมกว่า 95% ทั่วโลก มันทำงานสอดประสานกันอย่างไร? ไปดูกันเลยครับ!

3. 🧠 แก่นวิชา (Core Concepts)

ความงดงามของสมการ PID คือการแบ่งแยกหน้าที่รับผิดชอบตาม “กาลเวลา (Time dimensions)” ครับ หากเปรียบเทียบกับการขับรถพุ่งเข้าหาเป้าหมาย (Setpoint) เราสามารถสรุปบทบาทของ 3 พลังได้ดังนี้:

  • P (Proportional) = “ปัจจุบัน” (The Present): P-term จะดูแค่ว่า ณ วินาทีนี้ เราอยู่ห่างจากเป้าหมายแค่ไหน (Current Error) เปรียบเทียบ: เหมือนการมองเห็นว่าป้ายจอดรถอยู่ห่างออกไป 100 เมตร คุณจึง “เหยียบคันเร่งตามระยะห่าง” ยิ่งไกลยิ่งเหยียบมิด ยิ่งใกล้ยิ่งถอนคันเร่ง แต่มันไม่สนใจว่าที่ผ่านมาคุณขับมายังไง หรือถนนจะลื่นแค่ไหน
  • I (Integral) = “อดีต” (The Past): I-term จะดูว่า ที่ผ่านมาตั้งแต่ต้น เรามีความผิดพลาดสะสมมาเท่าไหร่แล้ว (Accumulated Error) เปรียบเทียบ: ถ้ารถของคุณบรรทุกของหนักมากจนเหยียบคันเร่งด้วย P อย่างเดียวแล้วรถไม่ยอมขยับไปแตะเส้นชัย (เกิด Offset) ตัว I จะจำไว้ว่า “เฮ้ย ผ่านมา 5 วินาทีแล้วยังไม่ถึงสักที!” แล้วมันจะค่อยๆ “ชดเชยน้ำหนักรถ” โดยการกดคันเร่งเพิ่มขึ้นเรื่อยๆ จนกว่ากันชนจะแตะเส้นชัยเป๊ะๆ
  • D (Derivative) = “อนาคต” (The Future): D-term จะดูว่า แนวโน้ม ของความผิดพลาดกำลังเปลี่ยนไปเร็วแค่ไหน (Rate of Change) เปรียบเทียบ: ถ้าคุณพุ่งเข้าหาป้ายจอดรถด้วยความเร็วสูงมาก ตัว D จะมองเห็นอนาคตเลยว่า “ถ้าขืนยังพุ่งด้วยความเร็วเท่านี้นะ เลยป้ายแน่นอน!” มันจึงสั่ง “แตะเบรก” สวนทางล่วงหน้า เพื่อให้รถชะลอและจอดสนิทอย่างนิ่มนวลที่สุด (Damping)

เมื่อนำ 3 ตัวนี้มารวมกัน P จะช่วยให้ระบบตอบสนองไว (Fast Response), I จะช่วยขจัดความผิดพลาดให้เป็นศูนย์ (Zero Steady-State Error), และ D จะช่วยลดความแกว่งและทำให้ระบบนิ่งเร็วขึ้น (Reduce Overshoot & Settling Time)

รูปประกอบบล็อกไดอะแกรม PID เต็มรูปแบบและกราฟผลตอบสนอง

4. 🧮 ร่ายมนต์สมการและโค้ดควบคุม (The Math & Implementation)

ในทางคณิตศาสตร์แบบ Continuous-time สมองกล PID จะรวมผลลัพธ์ของทั้ง 3 พจน์เข้าด้วยกันตามสมการ: $$ u(t) = K_p e(t) + K_i \int_{0}^{t} e(\tau) d\tau + K_d \frac{de(t)}{dt} $$

และหากเราแปลงลาปลาซ (Laplace Transform) เพื่อดูเป็น ฟังก์ชันถ่ายโอน (Transfer Function) ในโดเมน $s$ จะได้รูปแบบ Parallel (Ideal) form ที่สวยงามมาก: $$ C(s) = \frac{U(s)}{E(s)} = K_p + \frac{K_i}{s} + K_d s $$

การเขียนโค้ด C/C++ บน STM32 (Discrete Implementation): เมื่อนำมาลงไมโครคอนโทรลเลอร์ เราจะต้องแปลงสมการนี้ให้อยู่ในรูป Discrete-time ผ่าน Z-Transform (หรือ Euler approximation) โดยทำงานภายใต้ความถี่การสุ่ม (Sample Time: $dt$) ที่คงที่ โค้ดที่วิศวกรใช้จริงจะหน้าตาประมาณนี้ครับ:

// โครงสร้างของ PID Controller
typedef struct {
    float Kp, Ki, Kd;       // อัตราขยาย (Gains)
    float integral_sum;     // ผลสะสมของ I-term (อดีต)
    float prev_error;       // ความผิดพลาดรอบที่แล้ว (สำหรับหาอนาคต)
    float output_limit;     // ขีดจำกัดของ Actuator (เช่น PWM 100%)
} PID_Controller;

float PID_Compute(PID_Controller *pid, float setpoint, float measured_value, float dt) {
    // 1. หาความผิดพลาด ณ ปัจจุบัน
    float error = setpoint - measured_value;

    // 2. พลังแห่งปัจจุบัน (Proportional)
    float P_out = pid->Kp * error;

    // 3. พลังแห่งอดีต (Integral) พร้อมป้องกัน Integral Windup
    pid->integral_sum += (error * dt);
    float I_out = pid->Ki * pid->integral_sum;

    // 4. พลังแห่งอนาคต (Derivative)
    float derivative = (error - pid->prev_error) / dt;
    float D_out = pid->Kd * derivative;

    // 5. รวม 3 พลังประสาน (Total Output)
    float output = P_out + I_out + D_out;

    // 6. จำกัดการสั่งงานไม่ให้เกินขีดจำกัด Hardware (Saturation limits)
    if (output > pid->output_limit) {
        output = pid->output_limit;
        // เคล็ดลับ: ถ้า Output ชนเพดาน ต้องหยุดสะสม I-term (Anti-Windup)
        pid->integral_sum -= (error * dt); 
    } else if (output < -pid->output_limit) {
        output = -pid->output_limit;
        pid->integral_sum -= (error * dt);
    }

    // เก็บค่าไว้ใช้วิเคราะห์อนาคตในรอบถัดไป
    pid->prev_error = error;

    return output;
}

5. 🛡️ เคล็ดลับจากคัมภีร์ลับ (Under the Hood / Pro-Tips)

ถึงแม้สมการ PID จะดูสมบูรณ์แบบ แต่ในโลกของการทำ Hardware จริง มี “หลุมพราง” ที่วิศวกรระบบควบคุมต้องระวังเสมอครับ:

  1. ระวังผลกระทบจาก Zero-Order Hold (ZOH): การทำงานบนไมโครคอนโทรลเลอร์เป็นการทำงานแบบสุ่มเวลา (Sampled-data system) ค่า $dt$ ต้องถูกควบคุมให้ “คงที่เป๊ะๆ” ด้วย Hardware Timer Interrupt หากคุณเอาโค้ด PID ไปใส่ใน while(1) ธรรมดาที่เวลาหน่วงไม่แน่นอน (Jitter) ค่า Integral และ Derivative จะเพี้ยนจนระบบเสียเสถียรภาพทันที!
  2. Derivative Noise Amplification (การขยายสัญญาณรบกวนของ D-term): สัญญาณจากเซ็นเซอร์ในโลกจริงเต็มไปด้วย Noise หากคุณนำไปดิฟ ($de/dt$) แบบโต้งๆ มอเตอร์ของคุณจะครางเสียงแหลมและกระตุกรัวๆ (Jitter) วิศวกรระดับโปรจะไม่มีวันใช้ D-term เปล่าๆ แต่จะต้องคล่อมมันด้วย Low-Pass Filter เสมอ (เช่น เปลี่ยนจาก $K_d s$ เป็น $\frac{K_d s}{\tau_f s + 1}$)
  3. Integral Windup (การอิ่มตัวของอดีต): หาก Actuator ของคุณ (เช่น มอเตอร์) จ่ายพลังงานเต็ม 100% แล้ว แต่ยังไม่ถึงเป้าหมาย ตัว I-term จะยังคงบวกสะสมความผิดพลาดไปเรื่อยๆ จนทะลุฟ้า เมื่อระบบกลับมาทำงานปกติ ค่าที่สะสมไว้จะสั่งให้มอเตอร์วิ่งเลยเป้าไปไกลมาก (Overshoot รุนแรง) โค้ดด้านบนพี่ได้ใส่ลอจิก Anti-windup แบบเบื้องต้นไว้ให้แล้ว นั่นคือการหยุดบวกค่าเมื่อ Output ชนเพดานครับ

6. 🏁 บทสรุป (To be continued…)

การรวมพลังของ PID (Proportional-Integral-Derivative) คือสถาปัตยกรรมที่ลงตัวที่สุดระหว่างความเรียบง่ายและประสิทธิภาพ ด้วยการใช้ข้อมูลครบทั้ง 3 มิติเวลา (ปัจจุบัน, อดีต, อนาคต) ทำให้มันกลายเป็นมาตรฐานทองคำในการควบคุม Closed-loop systems ทุกประเภท ตั้งแต่การคุมอุณหภูมิตู้ฟักไข่ ไปจนถึงการรักษาสมดุลของโดรน

แต่ปัญหาโลกแตกที่ตามมาก็คือ… “แล้วเราจะรู้ได้อย่างไรว่าควรตั้งค่า $K_p, K_i, K_d$ เป็นตัวเลขเท่าไหร่?” การสุ่มเดา (Trial and Error) อาจจะทำให้หุ่นยนต์ของคุณพังพินาศได้ ในตอนต่อไป เราจะมาเปิดคัมภีร์การจูน (Loop Tuning) ที่โด่งดังที่สุดในโลกอย่าง Ziegler-Nichols Method กันครับ รับรองว่าคณิตศาสตร์จะช่วยชีวิตคุณได้อีกครั้ง!


ต้องการที่ปรึกษาด้านการออกแบบระบบควบคุม (Control Systems), หุ่นยนต์อัตโนมัติ (Robotics) หรือพัฒนาระบบ Automation ขั้นสูงให้กับโรงงานของคุณ? ทีมงาน WP Solution พร้อมให้บริการออกแบบและติดตั้งระบบแบบครบวงจร ดูรายละเอียดบริการของเราได้ที่: www.wpsolution2017.com หรือพูดคุยปรึกษาเบื้องต้นได้ที่ Line: wisit.p