RB0 ve RB1 kesmeleriyle Enkoder okuma yardım!

Başlatan DigMan, 12 Eylül 2014, 16:31:47

DigMan

Ete hocam merhaba.Ne zamandan beri uğraşıyorum ama bir türlü çözemedim şu enkoder okuyarak motor kontrolü yapmayı. o kadar araştırdım doğru düzgün kaynak da yok. sizin proje ve örnekleriniz de yarım yada tam anlaşılır değil.Eski yeni değişkenleriyle okumayla doğru sonuç alamayız. RB0 kesmesi, enkoderin 4 pozisyonundan birini alıp yükselen yada düşen kenarları sayıyor. Bu da her kesme bir tur demektir.eski ve yeni değişkenli port okuma yöntemi yanlış sonuçlar verir. Ayrıca pulse kaçırma olasığımız çok fazla nitekim de kaçırıyor.Yardımlarınıza ihtiyacım var. Daha doğru sonuçlar veren enkoder okuma yöntemi yok mu? B0 ve B1 kesmeleriyle nasıl yapabilirim?Yön tayinini başka türlü yapamazmıyız? varsa örnek programlar lütfen atın.Hocam şu konuyu bana aydınlatırmısınız? bilen başka arkadaşlar da yardımcı olursa sevinirim. Nereye baksam eski yeni değişkenli kesme prog örneği görüyorum.diğer kısımları yok.kaldı ki her turda bir kesme olacağından bu yöntem çok da uygun değil. enkoder bir turda 4 durum değiştiriyor bildiğiniz gibi..

Ben şuan enkoderin sadece A pinini RB0 ile okuyup limit switchsiz motoru durdurup yönünü değiştirebiliyorum.Fakat aldığı yol/mesafe tayininde sıkıntı yaşıyorum.Sanırım enkoderin her iki pinini -AB- kullanmak zorundayım.Bu durumda da eski-yeni yönteminden başka bir seçeneğimiz yok mu? Motorum 100 pulse.

Lütfen acil yardım hocam ve arkadaşlar... 

ete

Yalnızca bir yöne dönen bir encoder ile çalışıyorsan yalnızca A veya B çıkışını PORTB.0 kesmesine bağlarsın olur biter. Ama encoder'ı iki yönlü kullanacak isen dönüş yönünü anlayabilmen için bir önceki konumunu mutlaka bilmen gerekir. Aksi halde yön tespiti yapamazsın. Bu durumda ESKI ve YENI pozisyonların alınması kesinlikle zorunludur.

Baktımda bir sürü önfikir sahibi olmuşsun. Benim kodlarım yarım yada anlaşılmaz diye bir hükme varabilmen için bu soruyuda burada sormamış olman ve kendi işini kendin haletmen gerekirdi. Demekki bilgi açısından yarım olan sensin.
Benim kodlar yarım değil tamam kodlar. Çalışmasında da sorun yok. Digital güç kaynağında kullandığım gibi bir kaç makina işinde de kullandım. Zaten kendin de söylüyorsun İnterneti araştır hepsinde genel mantık aynıdır. Bu mantık içinde eski okuma (eski Konum) mutlaka yer alır.

Aşağıdaki şekle bakarsan bir encoderin konumlarını sırası ile göreceksin.


Her şeyden önce PORTB.1 kesmesi diye bir şey yok. PortB.4-7 kesmesi var. Bu durumda A ve B pinlerini PORTB.4 ve PORTB.5 pinlerine bağlarsın ve hangi pinde değişiklik olursa kesme oluşur. Yinede bir önceki kesme konumunu bilmen gerekir. Yoksa dönüş yönünü tespit edemezsin.

Ete

DigMan

Hocam, teşekkür ederim ilginiz için.verdiğin bilgiler benim için çok kıymetli.Burdaki herkes de benim gibi düşünüyodur eminim.beni yanlış anlamayın.size hiç bir lafım olamaz.sizin kodlarınız elbette çalışıyor bir sorun yok. ben sadece programın biraz da geri kalan kısmını da görmek istedim.çünkü enkoder ilk okuma konumu var, pwm kısmı var, bunların yerleri de çok önemli. Bu yüzden söyledim.

