PWM Duty Cycle için PID Kontrol Algoritması Nasıl Yazılır?

Bu yazıda, 1 DOF(Degree of Freedom) Helicopter için yazdığım PID Kontrol algoritmasından bahsedeceğim. Bu sistemde giriş motor için PWM ve çıkış ise açı olacaktır. Yani bu sistemde feedback(geri besleme) olarak helicopterin açı bilgisini kullanarak kontrol etmeye çalışacağız

Öncelikle değişkenlerimizi tanımlayalım;

int duty_cycle=0;
int angle=0;
int ref_angle=50;
int Kp=0;
int Ki=0;
int Kd=0;
int error=0;
int old_error=0;
int total_error=0;

Hata değişkenini aşağıdaki gibi gerçek açı değerini referanstan çıkararak buluruz.

error=ref_angle-angle;

Integral kazancı ile çarpacağımız toplam hatayı aşağıdaki gibi tanımlıyoruz.

total_error=total_error+error;

Integralin Wind-up'a girmemesi için önlem almak gerekirse;

if(total_error>100){total_error=0;}
// ya da
if(total_error>100){total_error=100;}

Yukarıdaki 100 sisteminize göre değişir. Hatanın toplamını sınırlamaz iseniz PID'nin integral kısmı farklı nedenlerden dolayı çok fazla büyüyebilir ki buna Kontrol Teorisinde "Wind-up effect" diyoruz. Bunun temel nedenleri, örnekleme(sampling) zamanımızın çok küçük olması ya da sistemin hareket etmesini engelleyecek bir dış etkiye maruz kalması olarak söylenebilir.

Aşağıdaki kodda, duty cycle'ı eşitliğin sağ tarafına da koymamın nedeni, hata değerleri sıfırlandığı zaman duty cycle'ın sıfırlanmaması aksi takdirde duty cycle da sıfırlanırsa sistem aniden durabilir.

duty_cycle=duty_cycle+Kp*error+Kd*(old_error-error)+Ki*total_error;

Bu sefer de, duty cycle değerini belirli bir aralıkta sınırlıyoruz.

if(duty_cycle>95){duty_cycle=95;}
if(duty_cycle<5){duty_cycle=5;}

Yukarıda duty cycle'ı alt ve üst sınır seviyelerini %5 sınırladım çünkü duty cycle %0 olduğunda tehlikeli olabilir. Üst sınırın %95'e çekilmesi çok önemli mi doğrusu onu bilmiyorum.

Şimdi de bu duty cycle değerini çıkışa vermemiz gerekir bu noktada hangi mikrokontrolör kullandığınız önemli. Mesela ben STM32f0 ile PWM ürettiğim için aşağıdaki gibi bir PWM veriyorum.

// TIM3 timer'ının 1. kanalından PWM veriyorum.
__HAL_TIM_SetCompare(&htim3,TIM_CHANNEL_1, duty_cycle);

Son olarak da, while döngüsünü sonuna aşağıda satırı ekleyerek son hata değerini kaydedebiliriz.

old_error=error;


Yanlışlarım varsa yorum yaparsanız düzeltmeye çalışırım.




Comments

Popular Posts