Pic İle Frekans Okuma

Başlatan toprak, 23 Kasım 2012, 22:00:50

Hattuşa

@ete hocam;
hpwm pininden pwm verme yerine tmr1 i aktif edip frekansı ordan versek olmaz mı? yani;
multi-calc. programında değerlere baktım.
biz %50 duty oranında pwm üreteceğiz ya, 5 khz %50 duty oranında frekans üretmek için 10 hesaplayıcıyı 10 khz seçip 1/32 de 63973 değerini buldum. bu değer 5 khz in high olma süresini bize vermez mi? yani 10 khz in toplam süresi 5khz in high olma süresi kadar,
aynı şekilde 200khz %50  duty için 400 khz lik zaman dilimini kullanırsak bu da aynı şekilde 200khz in high süresini verir. 1/32 de bu değer 3036 yani
biz bölme oranını 1/32 seçip alt sınır (5khz için) 63973 ile üst sınır 3036 (200khz için) bir değişken belirleyip bu arada bir pini toggle yaparsak işimiz olmaz mı?

bunu bu şekilde aşarız sorun olmaz ama bu arada bu işlemle birlikte gelen frekansı birbirini etkilemeden nasıl ölçeceğiz?

Hattuşa

#31
hocam 12F1822 ile 32 mhz dahili osc ile 110 khz çıkış alabiliyorum tabi isisde, en iyisi hpwm1 komutunu kullanmak sanırım. hocam frekansı okuma işini nasıl yapabilirim?
Device 12F1822 
Config1 FOSC_INTOSC, WDTE_OFF, PWRTE_OFF, MCLRE_OFF, CP_OFF, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_OFF, FCMEN_OFF
Config2 WRT_OFF, PLLEN_OFF, STVREN_OFF, BORV_25, LVP_OFF
OSCCON=%01111011
Xtal=32
' Declare PLL_Req TRUE '16mhz
ANSELA=0
PORTA=0
TRISA=%00000000
OPTION_REG.7=0
CM1CON0=0
ADCON0=0
Symbol P1 =TRISA.0 :Output P1
Symbol PEIE = INTCON.6 ' Peripheral Interrupt Enable
Symbol GIE = INTCON.7  ' Global Interrupt Enable
Symbol TmrIe =PIE1.0
Symbol TmRIf =PIR1.0
T1CON =%01000001
'PIE1 =%0000000
GIE =0
PEIE =1
TmrIe =1
TmRIf =0

All_Digital=TRUE

Dim FR As Word
FR =65525
GIE =1
On_Hardware_Interrupt GoTo KeSMe
MaIn:
Nop
Nop

GoTo MaIn

KeSMe:
        Context Save
       TmRIf =0
       If P1 =0 Then
P1 =1
  TMR1L=FR.Byte0
  TMR1H=FR.Byte1
Else
P1 =0
   TMR1L=FR.Byte0
  TMR1H=FR.Byte1
EndIf

        Context Restore

End


HOCAM frekansı okuma işleminde yardımcı olabilirmisiniz? bu kadar hızlı okuma işleminde gözüm korktu

ete

Önceki mesajımda belirttiğim şekilde çalışan bir frekansmetre projem var. En azından programı açıp bakabilir oradaki mantığı uygulayabilirsin.
İşin temeli,
- 1000 ms lik sabit bir zaman dilimi alacaksın. Zaman dilimini alırken TMR1 sayacını sıfırlayacaksın. Sayacı aktif hale getireceksin bölme oranını 1/1 al şayet taşma oluyor ise 1/2 bölme oranınıda kullanabilirsin.
- Süreyi başlat ve süre sonunda TMR1 i durdur. değerini frekans isimli değişkene aktar. Bu senin 1 sn de aldığın puls sayısıdır. dolayısıyla (bölme oranın 1/1 ise) direk frekanstır.

Ete

Hattuşa

hocam frekansmetre devrenizi inceledim asm de yazılmış, sorunum süre ile ilgili zira 1000ms yi bir programda bekletme işi benim bütün işimi altüst etmezmi? zira atıyorum 50 khz lik bir frekansım var bu frekansa göre 1000mS çok uzun bir süre

ete

