Timer1 ile puls aralık zamanını ölçmek

Başlatan ergün, 18 Temmuz 2018, 18:52:18

ete

Yazdıklarını kontrol etmeden senin bazı şeyleri kontrol etmende yarar görüyorum.
TR1 kullanarak frekans ölçme işi iki farklı yoldan yapılabilir.
Birincisi TMR1 sayacını hariçten puls alarak sayabilen bir sayıcı olarak ayarlayıp diğer taraftan zaman tutarak gelen palsleri sayma esanına dayanır. Bu şekilde çalışan bir frekans sayıcı yapmıştım ve Ete projelerinde yer almaktadır. Gerekirse inceleyebilirsin.

İkinci metod da ise Capture işlemi ile Frekansın Yükselen kenarı yakalanıp  süresi TMR1 ile ölçülüp ardından düşen kenar yakalanıp süresi ölçülerek iki süre toplanıp frkansın peryodu bulunması esasına dayanır. Gerisi ise 1/T formülü ile direk bulunan değer frekansa çevrilir.
Bu konuyla ilgili olarak da aşağıdaki linki okumanı ve örnekleri incelemeni öneririm.

http://etepic.com/index.php/topic,3540.msg33598.html#msg33598

Ete

MB_77

#31
bu mesaj tarafımdan silinmiştir.

ete

#32
Single Puls modunu kullanarak nasıl frekans hesaplandığı aynı devre şeması üzerinden aşağıdaki programda gösterdim.
Tabiiki bu programda gelen frekansı ölçülecek sinyalin %50 duty değerine sahip olduğu varsayılmıştır.
Bu varsayım paralelinde ölçülen HIGH puls süresi 2 ile çarpılarak peryot bulunuyor ve ardından bulunan değer 32 bit matematiği ile frkansa çevriliyor.

Ölçülen High puls süresi 58 bin küsür civarında çıkıyor. Fosc/4 olarak clk değerini esas aldığımız için 1 peryot süresi 32/4=8 ve 1/8=0,125 us olacaktır. dolayısıyla 58bin küsür ile bu rakamı çarpınca High peryodu gerçek süresini hesaplamış oluyoruz. Bunuda  2 ile çarparak toplam peryodu bulup bunu frekansa çeviriyoruz.

#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32

OSCCON      =%11110000      '32MHz internal osilatör frekansı seçildi
OPTION_REG  =%00000110      'Pull-up enabled,Yükselen kenar kesmesi kapalı,Tmr0 clock kaynağı içsel Fosc/4,Prescaler(Bölücüler) açık Tmr0 için,Bölme oranı 32Mhz için 1/128
WPUA.5      =0              'MCLR için bit5 Pull-up DİSABLED.Eğer MCLR ON yapılmışsa herzaman enabled.Bu pin çıkış yapılmışsa otamatikman PULL-UP DİSABLED OLUR.
WPUB        =%00000010      'PortB.1 Pull-Up AKTİF, diğerleri PASİF edildi.
ANSELA      =0              'PortA nın <4:0> arası analog-dijital olabilen pinlerini dijital yaptık.Pinler Dijital I/0 oldu.
ANSELB      =0              'PortB nin <7:1> arası analog-dijital olabilen pinlerini dijital yaptık.Pinler Dijital I/0 oldu.

PORTA=0:TRISA=%00100000     ' *** 16F1827 de MCLR_ON yapılınca TRISA.5=1 yapılması gerekiyor. Yoksa işlemci çalışmıyor. ***
                        '++++ mclr her zaman dijital inputtur. mclr on yapılınca pull up yapılmalıdır. aksi halde pin lowda kaldığı için mclr sürekli reset attırır.
PORTB=0:TRISB=%00000011     'Buton girişleri ayarlandı.
'---------------------------------------------------------------------