Ben ilk etapta sadece A yı kullanarak yol almak istedim.Fakat yön tayinini bilmem gerekiyor.Ben de 18F serisine geçip RB0 ve RB1 donanımsal kesmeleriyle AB enkoder kullanabilirim. Ama bahsettiğim sorun şu, yanlışsam lütfen düzeltin: Diyelim ki RB0 kesmesini yükselen kenara ayarladık.kesmeler sadece yükselen kenarda oluşacak. Enkoderin 0-1 den 1-1 e geçişinde yani.Hal böyle olunca aradan geçen komut süresini de hesaba katarsak aynı değerleri yakalama olasılığımız da oldukça yüksek olacak. Programda ilk enk değerini okuma yerimiz de önem taşıyor sanki. Hocam, bikaç problemim var onları da paylaşmak istiyorum.

1-RB0 kesmesiyle A çıkışını okuyorum. motor voltajı 12V iken, lcd den değişkenin içeriğini 5500 ölçüyorum.Motor voltajını 24V yaptığımda ise 2400 e düşüyor.Sanırım bu normal değil.Bunu pals kaçırdığı için mi yapıyor? çözüm ne olur?

2-18F serisi kullanarak AB çıkışlarını RB0 ve RB1 kesmelerine versek, bir yönde biri diğerine göre daha önce kesme oluşturacağından yön tayini/ileri-geri sayımı yapamazmıyız?

3-programım kayar kapı.durma ve kalkmaları hallettim gibi.Yapamadığım kısım; yön tayini ve belirli aralıklarda olması gereken yavaşlamalar. programı da gönderiyorum. eksik ve hatalarımını daha net görebilirsiniz hocam.yardım ve fikirlerinize gerçekten ihtiyacım var.




Device 16F876A
Declare XTAL 20
ALL_DIGITAL = On



'********* giriş ve çıkış port tanımlamaları *********


'GİRİŞLER

Symbol MENU  PORTC.0
Symbol ARTI  PORTC.1
Symbol EKSI  PORTC.2
Symbol ACIL  PORTB.1
Symbol RDR1  PORTB.2
Symbol RDR2  PORTB.3
Symbol UZAK  PORTB.4
Symbol FOTO  PORTB.5
Symbol IR_AL PORTB.7


'ÇIKIŞLAR

Symbol KILIT    PORTB.0
Symbol IR_VER   PORTB.6
Symbol R_data   PORTC.3
Symbol T_clk    PORTC.4
Symbol DSP_LT   PORTC.5
Symbol DSP_SH   PORTC.6
Symbol DSP_DT   PORTC.7
Symbol MTR_STOP PORTA.0
Symbol MTR_SAG  PORTA.1
Symbol MTR_SOL  PORTA.2
Symbol E2       PORTA.3
Symbol SES      PORTA.4
Symbol E1       PORTA.5



TRISB   = 1
TRISB.0 = 1
TRISB.6 = 0
TRISC   = 0
TRISC.0 = 1
TRISC.1 = 1
TRISC.2 = 1
TRISA   = 0
Input PORTB.0
Input PORTB.2
Input PORTB.3



'************ değişkenler ve sabitler ****************


Dim intTimer      As Byte
Dim BirSaniye     As Bit
Dim zorlanma      As Word
Dim A_Noktasi     As Bit
Dim B_Noktasi     As Bit
Dim Mesafe        As Word
Dim MesafeBulundu As Bit
Dim TurSay        As Word
Dim TurSayisi     As Byte
Dim Enkoder       As Word
Dim saniye        As Byte
Dim sayac         As Word
Dim say           As Word
Dim hiz           As Byte
Dim yol           As Byte
Dim A_yavas       As Word
Dim B_yavas       As Word
Dim AB_yavas      As Word
Dim enkSayac      As Word
Dim deger1        As Word



'************ ilk pozisyon tanımlamaları *************


TurSay        = 0
Enkoder       = 0
intTimer      = 0
saniye        = 0
BirSaniye     = 0
zorlanma      = 0
A_Noktasi     = 0
B_Noktasi     = 0
Mesafe        = 0
MesafeBulundu = 0
sayac         = 0
say           = 0
hiz           = 6                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             
yol           = 0
TurSayisi     = 0
A_yavas       = 0
B_yavas       = 0
AB_yavas      = 0
enkSayac      = 0
deger1        = 0



High MENU
High ARTI
High EKSI
High ACIL
High RDR1
High RDR2
High UZAK
High FOTO
High SES

DelayMS 1000



        'sayac = 0
        OPTION_REG = $C7 '$47   
        INTCON     = $F0
       

On Interrupt GoTo KESME


'*************************** MESAFE TANIMA ****************************


KAPI_AC:

Low MTR_SOL
Low MTR_SAG
High MTR_STOP
DelayMS 200

AC:
High MTR_STOP
Low MTR_SAG
PWM MTR_SOL, hiz, 50 
If say = 1 Then KAPI_KAPAT
GoTo AC


