pid kısmında desteğe ihtiyacım var

Başlatan helloworld, 31 Ekim 2014, 23:44:59

helloworld




#include <16F877A.h>
#device ADC=8;
// Denetleyici konfigürasyon ayarları
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000) // Gecikme fonksiyonu için kullanılacak osilatör frekansı belirtiliyor.

#use fast_io(c) //Port yönlendirme komutları C portu için geçerli
#use fast_io(e) //Port yönlendirme komutları E portu için geçerli

#INT_AD               // ADC çevrimi bitti kesmesi
void ADC_Kesmesi ( )
{
   output_high(pin_c5);  // RC5 çıkışı 1
   delay_ms(50);
   output_low(pin_c5);   // RC5 çıkışı 0
}

void main()
{

   set_tris_c(0x00);  // C portu komple çıkış
   set_tris_e(0x0F);  // E portu komple giriş

   output_c(0x00);    // C portu çıkışını sıfırla
   output_b(0x00);
   setup_adc(adc_clock_div_32);   // ADC clock frekansı fosc/32
   setup_adc_ports(ALL_ANALOG);   // Tüm AN girişleri analog 
   enable_interrupts(INT_AD);     // AD çevrimi bitti kesmesi tanıtılıyor
   enable_interrupts(GLOBAL);     // Tüm kesmeler aktif

   
   while(TRUE)   // sonsuz döngü
   {  float kp=0.5;
      unsigned int16 adc_val1,adc_val2,adc_fark,X;
      set_adc_channel(5);   // RE0/AN5 ucundaki sinyal A/D işlemine tabi tutulacak
      delay_us(20);         // Kanal seçiminde sonra bu bekleme süresi verilmelidir
      adc_val1=read_adc();     // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor

  //    voltaj1=0.0048828125*bilgi;  // Dijitale çevirme işlemine uğrayan sinyalin gerilimi hesaplanıyor
      set_adc_channel(6);   // RE1/AN6 ucundaki sinyal A/D işlemine tabi tutulacak
      delay_us(20);         // Kanal seçiminde sonra bu bekleme süresi verilmelidir
      adc_val2=read_adc();     // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor

    //  voltaj2=0.0048828125*bilgi;  // Dijitale çevirme işlemine uğrayan sinyalin gerilimi hesaplanıyor
        
     adc_fark=adc_val1-adc_val2;   //burada farkını buluyorum.fakat ondalıklı
      X=kp*adc_fark;   
      output_b(X);
      delay_us(50);
            
   }    
   
}



pid nin p sini hallettim sayılır.integral ve türev kısmını çalıştım gayet iyi anladım.fakat kod olarak yazamadım.
şimdilik kp,ki,kd değerlerinin ne olması gerektigi önemli değil? kod kısmını oturtmam gerek.yardımcı olabilir misiniz?şimdiden teşekkürler.

Erol YILMAZ


Tagli

PID bir kapalı çevrim kontrol yöntemidir. Kapalı çevrim, kontrol edilmek istenen değerin ölçülmesi ve bunun istenen referans değeri ile karşılaştırılarak mevcut hatanın tespit edilmesine dayanır. Kontrolcü, hatayı sıfırlamaya çalışır.

Senin sisteminde kontrol etmek istediğin değer nedir? Ortada bir motor olduğuna göre, bunun açısal konumunu, hızını veya uyguladığı torku kontrol edebilirsin. Bunun için de bir sensöre ihtiyacın var. Senin sisteminde herhangi bir sensör veya benzeri bir geri besleme göremedim. Tavsiyem öncelikle konum kontrolünü denemen. ISIS'i kullanmadığım için bilmiyorum, motorun konumunu algılamana olanak verecek bir eleman var mı?
Gökçe Tağlıoğlu

helloworld

#3
Motora kenetlenen Dinamo olucak o dinamonun çıkışı ac oldugu için onu doğrultucam.sonra onu picin analog bacagına götürücem.yani Çıkış=kp.(set-ölçüm) dersek burdaki ölçüm dinamodan gelen değer olucak.
Resimde de görüldüğü gibi analog uçların ikisinde voltaj degerleri var.bunların büyügü set küçüğü ölçüm olucak.
İntekgral ve derivasion kısmı nı kodlamada tıkandım.

