พิมพ์คำที่ต้องการค้นหา ทั้งภาษาไทยและอังกฤษ

  1. หน้าแรก
  2. คลังความรู้
  3. ระบบควบคุม
  4. P · PI · PD · PID

// บทที่ 13.16 · ระบบควบคุม · PID Control

ตัวควบคุม P, PI, PD และ PID

กว่า 90% ของลูปควบคุมในโรงงาน และแทบทุกลูปในมอเตอร์ไดรฟ์ โดรน และพาวเวอร์ซัพพลาย ใช้ PID หรือญาติของมัน สามเทอมนี้ดูความผิดพลาดในปัจจุบัน (P) อดีต (I) และแนวโน้มอนาคต (D) หน้านี้อธิบายว่าแต่ละเทอมเปลี่ยนขั้ว ศูนย์ และเฟสอย่างไร ออกแบบด้วยการวางขั้ว สร้างจริงด้วยออปแอมป์ และเจอปัญหาจริงอย่าง windup แล้วแก้อย่างไร สูตรใช้รหัส P

เขียนโดย อาจารย์มดอัปเดต
สรุปใน 30 วินาที
  • C(s)=KP+KIs+KDs=KDs2+KPs+KIsC(s) = K_P + \dfrac{K_I}{s} + K_Ds = \dfrac{K_Ds^2 + K_Ps + K_I}{s}: เพิ่มขั้วที่ศูนย์ 1 ตัว และศูนย์ 2 ตัว
  • P: เร็วขึ้น แต่ยังมีความผิดพลาดค้าง · I: ความผิดพลาดค้างเป็นศูนย์ แต่ช้าและแกว่งขึ้น · D: หน่วงการแกว่ง แต่ขยายสัญญาณรบกวน
  • PI ≈ ตัวชดเชย lag · PD ≈ lead · ออกแบบด้วยรูทโลคัส โบด หรือวางขั้วตรง ๆ
  • ใช้จริงต้องมี: ฟิลเตอร์ D, D จากเอาต์พุต, anti-windup
ระดับพื้นฐาน เริ่มเรียนควบคุมกลาง ป.ตรี วิศวกรรมขั้นสูง งานจริง · ป.โท

โครงสร้างของ PID สามรูปแบบ พื้นฐาน

ตัวควบคุมรับความผิดพลาด e(t)=r(t)−y(t)e(t) = r(t) - y(t) แล้วสร้างสัญญาณควบคุม u(t)u(t) ส่งให้ตัวขับ (ไดรเวอร์มอเตอร์ PWM ฮีตเตอร์) ตำราและผู้ผลิตแต่ละรายเขียนสูตรต่างกัน ต้องรู้ว่าตัวเลขที่เห็นเป็นรูปแบบไหน ไม่อย่างนั้นจูนผิด

P1 Parallel (independent) form รูปแบบขนาน

u(t)=KPe(t)+KI∫0te(τ) dτ+KDde(t)dt,C(s)=KP+KIs+KDsu(t) = K_Pe(t) + K_I\int_0^t e(\tau)\,d\tau + K_D\frac{de(t)}{dt}, \qquad C(s) = K_P + \frac{K_I}{s} + K_Ds

ใช้ในตำราและไลบรารีไมโครคอนโทรลเลอร์ส่วนใหญ่ (Arduino PID, MATLAB pid) · แต่ละเกนเป็นอิสระต่อกัน

P2 Ideal (standard, ISA) form รูปแบบมาตรฐาน

C(s)=KP(1+1Tis+Tds),KI=KPTi,KD=KPTdC(s) = K_P\left(1 + \frac{1}{T_is} + T_ds\right), \qquad K_I = \frac{K_P}{T_i}, \quad K_D = K_PT_d

TiT_i (เวลาอินทิกรัล, “reset time”) และ TdT_d (เวลาอนุพันธ์) มีหน่วยวินาที · ใช้ใน PLC และตัวควบคุมอุตสาหกรรม และในตาราง Ziegler–Nichols

P3 Series (interacting) form รูปแบบอนุกรม