DEFINE LCD_DREG PORTB       'LCD Data bacakları PortB ye bağlı
DEFINE LCD_DBIT 7           'LCD Data bacağı 7 den başlıyor
DEFINE LCD_EREG PORTA       'LCD Enable bacapı PortA ya bağlı
DEFINE LCD_EBIT 7           'LCD Enable bacapı 7 e bağlı
DEFINE LCD_RSREG PORTA      'LCD Reset bacapı PortA ya bağlı
DEFINE LCD_RSBIT 6          'LCD Reset bacağı 6 ye bağlı
DEFINE LCD_BITS 4           'LCD 4 Bit bağlı çalışacak
DEFINE LCD_LINES 2          'LCD 2 satırdan oluşuyor
DEFINE LCD_COMANDUS 2000    '2000 mikro sayniye komut gecikmesi veriliyor
DEFINE LCD_DATAUS 50'225       'Data bilgisinden sonraki gecikme bekleme süre 
'---------------------------------------------------------------------

PRYT    VAR WORD '60    'Timer1 sayacından okunan değer
FRK     VAR WORD '63
FREKNS  VAR WORD 67   

SAY      VAR BYTE
K          VAR BYTE   70     
TIMER   VAR BYTE 72
KESM    VAR BYTE 74
KESTI    VAR BIT  'kesme oluştu ise bu set ediliyor
'----------------------------------------------------------------------
         
SYMBOL TMR1GIF=PIR1.7     
SYMBOL T1GGO=T1GCON.3     

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

LCDOUT $FE,1
pause 250
       '
LCDOUT $FE,1,"SISTEM HAZIR"   
PAUSE 80           

KESTI=0
TMR1=0
PIE1.7=1
PIR1.7=0
INTCON=%11000000   

ON INTERRUPT GOTO KESME
   
'------------------------------------------------------------------------
PRYT=0
K=0
T1CON=%00000101
T1GCON=%11010000 
T1GGO=1
'------------------------------------------------------------------------
KESTI=0   
BASLA:
      IF KESTI=1 THEN
        FRK=PRYT**125
        FRK=(DIV32 1000)*2
        FREKNS=1000**1000
        FREKNS=DIV32 FRK
        LCDOUT $FE,$80,"PRYT =",DEC FRK,"   "
        LCDOUT $FE,$C0,"FRKNS=",DEC FREKNS
        KESTI=0
        PIE1.7=1
      ENDIF
     
      GOTO BASLA 
   

    DISABLE
    KESME:
           PRYT=TMR1
           KESTI=1
           PIR1.7=0
           T1GGO=1
           TMR1=0
           RESUME
           ENABLE             
    END


Genel mantık şöyle, Sİngle puls modu aktif edilerek Go/Done biti set edilip sistem başlatılıyor. Gate ucundan giren ilk yükselen kenarda TMR1 saymaya başlıyor ve sinyal düşen kenara döndüğü anda kesme oluşuyor ve kesme alt programı çalışıyor. Gerisini programdan anlayabilirsiniz.

Değişik Duty oranlarında hem high puls hemde low puls süresi hesaplanıp ikisi toplanarak işlem yapılmalıdır.
Şimdi bunun üzerinde çalışıp yaparsam buraya ayrıca koyacağım.

Ete

ete

#33
Farklı duty oranları ile çalışan programda aşağıdadır. Buradaki temel mantık, önce sinyalin HIGH kısmını süre olarak sayıp hesaplamak ve bunu YUKSEK isimli değişkene atmak. Ardından okunacak sinyal şeklini LOW a çevirip (T1GCON.6 nolu Timer1 Gate Polarity biti ile yapılıyor) aynı şekilde bu seferde sinyalin LOW peryodunu ölçmek ve daha sonra ikisini toplayıp toplam peryodu bulmak ve bunuda frekansa çevirmek şeklinde açıklanabilir.
#CONFIG
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_ON & _PWRTE_ON & _MCLRE_OFF & _CP_OFF & _CPD_OFF & _BOREN_ON & _CLKOUTEN_OFF & _IESO_OFF & _FCMEN_OFF
__CONFIG _CONFIG2, _WRT_OFF & _PLLEN_ON & _STVREN_ON & _BORV_19 & _LVP_OFF
#ENDCONFIG

DEFINE OSC 32

