Yukarı çıkan aşağı inen kapı için pic16f628a timer 0 kesmesi ile saydırma

Başlatan yasargunaydin, 12 Mart 2013, 12:20:02

yasargunaydin

Arkadaşlar Merhaba;
Aşağıda yazdığım problem için yardım edebilirmisiniz.
Aşağı yukarı hareket eden bir kapı var.En alt konumda kapalı iken swic takılı ve başlangıç pozisyonum.Yukarı durma noktasında swiç vb yok.Saydırma ile durduruyorum.(say=700)
Yukarı çıkarken kesmede say=say+1 ,aşağı inerken ise say2=say2-1 kullanmaya çalıştım ve dur butonuna basılır ise bunları hafza =say diyerek bir dahaki yukarı veya aşağı inmede sayım işlemine buradan başlamasını istedim.

Fakar yukarı çıkarken durdurulup aşağı indirilirse ve tekrar swiç görmeden yukarı basılırsa sayma işlemleri karışıyor.En üst durma noktası değişiyor.
Acaba kesmedemi bir hatam var.

Yardımlarınız için şimdiden teşekkürler...
PORTA=0
PORTB=0
TRISA=%11111111
TRISB=%00000000
'-----------------------------------------------------------------
@ DEVICE pic16F628A                      'işlemci 16F628                               
@ DEVICE pic16F628A, WDT_OFF              'Watch Dog timer açık
@ DEVICE pic16F628A, PWRT_ON             'Power on timer açık
@ DEVICE pic16F628A, PROTECT_OFF         'Kod Protek kapalı
@ DEVICE pic16F628A, MCLR_off            'MCLR pini kullanılıyor.
@ DEVICE pic16F628A, INTRC_OSC_NOCLKOUT  'Dahili osilatör kullanılacak
'-----------------------------------------------------------------

'-------------------------------------------------------------------------
ON INTERRUPT GoTo KESME   'kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10000101   'Pull up dirençleri İPTAL- Bölme oranı 1/64.
INTCON=%10100000  'Kesmeler aktif ve TMR0 kesmesi aktif
TMR0=0
CMCON=7    '16F628 de komparatör pinleri iptal hepsi giriş çıkış
'----------------------------------------------------------------------------

SYMBOL BASPOS=PORTA.1
SYMBOL YUKARI=PORTA.3
SYMBOL DUR=PORTA.2
SYMBOL ASAGI=PORTA.0
SYMBOL SENSOR=PORTA.4
SAY VAR WORD  'PERDE YUKARI ÇIKARKEN SAY
SAY2 VAR WORD  AŞAĞI INerken say
SAY2=0        'aşağı inerken saysın
HAFZA VAR WORD
HAFZA =0

PORTB=%00000000

BASLA:     

high portb.0
low portb.1
IF BASPOS=0 THEN GOTO ASAGIDA
GOTO BASLA


ASAGIDA:
SAY=0:say2=0
IF BASPOS=1 THEN GOTO ASAGIIN
high portb.6
low portb.0
low portb.1
IF YUKARI=0 THEN  GOTO YUKARICIK
GOTO ASAGIDA


YUKARDA:
high portb.7
low portb.0
low portb.1
IF ASAGI=0 THEN SAY=0:say2=700: GOTO ASAGIIN
GOTO YUKARDA

YUKARICIK:
high portb.1
low portb.0
low portb.6
low portb.7
IF SAY>700 THEN say=0 :GOTO YUKARDA
IF DUR=0 THEN  hafza=say : GOTO DURDUR
GOTO YUKARICIK

ASAGIIN:
high portb.0
low portb.1
low portb.6
low portb.7
IF  BASPOS=0 THEN  GOTO ASAGIDA
IF DUR=0 THEN  hafza=say2 :GOTO DURDUR
GOTO ASAGIIN




DURDUR:
Low portb.0
low portb.1
low portb.6
low portb.7
IF (YUKARI=0)  THEN SAY=HAFZA:GOTO YUKARICIK
IF ASAGI=0 THEN SAY2=hafza: GOTO ASAGIIN
GOTO DURDUR

DISABLE
KESME:
'high portb.2
'low portb.3
'low portb.4
SAY=SAY+1
SAY2=SAY2-1
pause 10
'high portb.3
'low portb.2
'low portb.4
SAY=SAY+1
SAY2=SAY2-1

pause 10
'high portb.4
'low portb.3
'low portb.2
SAY=SAY+1
SAY2=SAY2-1

pause 10

INTCON.1=0        'TMR0 Kesme bayrağı sıfırlanıyor
RESUME
ENABLE 
       
END




yasargunaydin


ete

Böyle bir sistemde tmr0 sayacı kapıya hareket verildikten sonra saymaya başlasa daha uygun olurdu.
Ayrıca zamanlama hesabı yaptınızmı bilemiyorum. Şu hali ile program her 16,3 ms de bir kesme oluşturacak şekilde kurulmuş gözüküyor ancak kesme içine koyduğunuz pause ler işini bozacak nitelikte. Zira tmr0 geri planda hiç durmadan çalışan bir sayaçtır. Sizin pauselerin işlenmesi esnasında da sayar ve kesmeden çıktığınızda muhtemelen epeyce saymış olarak çıkacak hatta anında yeniden kesme bile oluşturabilecektir.
Diğer taraftan neden kesme içinde 3 defa sayac değeri artırdığınızı anlamış değilim. Anlamadığım bir şeyde neden hem artırma hem diğer sayaç için eksiltme yaptığınız. Zira kapı yukarı giderken bir sayaç aşağı giderken diğer sayac sayması gerekirdi. Aslında tek sayaç bu işi mükemmel yapabilirdi.
Kapının alt konumdan üst konuma ulaşma süresini hesaplayıp buna uygun bir kesme süresi ayarlamanız daha uygun olurdu. Örnek veriyorum. Diyelimki kapı yukarı doğru son noktaya 20 sn de ulaşıyor. Bu 20000 ms eder. Bunu 200 e bölerseniz 100 sayısını elde edersiniz. O halde her 100 ms de bir kesme oluşturup kesmeleri sayarsanız 200 kesme sonunda kapıyı durdurmanız gerekir.  Ancak 4 Mhz de tmr0 kullanarak oluşturabileceğiniz en büyük kesme süresi yaklaşık 65 ms dir. Bu durumda 20000/65=307 defa kesme saymanız gerekir. Buda sayacınızın word tipinde bir değişken olmasını gerektirir.
Sonuç olarak kesme sürenizi sabit bir sayı olarak belirleyin. Mesela her 50 ms de bir olsun. Bunun için kesmeden çıkmadan tmr0  a yeni değer vereceğinizi unutmayın. Kesme içine pause hiç kullanmayın.
Kesmeyi kapıya hareket verince aktive edin. Bunu yaparken kendi sayacınızı sıfırlayın.
Aynı sayacı hem aşağı hem yukarınkonumda kullanabilirsiniz. Bir bit değişkeni (Yon) kullanıp 1 ise yukarı 0 ise aşağı hareket kabul edin. Böylece yon değişkenine bakarak sayacın kaç olmadı gerektiğine karar verin.
Kapı durduğunda Intcon.5=0 vererek kesmeyi kapatın. Benzer şekilde kapıya hareket verdiğinizde Intcon.5=1 diyerek yeniden açın.
Ete
Bilgi hazinedir paylaştıkça büyür.            http://etepic.com

yasargunaydin

Erol Bey;
Öncelikle cevabınız için çok teşekkür ederim.Yorumlarınızı uygulamak için çalışmaya başladım.Timer içinde pause kullanmam acimiliğimdendi.
say=say+1 amacım yukarı çıkarken say artsın ve kapı durdurulursa hafza=say (mesela 600) diyerek hafızaya almak.
aşağı butonuna basılıncada say2=hafza  devreye girsin ve 600 den geriye doğru saysın
amacım bu idi.Ama tabiki olmadı.bahsettiğiniz problemler ile karşı karşıyayım.

Proğramımda Intcon.5=1  ve Intcon.5=0 kullanıyorum daha iyi oldu.
Fakat hocam  her 50ms de kesme oluşması için yazmam gereken komutu yazamadım.Veya bunu her 25ms de istersem nasıl yazmalıyım.


Kesme bölümünde pause ları sildim ve proteusta kartıma lcd taktım.her kesmeye gittiğinde sayı 1 artıyor ve 1 kaç saniye içerisinde 65000 lere ulaşıyor.

Hocam tekrar teşekkürler

yasargunaydin

Hocam Heralde şimdi oldu,
sayıyı göreyim diye proteusta lcd de ekledim.şimdi oluyor gibi.Dediğiniz gibi yukarı çıkarken y=1 aşağı inerken a=1 yaptım ve kesme bölümünde  aşağıdaki gibi yazdım.Ama kesme süresini nasıl artırabilirim.Yarın 65000'e kadar saydırsamda kapı yeterli yüksekliğe çıkmazsa ne yaparım.Yardımlar için tekrar teşekkürler.

KESME:
IF (Y=1) AND (A=0) THEN SAY=SAY+1
IF (Y=0) AND (A=1) THEN SAY=SAY-1

INTCON.1=0        'TMR0 Kesme bayrağı sıfırlanıyor
RESUME
ENABLE 
       
END


Proğram aşağıdaki gibi


