PID วนซ้ำใน C


11

ฉันเป็นวิศวกรไฟฟ้าที่เป็นแรงผลักดันให้เข้าสู่โลกดิจิตอลและการเรียนรู้เมื่อฉันไป ฉันกำลังเขียนโปรแกรมตัวประมวลผล TI เพื่อทำลูปPID (สัดส่วน - อินทิกรัล - อนุพันธ์) ที่แสดงโดยแผนภาพนี้:

ภาพลูป PID จาก Wikipedia

ฉันจะอธิบายด้วย:

ข้อเสนอแนะเชิงลบ op-amp ที่มีขั้วสายดินไม่คว่ำ อินพุตผ่านเทอร์มินัลเชิงลบ ผลป้อนกลับเป็นวงจร RE ซีรี่ส์ขนานพร้อมกับตัวต้านทานและทั้งหมดนั้นขนานกับฝาปิด

ใครมีความคิดวิธีแปลงวงจรนี้เป็นรหัส C? ฉันออกจากองค์ประกอบของฉันเล็กน้อยและสามารถใช้ความช่วยเหลือได้


คุณสามารถลิงค์ไปยังรูปภาพและบางคนจะช่วยแปลงลิงค์นั้นให้เป็นรูปภาพจริงสำหรับคุณ
Joachim Sauer

2
ลิงค์ที่คุณโพสต์เองให้เป็นรหัสพื้นฐานสำหรับการดำเนินการ หากคุณไม่ทราบ C # นี่คือตัวอย่างของวง pid ใน C #
Neil

1
นีลพูดถูก ฉันติดตั้งลูปนั้นใน C กับ TI เกือบทุกประการ คำใบ้อย่างหนึ่ง: ใช้ลูปเวลาคงที่และแยกค่าคงที่dtเป็นค่าคงที่แทนที่จะทำการหารและคูณแบบพิเศษในลูป
AShelly

1
@ ไม่มีนั่นคือลิงค์ที่ฉันเพิ่มในการแก้ไข 2เพราะฉันไม่รู้ว่า PID loop คืออะไรและฉันสงสัยว่าคนอื่น ๆ ก็ไม่ได้เป็นเช่นนั้น

@MichaelT, ขอโทษที่ฉันขอโทษ
Neil

คำตอบ:


18

วงจร

ตกลงฉันเพิ่งสร้างบัญชีที่นี่เมื่อฉันเห็นคำถามนี้ ฉันไม่สามารถแก้ไขคำถามของคุณเพื่อที่ฉันจะได้แก้ไขข้อผิดพลาดที่คุณทำ ฉันเชื่อว่าคุณหมายถึงวงจรซีรีย์ RC ขนานแทนที่จะเป็น RE (ถ้าใช่ฉันไม่มีเงื่อนงำเดียวว่ามันหมายถึงอะไร)

ดูเหมือนว่าวงจรอะนาล็อกที่คุณต้องการจำลองโดยใช้ C มีลักษณะเช่นนี้

                         Ci
                  |------| |--------------|
                  |           Rp          |
                  |----/\/\/\/\-----------|
                  |          Rd    Cd     |
           Rf     |----/\/\/\---| |-------|
Vin o----/\/\/\---|                       |
                  |    |\                 |
                  |    | \                |
                  |----|- \               | 
                       |   \              |
                       |    \-------------|---------o  Vout
                       |    /
                       |   /
                       |+ /
                   ----| /
                  |    |/
                  |
                  |
               ___|___ GND
                _____
                 ___
                  _

LEGEND:
  Vin is the input signal.
  Vout is the Output.
  Rp controls the propotional term ( P in PID) 
  Ci controls the Integral term ( I id PID)
  Rd and Cd controls the differential term ( D in PID)
  Rf is the gain control, which is common to all of the above controllers.

(ฉันอดไม่ได้ที่จะวาดสิ่งนี้เพราะฉันอยากจะบอกคุณว่าวิศวกรไฟฟ้า / อิเล็กทรอนิกส์ใช้ในการสื่อสารในฟอรัมและอีเมลโดยไม่มีภาพ ... และทำไมเราถึงรักผู้จัดส่งแบบอักษรความกว้างคงที่)

