avatar_ete

Rotary Encoder Okuma

Başlatan ete, 06 Ekim 2014, 12:54:56

ete

Rotary encoderler her dönüşte belirli sayıda pals üreten aletlerdir. Genelde A-B ve C diye çıkışları bulunur.
A ile B bir birinden 90 derece faz farklı olarak kare dalga üretirler. C ise genelde dönen encoderin her tur başına tek puls ürettiği bir çıkışdır. Encoder de dönüş yönü tayini genellikle A ve B girişlerinin önceki ve sonraki değişen konumlarında  birer farklı bitlerinin XOR lanması ile yapılır. Neden XOR derseniz Encoder çıkışına bir göz atarak anlatmaya çalışayım.

Resme dikkat ederseniz A ve B çıkışları sırası ile %11 - %10 - %00 - %01 - %11 şeklinde gitmektedir.
Bu saat istikametinde dönüş için geçerli çıkış değerleridir. Encoder ters dönse idi %11 - %01 - %00 - %10 - %11 şeklinde değerler alınacak idi.
Şimdi birinci okuma %11 iken ikinci okumanın %10 olduğunu varsayarsak, Burada ESKI=%11 , YENI=%10 olacaktır.
YON=ESKI.1 ^ YENI.0 şeklinde bir XOR işlemi yaparsak 1 XOR 0 =1 değerini elde ederiz ki bu bize saat yönünde döndüğünü gösterecektir.
Şayet ESKI=%11 ve YENI=%01 şeklinde olsa idi (ters yöne dönüşte alınacak değerler),
YON=1 XOR 1=0 değerini elde edecektik ki buda bize encoderin saat yönünün tersi istikametinde döndüğünü gösterecek idi.
Bundan sonra bütün iş YON=1 ise SAYAC=SAYAC+1 ve YON=* ise SAYAC=SAYAC-1 şeklinde bir işlem ile sayacı kontrol etmek şeklinde açıklanabilir.
Her encoder için yön tayini yapılacak ise A ve B çıkışları Pic'e girilmelidir. 1 encoder için 2 giriş, 2 ayrı encoder için ise 4 giriş kullanılması gerekir.
İlişikteki dosyada PortB değişiklik kesmesi kullanılarak encoder okuması yapılmıştır. Dosya içinde hem tek encoder hemde iki ayrı encoder okunması ile ilgili örnek mevcuttur.
Verilen örnekler hem Motor tipi rotary encoderlere hemde Pot tipi encoderler için kullanılabilir. Aralarındaki farklar bağlantı şekillerindedir. Motor tipi encoderlerde encoder çıkışları direk Porta bağlanabilirler. Pot tipi encoderler de 3 uç bulunur.
Dıştaki uçlar 10K direnç ile Pullup yapılmalı, ortadaki uç ise 1K direnç ile GND ye bağlanmalıdır. Bu hali ile dıştaki uçlar direk A ve B çıkışı olarak kullanılabilir.

Ete



kdrsrn

Teşekkürler ETE Hocam. Daha bu seviyelere gelemedim ama ileride mutlaka işime yarayacaktır.

MS_59

teşekkürler hocam çok değerli bilgiler
mehmet

karabayram

Teşekkürler çok isime yaradı. Hocam bu arada kitap işi ne oldu? Merakla bekliyoruz.

ete

Kitap işi öylesine duruyor. İşin içinde bir ticari amaç olmayınca olmuyor. Uğraşacak zaman yok.
Faydalanmak isteyen bu şekilde de faydalanıyor zaten. Hatta bazı arkadaşlar fotokopi kitap haşine getirip banada kopya yolluyorlar.
Derslere ara da bir bakıyorum. Güncellenmesi yada yeniden yazılması gereken yerler var.
Epeyce bir iş var yeniden yazmayı düşünüyorum. Kısa zamanda başkayacağım.
Ete

Hattuşa

ete hocam;
reklam olarak görmezseniz alibabada şu encoderler var fiyatları neredeyse buton fiyatına yani çok ucuz. alsak kullansak işimizi görürmü? istediğim sağa-sola ve basma olarak 3 konumlu istiyorum ama onun teknik özellikleri nasıl olmalı? tecrübeniz varsa alibaba ile bizde alıp kullansak olurmu?
aşağıda 10 tanesi 5,80 dolar yani 17,5 tl ücretsiz kargo encoderin tanesi 1,75 tl ye geliyor. çok ilginç