OSCCON      =%11110000      '32MHz internal osilatör frekansı seçildi
OPTION_REG  =%00000110      'Pull-up enabled,Yükselen kenar kesmesi kapalı,Tmr0 clock kaynağı içsel Fosc/4,Prescaler(Bölücüler) açık Tmr0 için,Bölme oranı 32Mhz için 1/128
WPUA.5      =0              'MCLR için bit5 Pull-up DİSABLED.Eğer MCLR ON yapılmışsa herzaman enabled.Bu pin çıkış yapılmışsa otamatikman PULL-UP DİSABLED OLUR.
WPUB        =%00000010      'PortB.1 Pull-Up AKTİF, diğerleri PASİF edildi.
ANSELA      =0              'PortA nın <4:0> arası analog-dijital olabilen pinlerini dijital yaptık.Pinler Dijital I/0 oldu.
ANSELB      =0              'PortB nin <7:1> arası analog-dijital olabilen pinlerini dijital yaptık.Pinler Dijital I/0 oldu.

PORTA=0:TRISA=%00100000     ' *** 16F1827 de MCLR_ON yapılınca TRISA.5=1 yapılması gerekiyor. Yoksa işlemci çalışmıyor. ***
                        '++++ mclr her zaman dijital inputtur. mclr on yapılınca pull up yapılmalıdır. aksi halde pin lowda kaldığı için mclr sürekli reset attırır.
PORTB=0:TRISB=%00000011     'Buton girişleri ayarlandı.
'---------------------------------------------------------------------

DEFINE LCD_DREG PORTB       'LCD Data bacakları PortB ye bağlı
DEFINE LCD_DBIT 7           'LCD Data bacağı 7 den başlıyor
DEFINE LCD_EREG PORTA       'LCD Enable bacapı PortA ya bağlı
DEFINE LCD_EBIT 7           'LCD Enable bacapı 7 e bağlı
DEFINE LCD_RSREG PORTA      'LCD Reset bacapı PortA ya bağlı
DEFINE LCD_RSBIT 6          'LCD Reset bacağı 6 ye bağlı
DEFINE LCD_BITS 4           'LCD 4 Bit bağlı çalışacak
DEFINE LCD_LINES 2          'LCD 2 satırdan oluşuyor
DEFINE LCD_COMANDUS 2000    '2000 mikro sayniye komut gecikmesi veriliyor
DEFINE LCD_DATAUS 50'225       'Data bilgisinden sonraki gecikme bekleme süre 
'---------------------------------------------------------------------

PRYT    VAR WORD '60    'Timer1 sayacından okunan değer
FRK     VAR WORD '63
FREKNS  VAR WORD 67
YUKSEK  VAR WORD
ALCAK   VAR WORD 

SAY     VAR BYTE
K       VAR BYTE   70     
TIMER   VAR BYTE 72
KESM    VAR BYTE 74
KESTI   VAR BIT
'----------------------------------------------------------------------
         
SYMBOL TMR1GIF=PIR1.7       'Timer1 Gate kesme bayrak biti.Bu bit sıfırlanmalı.
SYMBOL T1GGO=T1GCON.3       'Timer1 Gate durum biti.Bu bit 1 olunca Timer1 Gate alıma hazır, Saymak için Kenar bekliyor demek. Timer1 Gate pulsi alıp etkinleşince bu bit otomatikman sıfırlanıyor ve Bu bit tekrar 1 olana kadar Timer1 artırımı olmıyacaktır.
SYMBOL T1GVAL=T1GCON.2      '++++++
SYMBOL TUS=PORTB.1
'----------------------------------------------------------------------

LCDOUT $FE,1
pause 250
       '
LCDOUT $FE,1,"SISTEM HAZIR"    '+++++  böyle daha bi hoş geldi
PAUSE 80           

KESTI=0
TMR1=0
PIE1.7=1
PIR1.7=0
INTCON=%11000000       'pasifti. halbuki kesme kullanıyoruz

ON INTERRUPT GOTO KESME
   
