Hobi Servo Sürelim (Bilgisayar Kontrollü)

      Hobi Servo Sürelim (Bilgisayar Kontrollü) için 43 yorum

20 Kasım 2016 da gözden geçirildi.
Hobi servolar girişine uyguladığımız darbenin genişliğine göre 0-180 derece arasında dönme açısını değiştirilebildiğimiz motorlardır. Model uçakların kanat açıları, uzaktan kumandalı arabaların direksiyon sistemleri, el-kol hamleleri-adım atma-tutma-bırakma gibi hareketler gerektiren ve çok yüksek tork gerektirmeyen robotlar için ideal motorlardır. Bu motorlar çeşitli boy ve torklarda olabiliyor:
ces_servo2

Ben burdaki tüm denemelerimi aşağıda gördüğünüz (TowerPro) mini servo üzerinden yaptım:
m_servo

Büyük resimden görüldüğü üzere servolarımızın üç girişi var, ikisi besleme üçüncüsü data(veya pwm) girişi yani darbe genişliği uyguladığımız giriştir. Hobi servomuzu kontrol etmek için bir kare dalga işaretinin darbe genişliğini belirli sınırlar içerisinde değiştiririz, yani ismini koymak gerekirse darbe-genişlik modülasyonu yaparız. Renklerden hangi pin ne işe yarıyor görebiliyoruz. Nitekim bizim servomuzda kahverengi:toprak, kırmızı:+, turuncu:data. Diğer hobi servolarda renkler nasıl bilmiyorum ama kırmızı(+) ve siyah(toprak) kablolar varsa kalan girişin pwm girişi olduğunu söyleyebiliriz.
Her şeyden önce servomuzu genel olarak nasıl sürüyoruz? Bu sorunun çoğu hobi servo için geçerli bir cevabı var:
20ms periyotlu bir kare dalga işaretimizin darbe genişliğini 1ms ile 2ms arasında değiştirerek hobi servomuza 0 ile 180 derece arasında açı veririz. Başka bir deyişle periyodu 20ms olan ve “duty cycle” ı %5 ile %10 arasında değişebilen pwm(darbe genişlik modülasyonu) işareti uygularız. Pwm demek istemiyorum çünkü bizim burda anlatmak istediğimiz sürme metodu “duty cycle” ayarlanmasından ziyade darbe genişliğinin mikrosaniyeler mertebesinden değiştirilmesi üzerine kurulmuştur. Yazının ilerleyen bölümünde sürme metodumuzun ne kadar basit ve temel bir işlem olduğu anlaşılacaktır. Servonun açısının ayarlanmasında periyodun 20ms olması şart değil, önemli olan uygulanan darbenin genişliği. Servonun belirlediğimiz konumda kalması için bu bilgiyi sürekli güncelliyoruz(her 20 ms de mesela), bu işareti kestiğinizde(besleme duruyor tabi) servo son açısında kalıyor ancak ufak bir tork servonun açısını değiştirebilir. Yani siz eğer yüke bağlı servonuzu belirli bir konumda tutmak istiyorsanız 20ms belki daha da düşük periyotlu bir işaretle servoyu kontrol etmeniz gerekir.
servo_surus
Ancak bu darbe aralıkları her hobi servo için böyle değil (şimdiden sonra yazı boyunca hobi servo yerine servo diyeceğim). Nitekim bizim kullanacağımız servonun darbe aralığı 540 us ile 2400 us arasında. Peki biz bu darbe sürelerini nerden öğreneceğiz, yok mu bu kullanacağımız servonun teknik bilgileri? Yok ne yazık ki. Burda kullanacağımız servonun web sitesinde motorun temel özelliklerini yazmakla yetinmişler, servo işte siz sürersiniz demek istiyorlar heralde(site:http://towerprocn.sh15.host.35.com/towerprocn/english/servo/SERVO.html).
Her marka servo için durum böyle değil tabii ki, mesela futaba’nın sitesinde motorun sürülmesi için gereken tüm bilgiler verilmiş(site:http://www.gpdealera.com/cgi-bin/wgainf100p.pgm?I=FUTM0503):

Torque: 196 oz-in @ 6V
(13.8 kg-cm @ 6V)

Communication: Pulse Width Modulation (PWM)
Operation range: 180°
Pulse cycle: 14.25ms
Pulse width: 920-2120us
gibi.
Bizim motorumuzun bu bilgileri verilmemiş ama olsun, bu bilgileri kendimiz buluruz hem de daha öğretici bir çalışma yapmış oluruz. Çalışmamızda mikro olarak 16F628 PIC mikro, dil olarak CCS C dili seçilmiştir.

Bu bilgileri bulma işine girmeden önce servomuza bir hareket verelim, bakalım çalışıyor mu! Servomuza 1ms darbe genişliği uygulayarak konumlandığı açıya bakalım. Besleme gerilimi olarak servonuzun teknik bilgilerine bakabilirsiniz. Bizim servomuz için “Operating voltage 4.2-6V” denilmiş. Genel olarak 6V uygulanabilir, ben 5V uyguluyorum. Servomuzun data girişine b0 pinini bağlayacak olursak bunun için bizim yazacağımız temel kod:

while(1){
      output_high(pin_b0);
      delay_us(1000);
      output_low(pin_b0);
      delay_us(19000);
}

olacaktır.
Evet ben servoları sürerken timer kullanmıyorum, bu yöntemle yaptığım denemelerden gayet memnunum. Dolayısıyla temel kodumuz bu basitlikte. Şimdi eğer:

long b0=600;
while(1){
      output_high(pin_b0);
      delay_us(b0);
      output_low(pin_b0);
      delay_us(20000-b0);
}

yazarsak servomuzun pozisyonunu b0 değişkeniyle kontrol edebiliriz. Hobi servo sürmek bu kadar basit:)
Şimdi gelin servomuzun hangi darbe aralıklarında çalıştığını öğrenelim. Ben bunu şöyle yaptım: devremde iki adet düğme var, düğmelerden biri b0 değişkenini 50us arttırıyor, diğeri 50us azaltıyor. Düğmelere basarak ilerlerken b0 değişkenini her değişmede bilgisayara gönderiyorum, yani şu anki b0 değerini takip diyorum.
Ne zaman ki servo artık değişime tepki vermiyor(daha fazla dönemiyor) o b0 değeri benim sınır değerim oluyor. Tabi bu teste başlamadan servomuzun ilk konumunun ortada bir yerde olması için b0 ın ilk değerini 1000us civarı seçmeliyiz. Bu işi yapan kod:

long b0=1000;
while(1){
if(!input(pin_b3)){ //dugmeye basildi
      b0+=50;
      delay_ms(200);
      deger=b0/10;
      putc(deger); //8 bitlik sayıyı bilgisayara gönder
}
if(!input(pin_b4)){ //dugmeye basildi
      b0-=50;
      delay_ms(200);
      deger=b0/10;
      putc(deger);
}
      output_high(pin_b0); //surmeye devam
      delay_us(b0);
      output_low(pin_b0);
      delay_us(20000-b0);

}//while

Bilgisayara göndermek şart değil b0 ın ilk değerini programınızda 1000us gibi sabit bir sayıya eşitleyin sonra düğmeye kaç defa bastıysanız o kadar 50 us ekleyerek(veya çıkararak) servonuzun sınır darbe genişliklerini tespit edebilirsiniz. Her düğmeye bastığınızda “toggle” eden bir led olursa adım kaçırmazsınız.

Sınır değerleri de bulduysak artık servomuzu istediğimiz açıya getirebiliriz. Peki ne kadar bir hassasiyetle? Devre düzeneğinizi bozmadan düğmelerle değiştirdiğiniz b0 değerini 50 us değil de daha az yapın, bakalım tepki veriyor mu? Bizim servomuz için bu hassasiyet “Dead band width =10 us” olarak verilmiş. Bu da yaklaşık 1 dereceye tekabül ediyor.

Peki bu yöntemle aynı anda kaç servoyu sürebiliriz?
Benim şu anda elimde 2 servo var, 2 sini rahatlıkla sürebiliyorum. ISIS simülasyonda 5 servoyu sürüyorum. Yazılan kod yine aynı mantıkta, 3 servo sürmek istersek:

long s1=650,s2=650,s3=650;
while(1){
      output_high(pin_b0);
      delay_us(s1);
      output_low(pin_b0);

      output_high(pin_b3);
      delay_us(s2);
      output_low(pin_b3);

      output_high(pin_b4);
      delay_us(s3);
      output_low(pin_b4);

      delay_us(20000-s1-s2-s3);

}//while

Gelelim bu bilgilerimizi güzel bir uygulamada kullanma kısmına:
Servolarımızı s1, s2, s3 değişkenileriyle kontrol edebileceğimizi gördük, peki bu değişkenleri nasıl değiştireceğiz? İlk uygulamamızdaki gibi düğmelerle mi? Bu değerleri bilgisayarımızdan göndersek nasıl olur?

Bence de güzel olur. Ancak bunun için küçük bir program yazmalıyız ve bir de arayüz hazırlamalıyız. Bence bu iş için en uygun yol visual studio.net ortamında C# kullanmak. Serialport nesnesi, hazır form elemanları ve kontrol kolaylığı tam bize göre. Yani bilgisayar kısmında işimiz kolay. Peki gelen verileri PIC le nasıl alacağız? UART kesmesiyle.
Kodumuz gayet basit:

while(1){

      output_high(pin_b0);
      delay_us(s1);
      output_low(pin_b0);

      output_high(pin_b3);
      delay_us(s2);
      output_low(pin_b3);

      output_high(pin_b4);
      delay_us(s3);
      output_low(pin_b4);

      delay_us(20000-s1-s2-s3);

}//while
}//main

