avatar_ete

Rotary Encoder Okuma

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

Hattuşa

#15
Ete hocam;
aşağıdaki siteden aldığım switchli 2 adet encoderi çalıştırmaya çalışıyorum.aliexpressten gelecekler ile aynısı.
http://www.direnc.net/ROTARY-ENCODER-SWITCHLI,PR-19361.html



aşağıya simülasyon dosyasında proton kodu ve şemayı ekledim. benimkisi tamamen sağ kulağı sol elimle göstermek oluyor. zira algoritma oluşturmayı tam beceremiyorum. nasipse yarın bu kodu devremde deneyeceğim. her encodere 2 şer adet menu ekledim. isisde doğru çalışıyor ama gerçekte nasıl bir sorun yaşarım bilmiyorum.

hocam kodu bu şekilde yazdım ama daha sade yazılabilir.benim mantığım pek basmadığı için böyle oldu, istediğim encoderin hareketini yavaşlatarak geçişlerin 2şer 3 er atlamasını engellemekti, zira arka planda timerde çalıştırmam gerektiği için herhangi bir gecikme koyamıyorum.

Device 18F4520
Config_Start
   OSC = HS ; HS oscillator
   FCMEN = OFF ; Fail-Safe Clock Monitor disabled
   IESO = OFF ; Oscillator Switchover mode disabled
   PWRT = OFF ; PWRT disabled
   BOREN = OFF ; Brown-out Reset disabled in hardware and software
   WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
   MCLRE = On ; MCLR pin enabled; RE3 input pin disabled
   LPT1OSC = OFF ; Timer1 configured for higher power operation
   PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
   CCP2MX = PORTBE ; CCP2 input/output is multiplexed with RB3
   STVREN = OFF ; Stack full/underflow will not cause Reset
   LVP = OFF ; Single-Supply ICSP disabled
   XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
   Debug = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
Config_End


Xtal 10
 CMCON=7
'---------------------------------------------------------------
PORTA=0:TRISA=%00000000
PORTB=0:TRISB=%11110011
PORTC=0:TRISC =0
PORTD=0:TRISD =0
PORTE=0:TRISE =0
'-------------------------------------------------------------
Declare LCD_Type ALPHA 
Declare LCD_DTPin PORTD.4 
Declare LCD_ENPin PORTD.0 
Declare LCD_RSPin PORTD.1 
Declare LCD_Interface 4 
Declare LCD_Lines 4 
Cls
DelayMS 100

On_Hardware_Interrupt GoTo KeSMe

INTCON=%00011000  'Kesmeler aktif ve   PORTB Değişiklik kesmesi aktif
INTCON3 =%00001000
'---------------------------------------------------------------------
Dim VoL1  As Byte  
Dim VoL2 As Byte
Dim VoL3  As Byte  
Dim VoL4 As Byte  
Dim TEMP As Byte
Dim TeMPa As Byte
Dim YONA As Bit
Dim YONB As Bit
Dim SaYa As Bit
Dim SaYb As Bit
Dim EbIt1 As Bit
Dim EbIt2 As Bit
Dim V1bIt0 As Bit
Dim V2bIt0 As Bit
Dim V3bIt0 As Bit
Dim V4bIt0 As Bit
Dim V1bIt1 As Bit
Dim V2bIt1 As Bit
Dim V3bIt1 As Bit
Dim V4bIt1 As Bit
Dim vL1 As Bit
Dim vL2 As Bit
Dim vL3 As Bit
Dim vL4 As Bit
Symbol AA =TEMP.4
Symbol BA =TeMPa.5
Symbol AB =TEMP.6
Symbol BB =TeMPa.7
Symbol BAYRAK=INTCON.0
'---------------------------------------------------------------------
Cls

DelayMS 250
VoL1 =ERead 1  :DelayMS 50
     If VoL1 =255 Then VoL1 =1
VoL2 =ERead 2  :DelayMS 50
     If VoL2 =255 Then VoL2 =1
VoL3 =ERead 3  :DelayMS 50
     If VoL3 =255 Then VoL3 =1
VoL4 =ERead 4  :DelayMS 50
     If VoL4 =255 Then VoL4 =1
