PORTB değişiklik kesmesi ile enkoder okuma

Başlatan DigMan, 05 Ekim 2014, 18:47:16

DigMan

Hocam ve diğer arkadaşlar merhaba.Hepinizin bayramını da kutlarım.

Hocam daha önce RB0 int ile enkoder okuma adında başlık açmıştım. Siz de bana RB değişiklik kesmesini önermiştiniz.O günden beri üzerinde çalışıyorum denemediğim uygulamadığım şey kalmadı.Bir türlü kesmeyi açamadım.Delircem hocam.Lütfen yardımlarını bekliyorum.Bu arada eğer ben de bir tersik yoksa B4 ve B7 portlarının hepsinin giriş olması gerekiyor kesme oluşması için. Doğrumudur hocam? siz de uygulamalarınızda bunu gördünüz mü? Ben durmadan deniyorum, durmadan yazıp uyguluyorum, bunca zamandır sessiz kalmam sorunları kendim çözebilmem içindi.Fakat olmadı bir türlü.sorun nedir anlayamadım.

en sade haliyle aşağıdaki gibi yazdım olmadı bir türlü.Motoru çeviriyorum kesmeye giriyor ama dengesiz çalışıyor.led yanıp sönüyor, yada sürekli yanıyor sönmüyor,motor hızlanıp yavaşlıyor, garip çalışıyor.Yardımlarınıza ihtiyacım var Hocam.emin olun kafayı yicem.Yapmadığım şey kalmadı gibi.nerde hata yapıyorum? enkoderı bir türlü okuyamıyorum:((


Device 16F876A
Declare XTAL 20
ALL_DIGITAL = On

REMINDERS OFF
Config HS_OSC, WDT_OFF, PWRTE_ON, BODEN_OFF, LVP_OFF
REMINDERS On

TRISB   = %11111111
Input  PORTB.4
Input  PORTB.5
Input  PORTB.6
Input  PORTB.7

        DelayMS 500
        On_Interrupt GoTo KESME
        OPTION_REG = $80 
        INTCON  = $88

eski = PORTB

basla:
If ARTI = 0 Then GoSub AC
If EKSI = 0 Then GoSub KAPAT
GoTo basla

AC:
High MTR_STOP
Low MTR_SAG
PWM MTR_SOL, hiz, 50
Return

KAPAT:
High MTR_STOP
Low MTR_SOL
PWM MTR_SAG, hiz, 50
Return


Disable
KESME:
Context SAVE       
   
   eski = PORTB
   Inc sayac
   If sayac = 5 Then sayac = 0 : Toggle LED
   INTCON.0 = 0
   
Context Restore                   
Resume
Enable


İlyas KAYA

#1
Pic Basic ile 3 gündür uğraşıyorum 15x200 palsi PBP ile okuyamadım. Okuyamadım değil motor yavaş çalışırken sorunsuz okuyor ancak motor hızlandığında 20mhz osilatör ve LCD bu hıza yetişemiyor.

Kötü komşu mal sahibi yapar hesabı bende oturdum dün geceden bu yana CCS C öğrendim.

Şuan hangi hızda olursa olsun okumayı epey sağlıklı yapıyorum.

ADC yi oku , pwm 'i bas , encoderi oku bütün işlemleri sadece 8 mhz de bitirdim.
8 mhz 'de ufak hatalar yapıyor ancak yaptığım iş de tamamen önemsiz.
Osilatörü 20 mhz 'e geri çıkarttığımda o ufak sorunlarda kalmayacaktır eminim.


Geriye sadece kullanıcı ara yüzü kaldı. İleri geri , sayım vs.


Tavsiyem CCS C ye geçin rahat edin.
Göz odur ki dağ ardını görsün,
Akıl odur ki başa geleceği bilsin.!

ete

PortB.0 kesmesi ile encoder okuma o kadar da zor değil.

Öncelikle PortB değişiklik kesmesi nedir onu açıklayalım isterseniz. Sonra bunu bir örnekle gösterelim.
PORTB de 4-7 bit pinlerine uygulanabilecek bir kesme türü dür.
Hangi pin kullanılacak ise o pinin Giriş olarak atanması gerekir. Kesme nasıl oluşur onuda açıklayalım. Bu sistemde yükselen kenar yada düşen kenar kesmesi diye bir şey yoktur.  İşe, PORTB yi yada yalnızca kesme oluşturan Port pinlerini okuyarak ve bunu geçici bir değişkene atarak başlanır. Böylece program Portun ilgili bitlerinin o andaki konumlarını  bilmiş olur.
Bu konumlardan birisi değiştiği anda kesme oluşur. Bu özelliği nedeni ile aynı pin yükselen kenarda da kesme oluşturur, düşen kenarda da kesme oluşturur. Şimdi örneğimize geçelim.

Varsayım: PORTB.6 (A) ve PORTB.7 (B) pinlerinden Encoderi giriyoruz. Encoderimiz tur başına 200 puls veren bir encoder olsun. Bu encoderin dönmesi halinde yön tayini yapılacak ve sayılan değer ekranda gösterilecektir.
'****************************************************************
'*  Name    : ENCODER.BAS                                       *
'*  Author  : [select VIEW...EDITOR OPTIONS]                    *
'*  Notice  : Copyright (c) 2014 [ETE]                          *
'*          : All Rights Reserved                               *
'*  Date    : 06.10.2014                                        *
'*  Version : 1.0                                               *
'*  Notes   :                                                   *
'*          :                                                   *
'****************************************************************
@ DEVICE pic16F628A
@ DEVICE pic16F628A, WDT_off
@ DEVICE pic16F628A, PWRT_On
@ DEVICE pic16F628A, PROTECT_OFF
@ DEVICE pic16F628A, MCLR_On
@ DEVICE pic16F628A, HS_OSC
DEFINE OSC 20
CMCON=7
'---------------------------------------------------------------
PORTA=0:TRISA=%00000000
PORTB=0:TRISB=%11000000
'-------------------------------------------------------------
DEFINE LCD_DREG   PORTA 'LCD data bacakları hangi porta bağlı?
DEFINE LCD_DBIT   0 'LCD data bacakları hangi bitten başlıyor?
DEFINE LCD_EREG   PORTB 'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT   0 'LCD Enable Bacağı Hangi bite bağlı ?
DEFINE LCD_RSREG  PORTB 'LCD RS Bacağı Hangi Porta bağlı ?
DEFINE LCD_RSBIT  1 '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.

INTCON=%10001000  'Kesmeler aktif ve   PORTB Değişiklik kesmesi aktif
'---------------------------------------------------------------------
SAYAC  VAR WORD 56
SAY    VAR BYTE 58
TEMP   VAR BYTE
ESKI   VAR BYTE
YENI   VAR BYTE

YON    VAR BIT

SYMBOL A=ESKI.6
SYMBOL B=YENI.7
SYMBOL BAYRAK=INTCON.0
'---------------------------------------------------------------------
LCDOUT $FE,1

PAUSE 250

LCDOUT $FE,$80,"LUTFEN  BEKLEYIN"
ESKI=PORTB
bayrak=0
sayac=0
PAUSE 250
LCDOUT $FE,1
BASLA:
      lcdout $FE,$80,"YON=",DEC1 YON
      LCDOUT $FE,$C0,"SAYAC=",DEC SAYAC ,"    "

      GOTO BASLA     
     
DISABLE
KESME:
         YENI=PORTB & %11000000
         YON=A ^ B
         IF YON=1 THEN
           SAYAC=SAYAC+1
         ELSE
           SAYAC=SAYAC-1
         ENDIF
         ESKI=YENI
         TEMP=PORTB
         BAYRAK=0
         RESUME
         ENABLE

Söz konusu programınnasıl çalıştığını görmek istiyorsanız ilişikteki dosyalara bakınız.

Ete

DigMan

İlyas, önerin için teşekkür ederim. Söylediğin şey hemen dönüş yapabileceğim bir durum değil. Basic de biraz daha zorlamam gerekiyor. Ete hocam çok teşekkür ediyorum hemen deneyip sonuçları bildiricem...

ete

Çift encoderlisinide hazırladım. Tekli olana Encoder_A çiftliolana Encoder_AB ismini verdim.
Dosya ilişiktedir.

Ete

DigMan

Hocam, ilk verdiğiniz neydi? Çift enkoderdan kast ettiğiniz nedir?
Bir de ilk verdiğiniz programda temp= portb diye hiç bir yerde kullanmadığımız bir kod var.Bu ne işimize yarıyor? bunu anlayamadım.

DigMan

Anladım hocam, çift motorlusuymuş.
Fakat, eski-yeni diye portb yi okumamıza rağmen hala temp=portb yi çözemedim :(

ete

Kesme mantığı,  portB nin 4-7 pinlerinden giriş olarak ayarlanmış olanlarda öncekine oranla bir değişiklik olup olmadığına göre çalışır. TEMP değişkeni Portun değerini komple alır. Alınan değer saklanır ve bu değer değiştiğinde hemen kesme oluşturulur.
Kesme den çıkmadan önce Portun değerini okuyarak saklmaış oluyoruz. Böylece sistem bu değerde herhangi bir değişiklik olduğunda kesmeyi aktif hale getirmektedir.

Ete

DigMan


Hocam harikasınız beyninize sağlık  :) evet dediğiniz gibi RB port değişiklik kesmesi enkoder için en idealimiş.Yazdım denedim, gerçekten güzel çalışıyor. Çok sağolun. En basit haliyle aşağıdaki gibi programım. Enkoder sayarken LCD de gördüğüm rakam oldukça büyüktü. Elimdeki motor 100 pulse. A ve B yi  kullandığımız için de çözünürlük 400 oluyor.Çıkan rakamı 400 e böldüğümde tur sayısını buldum.Yön tayini ve tur sayısı bakımından da bir problem yok herşey harika.Fakat motorun durduğunu algılamayı beceremedim.
Daha önce portb.0 kesmesini kullanıyodum. ayrıca tmr0 kesmesiyle anlık tur sayısı okuyup sıfırlayarak motorun durduğunu anlayabiliyordum.Burda da denedim ama iki kesme açılınca çakıldı program.Sanırım kesme içinde fazla kod kullanımından dolayı.kodları azaltmayı denedim olmadı.tmr0 kesmesini yaklaşık 1 sn ye ayarlamıştım.
(if eski = yeni then....) ifadesinden yola çıktım.motor durduğunda yada zorlandığında eşit olacakları kesin. ama pek sağlıklı olmadı her zaman algılamıyor.Düşünüyorum aklıma başka birşey gelmiyor.ikinci bir kesmede çakılmasaydı çok güzel olacaktı.Nasıl bir algoritma uygulayabilirim hocam? nasıl bir yol izlenebilir?  (Forumda araştırıyorum bu arada)

basla:
If ARTI = 0 Then GoSub ileri (+motoru süren pwm)
If EKSI = 0 Then GoSub geri (- motoru süren pwm)
GoSub cevir (sayac/400 değeri 7 segmente çevriliyor)
SHOut DSP_DT, DSP_SH, 1, [hane_100, hane_10, hane_1]
PulsOut DSP_LT, 1
GoTo basla

Disable
KESME:
Context SAVE       
   
     yeni = PORTB & %11000000
     yon = A ^ B         
         If yon = 1 Then Inc sayac
         if yon = 0 then Dec sayac
       
     eski = yeni
     temp = PORTB
     RB_BAYRAK = 0

Context Restore                   
Resume
Enable

ete

#9
Program bir döngüdür. İki etiket rasında gidip gelir. Bu gidip gelme esnasında önüne çıkan komutları işler ve bunlarında bir işlenme zamanı vardır. O halde bir değişken tanımlasan mesela DUR gibi. Basla il Goto basla arasında bir yere DUR=DUR+1 koysan. Bu DUR isimli değişkeni yalnızca Kesmeden çıkmadan evvel sıfırlasan nasıl olur? İlave bir kesme kullanmadan encoderin durup durmadığını kolaylıkla anlarsın. Her encoder kesmesi oldukça DUR=0 olacağı için dur değeri 250 ye ulaşamayacaktır. Ama Sonra Dur değeri şayet 250 olmuş ise encoderin durduğunu anlamış olursun. Bu noktada yapacaklarını yapıp Dur=0 yapmanda gerekli .
Encoderin durduğunu neden bilmek istiyorsun ?. Örneği verdim ama DUR Byte cinsinden olursa ve encoder durunca ekrana bilgi yazarsan sayaç 20 Mhz de çok hızlı sayıp anlık olarak 0 dan 250 ye ulaşmaktadır. Bu durumda Dur değişkeni Word cinsinden alınıp gerekirse daha büyük bekleme rakamları kullanılabilir mesela 1000-2000 gibi.
Ama ekrana sayılan değerler anında yazılsın istiyorsan LCD nede olsa encoderin saymasını az da olsa geciktirmektedir bunuda bilesin.

Ete


DigMan

#10
Hocam, evet söylediğiniz benim de aklımdan geçti ve değişkeni word yapıp 50000 değerini verdim. Hemen test ettim motor durmadı.sonra bu değişkende neler oluyor diye lcd ye yazdırıp izledim. 20MHz de çalışmama rağmen 50 yi zor görüyor.30 yapıp test ettim yaklaşık yarım saniyede hemen durdurdu.Bu rakam neden bu kdr küçük çıktı anlamadım ama işimi de gördü sonuçta.Daha sonra detaylı incelicem.Ben lcd veya 7 segmenti değişkenleri izlemek için kullanıyorum.Normalde projede yok yani hocam.
Hocam eğer mümkünse sizden bir ricam var.Şu enkoderin her durum değiştirme süresini çok merak ediyorum.elimdeki motor 24V/100pulse - 3300 d/dk.ben bu motorun A-B uçlarını analog osilaskopla ölçmüştüm ve her durum değişikliğini 2us olarak bulmuştum.Fakat siz bu kdr küçük çıkmaz dediniz kafama takıldı. Malum analogla yanlış ölçme olasılığım çok çok yüksek.benzer bir motor varsa elinizde ve de digital bir osilaskoba sahipseniz ölçmeniz mümkün mü? Bunu, güzel çalışmasına rağmen portb4...7 değişiklik kesmesi bile puls kaçırırmı diye soruyorum..

ete

100 Puls/dev encodere sahip 3300 dev/dak lık motor, 1 sn de 3300/60=55 devir ile döner. Bu durumda 55x100=5500 puls üretir. Bunu direk frekans olarak alsak peryodu 1000.000/5500=181 us eder ki bunun yarısı olarak yakalşık her puls 90us de bir değişmesi gerekir diye hesaplıyorum. Sen aynı süreyi 2us gibi bir değerle ölçtüğünü söylüyorsun ki buda imkansız olan şey bence. Bana göre program bu pulsleri yakalar.
Elimde motor+encoder düzeneği yok maalesef. Söylediğin denemeyi yapmam imkansız.

Ete


Powered by EzPortal