pid

Başlatan frederic, 28 Aralık 2015, 10:14:12

frederic

Merhaba dostlar, kendi yöntemlerim ile yazdığım PI kontrole benzer sistemler ile sonuç aldım geçmişte, fakat bu işi standarta uygun şekilde PID olarak yazmak istiyorum.

Aşağıda örnek kodlardan topladığım veriler var.

#define SAMPLE_FREQ  20 //50ms sample
#define KP_VALUE  6
#define KI_VALUE  20
#define KD_VALUE  0

void CalculateKValues(int16 Kp, int16 Ki, int16 Kd, int16 &K1, int16 &K2, int16 &K3)
{
   K1 = Kp + Ki/SAMPLE_FREQ + Kd*SAMPLE_FREQ;
   K2 = -(Kp + (2*Kd)*SAMPLE_FREQ);
   K3 = Kd*SAMPLE_FREQ;
}

Burdan sonrasında tıkandım, dökümanlardan okuduğum ve anladığım kadarı ile K1+K2+K3 verilerini toplayıp sistemde pid sonucu olarak kullanmam gerekiyor ? Yanılıyormuyum acaba ?

Mucit23

Evet genel olarak öyle. Bende bir motor kontrol sisteminde PID'yi aşağıdaki gibi uygulamıştım. Kontrol türüne göre P kontrol, PI kontrol, PID kontrol yaptırıyordum. DT dediğim sample time dı.

Ben sabit olarak 1 vermiştim. Motorda kullandığım enkoder düşük çözünürlüğe sahipti. Katsayılar biraz yüksek olunca salınım yapıyordu.

Ben pid'yi hobi olarak yapmıştım. Ama bana çok şey öğretti. Nasıl çalıştığını anlamak için P kontrol, PI kontrol veya PID kontrol gibi seçenekler ile motoru sürüyordum. 

signed int16 calc_pid(unsigned int16 set_value, unsigned int16 rpm_value){
  signed int16 output=0;
  error=0;
  
  error = set_value-rpm_value;
  err_dif=error-old_error;
  
  P= Kp * error;
  I = I + (Ki * error * DT);
  D = (Kd * err_dif) / DT;
  
  switch(control_type)
  {
    case 0:
      output=(signed int16)P;
    break;
    case 1:
      output=(signed int16)P+I;
    break;
    case 2:
      output=(signed int16)P+I+D;
    break;
  }

  old_error = error;
return output;
}


Edindiğim tecrübelere göre;

Geri besleme verisi ne kadar yüksek çözünürlükte olursa salınım oranı o kadar azalıyor.
Tepki süresinin hızlı olması için örnek alma PID hesaplama ve çıkışa verme gibi işlemler o kadar hızlı olmalı.