SYMBOL BASPOS=PORTA.1
SYMBOL YUKARI=PORTA.3
SYMBOL DUR=PORTA.2
SYMBOL ASAGI=PORTA.0
SYMBOL SENSOR=PORTA.4
SO VAR PORTB.5
SAY VAR WORD  'PERDE YUKARI ÇIKARKEN SAY
SAY2 VAR WORD  'DURURKEN SAYMA  SONRA AŞAĞI IN
SAY2=0        'aşağı inerken saysın
HAFZA VAR WORD
HAFZA =0

Y VAR BYTE 'YUKARI ÇIKARKEN Y=1 A=0 OLSUN
A VAR BYTE 'AŞAĞI İNERKEN   A=1  Y=0OLSUN
PORTB=%00000000

'CLEAR  'tüm değişkenler sıfırlandı
'PAUSE 200
'LCDOUT $FE,1
'SAY=0

'------------------------------------------------------------------------------

A=0:Y=0

BASLA:
Intcon.5=0 'KESMEYİ DURDUR 
high portb.0
low portb.1
A=1'AŞAĞI İNİYOR
IF BASPOS=0 THEN GOTO ASAGIDA
LCDOUT $FE,$84,DEC SAY,":"   
GOTO BASLA


ASAGIDA:
A=0:Y=0
Intcon.5=0  'KESMEYİ KAPAT
SAY=0
low portb.0
low portb.1
IF YUKARI=0 THEN Y=1:A=0: GOTO YUKARICIK
LCDOUT $FE,$84,DEC SAY,":"
'LCDOUT $fe,1,"SY.=",DEC SAY,":","SAY2.=",DEC SAY2,":"
LCDOUT $fe,$C0,"ASAGIDA", DEC SAY2
GOTO ASAGIDA


YUKARDA:
A=0:Y=0
Intcon.5=0 'KESMEYİ DURDUR
low portb.0
low portb.1
IF ASAGI=0 THEN A=1:Y=0:Intcon.5=1: GOTO ASAGIIN
LCDOUT $FE,$84,DEC SAY ,":" ,DEC A,":",DEC Y
'LCDOUT $fe,1,"SY.=",DEC SAY,":","HF.=",DEC HAFZA,":"
LCDOUT $fe,$C0,"YUKARDA"
GOTO YUKARDA


YUKARICIK:
A=0:Y=1
Intcon.5=1 'KESMEYİ AÇ
LCDOUT $FE,$84,DEC SAY ,":" ,DEC A,":",DEC Y
'LCDOUT $fe,1,"SY.=",DEC SAY,":","HF.=",DEC HAFZA,":"
high portb.1
low portb.0
IF SAY>20000 THEN Intcon.5=0:A=0:Y=0 :GOTO YUKARDA
IF DUR=0 THEN Intcon.5=0:A=0:Y=0 : GOTO DURDUR
GOTO YUKARICIK


ASAGIIN:
A=1:Y=0
Intcon.5=1 'KESMEYİ AÇ
IF SAY<10 THEN Intcon.5=0:A=0:Y=0:GOTO ASAGIDA
LCDOUT $FE,$84,DEC SAY ,":" ,DEC A,":",DEC Y
high portb.0
low portb.1
IF  BASPOS=0 THEN A=0:Y=0:Intcon.5=0: GOTO ASAGIDA
IF DUR=0 THEN Intcon.5=0:A=0:Y=0 :GOTO DURDUR
GOTO ASAGIIN



DURDUR:
A=0:Y=0
LCDOUT $FE,$84,DEC SAY ,":" ,DEC A,":",DEC Y
Intcon.5=0 'KESMEYİ DURDUR 
Low portb.0
low portb.1
IF (YUKARI=0)  THEN A=0:Y=1:Intcon.5=1:GOTO YUKARICIK
IF ASAGI=0 THEN A=1:Y=0:Intcon.5=1: GOTO ASAGIIN
GOTO DURDUR

DISABLE
KESME:
IF (Y=1) AND (A=0) THEN SAY=SAY+1
IF (Y=0) AND (A=1) THEN SAY=SAY-1

INTCON.1=0        'TMR0 Kesme bayrağı sıfırlanıyor
RESUME
ENABLE 
       
END

http://postimg.cc/image/svb34jyz1/


haydarpasamikro

Bir de şu aklınıda bulunsun:

SAY2 = SAY2 -1 derken eğer SAY2=0 ise SAY2 nin yeni değeri -1 değil 65535 olur(word iken). Byte olsaydı 255 olurdu. Çünkü işaretli sayılarla çalışmıyoruz.
Mikro Dünyası.Haydarpaşa Teknik ve Endüstri Meslek Lisesi Mikrodenetleyici Atl. Şefi

yasargunaydin

OPTION_REG=%00000100       'Pull up dirençleri AÇIK (PORTB.7 için) – Bölme  oranı 1/32. 'bölücü ayarlaması  000=1/2, 001=1/4  , 010=1/8  , 011=1/16 , 100=1/32 ,  101=1/64 , 110=1/128, 111=1/256

Ok.Aklımda tutarım.Sağol