Print At 1,2,"VOLUME_1:"
Print At 2,2,"VOLUME_2:"
Print At 3,2,"VOLUME_3:"
Print At 4,2,"VOLUME_4:"
GoSub EkRaNyAz1
GoSub EkRaNyAz2
GoSub VoLUm10
GoSub VolUm20


DelayMS 100
TEMP =PORTB & %11110000
BAYRAK=0
INTCON.7 =1      'kesme aktif edildi
BASLA:
If EbIt1 =1 Then GoSub EkRaNyAz1
If EbIt2 =1 Then GoSub EkRaNyAz2

If vL1 =1 Then GoSub VoLUm10
If vL2 =1 Then GoSub VoLUm11
If vL3 =1 Then GoSub VolUm20
If vL4 =1 Then GoSub VolUm21
GoTo BASLA

VoLUm10:
If V1bIt0 =1 Then
           Inc VoL1 
           If VoL1 >99 Then VoL1 =99
           EWrite 1,[VoL1]
           V1bIt0 =0
           EndIf
If V2bIt0 =1 Then
           Inc VoL2 
           If VoL2 >99 Then VoL2 =99
           EWrite 2,[VoL2]
           V2bIt0 =0
           EndIf
Print At 1,12,Dec2 VoL1
Print At 2,12,Dec2 VoL2
vL1 =0
Return

VoLUm11:
If V1bIt1 =1 Then
           Dec VoL1 
           If VoL1 <1 Then VoL1 =1
           EWrite 1,[VoL1]
           V1bIt1 =0
           EndIf
If V2bIt1 =1 Then
           Dec VoL2 
           If VoL2 <1 Then VoL2 =1
           EWrite 2,[VoL2]
           V2bIt1 =0
           EndIf
Print At 1,12,Dec2 VoL1
Print At 2,12,Dec2 VoL2
vL2 =0
Return



VolUm20:
If V3bIt0 =1 Then  
           Inc VoL3 
           If VoL3 >99 Then VoL3 =99
           EWrite 3,[VoL3]
           V3bIt0 =0
           EndIf
If V4bIt0 =1 Then 
           Inc VoL4 
           If VoL4 >99 Then VoL4 =99
           EWrite 4,[VoL4]
           V4bIt0 =0
           EndIf  
Print At 3,12,Dec2 VoL3
Print At 4,12,Dec2 VoL4 
vL3 =0          
Return

VolUm21:
If V3bIt1 =1 Then  
          Dec VoL3 
          If VoL3 <1 Then VoL3 =1
          EWrite 3,[VoL3]     
          V3bIt1 =0
          EndIf
If V4bIt1 =1 Then 
          Dec VoL4 
          If VoL4 <1 Then VoL4 =1
          EWrite 4,[VoL4]             
          V4bIt1 =0
          EndIf  
Print At 3,12,Dec2 VoL3
Print At 4,12,Dec2 VoL4  
vL4 =0         
Return



          
         
            
EkRaNyAz1:
EbIt1 =0
If SaYa =0 Then
Print At 1,1,">"
Print At 1,14,"<"
Print At 2,1," "
Print At 2,14," "
Else
Print At 1,1," "
Print At 1,14," "
Print At 2,1,">"
Print At 2,14,"<"
EndIf
Return 
    
EkRaNyAz2:
EbIt2 =0
If SaYb =0 Then
Print At 3,1,">"
Print At 3,14,"<"
Print At 4,1," "
Print At 4,14," "
Else
Print At 3,1," "
Print At 3,14," "
Print At 4,1,">"
Print At 4,14,"<"
EndIf
Return       

KeSMe:
Context Save 
If INTCON.1 =1 Then
INTCON.1 =0
Toggle SaYa
EbIt1 =1
ElseIf INTCON3.0 =1 Then
INTCON3.0 =0
Toggle SaYb
EbIt2 =1
ElseIf INTCON.0 =1 Then
TeMPa =PORTB
If (TEMP & %00110000)=(TeMPa & %00110000) Then OtEkI 
YONA =AA^BA

     If YONA =1 Then
      vL1 =1
        If SaYa =0 Then 
           V1bIt0 =1
           Else
           V2bIt0 =1
           EndIf
     Else
       vL2 =1
           If SaYa =0 Then
           V1bIt1 =1
           Else
           V2bIt1 =1
           EndIf

     EndIf
