dc motor PI kontrol. sorunumu bi türlü çözemedim

Başlatan zamzam23, 13 Eylül 2010, 11:36:29

zamzam23

arkadaslar PI kontrol yapmak istiyorum. yazdıgım kod şöyle:
#int_timer0  //20 usn
void  timer0_kesme ()   
    {
  if(bb==1)
  {
       if (yon==0) pals1=65535-pals1;
       pals1=pals1*50;
       sonuc1=ldiv(pals1,xx);
       hiz=sonuc1.quot; 
      // if(sonuc1.rem>(xx/2)) hiz=hiz+1;
       if(hiz>200) hiz=0;
           pals1=0;
       set_timer0(60);
       bb=0;    
       e= Ref-hiz;
       mpid=aa+Kp*e+Ki*e+(Kd*(e-eonceki));
       p=(int)mpid;
       aa=p;
       eonceki=e;
       set_pwm1_duty(p);
  }
  else bb=bb+1;
    }

#separate
void deneme(void)
{
   ext_int_edge(H_TO_L);
        enable_interrupts(int_ext);
           enable_interrupts(int_timer0);
        enable_interrupts(global); 
 lcd_send_byte(0,0x01); 
        lcdgit(1,1);    
        lcdyaz("DENEME");
        delay_ms(100);
 set_pwm1_duty(0);
        output_bit( PIN_C3, 1);//ENABLE
        output_bit( PIN_C0, 0);//MOTOR SAĞ
        output_bit( PIN_A5, 1);//MOTOR SOL
        
 ref=5.0;
 kd=0.0;
 ki=0.0;
 kp=1.0;
   lcd_send_byte(0,0x01); 
 while(true)
 {
 lcd_gotoxy(1,1);
  printf(lcd_putc,"hiz:%u",hiz);
}
}


burada hız bilgisini ve PI kontrolü aynı kesme içinde hesaplatıyorum. sorularım şunlar:
1-PI hesap şeklim dogru mu?
2-hız bilgsiyle PI hesabını aynı kesme içerisinde yapmam dogru mu? yoksa biri birinden biraz gecikmeli olarak mı yapmalıyım?
3-parametreleri hesaplama yöntemi nasıl olmalı?kd=0 ve ki=0 yapın kp yi 1 den baslayarak artırın sistem osilasyona girince... falan dediler. ama sistem bu sekılde osilasyona girmiyor. mesela ref=5cm/sn olsun. 20usn de bir hız bilgisini alıyorum cm/sn cinsinden. sonra PI hesaplatıyorum ama hiz 5 olunca zaten e=0 oluyor ve p=5 oluyor dolayısıyla set_pwm1_duty(p) hep sabit. osilasyon yok. acaba bir yerde hata mı yapıyorum?

Analyzer

Selam,

Osilasyona girmesi için yeterli süre kalmıyordur. P parametresinin tek olduğu sistemlerde; sistem istenilen değere ulaştığında enerji kesilir. İstenilen değerin altına düşünce tekrar enerjilendirilir. Aç-kapa yani. Böylelikle sistem istenilen düzeyde tutulmak istenir. Ancak sistem sürekli beli tepe ve taban değerleri arasında gelip gider. Örnekle açıklayayım. Bir rezistans ile su ısıtacaksınız ve istediğiniz değer 80C derece olsun. Sistem 80C dereceye geldiğinde kapatsın, altına indiğinde açsın. Ancak rezistansın ve termostatın ataletiyle sistem sürekli örn. 77-83C aralığında "gezer" Burada gördüğünüz gibi sistem "osilasyon"a girdi. I ve D parametreleri ise sistemi hem istenilen değere "oturtur" hem de bu oturtma işini ideal sürede yapılmasını sağlar (İdeal parametre değerlerinde)
Bu nedenle size tavsiyem, kapı kontrolünden önce motoru dışarıda istenilen değerlere hız oturuyor mu ve oturuyorsa ne kadar sürede oturuyor onu tespit etmeniz. Burada çok basit olarak sistem örnekle açıklanmış :

http://hilmi.trakya.edu.tr/ders_notlari/Otomatik_kontrol/Otomatik_Kontrol_6_PID.pdf