http://tr.aliexpress.com/item/10pcs-lot-Rotary-Encoder-Rotary-Encoder-Switch-EC11-Pots-Shaft-Length-20MM-20-Bits/32374584210.html?spm=2114.010208.3.2.VaSGFs&ws_ab_test=searchweb201556_1,searchweb201644_1_505_506_503_504_502_10001_10002_10016_10005_10006_10003_10004,searchweb201560_3,searchweb1451318400_-1,searchweb1451318411_6448&btsid=e6bec3ee-9b57-46e0-8eb3-d8d73599b5e0

ete

Aynısını kullanıyorum güç kaynağında.

Ete

Hattuşa

Alıntı yapılan: ete - 02 Şubat 2016, 13:23:23
Aynısını kullanıyorum güç kaynağında.

Ete


hocam o kaç konum? yani iç yapısında bir tanede buton varmı?

ete

 Bir tık çevirdiğiniz zaman %00 - %01 - %11 - %10 konumlarını verir.
3 tane pini var. Ortadaki uç GND ye bağlanacak. Yanlardakiler +besleme ile Pullup yapılacak.
Ete



Hattuşa

#9

Hattuşa

#10
Slm ete hocam, en basta verdiginiz encoderAB kodunu protona uyarlayarak denedim, itiraf edeyim ilk defa portb4-7 kesmesini kullaniyorum. Encoder potlari calistiramadim ezberci ve hazirci davrandigim icin boyle oldugunu dusunuyorum. Encoderlerin A-B cikislarini  10k ile +5v a saseleyip girdim. Orta ucunu 1k ile gndye saseledim.1.encder cikislarini 4-5 e 2. Encoder cikisini 6-7 ye bagladim. 1.ecoderi hareket ettirdigimde 2. Degeri degisior. Ayrica hep tek yone artis gosteriyor ve eksiltmiyor. Hocam bu portb4-7 kesmesi hangi mantikta calisiyor. Sunun icin sordum.
if potrb.4 = 0 then inc sayac1
if potrb.5= 0 then inc sayac2
if potrb.6 = 0 then inc sayac3
if potrb.7 = 0 then inc sayac4


Dedigimde sayac1 degeri her durumda artiyor.ben bu portb4-7 kesmesini anlayamadim acikcasi

ete