#INT_RDA
void seri_data_geldi(){
bx=getc(); // bx de long türünden

if(bx==200){ //sira ilk motorun
   sira=1;
}
if(bx==220){//sira ikinci motorun
   sira=2;
}
if(bx==240){//sira ucuncu motorun
   sira=3;
}

if(bx<200){ //gelen veri motorlara
if(sira==1){
   s1=10*bx+540;
}
if(sira==2){
   s2=10*bx+540;
}
if(sira==3){
   s3=10*bx+540;
}
}
output_toggle(pin_a1); //kesme geldi belirteci
}

Peki elimizde servo yoksa bu uygulamayı Proteusta simüle edebilir miyiz? Evet. Bunun için öncelikle “eltima virtual serial port” programı gibi bilgisayarımızda virtual serial port oluşturabilecek bir programa ihtiyacımız var. Çünkü “virtual port” oluşturamazsak visual studio.net ile açtığımız porta proteus bağlanamayacak, proteusla açtığımız porta vs.net bağlanamayacak. Bahsettiğim virtual serial port programı bilgisayarımızda birbirine bağlanmış sanal port çifti oluşturuyor, örn com1 ve com2 olarak. Proteustan com1 e bağlanıp başka programlardan com2 ye bağlanarak iki program arasında iletişimi sağlayabiliyoruz.