Hatta ısı kontrol sistemlerinde özellikle, auto-tuning özelliği vardır ve uygulanabilirliği kolaydır. (I ve D değerini sıfırla, osilasyona gidene kadar P'yi arttır. P değerine göre I ve D değerini tespit et)

Analyzer
Üşeniyorum, öyleyse yarın!

zamzam23

#2
anladım. ama projede yol alabılmem için öncelıkle sundan emın olmalıyım. yazdıgım kod normal sartlar altında calısır mı? kurdugum PI denklemi dogru mu?

birde; bu osilasyon periyodu gözle görülecek düzeyde midir yoksa yazlımla mı tutmalıyım süreyi?

picusta

1. tavsiyem kodunu fonksyonlara bölmen.PID hesaplamak için ayri fonksyon, enkoderden hiz bilgisini almak için ayri fonksyon, pwm'e göndermek için ayri (katsayi uygulasin).
Böylece fonksyonlari tek tek kolaylikla test edersin, birlestirmesi kolay olur.
PID fonksyonunda hata var. Integral terimi olmamis. PID 'yi hesaplamak için birkaç yolu var: seri, parallel veya ideal.
    mpid=aa+Kp*e+Ki*e+(Kd*(e-eonceki));

Düzeltmen gereken konular :
1) birimlere dikkat et, her fonksyonun çikisinin hangi birimde oldugunu belirt, fonksyon arasi çevirmek için katsayi uygula. (hiz'dan PID'ye, PID'den PWM)
2) degiskenlerin ne tïrde oldugunu yazmamissin. Hesaplamarda floating point degil de fixed point hesaplama kullan.
3) Degiskenleri overflow ve underflow kosullarina karsi koru, hesaplarini tek satirda yapma, her islemden sonra overflow ve underflow kousllarini test et.
4) Integral terimini formülde düzelttikten sonra, integrali sinirla sonsuza kadar büyümesin.
5) türev termini filtrele, 3 veya 4 önceki hata degerini kullanarak FIR uygula. Yoksa sistem titrek olur.
6) anlamadigin yerler olursa anlamadigin yerleri burada sor, yeni bir konu açma.

Osilasyon yöntemi ile ayarlamak sana göre olmayabilir. Termik sistemde güzel oluyor ama senin mekanik sistemde sakat, ayrica backslash gibi non lineariteler girdigi için güzel sonuç vermez. Senin kullanman gereken basamak fonksyonu uygulayip sonucu gözlemlemek ve parametreleri öyle ayarlamak. Bunun için motora %20 ver, sonra hizi gözlemle.



http://www.expertune.com/artCE87.html

zamzam23

#4
herne kadar uslubunuzu beğenmesem de yardım etmek istediğiniz belli.ama inanın kimseyi anlamakta zorluk cekmıyorum sizde cektıgım kadar.ne demek istediğiniz çözdükten sonra kodumda düzenlemeler yaptım.eksiklerim varsa lütfen soyleyın.
//----------------HIZ ÖLÇÜM (cm/s)-------------------
#int_timer0  //20 msn
void  timer0_kesme ()   
    {
  if(bb==1)
  {
       if (yon==0) pals1=65535-pals1;
       pals1=pals1*50;//20 msn*50=1sn
       sonuc1=ldiv(pals1,xx);
       hiz=sonuc1.quot;//1sn de aldıgı yol 
       if(hiz>200) hiz=0;
           pals1=0;
       set_timer0(60);
       bb=0;    
       pid();
  }
  else bb=bb+1;
    }
//-----------------PID FONKSİYONU------------------
 
 void pid(void)
 {
 
       e= Ref-hiz;
       oransal=Kp*e;
       integral=integral+Ki*e;
       if (integral>65000) integral=65000;
       if (integral<10) integral=10;
       mpid=aa+oransal+integral;//türevi kaldırdım şimdilik
       p=(int)mpid;
       if(p>30) p=30;
       aa=p;
       set_pwm1_duty(p);
       
 }
//-----------------ANA FONKSİYONU------------------
 #separate
void deneme(void)
{
   ext_int_edge(H_TO_L);
        enable_interrupts(int_ext);
           enable_interrupts(int_timer0);
        enable_interrupts(global); 
 lcd_send_byte(0,0x01); 
        lcdgit(1,1);    
        lcdyaz("DENEME");
        delay_ms(100);
 set_pwm1_duty(0);
        output_bit( PIN_C3, 1);//ENABLE
        output_bit( PIN_C0, 0);//MOTOR SAĞ
        output_bit( PIN_A5, 1);//MOTOR SOL
        
 ref=5.0;
 kd=0.0;
 ki=0.0;
 kp=1.0;
   lcd_send_byte(0,0x01); 
 while(true)
 {
 lcd_gotoxy(1,1);
  printf(lcd_putc,"hiz:%u",hiz);
}
}