'*************************************


KAPI_KAPAT:

Low MTR_SOL
Low MTR_SAG
High MTR_STOP
DelayMS 200

KAPAT:
High MTR_STOP
Low MTR_SOL
PWM MTR_SAG, hiz, 50
If say = 2 Then say = 0 : GoTo DUR
GoTo KAPAT


'*************************************


DUR:

Low MTR_SOL
Low MTR_SAG
High MTR_STOP
A_Noktasi = 0
MesafeBulundu = 1
say = 0
Enkoder = 0
enkSayac = 0
zorlanma = 100

TurSay = (Mesafe / 100) * 50

If RDR1 = 0 Then
    High RDR1
    Enkoder = 0
    enkSayac = 0
    hiz = 100
    say = 0
    GoTo NORMAL
EndIf
   
GoTo DUR


'***************** NORMAL ÇALIŞMA MODU *****************************************


NORMAL:
Low MTR_SOL
Low MTR_SAG
High MTR_STOP
hiz = 100
say = 0
DelayMS 200


loop_1:
High MTR_STOP
Low MTR_SAG
PWM MTR_SOL, hiz, 50
'B_yavas = (TurSay / 100) * 80
'If hiz = 100 Then katsay = 65
'If hiz = 150 Then katsay = 45
'If hiz = 250 Then katsay = 28
If enkSayac >= TurSay Then hiz = 30 
If say = 1 Then KAPATT
GoTo loop_1



KAPATT:

Low MTR_SOL
Low MTR_SAG
High MTR_STOP
Enkoder = 0
enkSayac = 0
hiz = 100
DelayMS 200


loop_2:
High MTR_STOP
Low MTR_SOL
If RDR1 = 0 Then
   High RDR1
   deger1 = Mesafe - enkSayac
   Enkoder = 0
   enkSayac = 0
   enkSayac = deger1
   GoTo NORMAL
EndIf   

PWM MTR_SAG, hiz, 50

'B_yavas = (TurSay / 100) * 80
'If hiz = 100 Then katsay = 65
'If hiz = 150 Then katsay = 45
'If hiz = 250 Then katsay = 28
If enkSayac >= TurSay Then hiz = 30 
If say = 2 Then say = 0 : GoTo DUR
GoTo loop_2



'***************** kesme geldiğinde görev dağılımı ******************



Disable
KESME:
       
If INTCON.1 = 1 Then  'yükselen kenarda encoder bilgisini sayan B0 INT girişi
   INTCON.1 = 0
   Inc Enkoder
   Inc sayac
       If MesafeBulundu = 0 Then
            If say = 1 Then Inc Mesafe   
       EndIf   
EndIf


If INTCON.2 = 1 Then
   INTCON.2 = 0
   Inc intTimer
   If intTimer >= 30 Then   '1 saniyelik timer0 kesmesi olduysa 30
      intTimer  = 0
      BirSaniye = 1
      enkSayac = Enkoder
      zorlanma = sayac
      sayac = 0
      Inc saniye
      Toggle SES
       
     
      If zorlanma = 0 Then      ' zorlanma yada durma olduysa - bir tur 250~ devir iken, 200 sıkışmış anlamına geliyor.
         say = say + 1
         'A_Noktasi = 1   
         
      EndIf                   
   EndIf
EndIf   

'SHOut R_data, T_clk, 5, [saniye]
BirSaniye = 0                   
Enable
Resume
End


   

ete

INT-0 ve INT-1 kesmeleri ile bu iş olmaz. Önceden de söylediğim gibi değişiklik kesmesi ile olur.
Verdiğim resimden yararlanarak açıklayayım.
ESKI=%01 (%BA) olarak başladığımızı farz edelim.
1. nolu okuma noktasına bakarsan A=1 ve B=1 olmuş bu bir port değişikliğidir. Önceden %00 ike şimdi %11 olmuş hemen kesme oluşur ve kesmeyi kim oluşturur tabiiki B pini oluşturur. Zaten kimin oluşturduğu çok da önemli değil.
Hemen YENI=%11  olarak encoder pinlerini okursun ve YON=ESKI.1 ^ YENI.0 şeklinde YON=1 bulursun bu diyelimki saat yönü olsun. O halde SAYAC=SAYAC+1 yapacaksın demektir.
Kesmeden çıkmadan ESKI=YENI yaparak son okumayı kayda alırsın. Kesmeden çıkarsın.
2. nolu okuma noktasına gelince yeniden kesme oluşur. Çünki ESKI=%11 iken YENI=%10 olmuştur. Benzer şekilde YON=1 çıkacaktır yine ve SAYAC=SAYAC+1 den sayac değeri toplanacaktır.
Bu noktada encoderin geri döndüğünü düşünelim. Encoder tekrar 1 noktasına gelince yeniden kesme oluşacaktır. Zira ESKI=%10 iken YENI=%11 olmuştur. YON=YON=ESKI.1 ^ YENI.0  eşitliğinden  YON=0 çıkacaktır. Bu ise SAYAC=SAYAC-1 şeklinde hesap yapmanı gerektirecektir.
Bu kadar basit bu iş ve bu sistemde tıkır tıkır çalışır.
Ben bu sistemide kullandım ama benim programların kesme haricindeki bölümleri çok yüklü olmayınca kesme kullanmak ile kullanmamak arasında bir fark oluşmadı. Bu yüzden yerine göre kesme ile yerine göre kesmesiz alt program şeklinde bu işi hallederim.

