รูปปกบทความ

1. 🎯 ตอนที่ 21: สมการ Difference Equation สำหรับเขียนโปรแกรม PID (เปลี่ยนแคลคูลัสให้เป็นโค้ด)

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

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

เราเรียนทฤษฎีแคลคูลัสของ PID ที่มีทั้งเครื่องหมายปริพันธ์ (Integral, $\int$) และอนุพันธ์ (Derivative, $\frac{d}{dt}$) กันมาอย่างโชกโชนในบทก่อนๆ แต่ปัญหาโลกแตกของวิศวกร Embedded อย่างพวกเราก็คือ… “ไมโครคอนโทรลเลอร์มันไม่รู้จักแคลคูลัสครับ!”

สมองกลอย่าง STM32, Arduino หรือ PLC ล้วนแต่เป็นสิ่งมีชีวิตในโลกดิจิทัลที่รู้จักแค่การบวก ลบ คูณ หาร (Algebraic operations) เท่านั้น การจะสั่งให้มัน “หาพื้นที่ใต้กราฟ” หรือ “หาความชัน” ของสัญญาณต่อเนื่อง มันทำตรงๆ ไม่ได้ครับ เราจึงต้องมีวุ้นแปลภาษาที่เรียกว่า สมการผลต่าง (Difference Equation) เพื่อสับย่อยเวลาต่อเนื่องให้กลายเป็น “เวลาสุ่ม (Discrete-time)”

วันนี้พี่จะพาไปดูเวทมนตร์ทางคณิตศาสตร์ที่แปลงสมการแคลคูลัสอันซับซ้อน ให้อยู่ในรูปของการบวกลบคูณหารธรรมดาๆ เพื่อปูทางไปสู่การเขียนโค้ด C/C++ ฝังลงชิปกันแบบมืออาชีพครับ!

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

ในโลกของเวลาวิยุต (Discrete-time) เราจะไม่ได้มองเวลาเป็นเส้นตรงต่อเนื่อง $t$ อีกต่อไป แต่เราจะมองเป็น “รอบการทำงาน” ที่เรียกว่า $k$ โดยแต่ละรอบจะห่างกันเท่ากับเวลาสุ่ม (Sampling Time, $T_s$)

เมื่อเราต้องแปลงสมการแคลคูลัส เราจะใช้วิธีการประมาณค่า (Approximation) ซึ่งมีวิธีคลาสสิกอยู่ 3 แบบหลักๆ ครับ:

  1. Forward Difference (ผลต่างข้างหน้า): มองไปข้างหน้า 1 ก้าว $s \to \frac{z-1}{T_s}$
  2. Backward Difference (ผลต่างย้อนหลัง): นำค่าปัจจุบันลบค่าในอดีต (นิยมใช้หาโหมด D) $s \to \frac{z-1}{T_s z}$
  3. Trapezoidal Approximation / Bilinear (การแปลงเชิงเส้นคู่): หาพื้นที่แบบสี่เหลี่ยมคางหมู (นิยมใช้หาโหมด I) $s \to \frac{2}{T_s}\frac{z-1}{z+1}$

การแปลงร่าง PID เข้าสู่สมการผลต่าง: สมการ Continuous PID ดั้งเดิมคือ: $$ u(t) = K_p e(t) + K_i \int e(t) dt + K_d \frac{de(t)}{dt} $$

เมื่อเราหั่นมันด้วยเวลาสุ่ม $T_s$ และใช้ Backward Difference กับโหมด D และใช้การบวกสะสม (Summation) กับโหมด I เราจะได้สมการที่เรียกว่า Positional Form (รูปแบบตำแหน่ง): $$ u[k] = K_p e[k] + K_i T_s \sum_{j=0}^{k} e[j] + \frac{K_d}{T_s} (e[k] - e[k-1]) $$

อธิบายง่ายๆ ภาษาคอมพิวเตอร์:

  • $e[k]$ คือ Error ปัจจุบัน
  • $e[k-1]$ คือ Error ของรอบที่แล้ว
  • $\sum e[j]$ คือ ตัวแปรผลรวม Error ตั้งแต่เปิดเครื่อง
รูปประกอบการแปลงสมการ Continuous เป็น Discrete-time และโครงสร้าง Positional/Velocity form

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

การเขียนโค้ดด้วยรูปแบบ Positional Form ที่เราเพิ่งได้มานั้นใช้งานได้จริง แต่ในทางปฏิบัติ มันมีจุดอ่อนร้ายแรงคือ “โหมด I ต้องสะสมค่าตัวเลขไปเรื่อยๆ” ซึ่งกินหน่วยความจำ และเสี่ยงต่อการเกิด Integral Windup อย่างรุนแรง

วิศวกรระดับโปรจึงคิดค้นโครงสร้างที่ฉลาดกว่าเรียกว่า Velocity Form (รูปแบบความเร็ว หรือ Incremental Form) โดยแทนที่เราจะคำนวณหาสัญญาณสั่งงาน $u[k]$ ตรงๆ เราจะคำนวณหา “ส่วนต่างของการสั่งงาน ($\Delta u[k]$)” แทน!