Dikkat etmemiz gereken bir diğer nokta proteusta kullandığımız servonun sağ tık menüsüyle açılan özelliklerinin kendi servomuzla uyuşuyor olmasıdır.

Çalışmamızdan bazı resimler:
resim1_1

vsnetproteus


EK NOTLAR:
14 Mayıs, 2010
Büyük servo sürerken servo harekete geçerken devrenin kaynağına bir anda yüklendiğinden mikro devresi(bizde PICli devre) reset atabiliyor. Buna karşı alacağımız ilk önlem PIC in besleme uçlarına büyükçe bir kapasite bağlamak. Bu da her zaman çözüm olmayabiliyor, servo sürücü ile PIC kaynağı nın izole edilmesi konusu zamanında denemediğim bir çalışma. Duruma göre farklı önlemler almak gerekebilir.

Çalışmayla ilgili tüm dosyalar:
Proteus(7.1 SP4) Simülasyon, servo3.c, servo3.hex
C# Proje Klasörü

43 thoughts on “Hobi Servo Sürelim (Bilgisayar Kontrollü)

  1. ahmet

    Selam.ben devreyi butonla kontrol edecem bilgisayarla değil.Devreyi yaptım servoya pals gidiyo ama servo dönmüyo.birde çalışınca sürekli titreme yapıyo.Elimle pals ucuna değince normal dönüyo.Yardım edin…

    Reply
  2. admin

    Ahmet servoyu hangi PIC in hangi piniyle sürüyorsun? Bu bilgilerle sana yardım edebilmemiz biraz zor. İyi çalışmalar.

    Reply
  3. aytac

    selamlar… ben bu uygulamada birşey sormak istiyorum. öncelikle ben pic16f877 kullanmak istiyorum. RS232 ile bilgisayar bağlantısında araya max 232 entegre kullanmamız gerekirmi? direk bilgisayara bağlama, gerilim farklılıkları sorunu yaratırmı?

    Reply
  4. admin

    http://antrak.org.tr/index.php?option=com_content&task=view&id=1192 adresinde seviye dönüştürücü kullanmaksızın 22k direnci üzerinden seri porttan PIC e direkt bağlantı yapılmış. Ancak yazının sonunda riskli bir uygulama olduğu notu da düşülmüş. Seriport ile PIC arasında gerilim seviyeleri açısından çok fark var, dolayısıyla max232 gibi bu iş için tasarlanmış bir seviye dönüştürücü kullanmamız daha uygun olacaktır.

    Reply
  5. kenan

    Dostum kralsın valla kitaplarda vay efendim pwm miş timermış onlarla bi sürü hesaplamaymış en iyi çözüm en basit olanıdır tebrik ederim. Saygılarla…

    Ben de delaylerle oynamayı düşünmüştüm senin gibi ama baya bi düşünmem gerekiyomuş paylaşım için teşekkürler çok iş görecek bu

    Reply
  6. Kenan

    En üstteki resimde rc servonun yanına 1 ytl bozuk para koyman dikkatimi çekti yabancı sitelerde dolarşırken onlarda da cent ya da peny görüyordum. Hoşuma gitti. Teşekkürler.

    Reply
  7. rıdvan

    ben 16f84 kullanarak buton ile kontrol etmek istiyorum nasıl yapabilirim. aslında rs232 ile de kontrol etmek istiyorum da onu yetiştiremeyebilirim. bitirme projem için lazım acil yardımcı olursanız sevinirim.

    Reply
  8. aydın

    öncelikle yaptıgınız örnek harika C# için harika bır örnek benim şöyle bir sorunum var usb ile bilgisayarın iletişimini bilgisyayardan görmek istiyorum acaba böyle direk bir elektronik devre varmıdır acaba yoksa nasıl bu devreyı oluşturablırıım şimdiden yardımlarınız için çok teşekküreler…

    Reply
  9. Ramazan ERYILDIZ

    Dostum eline koluna sağlık çok güzel bir anlatım. Ben bir öğretmenim ve bunu iznin olursa bu şekilde öğrencilerime anlatmak istiyorum. Tabii ki senin isminle.. Teşekkürler

    Reply
  10. elf

    cok gusel bır uygulama paylaşım için çok teşekkurler…Ancak benım yapacagım uygulamada virtual thermınalden c# da kı program kontrolu ıslemı yapmak ıstıyorum. c # da kı yapılmıs arabanın kontrolu acaba nasıl bır yol ızlemelıyım yardımcı olabılırmısınız??

    Reply
  11. can

    iyi güzel ama bu zamanları ben ayarlayamadım. yani ne yaparsam yapayım ya +90 ya-90 a döndü servoalar pratikte yapmöadım fakat proteusda denedim sadece lütfen yardım eder misiniz kod;

    #include
    #use delay (clock=10000000)
    long x, y;
    main()
    {
    x=10;
    y=30;
    while (1)
    {
    output_high(pin_b0);
    delay_us(600);
    output_low(pin_b0);
    delay_us(2000-600);
    }

    Reply
  12. Burak

    Merhaba,
    Kardsm on numara bi sunum ben pic basic pro ile pic assembly kullanıyorum ona rağmen cok kolay şekilde adapte edilecek boyutta vermıssın Allah razı olsun
    iyi çalışmalar kolay gelsin

    Reply
  13. okan

    selamlar,
    bu örnekte com port zarar görme olasılığı nedir?
    birde sitede vermiş olduğunuz kodlar ccs pic kodları mıdır?
    3 servoyu kontrol etmek için kullandığınız f628 a da sol taraftaki bağlantılarda eksiklik mi var ben bir proje hazırlıyorumda bilgisayar programcılığı okuyorum elektronik ve devrelerden pek fazla anlamam yardımcı olabilirmisiniz. Kolay gelsin.

    Reply
  14. admin

    Merhaba, comport un zarar görmesi için bir sebep yok, evet CCS C kodları, devre şemasına çok sade olmasından dolayı gerek görülmedi.

    Reply
  15. OKAN

    iyi akşamlar,
    isis te çalıştırdığımızda tek tur dönme işlemi yapan servolar c# ile yazılan yazılıma istediğimiz gibi aynı hex koduyla birini sağ diğerini sol vb şeklinde döndürme yapabilir miyiz acaba.
    az önceki sorumda eğer 6,7,8,9,10,18 harici olan pin uçlarına bi takım bağlantılar gerekiyorsa
    bunlar neler olmalı ve nasıl bi şekilde bağlanmalı.açıklayabilirmisiniz. Gerçekten bu konularda yeniyim ve hiç bir eğitim almadım ancak bilgisayar bölümü olarak bu tip bir projem var
    sizin yaptığınız servo.c kodunu internette bulduğum ccs c e kitabı ile anlamaya çalışıyorum.
    Başınızı ağrıttığım için de özür dilerim
    iyi akşamlar ve iyi çalışmalar

    Reply
  16. admin

    Diğer pinlere bağlantı gerekmiyor, hangi pinlerin kullanıldığı programdan da takip edilebilir. Birini sağa diğerini sola döndürebilirsiniz, motorlar birbirlerinden bağımsız ve uyguladığınız darbe genişliğine göre belirli bir açıya gidiyorlar. İyi çalışmalar.

    Reply
  17. sezgin

    merhaba,
    yaptığınız bu çalışmada servolar enerjisini 6 v gerilim kaynagından alıyorlar anladığım kadarıyla pic servoya ne kadar sure akım cekmesi gerektiğini bildiriyor, peki pic burda nekadar volt enerji kullanıyor
    ve bişey daha yorumlara cevabınızın birinde max 232 kullanmayı önermişsiniz aynı durumun bu uygulamadada zorunlulugu var mı.
    paylaşım için teşekkur ederim,iyi çalışmalar.

    Reply
  18. admin

    Ben servoları ve PIC i 5V ile beslemiştim. Bilgisayardan komut göndermek için en kolay yol olarak seri port kullanıyoruz ancak seri portun voltaj seviyesi(-10V, 10V) PICe(0V, 5V) uygun değil dolayısıyla araya uyumu sağlamak için max232 seri port buffer devresi koyuyoruz.

    Reply
  19. sezgin

    merhaba,
    proteus cızımını verdiğiniz uygulamada illaki max232 kullanmak zorunluluğu varmı yoksa diger kristal vb elemanlarla da bunu saglayabilirmiyiz,devrede 6v yerine 5v kullanmamız şartmı
    iyi çalışmalar hayırlı akşamlar.

    Reply
  20. admin

    6V yerine 5V şart değil, 6V PIC için bozulma sınırı(asıl değer için datasheet e bakılabilir), ben hem PIC i hem de motoru aynı kaynaktan beslediğim için besleme gerlimini 5V seçmiştim. max232, bilgisayarla PIC in haberleşmesi için kullanılır, max232 yerine ayrık devre elemanlarıyla bir devre düşünülebilir ancak risk almaya gerek yoktur max232 bu iş için uygun ve kolay çözümdür.

    Reply
  21. Metin

    Usta konuyu paylaşalı çok olmuş ama sana teşekkürü kendi adıma borç bilirim 🙂 Kendim bişeyler karalamaya çalıştım, porta veri atıyodum ama pic veriyi almıyodu sayende istediğimi yapıcam. Çok teşekkür ederim. 🙂

    Reply
  22. Pingback: PIC ile Hobi Servo Sürme (CCS kodlama) « Alıntım

  23. Pingback: PIC ile Hobi Servo Sürme (CCS kodlama) | Alıntım

  24. Birolun

    Anlatım için teşekkürler. Ben servoyu devreye bağlıyorum ve enerjiyi verdiğim anda ufak bir açı ile kendi kendine dönüyor enerjiyi kestiğimde ise eski haline geri geliyor. Neden acaba?

    Reply
  25. Birolun

    Bende orayı anlayamadım. Enerji verdiğimde yaklaşık 15 derece dönüyor. Enerjiyi tam kestiğimde de 15 derece tekrar dönerek eski haline geliyor.

    Reply
    1. ferdem

      Devrenizde kapasiteler varsa servo kapasitelerdeki enerji ile son hareket yapabilir, kontrol sinyali(PWM) kesilip besleme gerilimi aynı anda kesilmezse böyle bir durum oluşabilir, enerjiyi çektiğinizde bu durum anlık oluşuyor diye düşünüyorum.

      Reply
  26. DURSUN

    öncelikle pproje çok güzel görünüyor
    bu devreyi kuran ve çalıştıran var mı
    bu devre bilgisayardan uzaktan mı yoksa kablo ile mi iletişim kurulmuş durumda servo hareketleri için
    lütfen yardım

    Reply
  27. dursun

    ya çalıştıramadım bir türlü bu devreyi
    kafayı yıyeceğim
    bu projeyi bilgisayardan proteus ve c# ile nasıl kontrol edebilirim yardım cı olabilecek olan var mı

    Reply
  28. dursun

    çok güzel bir proje çalıştırdım sonunda
    çok basit anlatımı sayesinde kolay anlaşılabiliyor
    ben 6 servo hareket ettirmek istiyorum bu devre bunu destekler mi
    16f877 ile bunu yapabilir miyim
    çoğu sitede seri port bağlantılarında f4550 pic i kullanılmış
    hangisini önerirsiniz

    Reply
  29. ferdem

    Motor sayısı arttıkça Delay fonksiyonuyla işlem yapmak zorlaşır, Timer ları kullanarak yapmak daha doğru olur. 20MHz de çalıştırılan 16F877 yeterli olur.

    Reply
  30. dursun

    sizin yaptığınız devreye servoları ilave ettiim c kodunu düzenledim çalıştırdım
    proteusda sıkıntı çıkmadı
    c# arayüzünde de 6 servoya göre ekleme ve düzenleme yaptım fakat c# da son eklediğim tarckbarları hareket ettirdiğimde ne bir hata ne bir değişme ne de artışını gösteren labelindeki 0 değeri değişiyor
    gözden kaçırdığım bir yer mi var uygulamada acaba

    Reply
  31. ferdem

    Hocam konu C# ile ilgili, C# ta form elemanları nasıl kullanılır, trackbar nasıl kullanılır konularına çalışmalısınız. Sadece trackbar ekleyerek servo sayısını arttıramazsınız, o trackbarların değiştirilmesiyle arkada tetiklenen fonksiyonlar var. O fonksiyonlar hem labler leri değiştirir, hem seri porttan veri gönderilmesini sağlar…
    İyi çalışmalar.

    Reply
  32. nida

    merhaba ben 80286 da potansiyometre kontrolüyle aldığım pwm değeriyle servo motoru sürdürmeye çalışıyorum. assembly kullanmak zorundayım ve dediğiniz gibi lojik1 verip 1ms geciktiryor, lojik0 verip 19ms gecikme sağlıyorum. tabi bunu pwmden gelen değere göre toplam 20ms periyod olacak şekilde ayarlıyorum ancak motorumu sürdüremedim. rica ederim bana yardımcı olurmusunuz.

    Reply

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir