0

Çift kesme (RB0 ve Timer1) Kullanımı

Başlatan 0nur, 11 Eylül 2013, 12:28:30

0nur

Merhaba,

Motor devrini hesaplamak için encoderdan gelen verileri RB0 kesmesi ile sayıyorum, aynı zamanda timer1 kesmesinide kullanarak motor devrini hesaplamayı planlıyorum. Buna bir diğer alternatif olarak pulsin komutunu kullanmak ana döngüdeki işleyişi ne kadar yavaşlatır ve engeller ? Sizce RB0 ve Timer1 kesmesi ile mi yoksa pulsin komutu kullanarak mı yapmak daha mantıklı ?

Aşağıda yazmış olduğum proton kodunda amacım bir yandan timer1 500msnde bir kesme oluştururken diğer yandan b0 ile gelen sinyalleri saydırmak. 2 kesmeyi aynı anda kontrol etmek için kesme geldiğinde bak etiketine gönderip hangi kesmenin taşma bayrağı 1 ise ona bağlı yönlendirme yapıyorum. Timer1 in sayması gereken 500msn lik sürede tick değişkeni 1 artması gerekiyor, her b0 kesmesinde sayi değişkeni 1 artması gerekiyor, fakat sistemde her timer1 kesmesinde 2 değişkende 1 artıyor.. Çift interrupt kullanmadığım için bu hususta biraz kafam karıştı yardımcı olabilirseniz sevinirim.


Device 16F877   
Config HS_OSC , WDT_OFF, PWRTE_ON,  BODEN_OFF , LVP_OFF, CP_OFF 
Declare XTAL 4

'============================== LCD TANIMLAMALARI=====================================;

LCD_DTPIN = PORTD.4
LCD_RSPIN = PORTE.0
LCD_ENPIN = PORTE.1
LCD_INTERFACE =  4 ' 4-bit Interface
LCD_LINES =  4
LCD_TYPE  = alpha
LCD_COMMANDUS = 2000
LCD_DATAUS = 50
ALL_DIGITAL TRUE
Cls

'==========================================================================================================;           
'=====================================KESME TANIMLAMALARI ================================;             


On_Interrupt GoTo bak              'Software int. oluştuğunda INT etiketine git.

OPTION_REG.6=0
T1CON=%00110001    ' -------->>>  |  DİSABLE   |   DİSABLE   |   PS1    |  PS0   |   T1OSCEN  |   T1SYNC   |  TMR1CS   |   TMR1ON   |
         
Symbol INTF = INTCON.1      'RB0 KESME BARAĞI
Symbol INTE = INTCON.4      'RB0 KESME YETKİ
Symbol GIE = INTCON.7       'GLOBAL INT. YETKI
Symbol PEIE=   INTCON.6
Symbol TMR1E=  T1CON.0      ' TMR1 ENABLE BİTİ
Symbol TMR1IF= PIR1.0       ' TMR1 TAŞMA BAYRAĞI
Symbol TMR1IE= PIE1.0


TMR1IE=1 ' TMR1 AŞIMI KESME OLUŞTURMA AKTİF ETME BİTİ
TMR1IF=0 ' TMR1 AŞIM KESME BAYRAĞI
PEIE=1 
INTE=1                      'RB0 Kesmesi aktif
GIE=1                       'Aktif O an Tüm kesmelere Yetki ver     


TMR1H=$0b
TMR1L=$dc

'==========================================================================================================;
'=====================================PWM TANIMLAMALARI ================================; 

CCP1CON=%00001100
CCP1_PIN = PORTC.2   ' Select HPWM port and bit for CCP1 module. i.e. channel 1
CCP2_PIN = PORTC.1   ' Select HPWM port and bit for CCP2 module. i.e. channel 2     
   
'==========================================================================================================;
'============================= GİRİŞ - ÇIKIŞ VE DEĞİŞKENLER ==========================;
     
Input PORTB             
TRISC=0
Dim TICK As Word       
Dim Sayi  As Word         

Symbol mi=PORTC.0
Symbol mg=PORTC.1
Symbol led=PORTC.3
Symbol led2=PORTC.4       
Clear



'==========================================================================================================;
'============================= ANA DÖNGÜ ==============================================;

basla:
HPWM 1,125,1000
Print At 1,1,"RB0 KESMESI: ",@Sayi,"  "
Print At 2,1,"TMR1 TICK SAYISI: ",@TICK,"  "

GoTo basla                 
               
'============================================== KESME ======================================================       
   

bak:
If TMR1IF=1 Then GoTo INT
If INTF=1 Then GoTo Kesme
Return




Disable
INT:
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
Inc TICK
Toggle  led
Enable   
Resume


Kesme: 
Context SAVE                'kayıcıların içeriğini sakla
INTF=0 
Inc Sayi                'sayi değişkenini bir arttır   
Context Restore             'tüm kayıtcıların içeriğini tekrar yükle ve kesmeden çık
Stop


Mucit23

Bence rb0 kesmesini işin içine katma. Encoder dn gelen frekans yükseldikçe düzgün çalışmayabilir.

Encoden gelen sinyali saymak icin timer1 sayacını kullan. Timer1 clock kaynağını dışarıya verip encoderden gelen sinyalleri timer1 in harici clock girişine ver. Timer1 otomatikmen saysın. Sende timer 0 kesmesi ile timer1 in degerini oku. Sonra timer1 i sıfırlarsın.

Fakat bunada dikkat etmek gerekir. Encoder çok yüksek çözünürlüklü ise timer1 dolup taşabilir.
Bir ulusu yok etmenin En iyi yolu o ulusun dilini yok etmektir.

www.arectron.com/

0nur

Burada aslında en büyük sıkıntı şu ; iki kesmeyi aynı anda nasıl kontrol edebilirim... kesme oluştuğunda direk bak etiketine dallandırıp oradada iflerle bayrakların durumunu denetlemek uygun bir yöntemmi ? Ve motor devri ölçümü için düşündüğüm olay ; B0 kesmesi geldiğinde timer çalışmaya başlayıp bir sonraki kesmede kapanacak ve ben buradan peryodu elde edecem diye düşündüm. Bu konuyla ilgili bir örnek mevcutmu ?

ete

Yapmak istediğin işi yapmanın iki yolu var.Birincisini sen kullanmışsın zaten. Yeri gelmişken belirteyim bu yöntemde pek sorun çıkacağını sanmıyorum. Yalnızca kesme içinde çok iyi ve kısa kod yazman. Mesela kesme içinde iki bayrağı ayrı ayrı iflerle kontrol etmeye gerek yok. Yalnızca birisini if ile (TMR1 kesmesini) kontrol edersin. Zaten TMR1 kesmesi değilse B0 kesmesidir deyip altına b0 kesmesi ile ilgili kodu yazarsın.
Pek çok kez sorunsuzca kullandım bu metodu ben.

Diğeri ise TMR0 veya tercihan TMR1 sayacını dışarıdan tetikleyerek saydırma. Diyelimkli TMR1 sayacını dışarıdan girdiğimiz pulsler ile tetikleyerek saydıracağız. Encoder çıkışı TMR1 giriş pinine bağlanır. Program içinde zaman tutulur ve süre sonunda TMR1 değeri Devir değişkenine aktarılarak işlem tamamlanır. Aynı yerde TMR0 sayacınıda kullanabilirsin. Çözünürlük kurtardığı müddetçe bölme oranları en küçük seçmeye gayret etmelisin.

Ete

0nur

Yazılımda okuma yaparken rb0 kesmeye girdiğinde timerı açıp rb0 birdahaki kesmeye girene kadar çalıştırarak gelen sinyalin peryodunu hesaplamayı düşünüyorum. timer1 i 500 msn ye set ettim örneğin ve timer1 den 2 tick geldi. bu 2 tick arasında rb0 da 2 kez 1-0 1-0 değişimi oldu ve ben burada encoderın bir konum değişimini algılamış oldum. buradan Fr=1/t  => Fr = 1hz yani dönü frekansı 1 dev/sn olarak buluyorum. bunu da 60 ile çarptığımda benim elde etmem gereken devir 60 RPM oluyor. Sizce encoderdan bu şekilde veri okumak uygun bir yöntem mi ? Yada alternatif olarak nasıl birşey düşünebiliriz.

Not : elimdeki motorun encoderının devirdeki tick sayısı 16, yani 16 CPR ... Düşürme oranı ise 1:485

0nur


Device 16F877   
Config hs_OSC , WDT_OFF, PWRTE_ON,  BODEN_OFF , LVP_OFF, CP_OFF 

Declare Xtal 20

'============================== LCD TANIMLAMALARI=====================================;

Declare LCD_DTPin = PORTD.4
Declare LCD_RSPin = PORTE.0
Declare LCD_ENPin = PORTE.1
Declare LCD_Interface =  4 ' 4-bit Interface
Declare LCD_Lines =  4
Declare LCD_Type  = alpha
Declare LCD_CommandUs = 2000
Declare LCD_DataUs = 50
All_Digital TRUE
Cls

'==========================================================================================================;           
'=====================================KESME TANIMLAMALARI ================================;             


On_Hardware_Interrupt GoTo bak              'Software int. oluştuğunda INT etiketine git.

OPTION_REG.6=0
T1CON=%00110001    ' -------->>>  |  DİSABLE   |   DİSABLE   |   PS1    |  PS0   |   T1OSCEN  |   T1SYNC   |  TMR1CS   |   TMR1ON   |
         
Symbol INTF = INTCON.1      'RB0 KESME BARAĞI
Symbol INTE = INTCON.4      'RB0 KESME YETKİ
Symbol GIE = INTCON.7       'GLOBAL INT. YETKI
Symbol PEIE=   INTCON.6
Symbol TMR1E=  T1CON.0      ' TMR1 ENABLE BİTİ
Symbol TMR1IF= PIR1.0       ' TMR1 TAŞMA BAYRAĞI
Symbol TMR1IE= PIE1.0


TMR1IE=1 ' TMR1 AŞIMI KESME OLUŞTURMA AKTİF ETME BİTİ
TMR1IF=0 ' TMR1 AŞIM KESME BAYRAĞI
PEIE=1 
INTE=1                      'RB0 Kesmesi aktif
GIE=1                       'Aktif O an Tüm kesmelere Yetki ver     


TMR1H=$0b
TMR1L=$dc

'==========================================================================================================;
'=====================================PWM TANIMLAMALARI ================================; 

CCP1CON=%00001100
Declare CCP1_Pin = PORTC.2   ' Select HPWM port and bit for CCP1 module. i.e. channel 1
Declare CCP2_Pin = PORTC.1   ' Select HPWM port and bit for CCP2 module. i.e. channel 2     
   
'==========================================================================================================;
'============================= GİRİŞ - ÇIKIŞ VE DEĞİŞKENLER ==========================;
     
Input PORTB             
TRISC=0
Dim TICK As Word       
Dim Sayi As Word         
Dim sure As Word
Dim mod  As Byte
Dim rpm    As Word
Dim FR   As Word

Symbol mi=PORTC.0
Symbol mg=PORTC.1
Symbol led=PORTC.3
Symbol led2=PORTC.4       
Clear



'==========================================================================================================;
'============================= ANA DÖNGÜ ==============================================;
HPWM 1,125,1000
basla:




sure=TICK        '(sn)
FR=1/sure'(hz)
rpm=(fr*60)/7760

If mod=1 Then
TMR1E=1
EndIf
If mod=0 Then
TMR1E=0
EndIf


PulsIn 
mod=Sayi//2

Print At 1,1,"RB0 KESMESI: ",@Sayi,"  "
Print At 2,1,"RPM ",@rpm,"  "
Print At 3,1,"Sure ",@TICK,"  "
Print At 4,1,"Fr: ",@FR,"     "



GoTo basla                 
               
'============================================== KESME ======================================================       
   

bak:
Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
Inc TICK
Toggle  led
EndIf

If sure=2 Then
HPWM 1,0,1000
sure=0

DelayMS 2000
HPWM 1,125,1000
EndIf

If INTF=1 Then
'tick=0
INTF=0 
Inc Sayi
EndIf

Context Restore
Return





Kodu son haliyle şu şekilde düzenledim. Rb0 kesmesinin modunu alıp 0 sa tmr1 i aç 1 se tmr1  i kapat gibi düşündüm fakat bu verimli bir yöntem olmadı. Burada timer1 in aç-kapa kontrolünü hangi fonksyonla yapabiliriz?

ete

T1CON registeri sıfır biti aç kapayı hallediyordu yanlış hatırlamıyorsam. Yinede bir bak data sheete.
Ete

0nur

Bahsettiğiniz durumu

If mod=1 Then
TMR1E=1
EndIf
If mod=0 Then
TMR1E=0
EndIf


şu şekilde kontrol ediyorum zaten. Ama yazılımsal olarak bir sıkıntı var ben fonksiyon diye ifade ederken yanlış anlaşılmış zannedersem. RB0 kesmesi gelince timer1 i on-off olarak ayarlamayı if ile yaptım ama bu yöntemle hızı ölçemiyorum..

ete

Programının Kesme kısmına birlikte bakalım;

bak:
Context Save
If TMR1IF=1 Then  'şayet TMR1 kesmesi oluşmuş ise
TMR1H=$0b          'TMR1 e yeni değer ver
TMR1L=$dc
TMR1IF=0              'kesme bayrağını sıfırladın
Inc TICK                'tick değişkenini bir artırdın sanırım
Toggle  led           'led'e konum değiştirdin.
EndIf                    'bu aşamada TMR1 kesmesi ile işin kalmadı. Bu nedenle programı doğruca Contex restore komutına yönlendirmen gerekir.

If sure=2 Then   'bu komutların burada işi ne bunlar ana program kısmında olmalı.
HPWM 1,0,1000
sure=0

DelayMS 2000   'buarada 2 sn bekleme koymuşsun. Nasıl çalışsın bu sistem bu bekleme ile olmaz böyle !!!!!!!!!!!!
HPWM 1,125,1000  'buda ana program kısmında olması gerekir.
EndIf

If INTF=1 Then   'PORTB.0 kesmesi oluşmuş ise
'tick=0
INTF=0  bayrak sıfırlanıyor
Inc Sayi
EndIf

Context Restore
Return

Gördüğün gibi işi bozan komutlar koymuşsun oraya.
HPWM komutları ana program kısmında yer almalı ve gecikmeleri kaldırmalısın.
Kesme kısmı şöyle olmalı bence
bak:
Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
Inc TICK
Toggle  led
goto CIK
EndIf

'program bu satıra gelebiliyorsa oluşan kesme PORTB.0 kesmesidir. Orada birdaha if INTF=1 diye komut kullanmak gerekmez.
'tick=0
Inc Sayi
INTF=0 

CIK:
Context Restore
Return


ETE

0nur

Yukarıda if le denetlemeyi ana döngüye koyarak denedim orada olmayınca kesme içerisine aldım. orada 2 sn beklemeyi yapma sebebim 2 tick arası motoru durdurmak ve kaç pals geldiğini görmek idi. Aslında bahsettiğiniz gibi de denedim fakat yine hızı ölçemedim.

ete

Onur,

İstersen programın tamamını buraya koy. Çünki olması gerekenlerin bazılarını göremiyorum.
Mesela 20Mhz OSC frekansında her 500 ms de bir TMR1 kesmesi oluşturabilmen için TMR1L=$69 ve TMR1H=67 değerlerini alması gerekir. Bu değerlerle 500 ms de bir kesme yaratması için ise TMR1 bölme oranı 1/64 olması gerekir. Ancak T1CON registerinde 1/64 bölme oranı seçme imkanın yok. O halde en büyük bökme oranı olan 1/8 seçebilirsin. Bu bölme oranı ile elde edeceğin kesme süresi ise 100 ms olacaktır. Bu durumda ikinci bir register (değişken) kullanıp kesmeleride ayrıca sayman gerekiyor. O halde 500ms de bir kesme yerine 1000 ms de bir tick lerin toplamını alarak işini biraz daha kolaylaştırabilirsin.
Yapılacak iş şöyle;
SURE isimli bir değişkenimiz olsun bu kesmeleri saysın. 10 adet kesme olduğunda  1000 ms süre geçmiş olacak. Bu anda Tick sayısını alıp bir başka değişkene aktarmak ve Tick=0 yapmak gerekir. Aksi halde iş çorbaya döner.
Ana programda BASLA satırından evvel Tick=0:SUre=0 vererek ve RB0 kesmesi ile TMR1  kesmelerini aktif ederek işe başlıyoruz.
Kesme Kısmını yeniden yazıyorum.
DISABLE
bak:
Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
SURE=SURE+1
IF SURE=10 then
   SAYAC=TICK   'sayac ve TICK word tipi olmalıdır , TICK gelen encoder puls adedidir
   TICK=0
   SURE=0
ENDIF
Toggle  led  'bence bunu çıkar buradan Her şey çalıştıktan sonra koymaya çalışırsın zaman kaybettiriyor çünki
goto CIK
EndIf

'program bu satıra gelebiliyorsa oluşan kesme PORTB.0 kesmesidir. Orada birdaha if INTF=1 diye komut kullanmak gerekmez.
tick=tick+1
INTF=0 

CIK:
Context Restore
Return


Şimdi geriye okunan değerleri devir bilgisine çevirmek kalıyor.
ELinde SAYAC isimli bir değişken de tutulan 1sn içinde gelen encoder puls sayısı var.
Şayet motor devri ölçüyor isen motorun her bir devrinde encoderin kaç Tick verdiği bilmen gerekiyor. Diyelimki 100 veriyor.
O halde motorun 1 sn içinde ki devir sayısı  DEVIR=SAYAC/100 olur. Bunu dev/dak cinsinden göstermek istersek;
DEVIR=(SAYAC * 60) / 100 şeklinde ifade etmek gerekir.

Hepsi bu kadar. Bu metodu yüzlerce defa kullandım sorunsuz çalışır. Sende olmayan nedir yazdıklarımla mukayese et ve söyle lütfen.

Bu arada yaptığın bir yanlışlığıda ifade edeyim. ;
HPWM 1,125,1000 şeklindeki bir komut sabit bir komut olup bir kere verilmesi gereken bir emirdir. Bunu bir döngü içine sokarsan (BASLA: .....GOTO BASLA) her seferinde aynı komut verilecek demektir. Bu ise PWM sinyalinin aksamasına sebep olabileceği gibi boşuna programıda geciktirir. Bu nedenle sabit komutlarını yalnızca bir kere verecek şekilde tedbir almalısın.

Ete


0nur

#11
Merhaba ,

Timer1 e 3036 öndeğeri vererek 1:8 bölme oranında set ettiğimde 500 msn gecikme sağlayabiliyorum. Öncesinde yazmış olduğum kod aşağıda yer alıyor.


Device 16F877   
Config xt_OSC , WDT_OFF, PWRTE_ON,  BODEN_OFF , LVP_OFF, CP_OFF 

Declare Xtal 4

'============================== LCD TANIMLAMALARI=====================================;

Declare LCD_DTPin = PORTD.4
Declare LCD_RSPin = PORTE.0
Declare LCD_ENPin = PORTE.1
Declare LCD_Interface =  4 ' 4-bit Interface
Declare LCD_Lines =  4
Declare LCD_Type  = alpha
Declare LCD_CommandUs = 2000
Declare LCD_DataUs = 50
All_Digital TRUE
Cls

'==========================================================================================================;           
'=====================================KESME TANIMLAMALARI ================================;             


On_Hardware_Interrupt GoTo bak              'Software int. oluştuğunda INT etiketine git.

OPTION_REG.6=0
T1CON=%00110001    ' -------->>>  |  DİSABLE   |   DİSABLE   |   PS1    |  PS0   |   T1OSCEN  |   T1SYNC   |  TMR1CS   |   TMR1ON   |
         
Symbol INTF = INTCON.1      'RB0 KESME BARAĞI
Symbol INTE = INTCON.4      'RB0 KESME YETKİ
Symbol GIE = INTCON.7       'GLOBAL INT. YETKI
Symbol PEIE=   INTCON.6
Symbol TMR1E=  T1CON.0      ' TMR1 ENABLE BİTİ
Symbol TMR1IF= PIR1.0       ' TMR1 TAŞMA BAYRAĞI
Symbol TMR1IE= PIE1.0


TMR1IE=1 ' TMR1 AŞIMI KESME OLUŞTURMA AKTİF ETME BİTİ
TMR1IF=0 ' TMR1 AŞIM KESME BAYRAĞI
PEIE=1 
INTE=1                      'RB0 Kesmesi aktif
GIE=1                       'Aktif O an Tüm kesmelere Yetki ver     


TMR1H=$0b
TMR1L=$dc

'==========================================================================================================;
'=====================================PWM TANIMLAMALARI ================================; 

CCP1CON=%00001100
Declare CCP1_Pin = PORTC.2   ' Select HPWM port and bit for CCP1 module. i.e. channel 1
Declare CCP2_Pin = PORTC.1   ' Select HPWM port and bit for CCP2 module. i.e. channel 2     
   
'==========================================================================================================;
'============================= GİRİŞ - ÇIKIŞ VE DEĞİŞKENLER ==========================;
     
Input PORTB             
TRISC=0
Dim TICK As Word   
Dim sayac As Word   
   
Dim Sayi As Word         
Dim sure As Word
Dim mod  As Byte
Dim rpm    As Word
Dim FR   As Word


Symbol mi=PORTC.0
Symbol mg=PORTC.1
Symbol led=PORTC.3
Symbol led2=PORTC.4       
Clear



'==========================================================================================================;
'============================= ANA DÖNGÜ ==============================================;
HPWM 1,50,1000
mi=1
mg=0


basla:
sure=TICK*2       '(sn)
FR=1/sure'(hz)
rpm=(fr*60)/7760

If mod=1 Then
TMR1E=1
EndIf
If mod=0 Then
TMR1E=0
EndIf

mod=Sayi//2

Print At 1,1,"RB0 KESMESI: ",@Sayi,"  "
Print At 2,1,"RPM ",@rpm,"  "
Print At 3,1,"Sure ",@TICK,"  "
Print At 4,1,"Fr: ",@FR,"     "



GoTo basla                 
               
'============================================== KESME ======================================================       
   



Disable

bak:

Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
Inc TICK
GoTo CIK
EndIf


Inc Sayi
INTF=0 

CIK:
Context Restore
Enable

Return



ete

Söylediğin hesap 4 Mhz için geçerlidir. Kısaca ispatlayayım.

4 Mhz de bir komut çevrimi 1us dir. Bu şu demektir. TMR1 sayacı her saydığında 1us süre geçmiş olacaktır.
TMR1'e 3036 ön yükleme değeri verdiğimize göre ve bölme oranıda 1/8 olduğuna göre her 8 puls geçtiğinde TMR1 sayacı bir artacak demektir. Önce TMR1 sayacı kesme oluşturmak için ne kadar sayacak onu bulalım.  65536-3036=62500 puls sayacak. Bu kadar puls her 8 puls de bir sayılacağına göre 8 * 62500=500.000 us ederki bu 500 ms ye demektir.

Aynı hesabı 20 Mhz için yapalım; 20 Mhz de bir komut çevrimi 0,2us dir.
TMR1=3036 değerini verdik. kesme için 65536-3036=62500 puls sayacak bunu 8 pulsde bir sayacağı için 62500*8=500.000 puls saymış olacak her puls süresi 0,2 olduğuna göre 500.000 * 0,2=100.000 us süre geçmiş olacaktır.
Hesabın yanlış senin.

Ete


0nur

#13
Bahsettiğiniz şekilde yaparak programı aşağıdaki gibi düzenledim;


Device 16F877   
Config xt_OSC , WDT_OFF, PWRTE_ON,  BODEN_OFF , LVP_OFF, CP_OFF 

Declare Xtal 4

'============================== LCD TANIMLAMALARI=====================================;

Declare LCD_DTPin = PORTD.4
Declare LCD_RSPin = PORTE.0
Declare LCD_ENPin = PORTE.1
Declare LCD_Interface =  4 ' 4-bit Interface
Declare LCD_Lines =  4
Declare LCD_Type  = alpha
Declare LCD_CommandUs = 2000
Declare LCD_DataUs = 50
All_Digital TRUE
Cls

'==========================================================================================================;           
'=====================================KESME TANIMLAMALARI ================================;             


On_Hardware_Interrupt GoTo bak              'Software int. oluştuğunda INT etiketine git.

OPTION_REG.6=0
T1CON=%00110001    ' -------->>>  |  DİSABLE   |   DİSABLE   |   PS1    |  PS0   |   T1OSCEN  |   T1SYNC   |  TMR1CS   |   TMR1ON   |
         
Symbol INTF = INTCON.1      'RB0 KESME BARAĞI
Symbol INTE = INTCON.4      'RB0 KESME YETKİ
Symbol GIE = INTCON.7       'GLOBAL INT. YETKI
Symbol PEIE=   INTCON.6
Symbol TMR1E=  T1CON.0      ' TMR1 ENABLE BİTİ
Symbol TMR1IF= PIR1.0       ' TMR1 TAŞMA BAYRAĞI
Symbol TMR1IE= PIE1.0


TMR1IE=1 ' TMR1 AŞIMI KESME OLUŞTURMA AKTİF ETME BİTİ
TMR1IF=0 ' TMR1 AŞIM KESME BAYRAĞI
PEIE=1 
INTE=1                      'RB0 Kesmesi aktif
GIE=1                       'Aktif O an Tüm kesmelere Yetki ver     


TMR1H=$0b
TMR1L=$dc

'==========================================================================================================;
'=====================================PWM TANIMLAMALARI ================================; 

CCP1CON=%00001100
Declare CCP1_Pin = PORTC.2   ' Select HPWM port and bit for CCP1 module. i.e. channel 1
Declare CCP2_Pin = PORTC.1   ' Select HPWM port and bit for CCP2 module. i.e. channel 2     
   
'==========================================================================================================;
'============================= GİRİŞ - ÇIKIŞ VE DEĞİŞKENLER ==========================;
     
Input PORTB             
TRISC=0
Dim TICK As Word   
Dim sayac As Word   
             
Dim sure As Word
Dim rpm    As Word
Dim fr   As Word


Symbol mi=PORTC.0
Symbol mg=PORTC.1
Symbol led=PORTC.3
Symbol led2=PORTC.4       
Clear



'==========================================================================================================;
'============================= ANA DÖNGÜ ==============================================;
HPWM 1,128,1000
mi=1
mg=0


basla:

fr=(60*sayac)/(16)
rpm=fr/485

Print At 1,1,"RB0 KESMESI: ",@TICK,"  "
Print At 2,1,"Motor ",@fr," dev/sn "
Print At 3,1,"Saft  ",@rpm," dev/dk "
'Print At 4,1,"Fr: ",@FR,"     "



GoTo basla                 
               
'============================================== KESME ======================================================       
   



Disable

Disable
bak:
Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
sure=SURE+1

If sure=2 Then
   sayac=TICK   'sayac ve TICK word tipi olmalıdır , TICK gelen encoder puls adedidir
   TICK=0
   sure=0
EndIf
Toggle  led  'bence bunu çıkar buradan Her şey çalıştıktan sonra koymaya çalışırsın zaman kaybettiriyor çünki
GoTo CIK
EndIf

'program bu satıra gelebiliyorsa oluşan kesme PORTB.0 kesmesidir. Orada birdaha if INTF=1 diye komut kullanmak gerekmez.
TICK=tick+1
INTF=0 

CIK:
Context Restore
Return



Şuan 500msn de bir kesmeye girdiğinden sure 2 olunca işlemleri yaptırıyorum.  Fakat motoru zorladığımda 2 rpm den aniden 7 rpm gibi değerler görülebiliyor. Bunu anlık olarak okursak  daha iyi bir sonuç elde etmez miyiz?  yani sure değişkenini kaldırıp saydırma yaptırmadan

Yani şu şekilde ;


Device 16F877   
Config xt_OSC , WDT_OFF, PWRTE_ON,  BODEN_OFF , LVP_OFF, CP_OFF 

Declare Xtal 4

'============================== LCD TANIMLAMALARI=====================================;

Declare LCD_DTPin = PORTD.4
Declare LCD_RSPin = PORTE.0
Declare LCD_ENPin = PORTE.1
Declare LCD_Interface =  4 ' 4-bit Interface
Declare LCD_Lines =  4
Declare LCD_Type  = alpha
Declare LCD_CommandUs = 2000
Declare LCD_DataUs = 50
All_Digital TRUE
Cls