#11
PORTB.4 - PORTB.7 aralığındaki pinlerden her hangi birisi veya tamamı giriş yapılarak pin konumundaki en ufak bir değişiklikle programın kesme etiketine yönelmesi sağlanabilir. Bunu yapabilmesi için, programın başlangıcında PORTB okunup bir değişkene eşitlenmelidir. Arka planda çalışan asıl program okunan port bilgisini saklar ve programın çalışması esnasında sürekli olarak PORTB nin saklanan o konumu ile güncel konumunu karşılaştırır ve farklılık olduğu anda kesme yaratır.
Kesme etiketine geldikten sonra kesmenin hangi pinden kaynaklandığını sen kendin bulacaksın. Zaten 4 adet pin var kolaylıkla bulunur.
Kesme içinde yapacaklarını yaptıktan sonra kesmeden çıkmadan evvel TEMP=PORTB şeklinde portun o andaki konumunu yeniden okuyup kayıt altına alınmasını sağlaman gerekir. Yoksa en son okunmuş hali değerlendirilir sürekli.
Artık, kesmenin nasıl oluştuğunu anlamış olman gerekir.
Şimdi kesme içinde ne yapılmalı ona bakmak gerek.
PORTB.4-5 pinlerine Encoder-1 bağlı olduğunu söyledin. 6-7 yede Encoder-2 bağlı.
BASLA satırından evvel diyelimki encoder pinleri %0000xxxx şeklinde okunmuş olsun.
1 nolu encoderi çevirmeye başladığın anda %00 olan konum %01 şekline (veya %10 şekline veya %11 şekline) gelecektir. Bu durumda hemen kesme oluşacak ve sen kesme içinde gerekenleri yapacaksın.
Encoder okumanın püf noktası ard arda iki okuma yaparak aradaki farka bakmaktır. Fark yoksa encoder dönmüyor demektir.
Şimdi Encoder-1 üzerinden düşünelim. Açılışta %00 olan (%B1A1) pinleri üst üste yapılan okumalarda hep %00 veriyor ise encoder dönmüyor demektir.
Ama %B1A1=%01 olmuş ise encoder bir tarafa dönmüş anlamına gelecektir. Dönüş yönü ilk okuma olan %00'ın 2 nolu biti ("0") ile %01 okumasının 1 nolu biti ("1") bir biri ile XOR yapılarak bulunur. 0 XOR 1=1 dir.   O halde YON=1 olmuştur. Bunu ileri dönüş kabul edersen sayı artırılacak anlamına kullanabilirsin. O halda SAYI1=SAYI+1 yapılacaktır.
Encoder-1 döndüğü zaman %10 şeklinde bir sinyal gelmiş olsaydı 0 XOR 0=0 yani YÖN=0 değerini hesaplayacaktık. Buda encoderin ters tarafa döndüğünü gösterecek ve SAYI1=SAYI1-1 şeklinde bir işlem yapmamız gerekecek idi.
Bütün bu mantık aynı şekilde ikinci encoderede uygulanmalıdır.
Kesme ile encoder uygulaması yapılıyor ise Kesmeden çıkmadan okunmuş encoder çifti değeri tek bir değişkene verilip öyle çıkılmalıdır. Bu teorik olarak ilk okumanız (ESKI) olmuş olacak yendien kesme içine girdiğinizde ise YENI okumanızı yaparak ard arda (veya biraz bekleyerek) iki okuma gerçekleştirmiş olacaksınız. Programa başlarken hemen kesme oluşmayacağı için BASLA satırından evvel ESKI=(PORTB & %11110000)  şeklinde okuma yapmak  gerekir. Kesme içinde ise;
YENI=(PORTB & %11110000) şeklinde okuma yapıp;
IF (OLD & %00110000)=(YENI & %00110000) THEN OTEKI demeniz gerekir. Zira bu eşitlik doğru ise 1 nolu encoder de dönme hareketi olmamış anlamına gelir. Artık OTEKI etiketinde değişiklik varmı diye bakılmaz çünki ya birincide yada ikincide bir dönme olmuşki kesme etiketine gelmişsinizir. Öteki dedğimiz diğer encoderi kontrol eden bölüm  anlamına geliyor.
Artık sadece yön bilgileri hesaplanıp ona göre yukarıda anlattığım şekilde işlem yapılması gerekir.
Kesmeden çıkmadan Evvel TEMP=PORTB & %1111000 şeklinde port okunmalı ve sonra ESKI=YENI şeklinde okunan son değer eski olarak atanıp kesmeden çıkılmalıdır.

Biraz karmaşık gibi gözüküyor ama değil. Konsantre olursan halledersin.
Zaten yukarıda verdiğim örnek tamamen kesme ile çalışan bir örnek ve burada bahsettiklerimin hepsini içermektedir.
Aynı kodları yaptığım güç kaynağının volt ve amper ayar işlerini yapmak  için kullanmıştım.

Ete

gogoce

Yine güzel bir ders niteliği taşıyan bir çalışma hocam tebrikler . Bu aralar zaten encoder ile mesafe ölçümü konusunda basit bir çalışmam olacaktı . Bana resmen ışık tuttu .
Teşekkür ederim
Ne ukalayı affederim nede yapılan haksızlığı ...
Ya sus adam sansınlar , yada adam gibi kouş ilham alsınlar

Hattuşa

#13
slm ete hocam;
açıklayıcı bilgileriniz için tşk ederim. inan can simidi gibi yetiştiniz. hocam yazınızı tekrar tekrar okuyorum. anlamak adına...
dün gece yazınızı okuduğumda encoderleri kısmen çalıştırmayı başardım. şuan için encoderlerin içinde saydırdığım sayac değişkenleri düzgün çalışmıyor. sanırım onun nedeni de encoderlerin A ve B girişlerinin ters girilmiş olması olabilir veya Symbol AB=ESKIB.6
Symbol BB=YENIB.7 değerlerinin yanlış atanmasından da kaynaklanıyor olabilir. artık bugün için mesaideyim yarın sabah mesaiden çıktığımda denerim. bu noktada birşey sormak istiyorum portb change kesmesi içinde atamış olduğunuz temp =portb atamasıdır. bu atama ile daha sonra bir değerlendirme yapmıyoruz. portbnin durum değişimi ve bir önceki ile değerlendirilmesi eskia<>yenia ve eskib <>yenib arasında yapılıyor ve temp =portb işleminin işlevsiz davrandığını düşünüyorum. hocam düşüncemde bir yanlışlık olabilir mi?
sizin encoderAB PBP kodunuzu protona uyarlayıp ekte veriyorum. umarım protoncu arkadaşların işlerine yarar.