'------------------------------------------------------------------------
PRYT=0
K=0
T1CON=%00000101
'T1GCON=%10010000 ' LOW SAY
T1GCON=%11010000 'HIGH SAY
T1GGO=1
'------------------------------------------------------------------------
KESTI=0   
BASLA:
      IF KESTI=1 THEN       
        YUKSEK=YUKSEK**125
        YUKSEK=(DIV32 1000)'*2
        ALCAK=ALCAK**125
        ALCAK=DIV32 1000
        PRYT=ALCAK+YUKSEK
       
        FREKNS=1000**1000
        FREKNS=DIV32 PRYT
        LCDOUT $FE,$80,"PRYT =",DEC PRYT,"   "
        LCDOUT $FE,$C0,"FRKNS=",DEC FREKNS
        KESTI=0
        PIE1.7=1
        PRYT=0
      ENDIF
     
      GOTO BASLA 
   

    DISABLE
    KESME:
           IF T1GCON.6=1 THEN
              YUKSEK=TMR1
              T1GCON.6=0 
           ELSE
              ALCAK=TMR1
              T1GCON.6=1
              KESTI=1
           ENDIF 
           PIR1.7=0
           T1GGO=1
           TMR1=0
           RESUME
           ENABLE             
    END


Bu sistemin bütün frekansları gösteremeyeceğini hemen belirtmek isterim. Kapasite 16 bitlik TMR1 sayacı ile sınırlı. Burada 32 Mhz osc frekansı kullanmakda çok akıllıca olmuyor. Zira 10 ms lik bir peryot hesabında 4 Mhz lik OSC 10.000 sayarken  8 Mhzde bu rakam 20.000 e çıkar. 16 Mhz de ise  40.000 e ulaşır. Bu nedenle tavsiyem daha düşük OSC frekansları ile bu sistemi kullanmak olurdu. Kullanılacak frekansa göre
        YUKSEK=YUKSEK**125
        YUKSEK=(DIV32 1000)
formülleri değişecektir. 4 Mhzde bu iki satır direk silinmeli PRYT=YUKSEK+ALCAK şeklinde hesaplanmalıdır.
8 Mhzde ise
        YUKSEK=YUKSEK**5   (8/4=2 ve 1/2=0,5 olduğundan dolayı)
        YUKSEK=(DIV32 10)  şeklinde formül uygulanmalıdır. Burada da 0,5 virgülden kurtarmak için 10 ile çarpıp işlem yaptık sonunda 10 a bölerek eşitliği bozmamış olduk.

Ete

MB_77

#34
bu mesaj tarafımdan silinmiştir.

Analog

Çok teşekkür ederim Ete hocam ve MB_77.


FREKNS=1000**1000
FREKNS=DIV32 PRYT

Ete hocam formülde ki bu kısmı anlayamadım. Bu kısım aklımda boşta kaldı. Yardımcı olurmusun.
Saygılarımla.

Analog

Ete hocam düşük osülatör frekansı kullanmak uygun olur demişsiniz. Düşük frekansta ölçüm hassasiyetide düşer değilmi.

ete

Öyle dedim ama sonradan düşündümde yalnızca ölçülecek frekans aralığı değişiyor. Pek birşey farketmeyecek demektir bu. Hassasiyet pek düşmez sanırım. Elbette kurtardığı oranda yüksek frekans daha iyi.
Çoklu frekans aralığı için TMR1 Prescaler (bölme oranı) değiştirmek gerekir.
Elimizde 1/1 - 1/2 - 1/4 ve 1/8 bölme oranlarımız var. Yukarıdaki örnek 1/1 bölme oranına göre çalışıyor.
High peryodunu hesapladıktan sonra şayet 30000 den büyük ise bir üstteki bölme oranına geçip yeniden ölçüm yapıp sonucu bölme oranını hesaba katarak hesaplardım.
Bu metod işlemi epeyce karmaşık hale getirecek. Bu yöntemle yalnızca belirli frekansları ölçmek en iyisi sanırım.

Ete

MB_77

#38
bu mesaj tarafımdan silinmiştir.

ete

Verdiğim program butonsuz çalışıyor yükselen ve düşen kenar kesmesi ile.
Ete

MB_77

#40
bu mesaj tarafımdan silinmiştir.

ete

32 pic matematiği konusunda gelen bir kaç soruya bakarak bu konuda açıklama verme gereğini duydum.
Pic basic her ne kadar 32 bitlik değişkeni kullanmasa da 32 bit çarpma ve bölme işlemini yapabilmektedir. Programda vermiş olduğum ;
 YUKSEK=YUKSEK**125
        YUKSEK=(DIV32 1000)
        ALCAK=ALCAK**125
        ALCAK=DIV32 1000
        PRYT=ALCAK+YUKSEK
       
        FREKNS=1000**1000
        FREKNS=DIV32 PRYT
        LCDOUT $FE,$80,"PRYT =",DEC PRYT,"   "
        LCDOUT $FE,$C0,"FRKNS=",DEC FREKNS