GoTo CIK
OtEkI:
      YONB =AB ^BB
      
           If YONB =1 Then 
           vL3 =1
               If SaYb =0 Then 
                  V3bIt0 =1
                  Else
                  V4bIt0 =1
                  EndIf  
     Else
        vL4 =1
           If SaYb =0 Then  
                   V3bIt1 =1
                   Else
                   V4bIt1 =1
                   EndIf
                  
     EndIf
CIK:           
         TEMP= TeMPa 
         BAYRAK=0
EndIf
        Context Restore
End


F®T

#16
Encoder kaliteli olmayınca dönüşte kontaklarda oluşan ikilemeler sayaçta fazla saymalara sebep oluyor.Bende çok uğraşmıştım.Sanırım gnd ile encoder a,b uçları arasına birer adet 10 nf kapasite atmıştım.Faydası olsa bile kesin çözüm olmuyor.Encoder kaliteli olmalı yoksa sonuç almak zor.

http://etepic.com/index.php/topic,508.msg18308.html#msg18308
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Hattuşa

Alıntı yapılan: F.T - 20 Şubat 2016, 13:55:51
Encoder kaliteli olmayınca dönüşte kontaklarda oluşan ikilemeler sayaçta fazla saymalara sebep oluyor.Bende çok uğraşmıştım.Sanırım gnd ile encoder a,b uçları arasına birer adet 10 nf kapasite atmıştım.Faydası olsa bile kesin çözüm olmuyor.Encoder kaliteli olmalı yoksa sonuç almak zor.

http://etepic.com/index.php/topic,508.msg18308.html#msg18308

desene FT usta bizim çinden gelecek malzemelerle epey saç-baş yolarım. usta ben 100nF attım akşam ama gene etkisi olmadı, 10K pullupları 4k7 ye çektim parazitleri bastırsın diye ama tam deneyemedim.

İlyas KAYA

İlk palsi aldıktan sonra (misal sağa bir adım gitti) bir sayaç saydırın.
Bu sayaç 0,5 sn sonra bir tane bit'i set etsin.

Yani ilk sinyali aldıktan sonra ikinci sinyal 0,5 sn sonra olacaktır.

Böylece tek tek yavaş geçişlerde sorun olmaz , parazitleri önlemiş olursunuz. Hemde hızlıca çevrilse bile 0,5sn den sonra ikinci adımı yakalayacağı için çok hızlı hareket etmemiş olacaktır.
Göz odur ki dağ ardını görsün,
Akıl odur ki başa geleceği bilsin.!

Maxim

encoder çıkışlarına seri 10k ve sonrasına 10nf koyup deneyin

F®T

#20
Selami hocam maxim hocamın dediği gayet mantıklı görünüyor bir dene istersen.
Kalite her zaman önemli yoksa saç baş yolduruyor dediğin gibi.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

ete

Şimdiye kadar belkide 10 farklı encoder pot aldım. Bunların içinde Hall sensörli olanıda vardı optik çalışanıda vardı.
Aralarında ahım şahım bir çalışma farkı gözlemlemedim.
Asıl sorun şu potu çevirdiğiniz zaman tık - tık diye ses duyuyorsunuz.  Bir tıktan diğerine gidene kadar (ki çok ufak bir aralık bu) encoderin AB çıkışları 4 konumuda çıkışlarından veriyor. Gönül isterdiki her tık sonunda bir sonraki konuma geçsin ama öyle olmuyor. iki tık aralığında AB çıkışlarından %00-01-10-11 şeklinde (sıralama yanlış olabilir ve ayrıca dönüş yönüne bağlı olarak değişir) 4 konum geçmektedir. Programın hızlı bir şekilde bu geçişleri yakalaması yada programın bu geçişlerden yalnızca birinde işlem yapmasını sağlamak gerekir. Bu uygulamada epeyce soruna sebep oluyor buna eminim. Pek çok kişi her tıkta bir konum geldiğini sanıyor ama öyle olmuyor maalesef. Üstelik her tık sonunda sabit her zaman aynı konumda da kalmıyor. Buda ayrı bir sorun. Bunun sebebi kontak aralıklarının çok küçük olması. İşte bu noktada encoder kalitesi ön plana çıkabilir. Her tık sonunda aynı çıkışı basan encoder kalitelidir diyebiliriz. Gördüğüm kaliteli olan markalar, Vishay ve Alps idi. Markasızlar sorunlu olabiliyor ama yinede çalışıyorlar. Markalı olanları İstanbulda bulmuştum. Karaköyde. Gittiğimde boş vaktim olursa dolaşır bakarım. Şimdi varmı bilmiyorum. Bakmak lazım.

Ete

F®T

Hocam dediğiniz gibi mekanik sorundan kaynaklı.Bende potu bastırıp çevirdiğimde kararlı çalışma olduğunu görüyordum.Hata azalıyordu.Onun için pot kaliteli olursa programda şurup gibi çalışır.Ama Selami hocam çinden getirtiyor çok uğraşacak gibi.  :)
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Burak

Bende de var aynısından .. ESP8266 için wireless şifresini farklı ağlar için girmek ve ağ seçmek için tek bir düzenek ile nasıl hallederim diye düşünürken bundan satın aldım .. Ama sonra hiç deneme yapamadım ... Bi ara uğraşıp bende sonucu yazıcam buraya ...

Burak
Ω Gens Una Sumus Ω

canng

#24
Teşekkürler hocam

canng

Hocam merhabalar
Verdiğiniz bu örnek kodları 16f887 de çalıştıramadım. 887 nin kesme ayarlarını bir çok kaynaktan bulup denedim.sonuç alamadım.Hiçbir şekilde kesmeye gitmiyor.Sorun nedir acaba? Yardımcı olursanız çok mutlu olurum.şimdiden teşekkürler.

'************************************************************************************************************
@  __config _CONFIG1, _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _LVP_OFF & _CP_OFF
Include "MODEDEFS.BAS"

ANSEL   =  %00000000                   'Analog Kapalı
ANSELH =  %00000000

DEFINE OSC 4
DEFINE LCD_DREG      PORTB   
DEFINE LCD_DBIT      0      
DEFINE LCD_EREG      PORTD   
DEFINE LCD_EBIT      5      
define LCD RWREG    PORTD   
define LCD_RWBIT    4       
DEFINE LCD_RSREG   PORTC   
DEFINE LCD_RSBIT   7      
DEFINE LCD_BITS      4      
DEFINE LCD_LINES   2


ON INTERRUPT GoTo KESME 

'INTCON=%10001000  'Kesmeler aktif ve   PORTB Değişiklik kesmesi aktif
'INTCON = $90
OPTION_REG = $55
INTCON = %10001000   ' Enable interrupts



'OPTION_REG = $7f    


TrisB=%11000000
TrisC=%00000111
TrisD=%00001000

PORTB=0
PORTC=0
PORTD=0

SAYAC  VAR byte '56
SAY    VAR BYTE' 58
TEMP   VAR BYTE
ESKI   VAR BYTE
YENI   VAR BYTE
kes var byte

YON    VAR BIT

SYMBOL A=ESKI.6
SYMBOL B=YENI.7
SYMBOL BAYRAK=INTCON.0

LOW PORTD.4


LCDOUT $FE,1

kes=0

PAUSE 250

LCDOUT $FE,$80,"LUTFEN  BEKLEYIN"
ESKI=PORTB
bayrak=0
sayac=0
temp=0
say=0
PAUSE 250
LCDOUT $FE,1
BASLA:
      lcdout $FE,$80,"YON=",DEC1 YON
      LCDOUT $FE,$C0,"SAYAC=",DEC SAYAC ,"    "
      if kes=1 then high portb.2
      if kes=2 then low  portb.2
      GOTO BASLA     
     
DISABLE
KESME:
         YENI=PORTB & %11000000
         YON=A ^ B
         IF YON=1 THEN
           SAYAC=SAYAC+1
           kes=kes+1
           
         ELSE
           SAYAC=SAYAC-1
           kes=kes-1
         ENDIF
         ESKI=YENI
         TEMP=PORTB
         BAYRAK=0
         RESUME
         ENABLE     
         
         end
             

ete

Her işlemcide farklı özellikler bulunuyor. Neler olduğunu ancak Data sheet'ine bakarak anlayabiliyorsunuz.
Açıp baktım. Öncelikle olması gereken diğer eksiklerine bakalım.
Bu işlemcide birden fazla dahili OSC seçeneği olduğu için Define OSC 4 komutundan sonra OSCCON registerinede 4Mhz için değer vermelisin.
OSCCON=%01100001

Analog özelliği ANSEL registerleri ile iptal edildikten sonra Comparatör özelliklerinida kaldırman gerek.
CM1CON0=0 'C1 Komparatör iptal
CM2CON0=0 'C2 Komparatör iptal

PORTB de encoder giriş pinlerine Pullup özelliği vermen gerek.
WPUB=%11000000
OPTION_REG.7=0

Şimdi gelelim PORTB değişiklik kesmesine,
Encoder pinleri (AveB) giriş pini olarak ayarlanacak bunu yapmışsın.
Intcon registerinde ilgili bitler set edilecek. (7 ve 3 nolu bitler) bunuda yapmışsın (INTCON=%10001000)
IOCB yani Interrupt On Change B registerinde kesme oluşturacak bitleri set etmelisin bunu yapmamışsın.
IOCB=%11000000

BASLA etiketinden önce Port'u bir okuyup encoder pinlerinin değerlerini ESKI olarak yada alacaksın bunu eksik yapmışsın.
Doğrusu ESKI=PORTB & %11000000    'şeklind olmalı.
Bu aşamadan sonra sistem artık encoderde ki değişiklikleri algılayıp kesme içine görebilir.

Ete

canng

Ete Hocam size ne kadar teşekkür etsem azdır.Allah razı olsun
Tekrar teşekkür ederim

canng

#28
Hocam ısıste sorunsuz çalıştı ama kartın üzerinde tam kararlı çalışmıyor.Sağa çevirince 1 yazıyor tekrar sağ yapınca  0 oluyor.

sayac kısmı da ne tarafa çevirirsem çevireyim hep azalıyor.Nasıl düzeltebilirim ?

orta uc 1k ile gnd de
a ve b ucu 10k ile +5 de

birde ben kartı önceden yaptığım için enkoder girişleri portb4 ve portb5 e bağlı.Ayarları ona göre değiştirdim.Enkoder okumak için illaki clk ve dta pini şart mı ?

canng

Alıntı yapılan: ete - 24 Haziran 2018, 14:32:20
Her işlemcide farklı özellikler bulunuyor. Neler olduğunu ancak Data sheet'ine bakarak anlayabiliyorsunuz.
Açıp baktım. Öncelikle olması gereken diğer eksiklerine bakalım.
Bu işlemcide birden fazla dahili OSC seçeneği olduğu için Define OSC 4 komutundan sonra OSCCON registerinede 4Mhz için değer vermelisin.
OSCCON=%01100001

Analog özelliği ANSEL registerleri ile iptal edildikten sonra Comparatör özelliklerinida kaldırman gerek.
CM1CON0=0 'C1 Komparatör iptal
CM2CON0=0 'C2 Komparatör iptal

PORTB de encoder giriş pinlerine Pullup özelliği vermen gerek.
WPUB=%11000000
OPTION_REG.7=0

Şimdi gelelim PORTB değişiklik kesmesine,
Encoder pinleri (AveB) giriş pini olarak ayarlanacak bunu yapmışsın.
Intcon registerinde ilgili bitler set edilecek. (7 ve 3 nolu bitler) bunuda yapmışsın (INTCON=%10001000)
IOCB yani Interrupt On Change B registerinde kesme oluşturacak bitleri set etmelisin bunu yapmamışsın.
IOCB=%11000000

BASLA etiketinden önce Port'u bir okuyup encoder pinlerinin değerlerini ESKI olarak yada alacaksın bunu eksik yapmışsın.
Doğrusu ESKI=PORTB & %11000000    'şeklind olmalı.
Bu aşamadan sonra sistem artık encoderde ki değişiklikleri algılayıp kesme içine görebilir.

Ete



hocam güzel cevaplarınızı bekliyorum.müsait olunca yazarmısınız ?

Powered by EzPortal