คณิตศาสตร์ของ Velocity Form ทำได้โดยการนำสมการรอบปัจจุบัน $u[k]$ ลบด้วยสมการรอบอดีต $u[k-1]$: $$ \Delta u[k] = u[k] - u[k-1] $$ เมื่อจัดรูปสมการใหม่ (กระจายเทอม P, I, D) เราจะได้เวทมนตร์บรรทัดนี้ครับ: $$ \Delta u[k] = K_p(e[k] - e[k-1]) + K_i T_s e[k] + \frac{K_d}{T_s}(e[k] - 2e[k-1] + e[k-2]) $$

ดังนั้น สัญญาณที่เราจะส่งให้ Actuator คือ: $$ u[k] = u[k-1] + \Delta u[k] $$

ตัวอย่างการเขียนโค้ด (C/C++):

// ตัวแปรพารามิเตอร์ของระบบ (Global Variables)
float Kp = 2.0, Ki = 0.5, Kd = 0.1;
float Ts = 0.01;      // Sampling Time 10ms
float u_prev = 0.0;   // u[k-1]
float e_prev1 = 0.0;  // e[k-1]
float e_prev2 = 0.0;  // e[k-2]

float PID_Velocity_Form(float setpoint, float measured_value) {
    // 1. คำนวณ Error ปัจจุบัน e[k]
    float e_k = setpoint - measured_value;
    
    // 2. คำนวณส่วนต่างของแต่ละพจน์
    float delta_P = Kp * (e_k - e_prev1);
    float delta_I = Ki * Ts * e_k;
    float delta_D = (Kd / Ts) * (e_k - 2.0*e_prev1 + e_prev2);
    
    // 3. คำนวณส่วนต่างพลังงานรวม (Delta u[k])
    float delta_u = delta_P + delta_I + delta_D;
    
    // 4. สั่งงานจริง u[k] = u[k-1] + Delta u[k]
    float u_k = u_prev + delta_u;
    
    // *** ป้องกัน Integral Windup แบบง่ายที่สุด ***
    // ถ้า Output ชนเพดาน เราก็แค่จำกัดค่า u_k ไว้ 
    // โดยไม่ต้องไปเคลียร์ตัวแปรสะสม I เหมือนใน Positional Form!
    if(u_k > 100.0) u_k = 100.0;
    if(u_k < -100.0) u_k = -100.0;
    
    // 5. เลื่อนเวลา อดีตกลายเป็นอดีตที่ไกลกว่า
    u_prev = u_k;
    e_prev2 = e_prev1;
    e_prev1 = e_k;
    
    return u_k;
}

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

  1. เวทมนตร์ของ Velocity Form (Incremental PID): ข้อดีสูงสุดของสมการนี้คือมัน ป้องกัน Integral Windup โดยธรรมชาติ ครับ! เพราะมันไม่จำเป็นต้องมีตัวแปร integral_sum ให้ค่าล้นทะลุฟ้า หากมอเตอร์ของคุณจ่ายไฟตันที่ 100% แล้ว ค่า $u_k$ ก็จะค้างอยู่ที่ 100 ทันทีที่ Setpoint ลดลง หรือ Error เปลี่ยนทิศทาง มันก็สามารถลบออกจาก 100 ได้ทันที (Bumpless Transfer) มอเตอร์จะตอบสนองไวมากครับ
  2. เสถียรภาพจากการแปลง (Stability Mapping): รู้หรือไม่ว่า การใช้วิธี Forward Difference ในการแปลงแคลคูลัส มีความเสี่ยงสูงมากที่จะทำให้ระบบ “ระเบิด (Unstable)”! ในทางทฤษฎี (z-plane) พื้นที่เสถียรภาพของ s-plane ด้านซ้าย จะถูกส่งไปนอกวงกลมหนึ่งหน่วยของ z-plane ได้ง่ายมาก วิศวกรระดับโลกจึงมักจะเลือกใช้ Backward Difference หรือ Bilinear Transformation (Tustin) เสมอ เพราะมันการันตีได้ว่าระบบที่เสถียรในโดเมน $s$ จะถูกส่งเข้ามาอยู่ในวงกลมรัศมีหนึ่งหน่วย (Unit circle) ของโดเมน $z$ อย่างปลอดภัย 100%

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

Difference Equation คือสะพานเชื่อมระหว่างทฤษฎีแคลคูลัสอันสวยงามบนกระดาษ และบรรทัดโค้ดในโลกความเป็นจริง เมื่อเราแปลงร่างสมการ PID ให้อยู่ในรูปของผลต่าง โดยเฉพาะรูปแบบ Velocity Form เราจะได้สมองกลที่ทำงานได้รวดเร็ว ประหยัดหน่วยความจำ และทนทานต่อสภาวะอิ่มตัวของ Actuator ได้อย่างยอดเยี่ยม

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


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