şeklindeki kodda bu özellikten yararlanıyoruz.
YUKSEK=YUKSEK**125 ........   bu satırı neden kullandık. Program 32 Mhz hızla çalışmaktadır. Tmr1 ise Fosc/4 yani tam tamına işlemcinin kullandığı clock palsini kullanmaktadır. Bu palsin 1 peryodunun zaman olarak süresi
32.000.000/4.000.000=8.000.000 Hz yada 8 Mhz işlemci frekansını bize vermektedir. 1 clk palsi ise 1/8=0,125 us dir. Bu durumda TMR1 sayacı "YUKSEK" kadar saydığı zaman bunun süre olarak karşılığı YUKSEK * 0,125 kadardır.
0,125 pic matematiğinde kullanılabilecek bir değer değildir. O halde bunu kullanılır hale getirmemiz gerekcektir. Bunun için sayıyı 1000 ile çarpıp işlem sonucunda yeniden 1000 e bölerek hem hesabı yapmış oalcak hemde eşitliği bozmamış olacağız. Bu nedenle Sayac tutarını 125 ile 32 bit olarak (**) çarptık. Burada önemli bir konuya dikkatinizi çekmek isterim. 32 bitlik çarpım işlemci tarafından yapılır ve sizin sonucuna ulaşamayacağınız bir tampon hafızada tutulur. Bu sonucu göremezsiniz ama başka bir işlemde kullanabilirsiniz demektir bu. Bu özelliği kullanarak,
YUKSEK=(DIV32 1000) işlemi ile o sonucu tekrar 1000'e bölerek eşitliği sağamış oluyoruz. Bu işlemde tampon hafızadaki çarpım sonucu 1000 e bölünerek YULSEK isimli değişkene yerleştirilir.
Diğer önemli bir nokta ise Frekans formülünde Frekans=1/T yani 1sn/peryot (sn) şeklindeki formülü Frq=1.000.000us/T(us) şeklinde yazabiliyoruz.  Görüldüğü gibi bizim Peryot hesabımızda us cinsindendir. O halde frekansı bulmak için 1.000.000/peryot işlemini yapmamız gerekir. Sayı yine 32 bitlik sınırlarda olduğunda 1 milyan sayısını elde etmek için 1000 ile 1000 i 32 bit olarak çarpıp 1.000.000 elde ediyoruz ve tampon hafızaya atılmasını sağlıyoruz. Sonra;
FREKNS=DIV32 PRYT eşitliği ile tampon hafızayı PRYT deişkeninde saklı olan peryoda bölmüş oluyoruz.
İşlemlerin açıklaması bu kadardır.

Tampon hafıza toplama veya çıkarma işlemlerinde kullanılamaz. Yalnızca 32 bit çarpma ve bölme işlemlerinde kullanılabiliyor.

Ete

Analog

Alıntı yapılan: MB_77 - 11 Kasım 2018, 09:57:41
selamlar,

@analog

programda anladığım kadarıyla bir eksik yön var. şöyle bir durumu düşünelim; cihaz çalıştı, butona basıldı ve örneğin 100 Hz ölçtü ve ekranda gösterdi. sonra birşey oldu ve sinyal bağlantısı kesildi ama kullanıcı farkında değil. butona bastı ve yine 100Hz görmeye devam ediyor. sorun olduğunu algılayamayacak. başka sorunlar da olabilir.

bence ekranda, her okuma döngüsünde bir artan bir sayacın gösterilmesi hata kontrolüne yardımcı olabilir. okunan sinyale de bir id verilmiş olur. kayıtlarda da kullanıma kolaylık sağlayabilir.

Yardımların için çok teşekkür ederim Sayın MB_77. Timer1 Gate yoluyla frekans ölçmek pratik gözükmüyor ve tekrarlı ölçüm yaptığımda ölçümlerde sapmalar oluyor. Müsait bir zamanda capture metodunu deneyeceğim. Onda da yardımcı olursan sevinirim.
Saygılarımla.

ete


Analog


Powered by EzPortal