Bu dersimizde Servo motor kontrolünü inceleyecek ve bazı örnekler vererek konuyu anlamaya çalışacağız. Servo kelimesi daha ziyade pozisyon kontrolünün yapıldığı yada gerekli olduğu yerlerde kullanılan motorlar için motor aksamına ilave edilmiş muhtelif aksamları ifade etmektedir.
Muhtelif aksamlar kapsamına potansiyometre, encoder , switch yada manyetik switch ler gibi pozisyon bulmayı kolaylaştıran malzemeler girmektedir.
Genelde servo motorlar endüstriyel servo motorlar ve oyuncak yada modellerde kullanılan servo motorlar diye ikiye ayrılmaktadır. Öncelikle model uçak ve benzeri aletlerde kullanılan servoları inceleyecek daha sonra da diğer servolara göz atacağız.
Model servoları genelde belirli aralıklar motora yollanan puls lar ile çalışırlar. Pals genişliği motorun alacağı pozisyonu belirler.
Genellikle motora her 20 ms de bir puls gönderilmelidir. Bu , pek çok motor üreticisinin kullandığı puls sıklığı süresidir. Yine üreticiden üreticiye fark eden puls genişliği de motorun alacağı konumu belirler. Bir örnekle açıklamak en doğrusu olacak sanırım.
Elimizde bir servo motor olduğunu düşünün. Normalde motor miline bir disk taktığımızı ve üzerinede bir ok işareti yaptığımızı farz edelim. Okun yönü yatay olarak sağ tarafı gösteriyor olsun.
Bu şekilde motor mil yönü sağ yatayda.
Şimdi bu motora 1,50 ms süre ile bir HIGH palsi uygulayalım ve her 20 ms de bir bu sinyali tekrarlayalım. Motor hemen hareket alacak ve okun yönü 90 derece dik konuma gelecektir.
Sinyalin tekrarlanması motor pozisyonunda bir değişiklik yapmayacaktır. Aynı motora bu seferde 1,25 ms lik bir puls uygular isek bu seferde motor mili -90 derecelik konuma gelecek ve okun yönü sol tarafı gösterecektir.
Yine motora bu seferde 1,75 ms lik bir puls uygular isek, Motor yeniden başlangıç konumuna gelecektir.
Görüldüğü üzere verilen palsin süresi motor milinin konumunu değiştirmektedir. Şimdi bu işi Pic kullanarak yapmaya çalışalım.
Pic kullanarak bu işi yapmanın değişik yolları var tabiiki. Öncelikle en kolay olanı tatbik etmeye çalışacağız. Diyelimki 3adet servo motorumuz var ve bunları birer potansiyometre ile kontrol etmek istiyoruz.
Potansiyometrenin konumuna göre motorlarımızda konum değiştirecektir. Pot değeri okunacağı için ADC si olan bir pic kullanacağız. Bu da en popüler olanlardan bir tanesi olan 16F877 olsun. Önce programımızı verelim sonra açıklamasına geçelim
‘**************************************************************** ‘* Name : SERVO_ORNEK.BAS * ‘* Author : ETE-EROLEC-ERO] * ‘* Notice : Copyright (c) 2007 [E.T.E] * ‘* : All Rights Reserved * ‘* Date : 24.11.2007 * ‘* Version : 1.0 * ‘* Notes : * ‘* : * ‘**************************************************************** PORTA=0:TRISA=%00000111 PORTB=0:TRISB=%00000000 PORTC=0:TRISC=%00000000 PORTD=0:TRISD=%00000000 PORTE=0:TRISE=%00000000 ADCON1 = %00000010 ‘—————————————————————– @ DEVICE PIC16F877, WDT_OFF ‘Watch Dog timer kapalı @ DEVICE PIC16F877, PWRT_ON ‘Power on timer açık @ DEVICE PIC16F877, PROTECT_OFF ‘Kod Koruma kapalı @ DEVICE PIC16F877, BOD_ON @ DEVICE PIC16F877, XT_OSC ‘—————————————————————– DEFINE LCD_DREG PORTB DEFINE LCD_DBIT 0 DEFINE LCD_RSREG PORTB DEFINE LCD_RSBIT 5 DEFINE LCD_EREG PORTB DEFINE LCD_EBIT 4 DEFINE LCD_COMMANDUS 2000 DEFINE LCD_DATAUS 50 Define ADC_BITS 8 Define ADC_CLOCK 3 Define ADC_SAMPLEUS 50 HAMA var byte HAMB VAR BYTE HAMC VAR BYTE SUREA VAR BYTE SUREB VAR BYTE SUREC VAR BYTE SURE VAR WORD pause 250 lcdout $FE,1,” SER1 SER2 SER3″ BASLA: lcdout $FE,$C2,dec3 SUREA,” “,dec3 SUREB,” “,dec3 SUREC PORTC = 0 pulsout PORTC.0,SUREA pulsout PORTC.1, SUREB pulsout PORTC.2, SUREC SURE = (SUREA + SUREB + SUREC)*10 SURE = 12000 – SURE ‘ASLINDA 20.000 DEN ÇIKARMAK GEREK AMA KOMUT GECİKMELERİ NEDENİ İLE 12000 alıyoruz. pauseus SURE Adcin 0, HAMA :SUREA=(HAMA+1)*/200 Adcin 1, HAMB :SUREB=(HAMB+1)*/200 Adcin 2, HAMC :SUREC=(HAMC+1)*/200 goto BASLA end
Programın açıklamasına gelince; Öncelikle ADC okuma çözünürlüğünü 8 bit olarak ayarladığımız belirtelim bu şimdilik bizim için yeterli olacak.
Program BASLA satırından hemen sonra mevcut PULS sürelerini ekrana vermektedir. Kullandığımız motorlar, Protesu kütüphanesinde bulunan servo motorlar olup maksimum puls süreleri 2 ms olarak verilmiştir. Dolayısıyla program her 20 ms de bir pot ların pozisyonuna göre 0-2 ms (yada 0-2000us) arası pals verecek şekilde düzenlenmiştir.
Önemli komutları teker teker inceler isek; pulsout PORTC.0,SUREA komutu SUREA ile belirlenmiş süre kadar PORTC.0 dan puls çıkarır. Burada SUREA değişkeninde tutulan süre , 4 Mhz kristal kullanan devrede 10 us nin katları şeklinde dir. Yani SUREA=20 ise pul süresi 10×20=200 us olacaktır.
Üç çıkış için harcanan komut sürelerini toplayarak SURE isimli değişkende tutacağız. Bu toplanan değerler toplam puls süresinin 10′a bölünmüş hali olduğu için bu süreyi birde 10 ile çarpıyoruz.
Amacımız her 20.000 us de bir istenen pulsları çıkarmak olduğuna göre pulsout komutlarından sonra vermemiz gereken gecikme süresi 20.000-SURE şeklinde hesaplanması gerekir idi.
Ancak kullandığımız diğer komutların (ADC okumaları , Ekran gösterimleri ve pulsout komutlarının kendileri de biraz süre aldıklarından dolayı yaklaşık 8.000 us lik bir süre kaybı olmaktadır. Bu nedenle gerçek bekleme süresini 12.000-SURE eşitliği ile hesaplıyoruz.
Sonuçta PAUSEUS SURE komutu ile iki puls arasındaki gecikmeyi yaratıyor ve sonra ADC okumalarına geçiyoruz.
Sonuçta devreyi simule edersek karşımıza çıkan SKOP ekranında pulslar arasındaki mesafenin 20 ms olduğunu kolaylıkla görmek mümkün olabilmektedir.
ADC den okunan pot değerleri 0-255 arasında olacaktır. Bizim için gerekli olan maksimum puls süresi 2000 us olmasına rağmen Pulsout komutunda bu süreyi 2000/10 =200 olarak kullanmaktayız. Bu nedenle bize lazım olan değeri 200 kabul edeceğiz.
Böylece ADC ham değeri 255 olduğu zaman puls süresi değerimiz 200 , ADC değeri 0 çıktığı zamanda puls süresi değerimiz 0 çıkmalıdır. Bunu hesaplamanın yolu ise 200/256 eşitliğinden geçmektedir. Yani 200 birim için okunan değer (255+1) olacak olup bir birim okumanın karşılığı ise 0,78125 olacaktır. Sonuçta 32 bit çarpma yapacağımız ve sayının 256 ya bölünmüş halini bulacağımız için 0,78125 x 256 = 200 değeri bizim kullanacağımız değer olacaktır.
Böylece okunan ham değere 1 ekleyip bunu 200 ile çarpar ve 256 ya bölersek bize puls süresini verecektir. Bu işi ise */ komutu otomatik olarak yapmaktadır.
Böylece SUREA= (HamA+1)*/200 şeklindeki komut otomatik olarak pulsout komutunda kullanacağımız puls süresini bize verecektir.
İkinci örneğimizi TMR0 kesmesi kullanarak yapacağız. Öncelikle her 20 ms de bir kesme oluşturmamız gerekecek. Bu örneğimizde önce tek servo motor sürmeye çalışacak ikiniciyi sisteme ilave edeceğiz. Böylece birden fazla servonun bu yöntemle nasıl sürüleceğini görmüş olacaksınız.
Önce biraz teorik bilgi. TMR0 kesmesini her 20 ms de bir kesme oluşturacak şekilde kurabilmemiz için gerekli parametreler neler onları bulalım.
4 Mhz lik osilatör frekansında her bir komut çevrimi 1us idi. Bize her 20.000 us de bir kesme lazım olduğuna göre bir kere bölücü kullanmamız gerekecek.
Kesme süremiz 20.000 us bunu 256 ya bölersek . 78 sayısını elde ederiz. Bu sayıcının sayması gereken süre olduğu için TMR0 değeri 256-78=178 olarak bulunur. Bu durumda toplam süre; 78 x 256=19968 + 7us (komut gecikmesi)=19975 olarak bulunur.
Şimdi de bölücü olarak 1/128 kullanacağımızı varsayalım ve hesap yapalım. 20000/128=156 toplam süre, 156 x 128 = 19968 + 7us = 19975 olarak aynı değeri buluruz. O halde TMR0 ‘a vereceğimiz ön değer , 256-156 = 100 olacaktır. Komut gecikmeleri nedeni ile TMR0 değeri 110 olarak alınacaktır.
Şimdi programımıza geçelim.
‘**************************************************************** ‘* Name : SERVO_2.BAS * ‘* Author : ETE-EROLEC-ERO] * ‘* Notice : Copyright (c) 2007 [E.T.E] * ‘* : All Rights Reserved * ‘* Date : 02.05.2009 * ‘* Version : 1.0 * ‘* Notes : * ‘* : * ‘**************************************************************** PORTA=0:portb=0 TRISB=%00000011 ‘PortB tamamı çıkış yapıldı. TRISA=%00000000 ‘A portu tamamı çıkış yapıldı. ‘—————————————————————– @ DEVICE pic16F628 ‘işlemci 16F628 @ DEVICE pic16F628, WDT_OFF ‘Watch Dog timer kapalı @ DEVICE pic16F628, PWRT_ON ‘Power on timer açık @ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı @ DEVICE pic16F628, MCLR_off ‘MCLR pini kullanılıyor. @ DEVICE pic16F628, INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak ‘—————————————————————– DEFINE LCD_DREG PORTB ‘LCD data bacakları hangi porta bağlı? DEFINE LCD_DBIT 4 ‘LCD data bacakları hangi bitten başlıyor? DEFINE LCD_EREG PORTB ‘LCD Enable Bacağı Hangi Porta bağlı? DEFINE LCD_EBIT 3 ‘LCD Enable Bacağı Hangi bite bağlı ? DEFINE LCD_RSREG PORTB ‘LCD RS Bacağı Hangi Porta bağlı ? DEFINE LCD_RSBIT 2 ‘LCD RS bacağı Hangi Bite bağlı ? DEFINE LCD_BITS 4 ‘LCD 4 bit mi yoksa 8 bit olarak bağlı? DEFINE LCD_LINES 2 ‘LCD Kaç sıra yazabiliyor ‘————————————————————————- ON INTERRUPT GoTo KESME ‘kesme oluşursa KESME adlı etikete git. OPTION_REG=%00000110 ‘Pull up dirençleri AÇIK- Bölme oranı 1/128. INTCON=%00100000 ‘Kesmeler aktif ve TMR0 kesmesi aktif TMR0=110 CMCON=7 ‘16F628 de komparatör pinleri iptal hepsi giriş çıkış ‘—————————————————————————- SUREA VAR WORD I VAR WORD SYMBOL ARTIR=PORTB.0 SYMBOL AZALT=PORTB.1 SYMBOL MOTORA=PORTA.0 ‘—————————————————————————– CLEAR ‘tüm değişkenler sıfırlandı LCDOUT $FE,1 PAUSE 200 lcdout $FE,1,” SER1 ” INTCON.7=1 ‘—————————————————————————– BASLA: lcdout $FE,$C2,dec4 SUREA,” “ IF ARTIR=0 THEN IF SUREA<2000 THEN SUREA=SUREA+10 GOSUB DELAY ENDIF IF AZALT=0 THEN IF SUREA >10 THEN SUREA=SUREA-10 GOSUB DELAY ENDIF GOTO BASLA DELAY: FOR I=0 TO 2000 PAUSEUS 5 NEXT RETURN DISABLE KESME: TMR0=110 MOTORA=1 PAUSEUS SUREA MOTORA=0 INTCON.2=0 ‘TMR0 Kesme bayrağı sıfırlanıyor RESUME ENABLE END
Programın açıklaması olarak yalnızca Kesme kısmında neler yaptığımızı açıklayacağız. Kesme oluşur oluşmaz TMR0′a ön yükleme değerini veriyoruz o bir taraftan saymaya devam ediyor. Motora high sinyalini veriyoruz ve ayarlanan süre kadar bekleyip sinyali low a çevirip kesmeden çıkıyoruz. Sisteme başka servolar ilave edilebilir.
Kesme oluştuğu zaman bütün servolara High sinyali verilmeli ve süresi en kısa olan dan başlayarak puls süreleri verilmeli ve sonra sırası ile motorların sinyalleri Low a dönüştürülerek kesmeden çıkılmalıdır.
Biraz da diğer servolara bakmakta yarar var.
ENCODER KONTROLLU SERVO
Endüstriyel servolarda motor miline bağlı encoder yada potansiyometre bulunmaktadır. Encoder li tiplerde referans noktası yada başlangıç noktasında encoder değeri sıfır alınarak sağa dönüş de encoder den gelen palslar sayılarak uygun değerde motorun durdurulması veya dönen motorda uygun pozisyon yakalandıktan sonra motorun durdurulması sağlanabilir. Aynı işlem tabiiki diğer yönde de yapılabilir.
Şimdi bu örneğimize ait programımızı verelim. Programla yapacağımız işlemde sağa dönüş butonuna her basışta motorun 50 puls lık bir dönüş yapıp durması sağlanacaktır. Aynı şekilde sola dönüş butonunada her basışta motorumuz bu sefer ters yöne 50 pulslık bir dönüş yapıp duracaktır.
İşte Programımız ve devre şeması.
‘**************************************************************** ‘* Name : servo3.BAS * ‘* Author : [Erol Tahir Erdal] * ‘* Notice : Copyright (c) 2005 [ETE] * ‘* : All Rights Reserved * ‘* Date : 02.05.2009 * ‘* Version : 1.0 * ‘* Notes : * ‘* : * ‘**************************************************************** PORTA=0:portb=0 TRISB=%00000011 ‘PortB tamamı çıkış yapıldı. TRISA=%00000011 ‘A portu tamamı çıkış yapıldı. ‘—————————————————————– @ DEVICE pic16F628 ‘işlemci 16F628 @ DEVICE pic16F628, WDT_OFF ‘Watch Dog timer kapalı @ DEVICE pic16F628, PWRT_ON ‘Power on timer açık @ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı @ DEVICE pic16F628, MCLR_off ‘MCLR pini kullanılıyor. @ DEVICE pic16F628, INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak ‘—————————————————————– DEFINE LCD_DREG PORTB ‘LCD data bacakları hangi porta bağlı? DEFINE LCD_DBIT 4 ‘LCD data bacakları hangi bitten başlıyor? DEFINE LCD_EREG PORTB ‘LCD Enable Bacağı Hangi Porta bağlı? DEFINE LCD_EBIT 3 ‘LCD Enable Bacağı Hangi bite bağlı ? DEFINE LCD_RSREG PORTB ‘LCD RS Bacağı Hangi Porta bağlı ? DEFINE LCD_RSBIT 2 ‘LCD RS bacağı Hangi Bite bağlı ? DEFINE LCD_BITS 4 ‘LCD 4 bit mi yoksa 8 bit olarak bağlı? DEFINE LCD_LINES 2 ‘LCD Kaç sıra yazabiliyor ‘————————————————————————- OPTION_REG=%00000000 ‘Pull up dirençleri AÇIK- CMCON=7 ‘16F628 de komparatör pinleri iptal hepsi giriş çıkış ‘—————————————————————————- SAYI VAR WORD NEW var byte OLD VAR BYTE YON var bit SYMBOL ARTIR=PORTB.0 SYMBOL AZALT=PORTB.1 ‘—————————————————————————– CLEAR ‘tüm değişkenler sıfırlandı LCDOUT $FE,1 PAUSE 200 ‘—————————————————————————– BASLA: gosub ekran IF ARTIR=0 THEN SAG IF AZALT=0 THEN SOL GOTO BASLA SAG: SAYI=0:YON=1 ‘encoder bilgisi sıfırlandı porta.2=1 ‘motor sağ a dönecek şekilde harekete geçti GOSUB ENC GOTO BASLA SOL: SAYI=0:YON=0 PORTA.3=1 ‘motor sola dönecek şekilde çalışmaya başladı GOSUB ENC GOTO BASLA EKRAN: IF YON=1 then LCDOUT $fE,$02,”MOTOR YONU : SAG” ELSE LCDOUT $fE,$02,”MOTOR YONU : SOL” endif lcdout $FE,$C0,”PULS SAYISI:”,dec3 SAYI,” ” return ENC: NEW=PORTA & %00000011 ‘ilk encoder bilgisini al IF NEW=OLD THEN ENC ‘bir önceki ile kaşılaştır aynı ise yeniden al GOSUB EKRAN ‘aynı değil demekki encoder dönmüş OLD=NEW ’son okunanı eskiye eşitle SAYI=SAYI+1 ’sayı değerini bir artır. IF SAYI=50 THEN ‘50 değerini bulmuş ise PORTA.2=0 ‘hem sağ motoru hemde PORTA.3=0 ’sol motoru durdur. RETURN endif GOTO ENC END
Bu programda motorun dönüş yönü butonlar ile sağlandığı için encoder ile bir yön tayini yapılmamıştır. Gerekirse encoder ile de yön tayini kolaylıkla yapılabilir. Şema dan da görüleceği gibi encoder den gelen A ve B girişlerini kullandık. Bu iki giriş bir birinden yarım faz farkı olan iki sinyal üretirler.
Yukarıdan aşağı doğru çizdiğimiz kesikli çizgiler encoderin okuma noktalarını gösteriyor. Bu noktalarda soldan sağa doğru gidişte (diyelimki motor sağ a dönüyor olsun) okunacak bilgi çiftleri şöyle olacaktır; 00 10 11 01 00
Bu seferde motor sağdan sola yani sola dönerken aynı bilgilere bir göz atalım. 00 01 11 10 00 şeklinde olacaklardır.
Yön tayini ilk okumanın (OLD) A. biti ile son okumanın (NEW) B biti nin XOR yapılması ile bulunur. Önce motor sağa dönerken duruma bakalım.
Old=00 ve NEW= 10 olacaktır. (Old.0) XOR (NEW.1)= bize 0 XOR 1 şeklinde bir eşitlik verecek ve sonucu 0 olacaktır.
Şimdi de motor sola dönerken olan duruma bakalım. OLD=00 , NEW=01 Old.0 XOR New.1=0 XOR 0 şeklinde bir eşitlik verecek ve sonucu 1 olacaktır. (0 XOR 0)=1 , (1 XOR 1)=1 (1 XOR 0)=0 (0 XOR 1)=0 dır.
Gördüğünüz gibi bir yönde dönüşlerde ilgili bitler XOR yapılırsa yön biti daima aynı değeri alıyor. Sola dönüşte 0 , sağa dönüşte ise 1 olmaktadır. Tabiiki dönüş yönüne göre bitleri biz tayin ettik bu geröekte terside olabilir. Yani sola dönüşte yön biti 0 sağa dönüşte yön biti ise 1 olabilir.
Bu programda ve verdiğimiz kısa bilgide bir encoder okuma konusundaki bilgiyide vermiş olduk. Bir şey daha ekleyebiliriz. Yön bilgisine bağlı olarak saydırma sisteminde;
Yon=0 ise SAYI=SAYI+1
Yon=1 ise SAYI=SAYI-1
eşitlikleri kullanılabileceği gibi yönün şekline göre terside kullanılabilir. Yani 0 iken eksiltir 1 iken artırablirsinizde. Tabiiki limitleri daima kontrol etmelisiniz. Word cinsinden tayin edilmiş bir SAYI değişkeni 65535 den sonra otomatik olarak sıfır değerini alacaktır. Sizinde bu değerden önce limitleriniz olmalı ve sayma esnasında bu limitlere bakmalısınız.
POT KONTROLLU SERVO:
Piyasada bulunabilecek bir başka Servo modeli de DC yada AC motor miline akuple edilmiş bir Potansiyometresi bulunan motorlardır. Genellikle Damper kontrolünde kullanılan bu tip motorlarda pozisyon genelde 90 deredir. Ancak 180 derecede olabilir. İşin temelinde o derece konumunda potansiyometrenin de sıfır konumunda bulunması ve motor döndükçe motor mili ile birlikte potansiyometreninde dönerek belli değerlere ulaşması sağlanmaktadır.
Kontrol mekanizmasında potansiyometre orta ucu bir ADC çeviriciye girilerek pot değeri digitize edilir ve istenen değerle karşılaştırılarak motorun akımı kesilir. Böylece motor istenen pozisyonlarda durdurulmuş olur.
Bu konuda da bir örnek yapacağız. Ancak bu tip motoru direk simule edemeyeceğimiz için sistemde pot ve motor ayrı ayrı gözükecektir. Aslında pot ve motor mili birlikte hareket ediyor olacaklardır.
İşin prensibini biraz daha açıklamakta yarar var. 0 derece konumunda motor sıfır derece de, pot verisi ise sıfır olacaktır. Bu durumda motoru 90 derecelik bir konuma getirdiğimizde POT da orta konuma gelecek ve veri değeri 512 olacaktır (10 bitlik ADC) . Burada bazı motorlarda potansiyometrenin bir dişli düzeneği ile döndürüldüğünü hatırlatmak isterim.
Motor mili 180 derece dönünce pot 270 derece dönerek son noktasına gelmektedir. Bu durumda elinizdeki motora göre hareket etmenizi önermekten başka söyleyecek bir şeyim olamaz. Biz motor mili ile pot’un birlikte hareket ettiklerini varsayacağız. Motor milini 512 pot verisi konumunda bıraktığımızı ve sistemi kapatıp yeniden açtığımızı farz edelim. Bu durumda hemen pot okunacak ve motorun konumu hakkında hemen bilgi alınacaktır. Bu durumda motora sıfır konumuna git şeklinde bir emir verirsek neler olacak ona bir bakalım.
0 konumu 512 konumundan küçük olduğu için motor ters tarafa dönmelidir. O halde motora geri dön emri verilecek ve pot değerinin sıfır değerine ulaştığı nokta gözlenerek motor durdurulacaktır.
Aynı şekilde 512 konumunda bekleyen motora 1023 konumuna (maksimum pozisyonu) git emri verilirse ne olur onada bir bakalım;
1024 konumu motorun bulunduğu 512 konumundan daha büyük olduğu için motor ileri dönecektir.
Motora ileri dön komutu verilecek ve 1024 pozisyonuna gelip gelmediği gözlenerek motor durdurulacaktır.
Yukarıda bahsini ettiğimiz sistemi simulasyonda 2 adet pot ile çalıştıracağız. Birinci pot Konumlandırma Pot’u olarak çalışacak ve motorun pozisyonu bu pot ile ayarlanacaktır.
Diğer pot ise Motor miline bağlı olan konum potu olacak ve motor mili ile birlikte dönecek olan pot dur. Simulsayonda bu potun motor mili ile birlikte döndüğü kabul edilecek ve manuel olarak ayarlanarak diğer pot ile aynı konuma getirildiğinde motorun durduğu gözlemlenecektir.
Esas olan iki potun da aynı konuma gelmiş olmalarıdır. Bu nedenle önce konumlandırma potu bir yere ayarlanmalı motor çalışmaya başladıktan sonra yavaş yavaş motor mili potu aynı yere getirilmelidir. Bu aşamda motorun durduğu gözlemlenmelidir.
Şimdi bahsini ettiğimiz sisteme ait örnek programımızı ve devre şemasını verelim.
‘**************************************************************** ‘* Name : Servo_Pot.BAS * ‘* Author : [ E.T.E. ] * ‘* Notice : Copyright (c) 2008 İzinsiz kullanılamaz ) * ‘* : All Rights Reserved * ‘* Date : 02.05.2009 * ‘* Version : 1.0 * ‘* Notes : * ‘* : * ‘**************************************************************** @ DEVICE pic12F675 ‘işlemci 12F675 @ DEVICE pic12F675, WDT_ON ‘Watch Dog timer açık @ DEVICE pic12F675, PWRT_ON ‘Power on timer açık @ DEVICE pic12F675, PROTECT_OFF ‘Kod Koruma kapalı @ DEVICE pic12F675, MCLR_off ‘MCLR pini kullanılMIYOR. @ DEVICE pic12F675, INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak DEFINE OSCCAL_1K 1 ‘bu komut mutlaka olacak OSCCAL değerini yeniden pice yazdırıyor DEFINE OSC 4 DEFINE ADC_BITS 10 ‘ ADCIN resolution (Bits) DEFINE ADC_SAMPLEUS 10 ‘ ADC sampling time (uSec) CMCON = 7 ANSEL = %00010011 ADCON0=%10000000 GPIO=0 TRISIO=%00000011 WPU=0 ‘———————-değişkenler——————————- HAMK var word 60 HAMM VAR WORD 62 SYMBOL MOTORSAG=GPIO.4 SYMBOL MOTORSOL=GPIO.5 GOSUB ADCAL PAUSE 200 BASLA: gosub adcal WHILE HAMK>HAMM MOTORSAG=1 GOSUB ADCAL WEND WHILE HAMK MOTORSOL=1 GOSUB ADCAL WEND IF HAMK=HAMM THEN gosub fren GOTO BASLA FREN: motorsag=1 motorsol=1 PAUSE 500 MOTORSOL=0 MOTORSAG=0 RETURN ADCAL: ADCIN 0,HAMM ADCIN 1,HAMK RETURN
Servo kontrol Sistemlerine Çizgi takibi yapan robot sistemlerini de dahil edeceğiz. Onlarda bir nevi servo kontrol yapmaktadırlar. Amaçları önceden çizilmiş olan bir çizgiyi takip etmektir. Sonuçta pozisyon emri çizgi tarafından veriliyor ve sistemde bu emri yerine getirmeye çalışmaktadır.
Çizgi kontrolüne geçmeden kullanılan elemanlar hakkında biraz bilgi vermek gerekiyor.
Bu sistemlerde genelde cisimden yansılmalı fotosel gurubu kullanılmaktadır. Bir Infrared verici ledi sinyal yayınlar, verilen bu sinyal karşıda bulunan herhangi bir cisimden yansır ve geri döner. Yansıyan bu sinyaller ise bir foto transistör yada diyot tarafından alınarak yorum yapılır.
Genelde CNY70 gibi hazır sensörler kullanıldığı gibi sensör gurubunu kendinizde oluşturabilirsiniz. Bu şekide daha hassas sensörler yapmak mümkün olabilir.
Aşağıda kendinizin oluşturabileceği bir sensör gurubu şeması verilmektedir. Bu devrede çizgi ile sensörler arasındaki mesafe 15 mm kadar çıkartılabilir.
Siyah çizgi ışığı absorbe eder ve yansıtmaz. Bu nedenle sensör siyah çizgiyi görünce LM358 (yada LM741 –LM324 de olabilir) sensör çıkışı LOW, Beyaz çizgiyi görünce HIGH olacaktır.
Siyah çizgide yeşil led yanacaktır. Bu sensörden en azından 3 adet yapılacak ve araçta , sağ ve sol’a birer tane yerleştirilecek ortada ise sürekli siyah çizgiyi takip eden bir üçüncü sensör daha bulunacaktır.
Şimdi 3 lü sisteme göre olası alternatifleri inceleyelim.
-Siyah Çizgi orta sensör tarafından görülmekte dıştaki iki sensör ise beyaz alanı görmektedirler. (Çıkışlar 1 0 1) Bu durumda aracın ileri düz gitmesi beklenir. Her iki motor da açık olmalı.
– Araç hafifçe sağa döndü sol sensör siyah çizgiyi görecek, sağ ve orta sensör beyazda kalacaktır. Çıkışlar (0 1 1) Aracın hemen sola dönüp sol sensörün siyah çizgiden kurtulup orta sensörün siyah çizgiyi bulması gerekir. O halde sol motor kapalı sağ motor açık olacaktır.
– Araç hafifçe sola döndü sağ sensör siyah çizgiyi görecek sol ve orta sensör sensör beyazda kalacaktır. Çıkışlar (1 1 0), Aracın hemen sağa dönüp sağ sensörün siyah çizgiden kurtulması ve orta sensörün yeniden siyah çizgiyi görmesi gerekir. O halde sağ motor kapalı, sol motor açık olacaktır.
Olası alternatifler bunlar olup aşağıdaki program içinde bu alternatifler değerlendirilerek sistem çalıştırılacaktır.
Normal olarak bu gibi sistemlerde motor hareketleri çift yönlü olmalıdır. Bu nedenle her bir motor bir H-Köprü devresi ile sürülmelidir. Araca daha fazla manevra kabiliyeti verebilmek için gerekirse sağ ve sol motorlar birlikte hareket ettirilmelidir.
Yeri gelmiş iken H köprü devreleri konusunuda biraz açıklayalım. Genelde bir motorun 4 transistörle sürülmesi ve motorun mekanik kontak kullanılmadan ileri geri fren ve devir kontrolü yapılarak hareket ettirilmesini sağlayan bir sistemdir.
Sabit devir kontrollü sistemlerde iki tane lojik sürme girişi bulunmaktadır. Bunalrdan birisi High yapıldığı zaman motor bir yöne (diğeri Low da olmalı) tersi yapıldığı zamanda motor diğer yöne dönmektedir. Devir kontrolü gerekir ise lojik high yapılan tarafa PWM sinyali uygulanmalıdır.
Bu işler için hazır entegreler de bulunmaktadır. Bunlara örnek vermek gerekir ise L293 ve L298 piyasada bolca bulunabilen ve üzerinde 2 ayrı motor için köprü devresi bulunan entegrelerdir. Devremizde L293 kullanacağız.
‘**************************************************************** ‘* Name : ROBO01.BAS * ‘* Author : [select VIEW...EDITOR OPTIONS] * ‘* Notice : Copyright (c) 2008 [select VIEW...EDITOR OPTIONS] * ‘* : All Rights Reserved * ‘* Date : 02.05.2009 * ‘* Version : 1.0 * ‘* Notes : Çizgi izleyen Robot Araba * ‘* : * ‘**************************************************************** PORTA=0:TRISA=0 PORTB=0:TRISB=%00001111 CMCON=7 OPTION_REG.7=0 ‘PULLUP LARI BU KOMUT AÇIYOR GEREKİRSE SİLİP KAPATABİLİRSİN. SENSÖRLER İÇİNDİR. ‘—————————————————————– @ DEVICE pic16F628 ‘işlemci 16F628 @ DEVICE pic16F628, WDT_ON ‘Watch Dog timer açık @ DEVICE pic16F628, PWRT_ON ‘Power on timer açık @ DEVICE pic16F628, PROTECT_OFF ‘Kod Protek kapalı @ DEVICE pic16F628, MCLR_off ‘MCLR pini kullanılMIYOR. @ DEVICE pic16F628, INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak ‘—————————————————————– DEFINE OSC 4 ‘————————————————————————- GERI VAR BIT SYMBOL SOLSEN=PORTB.0 ‘SOL SENSOR SYMBOL ORTSEN=PORTB.1 ‘ORTA SENSOR SYMBOL SAGSEN=PORTB.2 ‘SAG SENSOR SYMBOL SAI =PORTB.5 ‘SAĞ İleri SYMBOL SAG =PORTB.4 ‘SAĞ Geri SYMBOL SAE=PORTA.0 ‘SAĞ Enable SYMBOL SOI=PORTB.6 ‘SOL İLERİ SYMBOL SOG=PORTB.7 ‘SOL GERİ SYMBOL SOE=PORTA.1 ‘SOL Enable ;***ILK HAREKET******************************************************** DUZGIT: WHILE ORTSEN=0 ‘orta sensör siyah çizgiyi görüyor ise SAI=1:SAG=0:SAE=1 ‘Sağ motoru ileri çalıştır SOI=1:SOG=0:SOE=1 ‘ Sol motoru ileri çalıştır Wend ‘yani araç düz gitsin. WHILE SOLSEN=0 ‘Araç hafif sağa doğru dönmüş ise sol sensör siyah çizgiyi görür SAI=0:SAG=1:SAE=1 ‘ bu durumda sağ motor geri dönecek SOI=1:SOG=0:SOE=1 ‘ sol motor ileri dönecek böylece WEND ’siyah çizgiye doğru dönüş hızlanacak WHILE SAGSEN=0 ‘Araç hafif sola doğru dönmüş ise sağ sensör siyah çzigiyi görür SOI=0:SOG=1:SOE=1 ‘ Sol motor geri doğru dönecek SAI=1:SAG=0:SAE=1 ‘ sağ motor ileri doğru dönecek, böylece wend ‘ siyah çizgiye doğru dönüş hızlanacak IF SAGSEN=1 and SOLSEN=1 and ORTSEN=1 THEN ’sensörlerin tamamı siyah çizgiyi SAI=0:SAG=0:SOI=0:SOG=0:SAE=0:SOE=0 ‘görmüyor ise tüm motorları durdur pause 1000 ‘ 1 sn bekle WHILE SAGSEN=1 AND SOLSEN=1 and ORTSEN=1 SAI=0:SAG=1:SAE=1 ‘ Sağ motor geriye dönsün SOI=0:SOG=1:SOE=1 ‘ Sol motor geriye dönsün WEND ‘araç geriye doğru gidip siyah çizgiyi bulsun. ENDIF GOTO DUZGIT
Hazırlayan: Erol Tahir Erdal (ETE)
PICBasic Dersleri PIC Basic Pro ile PIC Programlama 12 Kod ve proteus simülasyon dosyaları;
Şifre-Pass: 320volt.com
PICBasic Dersleri PIC Basic Pro ile PIC Programlama-13 Ders-13 Devam
Yayım tarihi: 2010/04/30 Etiketler: kılavuz ders, pic basic dersleri, PIC programlama, picbasic eğitim, picbasic pro
Abicim neden yorum yapılmamış anlayamadım. Süper anlatılmış. Tebrik ederim çok başarılı bir çalışma olmuş.
@Seyit Baba yorum sistemi bu sayfalara yeni eklendi yoksa ben dahil bir çok kişi ETE hocamıza duacı, minnetar sağolsun PIC programlama picbasic konusunda Türkiyede çok büyük katkıları var
Arkadaşlar güzel olanı örnek almak meziyettir. Ete hocama gönülden teşekkür ediyorum ve sitedeki tüm kardeşlerimi pic hakkında öğrendiklerimizi paylaşmaya tartışmaya davet ediyorum
ETE hocamız sayesinde pic programlamayı öğrendim. Hiç bir şey bilmezken şmdi profesyonel devreler üzerinde çalışıyorum. Kendisinden ALLAH razı olsun.
Hocam eline sağlık çok eğitici oldu teşekkürler.
konuyu bilmesemde kafamda ufak ufak ışıklar çaktı teşekkür ederim..
Hocam MErhabalar ,
Öncelikler elinize, emeğinize sağlık, sayenizde gerçekten çok güzel bir kaynak olmuş burası.çok teşekkür ederiz.
Benim bir sorum olacak.
Potansiyometre ile ADC’den pozisyon bilgisini alırken gelen değerler sürekli -6,+6 gibi bir aralıkta değişiyor ve bu değişimden dolayı gelen bilgi bana tam poziyon bilgisini vermiyor.Yakın veriyor.Yukarıda sizde ADC nin veriminin çok iyi olmayacağından bahsetmişsiniz.
Ancak şöylede bir gerçek var. Proteus similasyonunda program sıfır hata ile çalışıyor. Fiziki olarak devre üzerinde ise değerler saçmalıyor. Bu normalmidir. Yoksa devre üzerinde bir gürültü sinyalimi aramak lazım.
teşekkürler…
Kemal B.
Kemal,
Analog bir bilginin digital bilgiye çevrilmesi işi sonuçta bir kondansatörün şarj edilip zaman tutulması ve boşaldığı anda zaman değerinin digital bilgi olarak verilmesi esasına dayanır. Ne kadar hassas zamanlama yapsanızda şaşmalar elbette oluyor maalesef.
Genelde ölçüm zamanının uzun tutulması lçüm sonuçlarının doğruluğunu artırıyor. Ancak buda zaman zaman yetmiyor. Genelde iki ölçüm arasında arada birde olsa farklılıklar olabiliyor. Hele giriş değeri sürekli oynayanbilgilerde farklarda artabiliyor.
Bu işin çözümü ortalama almaktan geçiyor. Benim sıklıkla uyguladığım çözüm ADC okumasını üst üste mümkünse 50 defa yapıp bütün okumaları toplamak ve sonuçta toplam değeri 50 ye bölerek ortalama bir değer bulmak şeklindedir. Bu yöntem epeyce stabilite sağlamaktadır.
Ete
http://etepic.com
hocam 3potla 3 servo motoru kontrol ettiğiniz devreyi rf ile uzaktan kontrol etmeye çalışıyorum yanlız 20 mili saniyelik gecikmeyi ayarlıyamıyorum alıcı verici arasındaki uzaklık değiştikçe bekleme süresininde değişmesi gerekiyor çünkü haberleşme hızı değişiyor nasıl bir mantık izlemem gerekli? teşekkürler
Veren devre yalnızca hangi motorun ne kadarlık pals alacağının bilgisini yollar ise alıcı devrede bunu uygulayabilir. Dolayısıyla bir sorun olmaz diye düşünüyorum.
Bilginin yollanma hızı veya iki ünite arasındaki mesafe burada etki bir rol oynamaz diye düşünüyorum. Kesin oynamaz. AKıllıca bir mantık kurmanız gerek.
3 adet motor var ise 3 ayrı bilgi yollamanız yeterli.
Ancak unutmayın verilen puls lar us cinsinden olmalıdır. Yoksa süreyi 1,5ms nasıl vereceksiniz?. AMa bunu 1500us şeklinde vermeniz gayet kolay bence. Bu nedenle 6 adet bilgi yollamanız gerekecek. Sırası ile,
Birinci motor puls süresi (word cinsinen bir değişken ile önce Lowbyte sonra High byte verilmeli Mesela SureA.Byte0, SureA.Byte1 şeklinde) Daha sonra ikinci motor puls süresi ve son olarak da üçüncü motor puls süresini 6 adet byte şeklinde yollarsanız motorda bunu uygular ve sorun çıkmaz. Yeni bilgi gelinceye kadar eskisini uygular.
Ete
Hocam bende sizin programlardan yola çıkarak söylediğinize benzer bir program yazdım üç puls süresini farklı ön kontrol bitiyle gönderip alıcıda farklı kaydedicilerde yerleştrip tek bir wordde toplayıp işleme devam ettim verici programın ana kısmı şu
basla:
GOSUB GONDER
Adcin 0, HAMA :SUREA=(HAMA+1)*/200
Adcin 1, HAMB :SUREB=(HAMB+1)*/200
Adcin 2, HAMC :SUREC=(HAMC+1)*/200
goto BASLA
GONDER:
SEROUT2 CIKIS,396,[“E”,”T”,”E”,”A”,SUREA]
SEROUT2 CIKIS,396,[“E”,”T”,”E”,”B”,SUREB]
SEROUT2 CIKIS,396,[“E”,”T”,”E”,”C”,SUREC]
return
alıcıda bu
BASLA:
SerIn2 GIRIS,396,[WAIT (“ETEA”),surea]
SerIn2 GIRIS,396,[WAIT (“ETEB”),SUREB]
SerIn2 GIRIS,396,[WAIT (“ETEC”),SUREC]
pulsout KAMERA, SUREA
PULSOUT ELYON, SUREB
PULSOUT ELKAPA, SUREC
SURE = (SUREA + SUREB + SUREC)*10
SURE = 12000 – SURE
pauseus SURE
GOTO BASLA
END
uygulamada verici alıcıya yakınken çelışmıyor uzakken potun ilk ve son hareketini bi anda yapıyor ara değerler yok gibi bazende iki servo tek potla hareket ediyor..
Gönder kısmını şöyle yap;
GONDER:
SEROUT2 CIKIS,396,[“E”,”T”,”E”,SUREA,SUREB,SUREC]
RETURN
Tabiiki alacak olan da bu formata uygun şekilde alması gerekir.
Dolayısıyla Alıcı daki ALma kısmıda aşağıdaki şekilde olmalı.
SERIN2 GIRIS,396,[WAIT (“ETE”),SUREA,SUREB,SUREC]
Ancak bir konuya dikkatini çekmek isterim. Seri haberleşmede yollanan bilgi 8 bitlik olmak zorundadır. Şayet SUREA gibi bir değişken WORD tipinde ise ve taşıdığı değer 255 den büyük ise onu gönderme ve alma komutunda 16 bitlik kullanmazsın. SURE değişkenleri Word tipinden ise alma ve verme komutları şöyle olmalı;
SEROUT2 CIKIS,396,[“E”,”T”,”E”,SUREA.Byte0,SUREA.Byte1,SUREB.Byte0,SUREB.Byte1,SUREC.Byte0,SUREC.Byte1]
Alma komutuda benzer şekilde her bir değişkenin low byte’ıile high byteları ayrı ayrı yazılarak yollanmalı ve aynı sıra ile alınmalıdır.
Senin sorunun muhtemelen yolladığın bilginin yalnızca low byte larının yollanmasından kaynaklanıyordur.
Ete
Hocam çok teşekkür ederim dediğiniz gibi yaptım sorun çözüldü 8 bitlik adc olduğundan byte cinsinden değişkenlerdi yanlız şimdi tuhaf bir sorun var bu yazılımsal değil sanırım donanımda ben alıcı kısımda 3 servo haric iki tanede şu basit çin motoru denilen sarı motorlardan sürüyorum L293d ile 16f877nin b portuna bağlı tek tek lojik 1 verip kontrol ettim sorunsuz çalışıyor
sizin bilgiden yola çıkarak şöyle bir değişiklik yaptım SERIN2 GIRIS,396,[WAIT(“ETE”),SUREA,SUREB,SUREC,PORTB]tabi verici kısımda aynı şekilde ve sonra volt metreylealıcının portlarını kontrol ettim tam vericide tuşa basılıp brakıldığı anda alıcıda gerekli sinyal l293dye gönderiliyor sıkıntı şu sistem boştayken düzgün çalışıyor motoru bağlayınca tusu braksanda lojik seviye yaklaşık 5 ile 10 saniye arasında 1 olarak kalıyor yani tusu braksamda bir müddet motor çalışıyor neden acaba sistem boşta düzgün çalışıyor motor çalışırken beslemeyi ölçtüm 5vden 4.9 a düşüyor bariz bir değişiklik yok zıt emk danmı acaba yoksa fazla akım çekiyorda frekans hızımı düşüyorda pic yavaş işlem yapıyor o sürede motor çalışmaya devam ediyor valla çok soru sordum ama basit görünüp uğraştıran sorunlar.
Veysel,
Bahsini ettiğin sorunu anlayamadım. Boşta çalışan şey doluda da çalışması gerekir. Şema ve programın o kısmını görmeden bir şey söylemem mümkün değil maalesef.
Ete
Veysel Selamlar ,
Benzer bir problemi ben de yaşamıştım , DC motoru çalıştırdığım zaman devre doğru çalışmıyordu , Motorları beslediğim güç kaynağını, devreyi beselyen güç kaynağından ayırınca problem çözülmüştü. Yani ayrı birgüç kaynağı denemen belki problemi çözebilir.
Hocam öncelikle verdiğiniz dersler için teşekkürler, ben devre tasarımı ile yeni ilgilenmeye başladım; bunun sebebi de Parallax firmasının Kinect sensörünü kullanarak yaptığı bir mobil robot platform olan Eddie. Kendim evde bunun bir benzerini yapmaya çalışıyorum ama elektronik devreler hakkında çok bilgim yok. 2 tane servo motor kontrolü sağlayan ve kinectle birlikte toplam 6 sensörü kontrol eden bir elektronik devrenin yaklaşık olarak maliyeti ne kadar olur? Eğer maliyet çok olucaksa firmadan kontrol kartını satın almak zorunda kalacağım için projemi gerçekleştiremeyeceğim. Bana bu konuda bilgi verebilir misiniz?
Bu sorunun cevabını sağlıklı bir şekilde veremem. Sebepleri şunlar;
– Kinect sensörü nedir bilmiyorum hiç duymadım. Bildiğim bir sensördür ama ticari adı ile söylemişsin ne olduğunu bilemiyorum. Bilmediğim bir şeyin kontrolünü sağlayacak devreyide bilemem doğal olarak.
-O kadar fazla servo motor varki piyasada güçlerine göre sürme şekilleri veya çalışma şekillerine göre sürülme şekilleri değişir. Bu nedenle motor cinsi belli olmadığı için onu sürecek devre içinde bir şey söyleyemem.
– Toplam 6 sensör biri kinect olduğuna göre geri kalan 5 sensör nedir. ? Onlarda belli değil.
Analayacağın çok bilinmeyenli denklem gibi bir soru. BU nedenle cevabı vermem çok zor. Kendin bulmaya çalış cevabını.
Ete
iyi çalışmalar bu xor komutu ile enkoder palslerini düzenlemenizde bir hata olmalı çünkü enkoder palslerini direk bir xor entegresine verdiğimde çıkış hep aynı oluyor. açıklamalarınızda eksik birşey olmalı teşekkürler