24 Temmuz 2014 Perşembe

SERVO MOTOR KONTROL-2

  Bu çalışmamda daha önce yaptığım Analog joystick İle Motor Hız Kontrol Ve RPM Sayıcı Projesi'nde kullandığım analog potu kullanarak 2 adet servo motoru kontrol edeceğim. O projede sadece analog potun x-ekseni kullanıldı fakat bu çalışmamda y-eksenide dahil edilecek.  Yani hem x-ekseni hem de y-ekseninden değerler alacağım.




  Yukarıdaki resimde analog pot gözükmektedir. Yapısında iki adet pot bulunmaktadır. Bunlar ile hem x-ekseni hem de y-ekseninden bir gerilim alınarak ADC yardımıyla mikrodenetleyicimize iletilir. Alınan bu değerler işlenerek hangi eksende ne kadar derecelik hareket varsa servolarımıza iletilir ve servolar harekete geçirilir.

 
 Iki adet servomuz yukarıdaki gibi konumlandırılmıştır. Analog potumuz x-ekseninde bir değişiklik yaparsa alttaki servo devreye girecek veya y-ekseninde bir değişiklik olursa üstteki servo devreye girecektir. Hem servolar hem de analog pot +90 derece ile -90 derece arasında konumlandırılabilir.
 


Devre şeması



MikroC kodu;

#include "built_in.h" // hi(), lo(), komutlarını kullanmak için
# define servo1 PORTB.RB4 // servo motor çıkışı ayarlanır. PORTD.RD0
# define servo2 PORTB.RB5 // servo motor çıkışı ayarlanır. PORTD.RD1
char secilen_motor = 1, secilen_hiz = 1, secilen_poz = 0;
unsigned poz;
const int rc_poz_limit = 12500;         // PWM maksimum limit = 2.5 ms x 8 = 20 ms
const int rc_poz_min = 2400;            // PWM minimum limit = 1.5 ms
unsigned servo_pwm[2]={rc_poz_min,rc_poz_min};
unsigned short servo_say = 0;
bit servo1_on;
bit servo2_on;
bit bayrak;
unsigned rc_poz_interrupt = 53035;      // TMR1 için ön değer
unsigned int adc_deg[2]; // ADC'den alınan verilerimi tutar.
void interrupt(){
   if (pir1.tmr1if){                     // tmr1 kesmesi oluştu
      if (!bayrak){
         if (servo_say == 0 && servo1_on) servo1 = 1;
         if (servo_say == 1 && servo2_on) servo2 = 1;
         rc_poz_interrupt = 65535 - servo_pwm[servo_say];
         tmr1h = hi(rc_poz_interrupt);
         tmr1l = lo(rc_poz_interrupt);
      }
      if (bayrak) {
         if (servo_say == 0 && servo1_on) servo1 = 0;
         if (servo_say == 1 && servo2_on) servo2 = 0;
         rc_poz_interrupt = 65535 - rc_poz_limit + servo_pwm[servo_say];
         tmr1h = hi(rc_poz_interrupt);
         tmr1l = lo(rc_poz_interrupt);
         if (++servo_say > 7) servo_say = 0;
      }
      bayrak = !bayrak;
      pir1.TMR1IF = 0;
   }
}
void init(){
     TRISB=0X00;
     PORTB=0X00;
     delay_ms(300);
   /*TIMER1 DONANIM BIRIMI KULLANILIYOR CUNKU SERVO MOTORUN NE KADAR SURE 1 KALCAK VE NE KADAR SURE 0 KALACAĞINI HESAPLAMAK ICIN BU DONANIM BIRIMINE IHTIYAC VARDIR*/
     TMR1H = hi(rc_poz_interrupt);       // TMR1 için ön değer yüklendi
     TMR1L = lo(rc_poz_interrupt);
     PIE1.TMR1IE = 1;                    // TMR1 kesmesi aktif edildi
     T1CON.TMR1ON = 1;                   // TMR1 zamanlayıcısı çalıştırıldı
     RCON.IPEN = 0;                      // Çevresel kesme maskelemeleri iptal edildi
     INTCON.GIE = 1;                     // Kesmeler aktif edildi
     INTCON.PEIE = 1;
    /*ADC AYARLARI ICIN*/
     TRISA.RA0=1;
     TRISA.RA1=1;
     ADCON0=0x09;
     ADCON1=0b00001101;   // Use Internal Voltage Reference (Vdd and Vss)
     CMCON|=7;
     bayrak = 0;
     servo1_on = 1;
     servo2_on = 1;
     servo1 = 0;                         // bütün servoların ctrl pinlerine
     servo2 = 0;
     servo_pwm[0] = 2400;                // bütün servoların başlangıç pozisyonları
     servo_pwm[1] = 2400;
}
void servo_poz(unsigned secilen_motor, unsigned poz, unsigned short hiz){
    unsigned short i;
    while(servo_pwm[secilen_motor] < poz){
       servo_pwm[secilen_motor]++;
       for(i = 0; i < hiz; i++) delay_us(100);
    }
    while(servo_pwm[secilen_motor] > poz){
       servo_pwm[secilen_motor]--;
       for(i = 0; i < hiz; i++) delay_us(100);
    }
}
void main() {                           // ana program
    init();                             // init() altprogramı çalıştırılıyor
    delay_ms(500);
    while(1){                            // sonsuz döngü
           secilen_motor=0;
          while(secilen_motor<2){
               adc_deg[0]=ADC_READ(0);
               adc_deg[1]=ADC_READ(1);
               delay_ms(100);
               poz=(55,56*((adc_deg[secilen_motor]*45)/255))+2400;
               servo_poz(secilen_motor, poz, secilen_hiz);
               secilen_motor++;
          }

    }
}


                                              SONUÇ




Hiç yorum yok:

Yorum Gönder