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:

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

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.

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:
1
2
3
4
5
6
| 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:
1
2
3
4
5
6
7
| 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| 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:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
| 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ıza vs.net bağlanamayacak.
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:


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