'==========================================================================================================;           
'=====================================KESME TANIMLAMALARI ================================;             


On_Hardware_Interrupt GoTo bak              'Software int. oluştuğunda INT etiketine git.

OPTION_REG.6=0
T1CON=%00110001    ' -------->>>  |  DİSABLE   |   DİSABLE   |   PS1    |  PS0   |   T1OSCEN  |   T1SYNC   |  TMR1CS   |   TMR1ON   |
         
Symbol INTF = INTCON.1      'RB0 KESME BARAĞI
Symbol INTE = INTCON.4      'RB0 KESME YETKİ
Symbol GIE = INTCON.7       'GLOBAL INT. YETKI
Symbol PEIE=   INTCON.6
Symbol TMR1E=  T1CON.0      ' TMR1 ENABLE BİTİ
Symbol TMR1IF= PIR1.0       ' TMR1 TAŞMA BAYRAĞI
Symbol TMR1IE= PIE1.0


TMR1IE=1 ' TMR1 AŞIMI KESME OLUŞTURMA AKTİF ETME BİTİ
TMR1IF=0 ' TMR1 AŞIM KESME BAYRAĞI
PEIE=1 
INTE=1                      'RB0 Kesmesi aktif
GIE=1                       'Aktif O an Tüm kesmelere Yetki ver     


TMR1H=$0b
TMR1L=$dc

'==========================================================================================================;
'=====================================PWM TANIMLAMALARI ================================; 

CCP1CON=%00001100
Declare CCP1_Pin = PORTC.2   ' Select HPWM port and bit for CCP1 module. i.e. channel 1
Declare CCP2_Pin = PORTC.1   ' Select HPWM port and bit for CCP2 module. i.e. channel 2     
   
'==========================================================================================================;
'============================= GİRİŞ - ÇIKIŞ VE DEĞİŞKENLER ==========================;
     
Input PORTB             
TRISC=0
Dim TICK As Word   
Dim sayac As Word   
             
Dim sure As Word
Dim rpm    As Word
Dim fr   As Word


Symbol mi=PORTC.0
Symbol mg=PORTC.1
Symbol led=PORTC.3
Symbol led2=PORTC.4       
Clear



'==========================================================================================================;
'============================= ANA DÖNGÜ ==============================================;
HPWM 1,128,1000
mi=1
mg=0


basla:

fr=(120*sayac)/(16)
rpm=fr/485

Print At 1,1,"RB0 KESMESI: ",@TICK,"  "
Print At 2,1,"Motor ",@fr," dev/sn "
Print At 3,1,"Saft  ",@rpm," dev/dk "
'Print At 4,1,"Fr: ",@FR,"     "



GoTo basla                 
               
'============================================== KESME ======================================================       
   



Disable

Disable
bak:
Context Save
If TMR1IF=1 Then
TMR1H=$0b
TMR1L=$dc
TMR1IF=0
'SURE=SURE+1

'IF SURE=2 then
   sayac=TICK   'sayac ve TICK word tipi olmalıdır , TICK gelen encoder puls adedidir
   TICK=0
   'SURE=0
'ENDIF

GoTo CIK
EndIf

'program bu satıra gelebiliyorsa oluşan kesme PORTB.0 kesmesidir. Orada birdaha if INTF=1 diye komut kullanmak gerekmez.
TICK=tick+1
INTF=0 

CIK:
Context Restore
Return




Bu arada motor 24 rpm iken şuan 4 rpm görüyorum. Formullerdede bir hata olduğunu düşünmüyorum aslında encoder 16 cpr redüktör 1:485

ete

Hızı 4Mhz'e düşürerek işlemci performansını düşürdün. Bu durumda puls kaçırıyor olabilir sistemin.
Anlık değerlerle bir sonuca varman mümkün değil. AKlın yolu birdir. 20 Mhz de çalışacaksın ve mümkün olduğunca uzun sürelerde puls okuyacaksın hepsi bu.
Elbette bu benim fikrim. İstiyorsan devir hesabını 500ms ye ye görede yapabilirsin.

Ete

Powered by EzPortal