Ete

DigMan

Hocam şimdi anladım bunu yapıcam ve uygulucam.Forumda konuyla alakalı başka bir yerde, enkoder işi en mükemmel B0 ve B1 kesmeleri ile okunduğunu yazan yorumunuzu okumuştum. Ayrıca bir kart geçmişti elime alman üretimi.Bunda da RB0-RB1 kesmelerini kullanmışlardı. Bunu neye göre söylediniz? Bu yöntem daha iyi ise nasıl bir yol önerirsiniz hocam? çünkü kartta da hiç bir değişiklik yapmadan bu şekilde devam etmiş olurum.

ete

B0 ve B1 kesmelerinde sürekli olarak düşen kenarla yükselen kenar kesmesi yaratmak üzere kenar değişikliği yapmak gerekir. Ama değişiklik kesmesinde bir şey yapman gerekmiyor çünki kesme bir öncekinden farklı ise yaratılıyor. Tam da bize gerekli olan şey. Öyle değilmi.
Yorumum olduğunu söylemişsin ama hatırlamıyorum yerini bulursan söyle en azından o yorumu düzelteyim çünki doğru değil.

Ete

DigMan

Hocam teşekkür ederim. dediğiniz gibi tam bizim istediğimiz de bu.Şimdi tekrar yazıcam programı.
Kafama takılan bir kaç şey daha var hocam.Osilaskopla baktım, 24V da enkoderin her durum değişikliği 2us de gerçekleşiyor. 4 durum değişikliğini 8us de tamamlıyor. işlemcimiz yavaş kalıp pals kaçırma yaşar mıyız hocam? Bi de donanımsal kesmelerin hızı nedir? kristale ve osilatöre bağlımıdır? Bilgileriniz için sağolun...

ete

#7
2us de hiç bir encoder pulsi konum değiştirmez. Bir yanlışın olmalı. Us değilde ms olmasın.
ete

İlave:
2 us de bir puls değişimi demek sinyalin peryoudu'nun 4us olması demektir. 1/T formülünden Encoder frekansının ;
F=1000000/4=250.000 Hz yani 250 Khz olduğu hesaplanırki gördüğüm en büyük puls üreteci encoder 1000 puls üretebiliyor idi. Yanıda 250.000 çok büyük durmuyormu sence? Bir yanlışlık olduğu kesin bence.

DigMan

Analog osilaskopla ölçtüm hocam, dediğiniz gibi yanlış ölçmüş olabilirim. Ben şu motorlardaki pals - frekans ilişkisini de anlayabilmiş değilim.elimdeki motorun turu 100 pals. enkoder bir turda 4 durum değiştiriyorsa, her 25 palsde bir durum(örn.0-1) mu görmemiz gerekiyor? Peki 100 pals/palsler ne işimize yarıyor? Burayı bir türlü anlayamadım. enkoderi elimle çevirip lcd den okumaya çalıştığımda yukarıda söylediğimi doğrular bir şekilde sonuç aldım.AB çıkışı hemen durum değiştirmiyor.çalışması bu şekildemidir hocam?

hocam söylediğiniz gibi portb change kesmesini de yapmaya çalıştım ama sanırım diğer kesmelere benzemiyor.Bir türlü çalıştıramadım.Programı gönderiyorum nerde eksik yada yanlış yapıyorum bi bakarmısınız?


        OPTION_REG = $07   
        INTCON     = $A8
       

On Interrupt GoTo KESME

'******************************************

basla:
   
    If ARTI = 0 Then GoSub ac
    If EKSI = 0 Then GoSub kapat
    eski = PORTB & %00110000
   
GoTo basla

'******************************************

ac:


Return

