STM32F407’de PID Denetleyicisi
Uygulaması
PID (Proportional Integral Differential – Oransal İntegral
Diferansiyel) denetleyicisi düzenlemede temel yapı taşıdır. Bu birçok
farklı şekilde uygulanabilir. Bu örnekte mikrodenetleyicide nasıl kod yazılır
ve yeteneklerin basit bir gösterimi yapılmıştır.
İyi karıştırılırmış
bir su kabı düşünün (sistem) ki bu sistemin çevre sıcaklığının üstünde bir
sıcaklıkta kalması gerekmektedir (referans değer “R” olsun). Bizim yapmamız
gereken su içerisine bir termometre (sensor) koymak ve bununla sıcaklığı
okumaktır ( anlık değer “X” olsun). Su çok soğuk ise kabın altına
yerleştirilmiş olan ısıtıcı (aktuator) çalıştırılsın. Termometre okunarak
termometre değeri istenilen değere geldiğinde ısıtıcı kapatılsın. Suyun
sıcaklığı hala biraz zaman (aşmayı) için yükselir ve daha sonra azalmaya
başlar. Suyun sıcaklığı istenilen değerin altına düştüğünde, biz ısıtıcıyı
tekrar açalım. Isıtıcı ısınır ve suyu ısıtmaya başlar ama suyun sıcaklığı yine
istenilen değere ulaştığında işlem tekrarlanır. Biz bir düzenleme sistemine
sahibiz, burada denetleyicimiz; gerçek değeri gözlemler referans değer ile
karşılaştırırız ve karşılaştırmanın sonucunda sistemi etkileriz. Bu durum basit
bir şekilde figür 1’de gösterilmiştir.
Figür 1. Düzenlemenin ham ve basitleştirilmiş hali
Yukarıdaki
örnekte su sıcaklığı hiçbir zaman istenen değerde kalmaz, ancak bunun yerine
çevresinde salınımlar oluşur. Salınımlar sistemin “F”,
algılayıcı ve ısıtıcı özelliklerine bağlıdır. Sıcaklık davranışını iyileştirmek
ve salınımı azaltmak için denetleyicide daha karmaşık kararlar tanımlayarak
düzenleme sürecini geliştirebiliriz. Örneğin aşma miktarını biliyorsak
sıcaklığı istenilen değere gelmeden önce durdurabiliriz. Biz gerçek sıcaklığı istenilen sıcaklığa
yakın olduğunda suyu ısıtan sıcaklık miktarını azaltarak da bu bahsi geçen
aşmayı azaltabiliriz. Başka olasılıklarda vardır. Ama bunlar kontrol ünitesinde
ki tanımlamalar ile hayata geçirilebilirler. Bu duruma PID
düzenleme adı verilir.
Yukarıdaki
örnek açısından düzenleme teorisinin bileşenleri ikinci dereceden diferansiyel
eşitlikle açıklanabilir ve düzenlenmiş sistem ikinci dereceden olarak
isimlendirilir. Bunlar PID denetleyici tarafından en iyi şekilde
evcilleştirilmiştir.
Figür 2. PID denetleyici ile kontrol edilen sistem
PID denetleyicisinde ilk istenilen değer ve anlık
gerçek diğer karşılaştırılarak aralarındaki fark hesaplanır. Hesaplanan hata
sinyali oransal (Proportional),integral (Integral) ve farksal bölüme (Differential)
ayrılır. Bu üç bileşen ilgili faktörler (Kp, Kd, Ki)
ile toplanarak final değer elde edilir. Bu final değer (Reg) ısıtıcı tarafından kullanılan değerdir.
Böyle
bir PID denetleyicisi mikrodenetleyicide
periyodik olarak uygulanmalıdır. Yukarıdaki eylemlerin yapılma zamanı
düzenlenmiş sistemin cevap zamanını karşılamalıdır. Yani eylem zamanı yeteri
kadar kısa olmalıdır. Periyodik örnekleme, hesaplama ve değerin üretilmesi için
bu tekrar çağırılmalıdır. Aynı programlama çatısı daha önceki yazılarımızda FIR
ve IIR filtrelemede kullanılmıştır. Mikrodenetleyici kurulumu aynıdır. Tüm
denetleyici hesaplama fonksiyonları kesme fonksiyonu içerisindedir. Programın
listesi figür 3’de verilmiştir.
Program
değişkenlerin tanımlamaları ile başlar. İki integer tipte dairesel tampon
istenen ve gerçek değer için kullanılmıştır.
Ek olarak iki floating tipte işaretçi dairesel tampon (floating point
circular buffers) hata ve bir önceki çıkış değeri için kullanılmıştır. Bileşenler
için üç değişken ve ilgili ağırlık faktörleri için üç floating point sayı ve
kurulum tanımlanmıştır. Sonuç olarak değişim oranı hesaplaması için gerekli bir
değişken tanımlanmış ve kurulumu yapılmıştır.
Ana
program içerisinde ADC ve DAC kurulumları, örnekleme frekansı 10kHz olan her
100us ADC çevrimini başlatan timer
programlanmıştır. NVIC kesme denetleyici ADC kesme isteğini aktif hale getirmiştir. Daha sonra
mikrodenetleyici sonsuz döngüye girer. PID düzenleyicisi
program yürütülürken oransal (Proportional),
integral (integral) ve diferansiyel (Differential) bileşenler için ağırlıkların değişimine
izin verilir. Durum butonu periyodik olarak kontrol edilir, zaman gecikmesi
sonsuz döngü başında döngü tarafından tanımlanmaktadır. Sonraki 3 (üç) program
satırı oransal bileşen (Proportional component)
ağırlık değerini değiştirmek için kullanılır. Buton S370( port E’ bit 0’a bağlı olan buton)
buton S375 (port E bit 5’e bağlı olan buton)
ile birlikte basıldığında, o zaman ağırlık bir artırılır. Buton S370
buton S374 birlikte basıldığında ise (port E, bit 4, 0x10) daha sonra ağırlık
bir azaltılır. Üçüncü satır 0 ile 1000 arasında değerler (dâhil) ile orantılı
ağırlık değerini sınırlar. Sonraki üç satır diferansiyel bileşen için ağırlıklarla
aynı işi yapar ve sonraki üç satır integral bileşen için aynı işi yapar. Sonuç
olarak bu üç ağırlık LCD ekrana yazdırılır.
#include "stm32f4xx.h"
#include "LCD2x16.c"
int Ref[64], x[64], Ptr; // dairesel tamponların tanımlanması
int Error[64], Reg[64]; // hata ve önceki çıkış vektörlerinin
tanımlanması
float Prop, Dif, Int = 0; // üç bileşenin tanımlamaları
float Kp = 1.0, Ki = 0.0, Kd =
0.0; // kurulum parametrelerinin
tanımlamaları
float Ts = 0.0001; // TIM2’nin 8400 sabit değeri için 10kHz’e ayarlanması
int main ()
{
GPIO_setup();
// GPIO kurulumu
DAC_setup();
// DAC kurulumu
ADC_setup();
// ADC kurulumu
Timer2_setup();
// Timer 2 kurulumu
NVIC_EnableIRQ(ADC_IRQn);
// NVIC ADC kesme isteğinin
aktif edilmesi
LCD_init();
LCD_string("Kp:",
0x00); LCD_string("Kd:", 0x09); LCD_string("Ki:", 0x49);
// genlik ve zaman gecikmesinin ayarlanması – belirsiz döngü
while (1)
{
for (int i = 0; i < 2000000; i++) {}; // zaman gecikmesi
if ((GPIOE->IDR & 0x003f) == (0x01 + 0x20)) Kp++; // Kp’nin manuel ayarlanması
if ((GPIOE->IDR & 0x003f) == (0x01 + 0x10)) Kp--;
if (Kp<0) Kp = 0; if (Kp > 1000) Kp = 1000;
if ((GPIOE->IDR & 0x003f) == (0x02 + 0x20)) Kd +=
0.001; // Kd’nin manuel
ayarlanması
if ((GPIOE->IDR & 0x003f) == (0x02 + 0x10)) Kd -=
0.001;
if (Kd < 0) Kd = 0; if (Kd > 1) Kd = 1;
if ((GPIOE->IDR & 0x003f) == (0x04 + 0x20)) Ki +=
0.0001; // Ki’nin manuel
ayarlanması
if ((GPIOE->IDR & 0x003f) == (0x04 + 0x10)) Ki -=
0.0001;
if (Ki < 0) Ki = 0; if (Ki > 1) Ki = 1;
LCD_sInt3DG((int)Kp,0x03,1); // Kp’yi LCD ekrana yaz
LCD_sInt3DG((int)(Kd*1000),0x0c,1); // Kd’yi LCD ekrana yaz
LCD_sInt3DG((int)(Ki*10000),0x4c,1); // Ki’yi LCD ekrana yaz
};
}
// kesme fonksiyonu
void
ADC_IRQHandler(void) // yaklaşık
6us sürer
{
GPIOE->ODR |= 0x0100; // PE08 high yap
Ref[Ptr] = ADC1->DR; // ADC -> dairesel tampon x1
x[Ptr] = ADC2->DR; // ADC -> dairesel tampon x2
// PID hesaplamayı başlat
Error[Ptr] = Ref[Ptr] - x[Ptr]; // hatayı hesapla
Prop = Kp * (float)Error[Ptr]; // oransal kısım (Proportional)
Dif = Kd * (float)(Error[Ptr] - Error[(Ptr-1) & 63]) /
Ts; // diferansiyel kısım
Int += Ki * (float)Error[Ptr]; // integral kısmı
Reg[Ptr] = (int)(Prop + Dif + Int); // üçünü topla
// PID hesaplamasını durdur
if (Reg[Ptr] > 4095) DAC->DHR12R1 = 4095; // DAC çıkış limiti
else if (Reg[Ptr] < 0) DAC->DHR12R1 = 0;
else DAC->DHR12R1 = (int)Reg[Ptr]; // düzenleyici çıkışı-> DAC
DAC->DHR12R2 = Error[Ptr] + 2048; // hata -> DAC
Ptr = (Ptr + 1) & 63; // dairesel tampon işaretçisini artır
GPIOE->ODR &= ~0x0100; // PE08 low yap
}
Figür 3. PID denetleyici uygulaması
program listesi
Tüm
hesaplamalar kesme fonksiyonu içerisinde gerçekleşir. İki ADC’nin çevrim sonuçları önce dairesel tampona
saklanır. Bu iki değerin arasındaki fark hesaplanır. Sonra acilen üçüncü
dairesel tampona hata olarak saklanır. Sonraki üç satırda üç bileşen ve ağırlık
hesaplanır. Dördüncü satırda diğer bileşenler eklenir ve dördüncü dairesel
tampon olan “Reg” içerisine toplanarak saklanır.
Bu değer düzenleyici çıkışı olacaktır ve DAC’a
gönderilecektir. Fakat DAC 0 ile 4095 arasındaki
değerleri kabul edebilir, bu durumda diğer sayılarda bu aralık içerisine
katılır; örneğin 4097 ile DAC’da 1 sayısı
aynıdır ve bu düzenleyicide önemli hataya neden olur. Sayılar kabul edilebilir
değerler için en iyi şekilde sınırlandırılır ve bu sonraki üç kod satırında
yapılır. İkinci DAC hata sinyalinin analog
sürümünü üretmek için kullanılır ve değer hata değerine 2048 ekleyerek DAC aralığının yarısı için kaydırılır. Sonunda
dairesel tampon işaretçisi güncellenir.
Figür 4. Uygulama için bağlantı
Kesme
fonksiyonu içerisinde başlangıçta ve bitişte port e bit-0 high ve low yapılarak
fonksiyon içerisindeki harcanan zaman ölçülür. Bu yaklaşık olarak 6us’dir.
Program
DAC çıkışı (Reg, DAC1) ve ADC girişi
(gerçek değer, ADC2-> DR, ADC3 giriş)
arasında basit ikinci derece sistemini ekleyerek test edilebilir. Diğer ADC (ADC->DR, ADC2 girişi)
istenilen değerin okunması için kullanılır. İki seri bağlanmış RC devreleri
ikinci dereceden sistem için bir yedek olarak kullanılabilir; Bu gösterimi
kolaylaştırır. Ek olarak istenilen değer olan “Ref”
ve parazit sinyali olan “Intf” bir fonksiyon
jeneratörü kullanılarak üretilebilir. Komple örnek devrenin bağlantıları figür
4’de verilmiştir.
Figür
5’den 8’e figür 4’deki devre için gerçek değerler (X,
kırmızı), fark değerleri Kp, Kd ve Ki için
verilmiştir. Parazit sinyali “Intf” sıfır olarak
tutulur ve istenilen değer (Ref mavi) 10Hz
frekansında kare dalgadır. “Ref” sinyalinin
ofseti ADC göstergesinin ortasına yakın ayarlanır. Yatay gösterge çizelgesi
saniyeleri, dikey gösterge çizelgesi volt değerini verir.
Figür 5. Kp=1, Kd=0,Ki=0; oransal kazanç çok düşük ve gerçek
değer(kırmızı) istenilen değere ulaşmıyor.
Figür 6. Kp=50, Kd=0,Ki=0; oransal kazanç yüksek, gerçek değer(kırmızı)
istenilen değere(mavi) yakın, fakat salınımlar görünür halde
Figür 7. Kp=50, Kd=40, Ki=0; diferansiyel kazanç salınımları düzeltir
fakat gerçek değer(kırmızı) hala istenilen değer(mavi) ile aynı değil.
Figür 8. Kp=50, Kd=40, Ki=40; integral kazancı istenilen değerin
ortalamasını gerçek değerin ortalamasına doğru iter
Sonraki
diyagramlar figür 9’dan figür 12’ye kadar olan diyagramlarda düzenlenmiş sistem
cevapları (kırmızı) parazit sinyali (mavi) olarak verilmiştir. Referans sinyali
(gösterilmemiştir) 1.21V değerinde sabit tutulmuştur. Bu düzenleyici işini
düzgün yaparsa yanıtın sabit olduğu tahmin edilmiştir.
Figür 9. Kp=1, Kd=0, Ki=0; oransal kazanç çok düşük ve girişim yapan
sinyalin etkisi önemli
Figür 10. Kp=50, Kd=0, Ki=0; oransal kazanç yüksek, gerçek değer
(kırmızı) 1.21V’ta yakın lakin girişim sinyalinin neden olduğu salınımlar
görünür halde
Figür 11. Kp=50, Kd=40, Ki=0; diferansiyel kazanç salınımı düzeltmiş
lakin gerçek değer(kırmızı) istenilen değer (1.21V) ile aynı değil
Figür 12. Kp=50, Kd=40, Ki=40; integral kazanç istenilen değer (1.21V)
ile aynı olması için gerçek değerin ortalamasını alır.
Şimdilik bu kadar arkadaşlar
Sorularınız ve önerileriniz için m.hakki.kaplan@gmail.com adresinden her zaman bana ulaşabilirsiniz.
Hakkı KAPLAN
Bu yorum yazar tarafından silindi.
YanıtlaSilPID'de özellikle Integral bölümü en sıkıntılı kısımdır. Verilen örnekte Integral teorik olarak sonsuz değere çıkabildiğinden sistemin boşta çalışabileceği uygulamalarda bu sıkıntı yaratabilir; over-undershoot'lar çok fazla yükselebilir. Bu konuda bkz. anti-windup.
YanıtlaSilFırat Bey yorum ve bilgilendirmeniz için teşekkürler bahsettiğiniz konuya bakacağım
YanıtlaSilBu yorum yazar tarafından silindi.
YanıtlaSil