Türev kısmında {e(t)-e(t-1)} / t    Yapıcam buradaki süre farkı 20 ms den az olmaması lazım.timer larla kesme yapıp içine fonksiyon açıyım diyorum.nasıl olur acaba?

mesaj birleştirme:: 01 Kasım 2014, 16:06:23

Alıntı yapılan: Allegro - 01 Kasım 2014, 09:35:20
http://brettbeauregard.com/blog/2011/04/improving-the-beginners-pid-introduction/

bu siteden uyarlamaya calıstım 17 tane error verdi düzeltmeye çalıştım ama olmadı.

#include <16F877A.h>
#device ADC=8;
// Denetleyici konfigürasyon ayarları
#fuses XT,NOWDT,NOPROTECT,NOBROWNOUT,NOLVP,NOPUT,NOWRT,NODEBUG,NOCPD

#use delay (clock=4000000) // Gecikme fonksiyonu için kullanılacak osilatör frekansı belirtiliyor.

#use fast_io(c) //Port yönlendirme komutları C portu için geçerli
#use fast_io(e) //Port yönlendirme komutları E portu için geçerli

#INT_AD               // ADC çevrimi bitti kesmesi
void ADC_Kesmesi ( )
{
   output_high(pin_c5);  // RC5 çıkışı 1
   delay_ms(50);
   output_low(pin_c5);   // RC5 çıkışı 0
}

void main()
{

   set_tris_c(0x00);  // C portu komple çıkış
   set_tris_e(0x0F);  // E portu komple giriş

   output_c(0x00);    // C portu çıkışını sıfırla
   output_b(0x00);
   setup_adc(adc_clock_div_32);   // ADC clock frekansı fosc/32
   setup_adc_ports(ALL_ANALOG);   // Tüm AN girişleri analog 
   enable_interrupts(INT_AD);     // AD çevrimi bitti kesmesi tanıtılıyor
   enable_interrupts(GLOBAL);     // Tüm kesmeler aktif

   
   while(TRUE)   // sonsuz döngü
   {  
      
      unsigned long lastTime;
      unsigned int16 olculen,Output,Setpoint;
      double errSum,lastErr;
      double kp1,ki1,kd1;
         
         void hesapla()
         {
      // son hesaplama ne kadar sürdü
      unsigned long suan=millis();
      double timeChange=(double)(suan-lastTime);
      
      // bütün hata degerlerini hesapla
                
      set_adc_channel(5);   // RE0/AN5 ucundaki sinyal A/D işlemine tabi tutulacak
      delay_us(20);         // Kanal seçiminde sonra bu bekleme süresi verilmelidir
      Setpoint=read_adc();     // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor

  //    voltaj1=0.0048828125*bilgi;  // Dijitale çevirme işlemine uğrayan sinyalin gerilimi hesaplanıyor
      set_adc_channel(6);   // RE1/AN6 ucundaki sinyal A/D işlemine tabi tutulacak
      delay_us(20);         // Kanal seçiminde sonra bu bekleme süresi verilmelidir
      olculen=read_adc();     // ADC sonucu okunuyor ve bilgi değişkenine aktarılıyor

    //  voltaj2=0.0048828125*bilgi;  // Dijitale çevirme işlemine uğrayan sinyalin gerilimi hesaplanıyor
        
     double error=Setpoint-olculen;   //burada farkını buluyorum.fakat ondalıklı
      errSum+=(error*timeChange);
      double dErr=(error-lastErr)/timeChange;
      
      // pıd cıkısını düzenle
      
      Output=kp*error+ki*errSum+kd*dErr;
      
      //bir sonraki degerleri hatırlat
      lastErr=error;
      lastTime=suan;
         }
      
      void ayarlama(double Kp,double Ki,double Kd)
      {  
         kp1=Kp;
         ki1=Ki;
         kd1=Kd;
      }
      
      output_b(Output);
      delay_us(50);
            
   }    
   
}



errorlar da bunlar.



sadogan

Kabaca baktığımda
void hesapla()
void ayarlama(double Kp,double Ki,double Kd)
bu 2 fonsiyon main rutun içide yer alıyor alt fonksiyonlar main dişında olur
gerekli yerlerde çağırırlırlar.
Kısada "C" çalışmanız gerekiyor.