'******************************************

kapat:


Return

'******************************************


Disable
KESME:
       
If INTCON.0 = 1 Then  'RB PORT değişiklik kesme bayrağı
   INTCON.0 = 0
   yeni = PORTB & %00110000
   yon = eski.5 ^ yeni.4
   If yon = 1 Then Inc sayac
   If yon = 0 Then Dec sayac
   eski = yeni
     
EndIf
Resume
Enable
End

ete

#9
Eski değeri başla satırından evvel bir kereliğine belirlenmeli. Ana program içinde artık bir daha eski şudur denilmemeli zira kesme içinde de eski=yeni diyorsun birde ana programda bunu yaparsan program hangisini esas alacak sence. İş çorbaya döner. Başla satırından evvel bir kere eski yi tayin edersin ve ilk kesme oluştuğunda bu tayin edilen kullanılır. Sonrasında kesme içinde zaten eskiye değer veriyorsun.

Ben olsam önce ders notlarından PortB değişiklik kesmesi nasıl kullanılıyor bir bakardım. Sen sürekli kestirmeden gidiyorsun ama tökezliyorsun. Sebebi de bilgi eksikliğin elbette.
Kesme oluşunca kesme bayrağı mutlaka sıfırlanmalıdır. Intcon.0 bitini  kesmeden çıkmadan sıfırlaman gerekir. Değişiklik kesmesi en son okunan port değeri ile yeni değerleri karşılaştırarak değişiklik var ise kesme oluşturur. Bu nedenle kesmeden çıkmadan portB mutlaka okunmalıdır (durum=portb).
Böylece kesmeden çıkınca portda oluşacak değişiklik anında işlemci tarafından tespit edilir aksi halde kesme hiç oluşmaz.

Ete

DigMan

inanın hem sizin forum olsun hem de protonun kendi forumu olsun her yeri araştırıyorum, şu son yorumunuz gibi bir açıklama göremedim hiçbir yerde. Hocam bi de bişey farkettim. protonbasic.co.uk forumunda örneklere daha çok yer veriliyor.Bunun sebebi ise sanırım ırkımızla alakalı biraz. kıskanç ve fesat bir toplum olduğumuz için programlarımızı zor da kalmadıkça paylaşmıyoruz.Bunu forumun bir yerine not geçseniz de üyeler daha çok örneklerle konuşsa süper olacak.

Ayrıca neden kızdınız bana anlamadım :)  şu forumda neler görüyorum.siz de bizzat yaşıyorsunuz zaten. ben hiç olmazsa bunlardan kat ve kat iyiyim hocam kızmayın :)

bilgim tabiki eksik ve size sorarak öğrenmeye çalışıyorum.hazıra konmak yok araştırıyorum. son yaptığınız açıklama gayet anlaşılır ve hiç bir yerde yok.örnek olsa harika olacak ama napalım buna da şükür..

ete

Kızdığımıda nerden çıkardın. Kızmış olsam cevap yazmam yada yazdığım cevapta direk kızdığımıda söylerim ben.
Genelde uslubum serttir. Bu sertlik zaman zaman yanlış değerlendiriliyor halbuki yönlendirme amaçlıdır o uslup.
Genelde işe yarıyor. Amacım kişinin bir şeyler öğrenmesidir. Örneği direk olarak yazmış olsam birşeyler öğrenebileceğini sanmam. Ama bu şekilde adım adım öğrenerek gidiyorsun ne güzel işte değilmi?
Bu açıklamaların sana yeteceğini umuyorum. Yapamazsan zaten sonunda ben yazacağım olmayan kısmı. Ama buna güvenme çok zor yazarım artık bu kadar açıklamadan sonra. Sen en iyisi başarmaya çalış bence.
Ayrıca örnek yok diye sızlanma en can alıcı yerlere parantez içinde açıklamalar koyuyorumki işin örneği odur aslında.
BU kesme türünde can alıcı nokta Port'un okunması olayıdır. Basla satırından evvel DURUM=PORTB şeklinde bir satır koyarsan işe başlamadan işlemciye PortB nin durumu hakkında bilgi vermiş olursun. Bu bilgi değişince kesme oluşacaktır hemen.
O halde kesmeden çıkmadan tekrar aynı bilgiyi işlemciye vermek gerekir. Bu durumda Kesmeden çıkmadan evvel DURUM=PORTB şeklindeki komut satırı bu işi yapacaktır.
Artık geriye sana sadece kesme bayrağını sıfırlamak kalıyor zaten. Bak açıklama örneğin yerine geçiyor işte.

Ete

Powered by EzPortal