ฉันต้องยอมรับว่าวงจรที่คุณใช้นั้นง่ายต่อการติดตั้ง แต่มีความซับซ้อนทางด้านคณิตศาสตร์เมื่อพูดถึงการปรับค่าคงที่ Propotional, Integral และ Derivative ของระบบให้เป็นค่าที่ต้องการแยกกันไม่ได้

ฉันขอแนะนำให้คุณใช้วงจรจากแหล่งนี้เพื่อศึกษา

แม้ว่าการตั้งค่าเล็กน้อยน่าเบื่อ แต่ในทางคณิตศาสตร์มันง่ายกว่ามากในการวิเคราะห์ในขณะที่คุณสามารถเชื่อมโยงโดยตรงกับแบบฟอร์มมาตรฐานทางคณิตศาสตร์แทนที่จะเป็นแบบอุดมคติ

ในที่สุด Vout ก็จะควบคุมมอเตอร์หรืออะไรก็ตามที่จำเป็นต้องควบคุม และ Vin คือแรงดันไฟฟ้าแบบผันแปรของกระบวนการ

ก่อนทำให้เท้าเปียกใน C (ทะเล?)

ฉันถือว่าคุณกำลังอ่านสัญญาณจากอะนาล็อกบางตัวถึงตัวแปลงสัญญาณดิจิตอล ถ้าไม่เช่นนั้นคุณจะต้องจำลองสัญญาณเป็นอินพุต

หากใช้แบบฟอร์มมาตรฐานเรามี

สมมติว่าเวลาที่ใช้ลูปมีขนาดเล็กพอ (เป็นกระบวนการที่ช้า) เราสามารถใช้ฟังก์ชันต่อไปนี้สำหรับการคำนวณเอาต์พุต

output = Kp * err + (Ki * int * dt) + (Kd * der /dt);

ที่ไหน

Kp = Proptional Constant.
Ki = Integral Constant.
Kd = Derivative Constant.
err = Expected Output - Actual Output ie. error;
int  = int from previous loop + err; ( i.e. integral error )
der  = err - err from previous loop; ( i.e. differential error)
dt = execution time of loop.

โดยเริ่มต้น 'der' และ 'int' จะเป็นศูนย์ หากคุณใช้ฟังก์ชั่นการหน่วงเวลาในโค้ดเพื่อปรับความถี่การวนซ้ำเพื่อบอกว่า 1 KHz ดังนั้น dt ของคุณจะเป็น 0.001 วินาที

การเขียนแบบ C

ฉันพบนี้รหัสที่ยอดเยี่ยมสำหรับ PID ใน C แม้ว่ามันจะไม่ครอบคลุมทุกแง่มุมของมันหนึ่งที่ดี แต่อย่างไรก็ตาม

//get value of setpoint from user
while(1){
  // reset Timer
  // write code to escape loop on receiving a keyboard interrupt.
  // read the value of Vin from ADC ( Analogue to digital converter).
  // Calculate the output using the formula discussed previously.
  // Apply the calculated outpout to DAC ( digital to analogue converter).
  // wait till the Timer reach 'dt' seconds.
}

หากเราใช้กระบวนการที่ช้าแล้วเราสามารถใช้ความถี่ที่ต่ำกว่าเช่นเวลาการเรียกใช้โค้ด dt >>> สำหรับลูปเดี่ยว (ไกลยิ่งกว่า) ในกรณีเช่นนี้เราสามารถทำได้ด้วยตัวจับเวลาและใช้ฟังก์ชั่นการหน่วงเวลาแทน


6
Ascii Diagram ทำให้ใจฉันสั่น +1
l46kok

1
ลิงก์ "แหล่งที่มานี้" ใช้งานไม่ได้
Ccr

ขอโทษด้วยที่ได้ยินว่ามีทรัพยากรดีๆหายไป :( แนวคิดได้รับการอธิบายในขณะที่โค้ดตัวอย่างลูปที่ฉันได้แบ่งปันฉันไม่เคยมีประสบการณ์เกี่ยวกับวิธีจัดการกับสถานการณ์นี้บางทีบรรณาธิการบางคนสามารถแก้ไขได้ด้วย ข้อความที่ถูกต้อง. (ลิงก์ตาย)
D34dman

2
อาจมี "แหล่งข้อมูลนี้" ที่ขาดหายไปที่นี่: educypedia.karadimov.info/library/piddocs.pdf
David Suarez
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.