22 Temmuz 2014 Salı

SERVO MOTOR KONTROL-1

 Servo motorlar günümüzde pek çok yerde kullanılmaktadır. Genellikle model uçaklar, araba gibi yerlerde sıkça kullanılır. Boyutları küçük olmasına rağmen torku yüksek olması bu motorların en önemli özelliklerinden biridir. Diğer önemli özelliği ise mikrodenetleyiciler ile arasında herhangi bir ara devre olmadan direk mikrodenetleyiciye bağlanabilir. Piyasa da genellikle 180 derece dönebilen mevcuttur ama 360 derece dönebilenlerde vardır.


Benim bu çalışmada kullanacağım TowerPro markalı servo motordur.  Servo motorun 3 adet kablosu bulunur;
   *  Kırmızı kablo VCC(4.5V-6V)
   *  Kahve rengi    GND
   *  TURUNCU    Data




 Servo motorun çalıştırılması için periyodu sabit olmalıdır yani 20ms  gibi. Bu 20 ms periydun içinde biz darbenin lojik 1 kalma süresini sınırları içinde ayarlarsak motor istediğimiz yöne sürebiliriz. Örneğin; Data ucuna 0.5 ms bir lojik 1 uygulayalım sonra 19.5ms lojik 0 uygulayalım motor sola doğru hareket edecektir. Bunu devamlı yaparsak motor sola gidecek ver orada kitlenecektir. Bu işlemler ortaya ve sağa doğru hareketler içinde geçerlidir.

 Ben bu çalışmamda yapmak istediğim şey şimdilik motor önce -90 derece gidecek ve +10 derece arta arta +90 dereceye kadar gidecek.

Devre şeması
 
 
Devrede 20Mhz kristal, 2 adet 22pf kondansatör , 1 adet servo motor ve son olarak 18f4550 mikrodenetliyimiz bulunmaktadır.

MikroC  kodumuz; Kod yeterince açıktır ve yanlarında açıklamaları yazdım. Biraz göz atarsanız mantığını anlayabilirsiniz.


 #include "built_in.h" // hi(), lo(), komutlarını kullanmak için
# define servo PORTD.RD0 // servo motor için çıkışı ayarlanır PORTD.RD0
char say = 1, secilen_hiz = 1, secilen_poz = 0;
unsigned poz;
const int rc_poz_limit = 12500;         // PWM maksimum limit 2.5ms
const int rc_poz_min = 2400;            // PWM minimum limit  0.5ms
unsigned servo_pwm;             // ne kadar lojik  1 kalacağını belirler.
unsigned short servo_idx = 0;   // Bunun neden kullandığı sonraki projede daha açık anlayacaksınız
bit servo1_on;
bit bayrak;
unsigned rc_poz_interrupt = 53035;      // TMR1 için ön değer
unsigned short adc_deg;
void interrupt()
{
   if (pir1.tmr1if){                     // tmr1 kesmesi oluştu
      if (!bayrak){
         if (servo_idx == 0 && servo1_on) servo = 1;
         rc_poz_interrupt = 65535 - servo_pwm;
         tmr1h = hi(rc_poz_interrupt);
         tmr1l = lo(rc_poz_interrupt);
      }
      if (bayrak){
         if (servo_idx == 0 && servo1_on) servo = 0;
         rc_poz_interrupt = 65535 - rc_poz_limit + servo_pwm;
         tmr1h = hi(rc_poz_interrupt);
         tmr1l = lo(rc_poz_interrupt);
         if (++servo_idx > 7) servo_idx = 0;
      }
      bayrak = !bayrak;// 20ms elde etmek için bu işlem yapıldı
      pir1.TMR1IF = 0;
   }
}
void init()
{
    TRISD =0x00;                          // PORTD çıkış olarak yönlendirildi
    PORTD =0x00;                          // PORTD sıfırlandı
    delay_ms(300);
    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;                    // Çevresel kesmeler aktif edildi
    bayrak = 0;
    servo1_on = 1;
    servo = 0;                         //  servo ilk anda çalışmıyor.
    servo_pwm = 2400;                // bütün servoların başlangıç pozisyonları
}
void pozisyon(unsigned poz, unsigned short hiz)   // servonun pozisyonunu ayarlama
{
    unsigned short i;
    while(servo_pwm < poz){
       servo_pwm++;
       for(i = 0; i < hiz; i++) delay_us(100);
    }
    while(servo_pwm > poz){
       servo_pwm--;
       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ü
     say=1;
     while(say < 9)
       {
          delay_ms(100);
          poz = (55,56 * secilen_poz) + 2400;
          pozisyon(poz, secilen_hiz);
          say++;
       }
      secilen_poz = secilen_poz + 10;  // servo pozisyonları 10 derece artırıldı
       if (secilen_poz > 180) secilen_poz = 0;      // pozisyon 180 ( ya da +90 )
    }                                               // dereceyi aştı ise 0 derece
}

                                                         SONUC





Kaynak
*MikroC  ve  PIC18F4550 kitabı
*http://320volt.com/picbasic-dersleri-pic-basic-pro-ile-pic-programlama-12/
*http://embedded-lab.com/blog/?p=4653
*http://www.fatiherdem.net/hobi-servo-surelim/

Hiç yorum yok:

Yorum Gönder