1-katsayı 1 oldugundan gerek yok.
2-değişkenler float.ondalıklı.
3-yapıldı.
4-yapıldı.
5-türev iptal edildi.
6-anlasıldı ok.
birde dediğiniz gibi basamak giriş uygulayıp sonucu gözlemle demekle deneme yanılma yap diyorsunuz sanırım. bu yöntemle parametrelerı bulmam cok zor olmazmı?biri değişirken diğeri de değişiyor cunkü.

picusta

Hizin birimi metre saniye cinsinden mi ?
mpid'e niye aa'yi ekliyorsun ? integral terimi aslinda o. onu silmelisin veya :
aa yerine çalisma noktasina göre bir deger vermelisin. bir nevi feedworward gibi olabilir : filtrelenmis komut degeri.

if (integral<10) integral=10;  integral 0 ve negatif degerini alabilir.

Encoder ile baglanti kesilirse diye kod eklemelisin.

Hatali olabilir :
- if(hiz>200) hiz=0;
- pals degiskenini nasil elde ediyorsun? çözünürlük nedir ?

Float hesaplamalar güzel de söyle sorunlar olabiliyor :
- çok zaman aliyor, hesaplamalar 20 ms'de biter mi ?
- hesaplamalarini interrupt'de yaptigin için interrupt uzun sürecek baska interruptlere yetisebilecekmisin ?
- Derleme seçeneklerine dikkat et. intterupt basinda context saving'e float eklesin.   Floating point kütüphanesini interrupt'de kullanirsan ana programdaki float hesaplamalarini etkileyebilir.

O yüzden int veya fixed point daha iyi olur.

DC motor kontrolünde en güzeli kaskad kontrol yapmak. önce 1. PID ile (örnekleme süresi birkaç PWM cycle olacak)  motorun sargilarindaki akimi kontrol edeceksin sonra hizi 2. PID ile kontrol edeceksin (daha yavas).

Analyser'in verdigi linkteki 1. sayfadaki gibi,  açik sisteme basamak uygulayip karakteristiklerini bulacaksin : cevap süresi, delay (L, T ve K parametreleri).
O degerlere göre ayarliyacaksin.
Bunun için söyle yap : %30 PWM ver, hiz degiskenini her 20ms'de hesapladiktan sonra bir tabloya (256 örnek = 5saniye) kaydet (PID fonksyonu yok, çünkü açik sistemdeyiz). Sonra bu tabloyu seri port ile PC'ye at ve excel'de çiz ve L,T, K parametrelerini bul.  Daha sonraki asamada pic'e yazilimla bu tabloyu yorumlatabiliriz. Ve auto-tune sistemin olur.


zamzam23

#6
- hız birimi kodda yazıyordu. cm/sn
- if(hiz>200) hiz=0; satırının pid ile alakası yok. başka bişi için.
- encoder ile bağlantı kesilirse kodunu eklerim.o sonranın işi. yeterki suan pid calıssın.
- palsları RB0 kesmesiyle elde ediyorum.
- formuledekı aa değeri olmalı değilmi? sonucta oncekı pwm değerinin üzerie yazmayacakmı formul sonucunu?

pid kontrol olmadan sadece motoru çevirip hız değerlerini eeproma kaydedip o degerlerle LTK değerlerini mi bulmam gerekiyor önce?evetse yarın ilk işim bu olur.

birde şunu sorucam.akım kontrol demssiniz. 0R1 direnci nereye bağlamam gerektiini öğrendim. onun üzerine dusen gerilimi adc ile sayısala cevırıp ona göre set_pwm1_duty değerini artırıcam veya azaltıcam. akım kontrol bu mu demek?

birde sunu soayım:

burada m diye bir parametre var Kc yi hesaplarken kullanılıyor. bu nedir.

kafama takılan bir başka konu:
benim bir encoderim var. hız bilgisini bununla alıyorum.pid kullanmadan sadece encoderden geen verılere göre, kontrol edemezmıyım kapıyı? su kadar sure boyunca hızı su kadar artır veya azalt türünde.siz ne önerir siniz?pid deki temel mantık nedir burda?

picusta

Palslari nasil elde ettigini tam olarak açikla, kodu buraya yaz, kaç pals/tur'luk enkoder kulaniyorsun, timer1'den okuma mi, capture mü ?

aa degeri integral terimi. onu sil.  AA 'yi feedforward yapabilirsin.