C(s)=K′(1+1Ti′s)(1+Td′s) ⇒ KP=K′Ti′+Td′Ti′,  Ti=Ti′+Td′,  Td=Ti′Td′Ti′+Td′C(s) = K'\left(1 + \frac{1}{T_i's}\right)\left(1 + T_d's\right) \ \Rightarrow\ K_P = K'\frac{T_i' + T_d'}{T_i'},\ \ T_i = T_i' + T_d',\ \ T_d = \frac{T_i'T_d'}{T_i' + T_d'}

= PI อนุกรมกับ PD · ศูนย์สองตัวเป็นจำนวนจริงเสมอ (−1/Ti′-1/T_i' และ −1/Td′-1/T_d') · ตัวควบคุมแอนะล็อกรุ่นเก่าและวงจรออปแอมป์หลายแบบเป็นแบบนี้

P4 PID as poles and zeros PID ในภาษาขั้วและศูนย์

C(s)=KDs2+KPs+KIs=KD(s+z1)(s+z2)sC(s) = \frac{K_Ds^2 + K_Ps + K_I}{s} = \frac{K_D(s + z_1)(s + z_2)}{s}

ขั้วที่ s=0s = 0 (ยกชนิดของระบบ) + ศูนย์สองตัว (จริงหรือเชิงซ้อนก็ได้ในรูปแบบขนาน) · PI: ศูนย์ที่ −KI/KP-K_I/K_P · PD: ศูนย์ที่ −KP/KD-K_P/K_D · ภาพนี้คือกุญแจในการออกแบบด้วยรูทโลคัส

ผลของแต่ละเทอม พื้นฐาน

ตารางนี้เป็นแนวโน้มทั่วไปเมื่อเพิ่มแต่ละเกนทีละตัว (ระบบอันดับต่ำ เสถียรวงเปิด) ใช้เป็นจุดเริ่มคิด ไม่ใช่กฎตายตัว ทดลองเองในแล็บด้านล่างได้ทันที

เพิ่มRise timeOvershootSettling timeess (ขั้นบันได)เสถียรภาพในภาษาขั้ว/เฟส
KPK_Pลดลงเพิ่มขึ้นเปลี่ยนเล็กน้อยลดลง ไม่เป็นศูนย์ (type 0)แย่ลงเลื่อนโบดขึ้น ขั้วเดินตามรูทโลคัส
KIK_Iลดลงเพิ่มขึ้นเพิ่มขึ้นเป็นศูนย์แย่ลงขั้วที่ 0 · เฟสล่าช้า −90° ที่ความถี่ต่ำ
KDK_Dเปลี่ยนเล็กน้อยลดลงลดลงไม่เปลี่ยนดีขึ้น (ถ้า KDK_D ไม่มากเกิน)ศูนย์ · เฟสนำ +90° ที่ความถี่สูง

ในโบดไดอะแกรม มองง่ายกว่า: เทอม I เพิ่มเกนมหาศาลที่ความถี่ต่ำ (ความแม่นยำ) แต่ดึงเฟสลง เทอม D ยกเฟสขึ้นที่ความถี่สูง (เพิ่มเฟสมาร์จิน) แต่ยกเกนความถี่สูงด้วย (สัญญาณรบกวน) ตัวควบคุมที่ดีจึงวาง “ช่วงทำงาน” ของแต่ละเทอมให้อยู่คนละความถี่

ตัวควบคุม P: เร็วขึ้น แต่ไม่แม่น พื้นฐาน

ใช้พลานต์ตัวเดียวกันตลอดหน้านี้ G(s)=1(s+1)(s+2)G(s) = \dfrac{1}{(s+1)(s+2)} (เช่น มอเตอร์ที่มีค่าคงเวลาทางกลและทางไฟฟ้า หรือวงจร RC สองชั้น) จะได้เทียบกันได้ว่าแต่ละแบบให้อะไร

P5 P-control offset ความผิดพลาดค้างของตัวควบคุม P

ess=11+KPG(0)e_{ss} = \frac{1}{1 + K_PG(0)}

ระบบ type 0 (ไม่มีขั้วที่ 0) จะมีความผิดพลาดค้างเสมอ ลดได้ด้วย KPK_P สูง แต่จะแกว่งมากขึ้น ดูความผิดพลาดอยู่ตัว

ตัวอย่าง P-1 · ตัวควบคุม P

หา KPK_P ที่ให้ ζ=0.5\zeta = 0.5 สำหรับ G(s)=1(s+1)(s+2)G(s) = \dfrac{1}{(s+1)(s+2)} แล้วหา overshoot และความผิดพลาดค้าง

  1. สมการลักษณะเฉพาะ: (s+1)(s+2)+KP=s2+3s+(2+KP)=0(s+1)(s+2) + K_P = s^2 + 3s + (2 + K_P) = 0

  2. เทียบกับ s2+2ζωns+ωn2s^2 + 2\zeta\omega_ns + \omega_n^2: 2(0.5)ωn=3⇒ωn=32(0.5)\omega_n = 3 \Rightarrow \omega_n = 3 และ 2+KP=9⇒KP=72 + K_P = 9 \Rightarrow \hlC{K_P = 7}

  3. Mp=e−πζ/1−ζ2=e−π(0.5)/0.866=16.3%M_p = e^{-\pi\zeta/\sqrt{1-\zeta^2}} = e^{-\pi(0.5)/0.866} = 16.3\% · ts≈4/(ζωn)=2.67t_s \approx 4/(\zeta\omega_n) = 2.67 s

  4. ความผิดพลาดค้าง P5: G(0)=12G(0) = \tfrac12 ได้ ess=11+7/2=29=0.222e_{ss} = \dfrac{1}{1 + 7/2} = \dfrac29 = 0.222

KP=7K_P = 7: overshoot 16.3% แต่เอาต์พุตไปค้างที่ 0.778 ไม่ถึง 1 (ผิด 22%) การเพิ่ม KPK_P ลดความผิดพลาดได้แต่ ζ\zeta จะลดลง แกว่งมากขึ้น P อย่างเดียวจึงแลกกันระหว่าง “แม่น” กับ “นิ่ง”

python-control: overshoot 16.30%, tst_s (2%) = 2.70 s, ค่าสุดท้าย 0.778 ✓

ตัวควบคุม PI: กำจัดความผิดพลาดค้าง พื้นฐาน

เพิ่มอินทิเกรเตอร์ C(s)=KP+KIs=KP(s+KI/KP)sC(s) = K_P + \dfrac{K_I}{s} = \dfrac{K_P(s + K_I/K_P)}{s} ได้ขั้วที่ศูนย์ (ระบบกลายเป็น type 1 ความผิดพลาดต่อขั้นบันไดเป็นศูนย์) และศูนย์ที่ −KI/KP-K_I/K_P เทคนิคที่นิยมคือวางศูนย์ของ PI หักล้างขั้วที่ช้าที่สุดของพลานต์ ระบบที่เหลือจะง่ายและเร็วขึ้น

ตัวอย่าง P-2 · PI หักล้างขั้ว

ออกแบบ PI ให้พลานต์เดิมมี ζ=0.5\zeta = 0.5 และความผิดพลาดค้างเป็นศูนย์

  1. วางศูนย์ของ PI ที่ s=−1s = -1 หักล้างขั้วช้า: C(s)=KP(s+1)sC(s) = \dfrac{K_P(s + 1)}{s} ได้ L(s)=KPs(s+2)L(s) = \dfrac{K_P}{s(s + 2)}

  2. วงปิด: s2+2s+KP=0s^2 + 2s + K_P = 0 · 2ζωn=2⇒ωn=22\zeta\omega_n = 2 \Rightarrow \omega_n = 2 · KP=ωn2=4K_P = \omega_n^2 = 4

  3. ศูนย์อยู่ที่ −KI/KP=−1⇒KI=4-K_I/K_P = -1 \Rightarrow \hlC{K_I = 4}

C(s)=4+4sC(s) = 4 + \dfrac{4}{s} · overshoot 16.3% เท่าเดิม ความผิดพลาดค้างเป็นศูนย์ แต่ ts≈4/1=4t_s \approx 4/1 = 4 s ช้ากว่าแบบ P (2.7 s) เพราะ ζωn\zeta\omega_n ลดจาก 1.5 เหลือ 1 นี่คือราคาของเทอม I

python-control: overshoot 16.30%, tst_s = 4.05 s, ค่าสุดท้าย 1.000 ✓ · การหักล้างขั้วใช้ได้เมื่อขั้วของพลานต์เสถียรและรู้ค่าแม่นพอ ห้ามหักล้างขั้วฝั่งขวาเด็ดขาด (ดูหน้าควบคุมได้)

ตัวควบคุม PD: หน่วงการแกว่ง กลาง

เทอม D ตอบสนองต่ออัตราการเปลี่ยนของความผิดพลาด ถ้าเอาต์พุตกำลังพุ่งเข้าหาเป้าเร็ว D จะ “เบรก” ก่อนถึง จึงลด overshoot ในทางฟิสิกส์ PD กับมอเตอร์ตำแหน่งเหมือนการเพิ่มสปริง (P) และแดมเปอร์ (D) เสมือน ดูตัวอย่างลูปตำแหน่ง G(s)=1s(s+2)G(s) = \dfrac{1}{s(s+2)}

ตัวอย่าง P-3 · PD กับเซอร์โวตำแหน่ง

ออกแบบ PD ให้ G(s)=1s(s+2)G(s) = \dfrac{1}{s(s+2)} มีขั้ววงปิดที่ ζ=0.7, ωn=4\zeta = 0.7,\ \omega_n = 4 rad/s

  1. s(s+2)+KDs+KP=s2+(2+KD)s+KP=0s(s + 2) + K_Ds + K_P = s^2 + (2 + K_D)s + K_P = 0

  2. เทียบสัมประสิทธิ์: KP=ωn2=16K_P = \omega_n^2 = 16 และ 2+KD=2(0.7)(4)=5.6⇒KD=3.62 + K_D = 2(0.7)(4) = 5.6 \Rightarrow \hlC{K_D = 3.6}

  3. ระวัง: วงปิดคือ T(s)=3.6s+16s2+5.6s+16T(s) = \dfrac{3.6s + 16}{s^2 + 5.6s + 16} มีศูนย์ที่ −16/3.6=−4.44-16/3.6 = -4.44 ใกล้ขั้ว ทำให้ตอบสนองเร็วและพุ่งเกินกว่าระบบอันดับสองบริสุทธิ์

KP=16, KD=3.6K_P = 16,\ K_D = 3.6 · ขั้วอยู่ตรงตามสเปก แต่ overshoot จริง 9.5% (สูตรอันดับสองทำนาย 4.6%) เพราะศูนย์ของ PD

python-control: overshoot 9.52%, rise 0.32 s · ถ้าต้องการ overshoot ตามสูตรจริง ให้คำนวณ D จากเอาต์พุต (−KDy-K_Dy แทน KDeK_De) ศูนย์จะหายไปจาก T(s)T(s) ทดลองได้ด้วยตัวเลือก “D จากเอาต์พุต” ในแล็บ P7

P6 Filtered derivative เทอม D ที่มีฟิลเตอร์ (ใช้จริงเสมอ)

C(s)=KP+KIs+KDs1+Tfs,Tf=TdN=KDNKP,  N≈5 ถึง 20C(s) = K_P + \frac{K_I}{s} + \frac{K_Ds}{1 + T_fs}, \qquad T_f = \frac{T_d}{N} = \frac{K_D}{NK_P},\ \ N \approx 5 \text{ ถึง } 20

D บริสุทธิ์มีเกนโตไม่จำกัดที่ความถี่สูง (∣jωKD∣→∞|j\omega K_D| \to \infty) สัญญาณรบกวนจากเซนเซอร์จะถูกขยาย ฟิลเตอร์จำกัดเกนความถี่สูงไว้ที่ KP(1+N)K_P(1 + N) · PD + ฟิลเตอร์ = ตัวชดเชย lead ทุกประการ

ออกแบบ PID ด้วยการวางขั้ว กลาง

พลานต์อันดับสอง + PID ได้ระบบวงปิดอันดับสาม มีสามเกนให้เลือกพอดีกับสามสัมประสิทธิ์ จึงวางขั้ววงปิดได้ทุกตัวตามต้องการ นิยมเลือกคู่ขั้วเด่นจากสเปก ζ,ωn\zeta, \omega_n และขั้วที่สามให้ไกลกว่าประมาณ 5 เท่า

ตัวอย่าง P-4 · PID วางขั้ว

ออกแบบ PID ให้ G(s)=1(s+1)(s+2)G(s) = \dfrac{1}{(s+1)(s+2)} มีขั้วเด่นที่ ζ=0.7, ωn=3\zeta = 0.7,\ \omega_n = 3 และขั้วที่สามที่ −10-10

  1. สมการลักษณะเฉพาะ P4: s(s+1)(s+2)+KDs2+KPs+KI=0s(s+1)(s+2) + K_Ds^2 + K_Ps + K_I = 0

    s3+(3+KD)s2+(2+KP)s+KI=0s^3 + (3 + K_D)s^2 + (2 + K_P)s + K_I = 0
  2. พหุนามที่ต้องการ

    (s2+4.2s+9)(s+10)=s3+14.2s2+51s+90(s^2 + 4.2s + 9)(s + 10) = s^3 + 14.2s^2 + 51s + 90
  3. เทียบสัมประสิทธิ์: 3+KD=14.23 + K_D = 14.2, 2+KP=512 + K_P = 51, KI=90K_I = 90

KP=49, KI=90, KD=11.2\hlC{K_P = 49,\ K_I = 90,\ K_D = 11.2} · ศูนย์ของ PID อยู่ที่ −2.19±j1.80-2.19 \pm j1.80 ทำให้ overshoot จริง 9.6% (มากกว่า 4.6% ที่ ζ=0.7\zeta = 0.7 ทำนาย) และ ts≈1.05t_s \approx 1.05 s

python-control ยืนยันขั้ววงปิด −2.1±j2.14, −10-2.1 \pm j2.14,\ -10 และ overshoot 9.57% · แก้ overshoot ส่วนเกินได้ด้วย setpoint weighting P7 หรือ prefilter โดยไม่ต้องเปลี่ยนขั้วเลย

วิธีอื่นที่ใช้บ่อย: ออกแบบด้วยรูทโลคัส (วางศูนย์ของ PD ให้โลคัสผ่านจุดที่ต้องการ แล้ววางศูนย์ PI ใกล้จุดกำเนิด) ด้วยโบด (เลือกความถี่ครอสโอเวอร์และเฟสมาร์จิน) หรือจูนจากการทดลองด้วยกฎ Ziegler–Nichols เมื่อไม่มีแบบจำลอง

PID ในงานจริง: kick, setpoint weighting และ windup ขั้นสูง

สูตรในตำราทำงานได้ในโลกเชิงเส้นที่ไม่มีขีดจำกัด แต่ตัวขับจริงอิ่มตัว เซนเซอร์มีสัญญาณรบกวน และค่าอ้างอิงเปลี่ยนแบบขั้นบันได ปัญหาสามข้อนี้แก้ได้ด้วยการเปลี่ยนโครงสร้างเล็กน้อย

P7 Setpoint weighting (2-DOF PID) ถ่วงน้ำหนักค่าอ้างอิง

u=KP(br−y)+KI∫(r−y) dt+KDddt(cr−y),0≤b≤1,  c=0 (นิยม)u = K_P(br - y) + K_I\int(r - y)\,dt + K_D\frac{d}{dt}(cr - y), \qquad 0 \le b \le 1,\ \ c = 0 \text{ (นิยม)}

c=0c = 0: D คำนวณจากเอาต์พุตอย่างเดียว ไม่กระตุก (derivative kick) ตอนค่าอ้างอิงกระโดด · b<1b \lt 1: ลด overshoot ต่อค่าอ้างอิง · เทอม I ต้องใช้ r−yr - y เต็ม ๆ เพื่อให้ไม่มีความผิดพลาดค้าง · ขั้ววงปิดและการต้านการรบกวนเหมือนเดิมทุกประการ

P8 Anti-windup ป้องกันอินทิกรัลสะสมเกิน

clamping: I˙={0u≠usat และ e u>0KIeกรณีอื่นback-calculation: I˙=KIe+1Tt(usat−u)\text{clamping: } \dot I = \begin{cases} 0 & u \ne u_{sat} \text{ และ } e\,u \gt 0 \\ K_Ie & \text{กรณีอื่น} \end{cases} \qquad \text{back-calculation: } \dot I = K_Ie + \frac{1}{T_t}(u_{sat} - u)

usatu_{sat} คือค่าหลังอิ่มตัว · TtT_t (tracking time) นิยม TiTd\sqrt{T_iT_d} หรือประมาณ Ti/2T_i/2 · ไมโครคอนโทรลเลอร์ใช้ clamping บ่อยที่สุดเพราะเขียนง่าย

ลองในแล็บ: เลือกพลานต์ “ฮีตเตอร์ + หน่วงเวลา” เปิด “จำกัด |u|” แล้วปิด anti-windup จะเห็นเอาต์พุตพุ่งเกินมากและช้า เพราะอินทิกรัลสะสมระหว่างที่ฮีตเตอร์เปิดเต็ม เปิด anti-windup แล้วเทียบ (กดปักกราฟไว้ก่อน)

สร้าง PID ด้วยออปแอมป์ตัวเดียว กลาง

สำหรับนักศึกษาไฟฟ้า นี่คือจุดที่ทฤษฎีกลายเป็นวงจรบนเบรดบอร์ด ใช้วงจรออปแอมป์อินเวอร์ติง Vo/Vi=−Zf/ZiV_o/V_i = -Z_f/Z_i ให้ ZiZ_i เป็น R1R_1 ขนานกับ C1C_1 และ ZfZ_f เป็น R2R_2 อนุกรมกับ C2C_2

P9 Single op-amp PID PID ด้วยออปแอมป์ตัวเดียว

VoVi=−(1+R1C1s)(1+R2C2s)R1C2s ⇒ KP=R1C1+R2C2R1C2,KI=1R1C2,KD=R2C1\frac{V_o}{V_i} = -\frac{(1 + R_1C_1s)(1 + R_2C_2s)}{R_1C_2s} \ \Rightarrow\ K_P = \frac{R_1C_1 + R_2C_2}{R_1C_2},\quad K_I = \frac{1}{R_1C_2},\quad K_D = R_2C_1

เป็นรูปแบบอนุกรม P3 ศูนย์อยู่ที่ −1/R1C1-1/R_1C_1 และ −1/R2C2-1/R_2C_2 · เครื่องหมายลบแก้ด้วยอินเวอร์เตอร์อีกตัว หรือสลับขั้วที่จุดรวมสัญญาณ · ใส่ R เล็กอนุกรมกับ C1C_1 เพื่อเป็นฟิลเตอร์ D P6

ตัวอย่าง P-5 · เลือกค่าอุปกรณ์

วงจร PID ออปแอมป์ใช้ R1=100 kΩ, C2=1 μF, R2=10 kΩ, C1=10 μFR_1 = 100\ \text{k}\Omega,\ C_2 = 1\ \mu\text{F},\ R_2 = 10\ \text{k}\Omega,\ C_1 = 10\ \mu\text{F} ได้เกนเท่าไร

  1. R1C2=105×10−6=0.1R_1C_2 = 10^5 \times 10^{-6} = 0.1 s · R1C1=1R_1C_1 = 1 s · R2C2=0.01R_2C_2 = 0.01 s · R2C1=0.1R_2C_1 = 0.1 s

  2. แทน P9: KP=1+0.010.1=10.1K_P = \dfrac{1 + 0.01}{0.1} = 10.1, KI=10.1=10 s−1K_I = \dfrac{1}{0.1} = 10\ \text{s}^{-1}, KD=0.1K_D = 0.1 s

C(s)=−(10.1+10s+0.1s)C(s) = -\left(10.1 + \dfrac{10}{s} + 0.1s\right) ศูนย์อยู่ที่ −1-1 และ −100-100 rad/s

ตรวจ: (1+s)(1+0.01s)0.1s=0.01s2+1.01s+10.1s=0.1s+10.1+10s\dfrac{(1 + s)(1 + 0.01s)}{0.1s} = \dfrac{0.01s^2 + 1.01s + 1}{0.1s} = 0.1s + 10.1 + \dfrac{10}{s} ✓ · วงจรนี้คือหัวใจของ Type II/III compensator ในพาวเวอร์ซัพพลาย

PID ในไมโครคอนโทรลเลอร์ กลาง

ทุกคาบสุ่ม TsT_s อ่านเซนเซอร์ คำนวณ แล้วเขียน PWM โค้ดด้านล่างรวม D จากเอาต์พุต ฟิลเตอร์ D และ anti-windup แบบ clamping ไว้แล้ว รายละเอียดการแปลงและการเลือก TsT_s อยู่ที่ควบคุมดิจิทัล

// เรียกทุก Ts วินาที (เช่น จาก timer interrupt)
float pid_step(float r, float y) {
  float e = r - y;
  float P = Kp * e;
  // D จากเอาต์พุต + ฟิลเตอร์อันดับหนึ่ง (Tf = Kd/(N*Kp))
  D = (Tf * D - Kd * (y - y_prev)) / (Tf + Ts);
  y_prev = y;
  float u = P + I + D;
  float u_sat = fminf(fmaxf(u, U_MIN), U_MAX);
  // anti-windup: อินทิเกรตเฉพาะเมื่อไม่ได้ดันให้อิ่มตัวหนักขึ้น
  if (u == u_sat || (e * u) < 0) I += Ki * Ts * e;
  return u_sat;
}

แล็บจำลอง PID

เลือกพลานต์ เลื่อน KP,KI,KDK_P, K_I, K_D (สเกลลอการิทึม ลากซ้ายสุดคือปิดเทอมนั้น) และ NN ของฟิลเตอร์ ระบบจำลองในโดเมนเวลาจริงทีละก้าว (ไม่ใช่สูตร) จึงรวมการอิ่มตัว หน่วงเวลา และสัญญาณรบกวนที่โหลด (ขั้นบันไดเข้าที่อินพุตพลานต์ครึ่งทาง ขนาดเทียบเท่าครึ่งหนึ่งของค่าอ้างอิง) ได้ กด “ปักกราฟไว้เทียบ” ก่อนเปลี่ยนค่าจะเห็นผลชัด

กำลังโหลดแล็บ (ต้องเปิด JavaScript)

โจทย์ท้าทาย: (1) เลือกพลานต์อันดับสาม เพิ่ม KPK_P อย่างเดียวจนแกว่งค้าง จด KcrK_{cr} และคาบ แล้วเทียบกับเราท์ (ควรได้ Kcr=8K_{cr} = 8, ωcr=3\omega_{cr} = \sqrt3) (2) ใช้ค่านั้นจูนด้วยZiegler–Nichols (3) พลานต์มวล-สปริง ลองเพิ่มแค่ KDK_D ดูการแกว่งหายไป

ข้อผิดพลาดที่พบบ่อย

  • ใส่เกน ISA ลงไลบรารีแบบขนาน → KI=KP/TiK_I = K_P/T_i ไม่ใช่ TiT_i P2
  • ลืมคูณ/หาร TsT_s ในโค้ด → KIK_I แบบดิจิทัลต้องคูณ TsT_s เทอม D ต้องหาร TsT_s เปลี่ยนคาบสุ่มแล้วต้องแก้ด้วย
  • ใช้ D บริสุทธิ์ → สัญญาณรบกวนถูกขยาย ตัวขับสั่น ใส่ฟิลเตอร์เสมอ P6
  • overshoot มากเกินสูตรทั้งที่ขั้วถูก → ศูนย์ของ PID ใช้ setpoint weighting P7
  • ตัวขับอิ่มตัวแล้ว overshoot มหาศาล → integral windup ใส่ anti-windup P8
  • หักล้างขั้วฝั่งขวาด้วยศูนย์ของตัวควบคุม → ขั้วนั้นยังอยู่ภายใน ระบบไม่เสถียรภายใน (internally unstable)
  • เพิ่ม KI เพื่อให้เร็วขึ้น → I ไม่ได้ทำให้เร็ว มันทำให้แม่น เพิ่มมากไปจะแกว่งและไม่เสถียร (ดู R-8 ในหน้าเราท์)

ต่อยอดไปหน้าถัดไป

เมื่อไม่มีแบบจำลองแม่นพอ หรืออยากได้ค่าเริ่มต้นเร็ว ๆ ใช้วิธีจูนจากการทดลอง Ziegler–Nichols, Cohen–Coon, IMC และ relay auto-tune ส่วนการนำ PID ไปใช้ในลูปซ้อนของมอเตอร์และหุ่นยนต์ ดูเมคาทรอนิกส์

คำถามที่พบบ่อย

Kp Ki Kd แต่ละตัวทำอะไร พูดสั้น ๆ?

Kp ตอบสนองต่อความผิดพลาดตอนนี้ ยิ่งมากยิ่งเร็วแต่แกว่งมากขึ้น Ki สะสมความผิดพลาดในอดีต ทำให้ความผิดพลาดอยู่ตัวเป็นศูนย์แต่เพิ่มความล่าช้าและ overshoot Kd ดูแนวโน้มอนาคต (อัตราการเปลี่ยน) ช่วยหน่วงการแกว่งและเพิ่มเฟสมาร์จิน แต่ขยายสัญญาณรบกวนความถี่สูง

ทำไม PI จึงทำให้ความผิดพลาดอยู่ตัวเป็นศูนย์?

เทอม I เพิ่มขั้วที่ s = 0 ทำให้ชนิดของระบบเพิ่มขึ้นหนึ่ง ในเชิงกายภาพ ถ้ายังมีความผิดพลาดค้างอยู่แม้นิดเดียว อินทิกรัลจะโตไปเรื่อย ๆ จนสัญญาณควบคุมเปลี่ยนพอที่จะกำจัดความผิดพลาดนั้น สภาวะอยู่ตัวจึงเกิดได้เฉพาะเมื่อความผิดพลาดเป็นศูนย์

ทำไมงานจริงส่วนใหญ่ใช้ PI ไม่ค่อยใช้ D?

เพราะกระบวนการส่วนใหญ่ (อุณหภูมิ การไหล ความดัน ลูปความเร็วมอเตอร์) ช้าและสัญญาณวัดมีสัญญาณรบกวน เทอม D ขยายสัญญาณรบกวนและทำให้ตัวขับทำงานหนัก PI จึงพอ ส่วนระบบที่ต้องการหน่วงเพิ่ม เช่น ลูปตำแหน่งของเซอร์โว โดรน หรือพาวเวอร์ซัพพลาย ใช้ D (หรือ lead) พร้อมฟิลเตอร์

Integral windup คืออะไร แก้อย่างไร?

เมื่อตัวขับอิ่มตัว (เช่น PWM เต็ม 100%) ความผิดพลาดยังค้าง อินทิกรัลจึงสะสมเกินจริง เมื่อเอาต์พุตถึงเป้าแล้วต้องใช้เวลานานกว่าจะคายค่าที่สะสม ทำให้ overshoot มาก แก้ด้วย anti-windup เช่น หยุดอินทิเกรตเมื่ออิ่มตัว (clamping) หรือป้อนกลับส่วนต่างระหว่างค่าที่สั่งกับค่าที่อิ่มตัวมาลดอินทิกรัล (back-calculation)

PID กับตัวชดเชย lead lag เกี่ยวกันอย่างไร?

PI คือ lag ที่ขั้วอยู่ที่ศูนย์พอดี PD คือ lead ที่ขั้วอยู่ไกลมาก (อนันต์) ส่วน PD ที่มีฟิลเตอร์อนุพันธ์คือ lead ทุกประการ ดังนั้น PID ที่มีฟิลเตอร์ก็คือ lag-lead และ Type III compensator ของพาวเวอร์ซัพพลายก็คือ PID บวกขั้วเพิ่มหนึ่งตัว

อาจารย์มด · ธีรวุฒิ แสวงบุญ
อาจารย์สาขาวิชาวิศวกรรมไฟฟ้า มหาวิทยาลัยราชภัฏธนบุรี สมุทรปราการ · ดูโปรไฟล์