C'de PID döngülerini programlama


11

Ben bir elektrik mühendisiyim ve bu dijital dünyaya bir çeşit itici güçtü ve öğrenirken öğrendim. Bu diyagram ile gösterilen bir PID (orantılı-integral-türev) döngü yapmak için bir TI işlemci programlıyorum :

Wikipedia'dan PID döngü görüntüsü

Ayrıca tarif edeceğim:

Negatif geri besleme op-amp, ters çevirmeyen terminal topraklı. Negatif terminal üzerinden giriş. Geri besleme döngüsü, bir dirençle paralel olan ve bir başlığa paralel olan bir RE serisi devredir.

Herkes nasıl bu devre C koduna dönüştürmek için bir fikrin var mı? Bu konudaki unsurumdan biraz uzaktayım ve yardımı kullanabilirim.


Şunları yapabilirsiniz bağlantısı olan bir resim ve birisi yardımsever sizin için gerçek bir resmin içine bu bağlantıyı dönüştürecektir.
Joachim Sauer

2
Kendini yayınlanmıştır bağlantı bu konuda gidiş için temel bir pseudocode sağlar. C # sakıncası yoksa, C # bir pid döngü örneği .
Neil

1
Neil haklı. TI'de C'ye neredeyse tam olarak bu döngüyü uyguladım. Bir ipucu: döngüde dtfazladan bölme ve çarpma yapmak yerine sabit bir zaman döngüsü kullanın ve sabitleri sabitlere katlayın.
AShelly

1
@ Neil bu PID döngü ne olduğunu bilmiyordum çünkü revizyon 2 ekledi bir bağlantı oldu ve ben de diğerleri de şüpheli.

@MichaelT, ah özür dilerim.
Neil

Yanıtlar:


18

Devre

Tamam, bu soruyu gördüğümde burada bir hesap oluşturdum. Yaptığınız yazım hatasını düzeltebilmeniz için sorunuzu düzenleyemiyorum. RE yerine paralel olarak RC serisi devre demek istediğinize inanıyorum (eğer öyleyse, ne anlama geldiğini bilmiyorum)

C kullanarak benzetim yapmak istediğiniz analog devre gibi görünüyor

                         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.

(Elektrik / elektronik mühendislerinin resimler olmadan forumlarda ve e-postalarda nasıl iletişim kurduğunu ve neden sadece kurye, sabit genişlikli yazı tipini sevdiğimizi söylemek istediğim için bunu çizme isteğime dayanamadım)

İtiraf etmeliyim ki, kullandığınız devrenin kurulumu basittir, ancak sistemin Eğik, İntegral ve Türev sabitlerini bireysel olarak istenen bir değere ayarlamak mümkün olmadığında matematiksel olarak çok karmaşıktır.

Bu kaynaktan gelen devreyi çalışmak için kullanmanızı şiddetle tavsiye ediyorum .

Kurmak biraz sıkıcı olsa da, matematiksel olarak analiz etmek çok daha basittir, çünkü onu ideal bir form yerine standart matematiksel formla doğrudan ilişkilendirebilirsiniz.

Son olarak Vout bir motoru veya kontrol edilmesi gereken her şeyi kontrol etmeye gider. Ve Vin, Proses değişken voltajıdır.

C (deniz?)

Bir çeşit analogdan dijital dönüştürücüye sinyalleri okuduğunuzu varsayıyorum. Değilse, sinyali bir giriş olarak simüle etmeniz gerekir.

Standart formumuz varsa,

Döngü çalışma süresinin yeterince küçük olduğunu varsayarak (yavaş bir işlem), çıktıyı hesaplamak için aşağıdaki işlevi kullanabiliriz,

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

nerede

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.

başlangıçta 'der' ve 'int' sıfır olur. Döngü frekansını 1 KHz olarak ayarlamak için kodda bir gecikme fonksiyonu kullanırsanız, dt'niz 0.001 saniye olacaktır.

C ile çizilmiş

Her yönünü kapsamıyor olsa da, C PID için bu mükemmel kodu buldum , yine de iyi bir tane.

//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.
}

Yavaş bir süreç alırsak, tek döngü için dt >>> kod yürütme süresi (çok daha büyük) olacak şekilde daha düşük frekans kullanabiliriz. Bu gibi durumlarda zamanlayıcıyı ortadan kaldırabilir ve bunun yerine bir gecikme fonksiyonu kullanabiliriz.


6
Ascii Diyagramı aklımı aldı. +1
l46kok

1
bağlantı "bu kaynak" çalışmıyor
Ccr

Oh duyduğuma üzüldüm, iyi bir kaynak kayboldu :(. Kavram paylaştığım while döngü örnek kodunda açıklanmıştır. Bu durumu nasıl ele alacağım konusunda deneyimli değilim, belki bazı editörler bunu düzeltebilir uygun mesaj. (ölü bağlantı)
D34dman

2
Eksik "bu kaynak" burada bulunabilir: educypedia.karadimov.info/library/piddocs.pdf
David Suarez
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.