Device 16F628A
Config BOREN_OFF, CP_OFF, DATA_CP_OFF, PWRTE_OFF, WDT_OFF, LVP_OFF, MCLRE_ON, HS_OSC, DATA_CP_OFF, WDT_OFF

Xtal 20
 CMCON=7
'---------------------------------------------------------------
PORTA=0:TRISA=%00000000
PORTB=0:TRISB=%11110000
'-------------------------------------------------------------
Declare LCD_Type ALPHA 
Declare LCD_DTPin PORTA.0 
Declare LCD_ENPin PORTB.0 
Declare LCD_RSPin PORTB.1 
Declare LCD_Interface 4 
Declare LCD_Lines 4 
Cls
DelayMS 100

On_Hardware_Interrupt GoTo Z_KeSMe

INTCON=%10001000  'Kesmeler aktif ve   PORTB Değişiklik kesmesi aktif
'---------------------------------------------------------------------
Dim SAYACA  As Word  
Dim SAYACB As Word  
Dim TEMP As Byte
Dim ESKIA As Byte
Dim YENIA As Byte
Dim ESKIB As Byte
Dim YENIB As Byte
Dim eskiC As Byte

Dim YONA As Bit
Dim YONB As Bit

Dim AA As ESKIA.4
Dim BA As YENIA.5
Symbol AB=ESKIB.6
Symbol BB=YENIB.7
Symbol BAYRAK=INTCON.0
'---------------------------------------------------------------------
Cls

DelayMS 250

ESKIA=PORTB & %00110000 
ESKIB=PORTB & %11000000
BAYRAK=0
SAYACA=0
SAYACB=0
DelayMS 250
Cls
BASLA:
      Print At 1,1,"YONA=",Dec1 YONA, "    YONB=",Dec1 YONB
      Print At 2,1,"SA=",Dec5 SAYACA ,"  SB=",Dec5 SAYACB
      Print At 3,1,Bin8 YENIA,"  ",Bin8 eskiC,"  "
      Print At 4,1,Bin8 TEMP,"   ",Bin AA," ",Bin BA," "

      GoTo BASLA      
      

Z_KeSMe:
Context Save 
         YENIA=PORTB & %00110000
         If YENIA=ESKIA Then SAY_B
SAY_A:                
         YONA=AA ^ BA
         If YONA=1 Then
           SAYACA=SAYACA+1
         Else
           SAYACA=SAYACA-1
         EndIf
         eskiC =ESKIA
         ESKIA=YENIA
         GoTo CIK
SAY_B:    
         YENIB=PORTB & %11000000
         YONB=AB ^ BB
         If YONB=1 Then
           SAYACB=SAYACB+1
         Else
           SAYACB=SAYACB-1
         EndIf
         ESKIB=YENIB
CIK:             
         TEMP=PORTB 
         BAYRAK=0
        Context Restore
End

ete

#14
Port durumunu okumanın program içinde başka işlevi yok. Tek amacı işlemciye portun durumunu iletmek.
Sonuçta o kullanıyor okunan değeri ama arka planda yapıyor bu işi.
Bu nedenle okunan port değerini içeren değişkeni program içinde başka yerlerde kullanmamak gerekir . Yoksa sorun çıkar.

Bu arada encoder orta pini direk GND ye bağlarsan daha sıhhatli çalışır. Burada temel amaç Artı ile Eksinin direk çakışmamasıdır.
A ve B uçları 10K ile artıya bağlı olduklarından çakışma daima 10K direnç üzerinden olacaktır. Bu nedenle sorun yok. Ama aynı uçların LOW a çekilmeleri için 1K nın 10K direnci yenerek yapması şeklind eolurki burada GND biraz güç kaybeder. Bu nedenle orta uç direk GND ye verilmelidir.

Ete

Powered by EzPortal