Zaman 2 türlü tutulur. Birincisi ,
- PAUSE 1000 dersin ve programı 1000ms boyunca bloke edersin süre sonunda işine devam edersin.
- İkinci yöntemde TMR0 kesmesini 16684us için kurarsın , kesmeleri sayarsın 61 adet kesme oluşunca 1000 ms geçmiş olur.
İkinci yöntem sana daha uygun.
Frekans sayarken zaten harici giriş kullanacaksın. Onun başında beklemen gerekmiyor. Bu durumda 1000ms beklesende olur beklemesende değilmi.? Program 1000ms beklerken arka planda işlemci gelen pulsları saymasına devam eder.

Ete

Hattuşa

@ete hocam;
daha önceden hiç yapmadığım bir uygulama olduğu için kafa basmıyor,
kabaca anlatayım, yanlışmı anladım acaba?
öncelikle intcon registerinden kesmeyi ve Peripheral Interruptu aktif ettim. t1con u set ettim (yada ettiğimi sanıyorum. portb.6 ya ölçülecek frekansı girdim. T1CK yi aktif ettim. Pİe.0 ve pir0 danda timer1 i aktif ettim. buraya kadar sorun yok.
sayac ve say adlı  word tipi değişkenlerimide tanımladım. TMR1L ve TMR1H yi sıfırladım. kesme içinde TMR1 taşma yaptığında sayac değişkenine T1CKI adedini atmak gerekiyor sanırım ama nasıl yapılabilir düşünemedim. nette epey aradım ama bulamadım. burdan sonrası için yardım istiyorum hocam  :D  :D  :D
Device 16F628A
Config BOREN_OFF, CP_OFF, DATA_CP_OFF, PWRTE_OFF, WDT_OFF, LVP_OFF, MCLRE_ON, INTRC_OSC_NOCLKOUT, DATA_CP_OFF, WDT_OFF
Xtal =4


Declare All_Digital TRUE
TRISA =%00000000
TRISB =%01000000
PORTA =0
PORTB =0
Declare LCD_DTPin PORTA.0  ' LCD Data Pin   
Declare LCD_RSPin PORTB.0  ' LCD RS Pin
Declare LCD_ENPin PORTB.1  ' LCD EN Pin
Declare LCD_Lines 2        ' LCD Satır
Declare LCD_Interface 4    ' LCD Data Pin Sayısı 4
Cls
DelayMS 100
CMCON =7
OPTION_REG =%10100000        'pulluplar kapalı, TOCKI aktif

Symbol PEIE = INTCON.6 ' Peripheral Interrupt Enable
Symbol GIE = INTCON.7  ' Global Interrupt Enable

Symbol TmrIe =PIE1.0
Symbol TmRIf =PIR1.0
T1CON =%00001111

GIE =0
PEIE =1
TmrIe =1
TmRIf =0
TMR1L =0
TMR1H =0

Dim SaYaC As Word
Dim SaY As Word
GIE =1
On_Hardware_Interrupt GoTo KeSMe
MaIn:
Print At 1,1,Dec SaYaC,"  "
Print At 2,1,Dec SaY,"  "

GoTo MaIn


KeSMe:
        Context Save
       TmRIf =0
     

        Context Restore
End



ete

Önceden yapmadığın uygulamaları yaptığın zaman zaten bu işi öğrenmiş olacaksın.
Yazdıklarımıda dikkatli oku lütfen. Sana TMR1 kesmesi açacaksın dememiştim.
Mantıklı düşünmeye çalış.!!!
TMR1 sayacı dışarıdan gelen puls leri sayacak,
Zaman tutup sayacı sıfırlayıp zaman tuttun diyelim, 1000 ms içinde sayac 200 saydı. Peki bu kesme oluştururmu? Oluşturmaz oluşturması için sayac değerinin 65535 değerini aşması gerekir. Zaten bize kesme lazım değilki sayacın ne kadar puls saydığı lazım. Kesme işimizi bozar.
Sayac 200 saydı bu 200 hz demektir. Sayac 1000 saydı bu 1 khz demektir. Yapman gereken sayacı sıfırlayıp zaman tutman. Süre sonunda sayac değerini alıp frekans olarak kullanman.
Zamanı kesme ile hallet demiştim.
Saat projelerinde RTC siz saat yaparken TMR0 sayacını kullanıyoruz. 16384 us lik bir süre ayarlayıp 60-61 kesmede 1000 ms elde ediyoruz. Sende aynı özelliği kullan demiştim.
Ama dediklerimin hiç birisini anlamamışsın. Bu sefer anlarsın umarım.

Ete

Hattuşa

hocam
Device 16F628A
Config BOREN_OFF, CP_OFF, DATA_CP_OFF, PWRTE_OFF, WDT_OFF, LVP_OFF, MCLRE_ON, INTRC_OSC_NOCLKOUT, DATA_CP_OFF, WDT_OFF
Xtal =4


Declare All_Digital TRUE
TRISA =%00000000
TRISB =%01000000
PORTA =0
PORTB =0
Declare LCD_DTPin PORTA.0  ' LCD Data Pin   
Declare LCD_RSPin PORTB.0  ' LCD RS Pin
Declare LCD_ENPin PORTB.1  ' LCD EN Pin
Declare LCD_Lines 2        ' LCD Satır
Declare LCD_Interface 4    ' LCD Data Pin Sayısı 4
Cls
DelayMS 100
CMCON =7
OPTION_REG =%10000000        'pulluplar kapalı, TOCKI aktif


T1CON =%00000011
Symbol kEs =PIE1.0
Symbol bAyRaK =PIR1.0

Dim SaYaC As Word

MaIn:
TMR1L =0
TMR1H =0
bAyRaK =0
kEs =1
While bAyRaK =1  :Wend'taşana kadar bekle
kEs =0
bAyRaK =0
SaYaC.Byte0 =TMR1L
SaYaC.Byte1 =TMR1H
Print At 1,1,Dec SaYaC,"  "


GoTo MaIn


End


hocam son yazınıızı okumadan bu şekilde yapmıştım. ama çalışmadı :D
akşama doğru dediğiniz gibi tekrar yazıp deneyeyim.
yani tmr0 i aktif edip 1 sn süreye ayarlayacağım. t1cki den gelen pulsleride bu tmr0 taşma anına kadar sayaç =sayaç +1 ile saydırıp bu değeri frekans hesaplaması için kullanacağım.  tamam hocam birde öyle deneyeyim. yalnız yukarıda ki niye çalışmadı onu da anlamış değilim. t1cki pinini aktif edip tmr1 sayacını oraya atadığımı düşünüyorum tabi olmadı

ete

#38
Bak hala dediklerimi anlamadığını görüyorum.
TMR1 16 bitlik bir sayaçtır. Sayması için CLK palsine ihtiyaç duyar. Bu palsleri ya dahili osilatörden alır ve osilatörün frekansı hızında sayar yada onun için ayrılmış bir harici pin vardır. O pinden gelen CLK ile çalışırak oradan gelen pulsleri sayar.
T1CON registeri bu işleri organize eder. Bit bazında inceleyelim bu registeri (16F628A için)
Bit-7-6: kullanılmaz diyor sıfır verin demiş adam.
Bit-5-4: Bölücü ayarı bitleri; yani gelen CLK sinyalini bölerekmi alacak yoksa direkmi alacak bunu belirliyor bu bitler
- 11 verilirse 8 e bölerek alır yani her 8 clk palsinde TMR1 değeri bir artırılır
- 10 verilirse 4 de bölerek alır
- 01 verilirse 2 ye bölerek alır
- 00 verilirse direk gelen palsi bölmeden uygular.
Bit-3: T1OSCEN Timer1 Oscillator Enable biti Bu dahili kendi osc sini çalıştırıp çalıştırmayacağını belirler , 1 verilirse çalıştırır ,0 verilirse kapalı tutar. Sen sıfır vereceksin.
Bit-2 . Harici CLK dan beslenen sinyalin dahili CLK ile senkronu yapılsınmı yapılmasınmı onu sorar. Yapılmasına gerek yok , sıfır ver gitsin. Bu seçenek harici CLK kullanılırsa geçerlidir. Dahili CLK kullanılırsa anlamsızdır.
Bit-1 : TMR1CS Timer1 Clock Source Select Bit. Yani TMR1 CLK kaynağını seçme biti . Bu en önemli bit işte sana lazım olan bu bitdir. Bak 1 verilirsen PORTB.6 dan giren harici CLK ları sayar, sıfır verirsen Dahili (işlemci) Osilatöründen sayar.
Bit-0: TMR1ON , buda TMR1 sayacını aktif etme bitidir. 1 verisen aktif sıfır verirrsen pasif kalır.
Şimdi önce TMR1H=0:TMR1L=0 şeklinde sayacı sıfırlayıp sonra, bu tabloya bakıp, T1CON=%00000011 değerini verirsen TMR1 sayacı PORTB.6 dan bağladığın frekansın pulslerini saymaya başlar. Ne kadar süre ile sayacak ? 1000 ms. O halde hemen peşine Pause 1000 yazarsan ve hemen ardından,
T1CON=0 verip önce sayacı durdurup  sonra SAYAC.Byte0=TMR1L ve Sayac.Byte1=TMR1H dedinmi al sana frekans değerin SAYAC isimli değişkende demektir.
Hepsi bu kadar. Bu açıklamadan da bir şey anlayıp yapamaz isen bir şey sorma artık anlatmayacağım zira. Bu kodları yada mantığı kendine uygun hale getirmek zor olmasa gerek. Zor geliyorsa bu konuyu bırak bir başkası yapsın bildiğin işlerle uğraş.

Ete



Hattuşa

@ete hocam;
söylediklerinizi anladım, yalnız bişeye itiraz etmek istiyorum. lütfen yanlış anlamayın. timer1 bağımsız bir sayaçsa ve sayma işlemini ben pause komutu kullanmadan yapmak istiyorum. yani counter komutuda var biliyorsunuz, pine sayılacak frekansı giripte counter komutunu ve sayma süresini belirttiğimizde de istediğimiz sonucu alıyoruz yanlışmıyım hocam, ben tmr0 i aktif edip bağımsız bir şekilde arka planda 1000ms tmr0 ile bekletip, tmr1 değerini değişkenime aktarayım istiyordum.
en son eklediğim kodu ise hocam ultrasonic ses ile mesafe ölçme devresi yapmıştım ordan arakladımdı. çalışmaması konusu ise onda int0 ile aldırmıştım sanırım yada öyle hatırlıyorum.
hocam diyeceğim o ki benim gibi öğrenciniz olduktan sonra ALLAH size sabır versin.

trilian

#40
hocam FORMULÜNÜZDEN pic 18f252 kullanıyorum

pulsin portc.6,1,ust  ' OKUNAN 9240
pulsin portc.6,0,alt    'OKUNAN 1603

pulstot=UST+ALT
SONUC=100/PULSTOT
SONUC=SONUC*1000 'sonuç sıfır çıkıyor. yani kesirli oldugu için hesaplama yapamıyorum bunu nasıl yapabilirim.

100/10843=0.0092
0.0092*1000=9.2 çıkartmam gerek yardımcı olurmusunuz. teşekkürler

ete

TEMP=ALT+UST
SONUC=1000**1000
SONUC=DIV32 TEMP
LCDOUT $FE,$80,"sonuc=",dec sonuc/10,",",sonuc//10
şeklinde yapılabilir.
İki sayım değerini TEMP değişkeninde topluyoruz.
SONUC isimli değişkende 100 ile 1000 'i 32 bit çarpmamız gerek. Ancak sonucu 92 olarak bulabilmek için 100 yerine 1000 kullanıyoruz. SONUC=1000**1000 şeklindeki ifade 32 bitlik bir çarpım yapıp sonucu ara bir hafızada tutar.
SONUC=DIV32 TEMP dediğimizde ise aradaki bu çarpım değerini 32 bitlik bir bölme işlemi ile TEMP değişken değerine bölmüş oluruz.
Bu işlemin açık hali şöyledir.
TEMP=9240 + 1603=10843
SONUC=1000**1000=1000.000
SONUC=1000000/10843=92
Bu değeri ekrana yazdırırken önce 92/10 şeklinde tam sayı kısmını ardından 92//10 şeklinde (mod alma işlemidir) ondalık olan 2 sayısını yazdırıyoruz.
Umarım anlaşılmıştır.
Ete


trilian


trilian

ete hocam verdiğiniz şekilde 12 volt palsları sorunsuz okuyup hesapladım teşekkürler. Fakat şöyle bir problem oldu puls başlangıcı anlık 80 volt veriyor ve ardından 12 volta düşüyor 80 volt verdiğinde deger 65535 degeri veriyor. gelen voltaj ne olursa olsun bunu 12v veya 5 volta düşürüp nasıl bozmadan okuyabilirim.teşekkürler

ete

Sinyali 1K dirençten geçir ve öyle Pic'e gir. Pic pinine ayrıca 5V luk bir zener diyot bağla. Hatta zener diyotu 4,7V kullanırsan daha uygun olur.
Böylece kaynaktan gelen sinyal kaç volt olursa olsun pic pinine daima 5V veya 4,7V girer buda senin ölçüm yapman için yeterlidir.
Direnç değeri sorun olursa 470 Ohm kullanabilirsin.
Ete

Powered by EzPortal