Şimdi Ara

Arduino PID Motor Kontrol

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
14
Cevap
1
Favori
6.711
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • Merhaba arkadaşlar,

    Bitirme projesi olarak arduino ile pid motor kontrolü yapmamızı istedi hoca. Bir arkadaşımla birlikte yapıyorum ama ne ben ne de o programlama konusunda iyi sayılmayız.

    Arduino uno aldık biraz üstünde çalıştık ama pid işi biraz karıştırıyor malesef.

    hocanın bizden istediği şu; arduino nun pwm çıkışını alçak geçiren filtreden geçirdikten sonra laboratuvardaki motora vereceğiz ve feedback olarak da motorun şaftına bağlı olan tachogeneratorden gelen sinyali alacağız. input değerlerini arduino üzerinden potansiyometre ile vermemizi istiyor. Donanım olarak sıkıntımız yok zaten laboratuvardaki ekipmanları kullanıyoruz ama dediğim gibi büyük sıkıntı yazılım konusunda

    pid yazılımı konusunda yardım edebilecek arkadaşlar varsa lütfen yardımlarını esirgemesinler.

    şimdiden herkese teşekkür ediyorum.



  • takipteyim benim de buna benzer bir projem var. Umarım cevap veren arkadaşlar çıkar.
  • quote:

    Orijinalden alıntı: faruközalp

    takipteyim benim de buna benzer bir projem var. Umarım cevap veren arkadaşlar çıkar.

    evet umarım cevap veren çıkar
  • PID 'nin P si için

    set değerinden gerçek ( ölçtüğün ) değeri çıkar

    P katsayısıyla çarpıp arduino çıkışa ver

    sanırım hazır bir motor sürücün var

    arduinonun çıkışı ne olacak ? 0-10 V kontrol sinyali - bunu sürücünün hız kumanda girişine vereceksin


    I kısmı için gene set değerinden ölçtüğün değeri çıkar

    bunu long integer türünde bir değişkene her saykılda topla ( mesela her 10 milisaniyede bir )

    sonra bunu I katsayısına böl ve deminki P değerine topla


    D kısmı için de

    bir önce ölçtüğün değeri en son ölçtüğün değerden çıkar

    bunu D katsayısıyla çarpıp gene deminki PI toplamıyla topla

    temeli bu , yalnız D parçası osilasyona sebep olabilir bunun katsayısını küçük tut

    bir de PID de oluşan ham değerlerin kendisi değil (-1) ile çarpılmışı yani tersi gerekebilir

    onu deneyerek bulacaksın

    nasıl bulacaksın ?

    mesela önce P ile başladın ve kontrol çevrimini kapatınca motor hızı uçtu o zaman sinyalin yönü ters olması gerekirmiş - bunun gibi




  • quote:

    Orijinalden alıntı: anotherbrick

    PID 'nin P si için

    set değerinden gerçek ( ölçtüğün ) değeri çıkar

    P katsayısıyla çarpıp arduino çıkışa ver

    sanırım hazır bir motor sürücün var

    arduinonun çıkışı ne olacak ? 0-10 V kontrol sinyali - bunu sürücünün hız kumanda girişine vereceksin


    I kısmı için gene set değerinden ölçtüğün değeri çıkar

    bunu long integer türünde bir değişkene her saykılda topla ( mesela her 10 milisaniyede bir )

    sonra bunu I katsayısına böl ve deminki P değerine topla


    D kısmı için de

    bir önce ölçtüğün değeri en son ölçtüğün değerden çıkar

    bunu D katsayısıyla çarpıp gene deminki PI toplamıyla topla

    temeli bu , yalnız D parçası osilasyona sebep olabilir bunun katsayısını küçük tut

    bir de PID de oluşan ham değerlerin kendisi değil (-1) ile çarpılmışı yani tersi gerekebilir

    onu deneyerek bulacaksın

    nasıl bulacaksın ?

    mesela önce P ile başladın ve kontrol çevrimini kapatınca motor hızı uçtu o zaman sinyalin yönü ters olması gerekirmiş - bunun gibi




    Hocam öncelikle cevabın için çok teşekkür ediyorum.

    Ama PID kısmını bende zihnimde oluşturabiliyorum, dediğim gibi asıl sıkıntı kod kısmında yani giriş çıkış verme pinleri atama falan yapıyorum ama pid yi koda dökmede sıkıntı yaşıyorum o konuda yardımcı olabilir misiniz.

    bu arada sürücüm yok ama labdaki deney seti üzerindeki filtre ve power amplifier üzerinden motoru sürmeyi planlıyoruz. (en azından hoca öyle dedi)




  • arkadaşlar şu forumda arduino programlamadan anlayan üstatlar yok mu ya şu imdat çağrıma bir cevap verin lütfen
  • beyler ardunıo yu bılmıyorum ama hı-tech c ile yaptığım pid kontrollü çizgi izleyen robot var isterseniz örneğini atayım ona göre ardunio kodları ile değiştirip uygularsınız.
  • quote:

    Orijinalden alıntı: Apollo-07

    beyler ardunıo yu bılmıyorum ama hı-tech c ile yaptığım pid kontrollü çizgi izleyen robot var isterseniz örneğini atayım ona göre ardunio kodları ile değiştirip uygularsınız.

    valla burada paylaşabilirsen çok makbüle geçer
  • CybeR_chaqaL kullanıcısına yanıt
    Üniversite de yazmaya çalışmıştım isis de çalışmıştı ama devre üstünde bir türlü çalıştıramadım donanımsal dı sanırım hatalar.
    şimdi tekrardan bakayım dedım de unutmuşum proğramlamayı neredeyse :D

    // hı-tech pid deneme 877a
    #include <htc.h>
    #include "delay.h"
    char deger=0;
    long k=0,i,a,sens[8],maxdeg[8]={500,500,500,500,500,500,500,500},mindeg[8]={500,500,500,500,500,500,500,500};
    long fon=0,fon2=0,say=0,sensor,last_sensor,duz;
    long last_error,error,correction=0,mak=250,pr,der,derr;
    char kp=0.45,kd=5.25,m=0;
    void duz_hareket()
    {
    T2CKPS1=1; // Prescaler 1:16 oluyor
    T2CKPS0=1;
    TOUTPS3=0; // Postscale 1:1 oluyor
    TOUTPS2=0;
    TOUTPS1=0;
    TOUTPS0=0;
    PR2=250;

    CCPR1L=0x3E; // Duty registere 250 yükleniyor
    CCP1X=1; // Duty cycle 1ms periyodunda
    CCP1Y=0;
    CCP1M0=1; // CCP1 PWM modunda
    CCP1M1=1;
    CCP1M2=1;
    CCP1M3=1;

    CCPR2L=0x3E; // Duty registere 250 yükleniyor
    CCP2X=1; // Duty cycle 1ms periyodunda
    CCP2Y=0;
    CCP2M0=1; // CCP2 PWM modunda
    CCP2M1=1;
    CCP2M2=1;
    CCP2M3=1;

    TMR2ON=1; // Timer 2 çalıGtırılıyor*/
    PORTB=4;
    DelayMs(250);
    PORTB=0;
    char j=0;
    for(j=10;j<250;j++)
    {
    RB2=~RB2;
    CCPR1L=j;
    CCPR2L=j;
    DelayMs(1);
    }
    CCPR1L=250;
    CCPR2L=250;
    PORTB=0x0f;
    }
    void sifirla() // sıfırlanması gereken değerleri sıfırla...
    {
    fon=0;
    fon2=0;
    say=0;
    duz=0;
    }
    void sensor_oku()
    {
    RB2=~RB2;
    CHS2=0; // AN0 seçiliyor
    CHS1=0;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[0]=deger;
    CHS2=0; // AN1 seçiliyor
    CHS1=0;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[1]=deger;
    CHS2=0; // AN2 seçiliyor
    CHS1=1;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[2]=deger;
    CHS2=0; // AN3 seçiliyor
    CHS1=1;
    CHS0=1;
    DelayUs(35);
    deger=(ADRESH*256+ADRESL);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    sens[3]=deger;
    CHS2=1; // AN4 seçiliyor
    CHS1=0;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[4]=deger;
    CHS2=1; // AN5 seçiliyor
    CHS1=0;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[5]=deger;
    CHS2=1; // AN6 seçiliyor
    CHS1=1;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[6]=deger;
    CHS2=1; // AN7 seçiliyor
    CHS1=1;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[7]=deger;
    for(i=0;i<8;i++)
    {
    sens=(int)((1000*(sens-mindeg))/(maxdeg-mindeg));
    if(sens<250)
    {
    sens=0;
    }
    else if(sens>850)
    {
    sens=1000;
    }
    fon=fon+(sens*say);
    fon2=fon2+sens;
    say=say+1000;
    duz=duz+sens;
    if((fon/fon2)==0)
    {
    sensor=last_sensor;
    }
    else
    {
    sensor=(fon/fon2);
    }
    last_sensor=sensor;
    }
    }
    void ilk_ayar()
    {
    for(a=0;a<25;a++)
    {
    PORTB=0;
    for(i=0;i<255;i++)
    {
    CHS2=0; // AN0 seçiliyor
    CHS1=0;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[0]=deger;
    CHS2=0; // AN1 seçiliyor
    CHS1=0;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[1]=deger;
    CHS2=0; // AN2 seçiliyor
    CHS1=1;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[2]=deger;
    CHS2=0; // AN3 seçiliyor
    CHS1=1;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[3]=deger;
    CHS2=1; // AN4 seçiliyor
    CHS1=0;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[4]=deger;
    CHS2=1; // AN5 seçiliyor
    CHS1=0;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[5]=deger;
    CHS2=1; // AN6 seçiliyor
    CHS1=1;
    CHS0=0;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[6]=deger;
    CHS2=1; // AN7 seçiliyor
    CHS1=1;
    CHS0=1;
    DelayUs(35);
    GO=1; // Çevrim baGlatılıyor
    while(GO);
    deger=(ADRESH*256+ADRESL);
    sens[7]=deger;
    for(k=0;k<8;k++)
    {
    if(sens[k]>maxdeg[k])
    {
    maxdeg[k]=sens[k];
    }
    if(sens[k]<mindeg[k])
    {
    mindeg[k]=sens[k];
    }
    }
    }
    }
    for(m=0;m<=5;m++)
    {
    DelayMs(250);DelayMs(250);
    RB1=~RB1;
    }

    }
    void main(void)
    {

    TRISA=0xEF; // analog okumalar acıldı
    TRISE=0xFF; // RA0 ve RA1 giriG
    TRISC=0xF0; // PORTC çıkıG olarak ayarlanıyor
    TRISB=0xF0; // RB4..RB7 giriG, diğerleri çıkıG
    PORTB=0x00; // PORTB sıfırlanıyor
    PORTC=0;
    PCFG3=0; // AN0-AN7 analog girişleri açıldı
    PCFG2=0;
    PCFG1=0;
    PCFG0=0;

    ADFM=1; // Sağa dayalı yazılıyor
    ADON=1;
    // ADIF=0; // ADC bayrağı temizleniyor
    // ADIE=1; // ADC kesmesi izni veriliyor
    TMR2IF=0;
    TMR2IE=1;
    PEIE=1; // Genel ve yardımcı kesme izinleri veriliyor
    GIE=1;
    ilk_ayar();
    for(;;)
    {
    duz_hareket();
    PORTB=255;
    PORTD=0;
    while(1)
    {
    sensor_oku();
    error=sensor-750;
    if(error>-70 && error<70)
    {
    CCPR1L=200;
    CCPR2L=200;
    }
    else
    {
    CCPR1L=250;
    CCPR2L=250;
    }
    pr=(error*kp); // oransal deger = hata *kp
    der=(error-last_error);
    derr=der*kd;
    last_error=error;
    correction=pr+derr;
    if(correction>mak)
    {
    correction=mak;
    }
    if(correction<-mak)
    {
    correction=-mak;
    }
    if(correction>0)
    {
    CCPR1L=(mak-correction);
    CCPR2L=250;
    }
    else
    {
    CCPR2L=(mak+correction);
    CCPR1L=250;
    }
    sifirla();
    }
    }
    }

    void interrupt
    an_dig(void)
    {
    // if(ADIF) // Çevrim bitiş kesmesi bekleniyor
    // {
    // deger=ADRESH*256+ADRESL;
    // ADIF=0; // Kesme bayrağı sıfırlanıyor
    // }
    if(TMR2IF)
    {
    TMR2IF=0;
    }
    }




  • Hocam benimde aslinda pek bilgim yok ama bir onerim olcak. Arduinoturkiye foruma bakarsaniz kesinlikle yardimci olurlar.

    < Bu ileti mobil sürüm kullanılarak atıldı >
  • Yapabilen var mı acaba?
  • Yaptığım çizgi izleyene ait PID kısmından bir örnek. analogWrite komutu ile sinyali PWM kanalına aktarmış oluyoruz.
     
    else if ((sensor_counter > black_up) && (sensor_counter != 8)) {
    calculateLinePos(BLP);
    motorDIR(0, 0);

    P = ((reference_point - black_line_pos) * KP);

    I = ((I + (reference_point - black_line_pos)) * KI);

    D = (((reference_point - black_line_pos) - last_error) * KD);

    last_error = reference_point - black_line_pos;

    PID = ((P + I + D) / prescaler);

    if (PID > 0) {
    sagHiz = maxSpeed - PID;
    solHiz = maxSpeed;

    if (sagHiz < 0)
    sagHiz = 0;
    }

    if (PID == 0) {
    solHiz = maxSpeed;
    sagHiz = maxSpeed;
    }

    if (PID < 0) {
    sagHiz = maxSpeed;
    solHiz = maxSpeed + PID;

    if (solHiz < 0)
    solHiz = 0;
    }
    analogWrite(PWMA, sagHiz);
    analogWrite(PWMB, solHiz);
    }




  • Burada cevabı arayanlar için arduino sitesinde çok güzel bir kütüphane oluşturulmuş, rahatça yapabilirsiniz.
    http://playground.arduino.cc/Code/PIDLibrary
  • http://playground.arduino.cc/Code/PIDLibrary kullanarak yaptığım bir çalışmayı aşağıdaki videodan izleyebilirsiniz.

    https://www.youtube.com/watch?v=6iFlfeCihDY

    ana döngüde tek yaptığım aşağıdaki yazılım.
    PID kontrolün en önemli özelliği linear time invariant sistemler için kullanılabiliyor olması.
    Eğer sisteminizin tepkileri zamanla değişiyorsa sistemi modelleyip adaptive tuning yapmanız gerekir.

    myPID.Compute();
    ServoOutput=servocenter+Output;
    myServo.writeMicroseconds(ServoOutput);

    Kolay gelsin




  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.