eeprom yerine RAM'a kaydedebilirsin eger yetiyorsa.

Kullandigin islemci nedir ? hesaplama süresi ne kadar tutuyor bakabildin mi?

Evet akim kontrol, akimi ölçüp onu degistrimek için etki vermek demek. Fakat bunu yaparken hizli olmalisin çünkü sistemin cevap süresi L / R (bobin endüktansi/ direnç) motora göre degisir. Bu süreyi 5 ms alirsak, bu sürede 5 veya 10 kez kontrol etmelisin. Her 1ms'de bir (1Khz) interrupt gelecek akimi ölçecek referans ile karsilastirip PWM degerini tazeleyecek (PWM de 5 Khz dersek).  Bu 1. kontrolörün. bunu analojik olarak Opamp ile'de yapabilirsin çünkü hizli kontrol gerekir. Akim kontrolü yapinca motorun uyguladigi tork'u da kontrol ediyorsun dogru orantili olarak.

2. kontrolör ise hiz kontrol mekanik sistemin cevap süresi atalet ile dogru orantili, ve daha yavas çalisir.

m parametresi amortisman, istenilen kontrolün kalitesi olarak görebiliriz. Hizli ama osilasyonlu mu tercih edersin, yoksa daha yavas ama osilasyonsuz ve stabil bir tepki süresi mi istiyorsun ? En hizli cevap süresi(%5) m=0.7'de alinir. Stabilite/performans bakimindan iyi bir pazarlik olan m=1.2 kullanilir.

Tabii sadece encodere bakarak yapabilirsin, yani tek kontrolör (hiz).
Sistemi incelersen 2 kisimdan olustugunu anlarsin:
1. Elektromaynetik : Motorun sargilari (L/R)
2. mekanik : disliler, kapinin kütlesi (ataleti) ve sürtünme.
Tek kontrölör 2. dereceden bir sistemin kontrol edecek.

önce deneme amaçli basamak cevabi elde et ona göre kontrolü seçeriz.






zamzam23

pals leri elde edişim bu şekilde. A kanalı b0 pinine b kanalı c5 pinine bağlı.100 palslik encoder var.18f452,20mhz kullanılıyorum.
#int_ext
void harici_kesme () 
{
if(mod==1)
{
   if(input(pin_c5))      pals++;
    else    pals--;
    }
else
{
 if(input(pin_c5))      pals--;
    else    pals++;
}
}


kod calısıyor

zamzam23

içime bi kurt düştü.acaba yazdıgım kodda pic encoderden pals kacırırmı? 20mhz kristal var.

picusta

Sonuç ?
islemci ne kadar sürede hesapliyor ?
Sistemin basamak cevabi neye benziyor ?(hnagi çalisma noktasinda ?)
seçtigin islemcinin kesmeleri 2 öncelik ile çalistigindan sanslisin. Palsleri yüksek öncelikli kesme ile sayicaksin, düsük öncelikli interruptta PID.
Yanliz unutmaman gereken sey pals degiskeni her iki kesmede kullaniliyor. Eger birisi ona erisirken digeri degerini degistirirse sorun olabilir. (2 byte'lik deger oldugundan 1. bayt, 2. bayt)
Bu yöntem yerine capture ve compare modunu kullanmaya bak.

zamzam23

yarın basamak cevabı çizdirip eklicem buraya.

zamzam23

Alıntı yapılan: picusta - 18 Eylül 2010, 09:54:50
Yanliz unutmaman gereken sey pals degiskeni her iki kesmede kullaniliyor. Eger birisi ona erisirken digeri degerini degistirirse sorun olabilir. (2 byte'lik deger oldugundan 1. bayt, 2. bayt)
birisi ona erişirken diğeri değerini değiştiremez cunku bır ınterrupt bitmeden diğerine gecemez.

teknikelektronikci

Ozel encoder girisi olan pic ler var cozum ollabilirmi
Ey Türk istikbalinin evlâdı! İşte, bu ahval ve şerâit içinde dahi, vazifen; Türk İstiklâl ve Cumhuriyetini kurtarmaktır! Muhtaç olduğun kudret, damarlarındaki asil kanda mevcuttur!

zamzam23

arastırmıstım onları da ama sonra vazgecmıstım sebebı sımdı aklıma gelmıyor. pahalı bıraz belkı sebep bu olabılır. ayrıca o da sayma yapıyor bızde sayma yapıcaz farkı varmıkı baska.