avatar_Hattuşa

1hz-10hz değişen duty ile frekans oluşturmak

Başlatan Hattuşa, 22 Nisan 2018, 14:26:54

Hattuşa

selam ETE hocam;
timer ve interrupt ile 1 hz -10 hz arası değişken duty değeri ile bir frekans oluşturmak istiyorum.bu maksatla 18f4520 nin timer0 sayıcısını kullandım. timer0 i aktif ettim. picmulticalcilator ile hesaplattığımda;(4 mhz osc)
1 hz =3036 değerini 1/16 bölme oranında belirledim
10 hz =59286 değerini 1/16 bölme oranında belirledim.
1 hz için 65536-3036 =62499 prascaler sayması lazım. 1 hz lik adımları oluşturması için. ben bu 62499 değerini 100 adımlık duty oranı oluşturmak için 100 e böldüm. ve atıyorum. %50 ye %50 lik bir duty de 1 hz verebilmek için tmr1high =(62499*50)/100 ile 31249 değerini buldum. aynı şekilde tmr1low =(62499*50)/100 =31249 değerini elde ettim.
multicalcilatorde hesapladığımda;
1 hz =1000ms =>3036 prascaler değeri
%50 ye %50 yani 500ms high+500ms low için =>34286 değeri oluşuyor. buraya kadar sorun yok. yaptığım matematiksel işlem ile;
1 kanal adc değeri ile 1-10hz arası frekans değerini belirliyorum.
2. kanal adc ile de elde ettiğim frekans değerini 100 adımlık bölme oranına uygulayıp, prascalerin alması gereken değeri belirliyorum.(high ve low süreleri için). sonra bunu tmr0L ve tmr0H değerlerine yüklüyorum.
ekranda yaptığım işlemlerin hatası yok (bana göre  ;D)
sorun yüklediğim tmr0l ve tmr0h değerlerinin verdiğim değerlere yüklenmemesi, nasıl anladınız derseniz. değerleri yüklüyorum. kesme içerisinde de tmr0 değerlerini başka bir değişkene yüklediğimde de alakasız olduğunu görüyorum.
hocam başımda saç kalmadı. yardım etmezseniz yolmak için peruk takmak zorunda kalacağım.

konu ile ilgili bas dosyası


Device = 18F4520
Config_Start
   OSC = XT ; XT oscillator
   FCMEN = OFF ; Fail-Safe Clock Monitor disabled
   IESO = OFF ; Oscillator Switchover mode disabled
   PWRT = OFF ; PWRT disabled
   BOREN = OFF ; Brown-out Reset disabled in hardware and software
   WDT = OFF ; WDT disabled (control is placed on the SWDTEN bit)
   MCLRE = On ; MCLR pin enabled; RE3 input pin disabled
   LPT1OSC = OFF ; Timer1 configured for higher power operation
   PBADEN = OFF ; PORTB<4:0> pins are configured as digital I/O on Reset
   STVREN = OFF ; Stack full/underflow will not cause Reset
   LVP = OFF ; Single-Supply ICSP disabled
   XINST = OFF ; Instruction set extension and Indexed Addressing mode disabled (Legacy mode)
   Debug = OFF ; Background debugger disabled, RB6 and RB7 configured as general purpose I/O pins
Config_End




Xtal 4
TRISA =%00000011
TRISB =0
TRISC =0
TRISD =0
TRISE =0
PORTA =0
PORTB =0
PORTC =0
PORTD =0
PORTE =0
ADCON0 =%00000001       
ADCON1 =%00001101
ADCON2 =%10010000     
CCP2CON =0
CCP1CON =0
Declare Adin_Delay =100
Declare All_Digital TRUE
Symbol GIE = INTCON.7    ' Global Interrupt Enable
Symbol PEIE = INTCON.6   ' Peripheral Interrupt Enable
Symbol TMR0IF = INTCON.2 ' TMR0 Overflow Interrupt Flag
Symbol TMR0IE = INTCON.5 ' TMR0 Overflow Interrupt Enable
TMR0IE =1
TMR0IF =0
PEIE =1
GIE =0
On_Hardware_Interrupt GoTo KeSMe

Declare LCD_DTPort =PORTD
Declare LCD_ENPin =PORTC.0
Declare LCD_RWPin =PORTC.1
Declare LCD_RSPin =PORTC.2
Declare LCD_CS1Pin =PORTC.4
Declare LCD_CS2Pin =PORTC.3
Declare LCD_Type = Graphic
Declare Internal_Font =On               
Declare Font_Addr =0
Declare GLCD_CS_Invert =OFF
Declare GLCD_EXTERNAL_PRINT =PPRINT
Declare GLCD_Strobe_Delay 10
Cls
DelayMS 300

Dim sAy As Bit
Dim AdC0 As Word
Dim AdC1 As Word
Dim hZadIm As Word
Dim X As Byte
Dim hZ As Dword
Dim dUtYAdIm As Byte
Dim dUtYAdIm1 As Byte
Dim dUtYhEsAp As Word
Dim hZhIgh As Word
Dim hZLOW As Word
Dim HzdUtY As Word
'Dim dUtYBeLIrLE As Float
Dim kalan As Byte
Dim aLt As Word
Dim UST As Word
Dim HzBaK As Byte
Dim dUtyBaK As Byte
Dim t1 As Word
Dim t2 As Word
Dim tOtAl As Word
Dim tOtAla As Word
hZhIgh =3036


TMR0L =hZhIgh.LowByte
TMR0H =hZhIgh.HighByte
'FrQmIN =3036     '1/16
'FrQmAx =59286     '1/16
'fark =56250

Print Font YENI_FONT
Print At 1,1,"FREQ:"
Print At 13,1,"DUTY:"


DelayMS 100
OnMaIn:
For X =0 To 100
GoSub hZbELIrLe
GoSub dUtyBeLIrLe
Next

T0CON =%10000011     '1/16 prascaler bölme oranı
GIE =1
MaIn:
GoSub hZbELIrLe
GoSub dUtyBeLIrLe     
Print At 1,30,Dec hZ,"   ",Dec(hZadIm /10) ,".",Dec kalan," HZ  "
Print At 13,30,Dec dUtYAdIm ," YUZDE  ",Dec dUtYAdIm1,"  "
Print At 25,1,"U: ",Dec UST ,"  " ,Dec hZhIgh,"  "
Print At 37,1,"A: ",Dec aLt,"  ",Dec hZLOW ,"  " ',Dec hZhIgh,"  "
Print At 50,1,Dec t1 ,"  " ,Dec t2,"  "
DelayMS 100
GoTo MaIn

hZbELIrLe:
AdC0 =ADIn 0
While ADCON0.1 =1 :Wend
hZadIm =AdC0 /10.2   '1 hz ile 10hz i 100 adımda artırıp eksilteceğiz
hZ =(hZadIm *562) +3036
kalan =hZadIm //10
Return
dUtyBeLIrLe:
AdC1 =ADIn 1
While ADCON0.1 =1 :Wend
dUtYAdIm =(AdC1 /10.3) +1   'duty oranını 10 adımda artırıp eksilteceğiz
dUtYAdIm1 =100-dUtYAdIm
UST =(dUtYAdIm * (65536-hZ)) /100
aLt =(dUtYAdIm1 * (65536-hZ)) /100
hZhIgh =65536-UST
hZLOW =65536 -aLt
tOtAl =hZhIgh +hZLOW
tOtAla =65536 -hZ
Return


KeSMe:
Context Save
TMR0IF =0
Toggle sAy
If sAy =1 Then

   PORTE.0 =1
   PORTE.1 =1
   TMR0L =hZhIgh.LowByte
   TMR0H =hZhIgh.HighByte
   
   t1.LowByte =TMR0L
   t1.HighByte=TMR0H
Else
   TMR0L =hZLOW.LowByte
   TMR0H =hZLOW.HighByte
   PORTE.0 =0
   PORTE.1 =0
   t2.LowByte =TMR0L
   t2.HighByte=TMR0H
   EndIf
   

Context Restore
End
Include "YENI_FONT.fnt"




ete

1 Hz lik bir sinyal için Tmr1 sayacıın 1000 ms lil bir sayma yapması gerekir.
Peryot= 1/F= 1000.000/1=1.000.000us yada = 1000 ms olması gerekir.  16 bit blme oranı ile önyükleme değeri olarak 3036 verirsek, 65536-3036=62.500 sayar bunu 16 ile çarparsak tam 1.000.000 us elde edirizki bu hesap doğru demektir.

Gelelim 10 hz lk sinyale = 1000/10=100 ms lik süre sayılması gerekir. 100 ms için, yine bölme oranını değiştirmeden sayacımızın 59286 dan başlayıp 65536 ya gelmesi gerekir ki buda 65536-58286=6.250 sayması anlamına gelir bunu 16 ile çarparsak 100.000us yada 100 ms ederki aradığımızda budur. O halde tanımlamalar doğru demektir.
Hata yapılması muhtemel olan şey TMR0 sayacının 8 bşt değil 16 bit çalıştırılması onusuna gelince ;
TMR1=%10000011 değerini vermişsinki bu doğru. Geriye TMR0'a önyükleme değeri veriliyormu ona bakmak gerekiyor.
İşte burada hatan var sanırım.
3036 ön yükleme değerini eşitlediğin değişken;
hZhIgh =3036 şeklinde
Ama kesmeden çıkarken kullandıkların farklı şeyler;
   TMR0L =hZLOW.LowByte
   TMR0H =hZLOW.HighByte
burada hatalısın.
HZLOW yerine HZHIGH:LOWbyte olmalı yada 3036 değerini HZ ye eşitlemelisin.
Ete

Hattuşa

hocam bahsettiğiniz konuda tmr0l veya tmr0h değerlerinin yeri değiştiğinde frekansın yükselen-düşen kenarlarında değişim olur farketmez diye düşünüyorum. benim sorunum(ekrana print ettiğimde) yüklediğim tmr0 değerinin kesme içerisinde geçersiz oluşu, yani diyelim ki %50 ye %50 lik bir peryodda
tmr0l =hzhihg.lowbyte
tmr0h =hzhihg.highbyte

dediğimde ve ekrana tmr0 değerini bastığımda benim vermiş olduğum değeri almıyor ve sürekli değişken alakasız bir değer oluşuyor. ben bu noktada takıldım kaldım. hatta tmr0 değerini ana ekranda değilde kesmenin uzun olması nedeniyle kesme içinde bile hesaplatsam tmr0 değerini yükleyemiyorum.

ilk defa böyle birşeyle karşılaştım. yani verilen değer, komut doğru mcu nun yaptığı farklı. acaba isisden mi kaynaklı diyeceğim. ama bunun isisden kaynaklı olabileceğini de sanmıyorum.

F®T

Pro-tr hocam protonda compıler ettim bir sürü hata verdi. inc dosyası ve işlemciyi tanımama hatası oluyor.Protonun hangi versiyonunu kullanıyon. Ayrıca inc dosyası da lazım.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

F®T

Proton free versiyonunu kullanıyom bu işlemciyi kabul etmiyor.Bende 18f46k22 sectim.Hatalar gitti Fakat glcd inc dosyası olmayınca derlemedi.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Hattuşa

#5
font dosyasını ekledim  ferrit usta.
proton IDE 2,0,3,3,
conbiler 3,6,0,2,
loader 1,0,0,6
kullanıyorum.

nasipse bu 1hz-10hz işini adc yerine birde butonlarla deneyeyim. bişey farkedecekmi?

F®T

#6
Selami hocam bendede aynı dosyalar var fakat derlemede işlemci yok hatası veriyor.Programı tekrar indirip yükliyeyim belki düzelir.
ETE hocamın dediğini denedinmi.Muhtemelen orlarda bir sıkıntı var.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

ete

Selami ,
Ne yapmaya çalıştığını pek anlayamadım. Amacın bellide bunu yapmak için tuttuğun yolda sakatlık var gibi.
Değişkenlerine bakıyrum bir tane bile Float yok. Ama hZadIm =AdC0 /10.2  böyle bir işlem yapmaya çalışıyorsun. Sence doğrumu?

İşin bütününü anlamayınca yorum yapmakta zor. Birde derleyici Proton olunca elim kolum bağlanıyor.

Ete

Hattuşa

FERRIT hocam;

Symbol wTImer0 = TMR0L.Word 


şeklinde protonda direk tmr0 değişkeni de verilebiliyor. bunu da denedim. şöyle ki protonda bir word değerini 16 bitlik tmr0 değişkenine atarken byte byte verme yerine direk
wtimer0 =(hesaplanan değer)
şeklinde bile yapılabiliyor. ne var ki benim atadığım tmr0 değeri kesme içerisinde başka değerler alıyor. bu tmr0 değişkenine MCU içerisinde başka ulaşma yolu yokmudur?

Hattuşa

Alıntı yapılan: ete - 22 Nisan 2018, 23:21:01
Selami ,
Ne yapmaya çalıştığını pek anlayamadım. Amacın bellide bunu yapmak için tuttuğun yolda sakatlık var gibi.
Değişkenlerine bakıyrum bir tane bile Float yok. Ama hZadIm =AdC0 /10.2  böyle bir işlem yapmaya çalışıyorsun. Sence doğrumu?

İşin bütününü anlamayınca yorum yapmakta zor. Birde derleyici Proton olunca elim kolum bağlanıyor.

Ete


ETE hocam. haklısınız ben sol kulağımı sağ elimle göstermeye çalıştığımdan kaynaklanıyor olabilir. kafam bu şekilde bastığı için bu yolu denedim. hatamı bulmaya çalışıyorum.
eğer sizin için sakıncası yoksa 1hz-10hz arası duty değerleri ile oynayabileceğimiz bir kodu herhangi bir mcu da picbasicte yazmayı deneyebilirmisiniz? bende hatamı görmek istiyorum

Hattuşa

ETE hocam yapmaya çalıştığım aslında basit bir mantıktı, şöyle ki

1 hz tmr0 da 1/16 bölme oranında prascaler değeri 3036
10 hz değeri de 59286

tmr kesmesi 1 hz için konuşuyorum. tmr0 a 3036 yı yüklediğimizde 3036 dan başlayarak saymaya başlar ve 65536 dediğinde kesme oluşur doğru mu?
bende 65536 -3036 =62500 ile
65536 -59286 =6250 arası
yani 1 adc kanalı ile 6250 ile 62500 arası değişen bir değer oluşturdum. bu değere hz adını verdim.
hz değerim 6250 olduğunda 10 hz i 62500 olduğunda da 1 hz i verecek. (yani bir peryod high olduğunda başlar duty oluşur low olduğunda cycle oluşur. tekrar high olduğunda peryod biter)
ben peryodun high den tekrar high e geldiği peryodun tamamına hz adını verdim ve bir adc kanalını buna atadım.
başka bir adc kanalı ile elimdeki bu hz değerini 100 dilime ayırdım. yani 2.adc kanalından elde ettiğim % değerini mesela %10 olsun. elimdeki hz değerinin %10 nu duty kalan %90 nı da cycle değeri olarak hesapladım.
timer kesmesi içerisinde de bir biti toggle yaptım. bu bit 1 olduğunda hz değerinin %10 luk duty değerini tmr0 a yükledim ve başka bir pini de high yaparak frekansın bu kanaldan çıkmasını istedim.. bitin 0 olduğu durumda da 2. adc kanalından elde ettiğim %90 lık hz değerini tmr0 a yükleyip frekansı oluşturan pini lowa çekerek peryodu tamamlamaya çalıştım. gel gör ki yüklemeye çalıştığım tmr0 değeri kesme içerisinde kafasına göre takılıyor verdiğim değeri almıyor.

hocam ben biraz anlatma özürlüyüm. bu kadarını izah edebildim. sizin daha güzel fikirleriniz varsa emin olun sabırsızlıkla bekliyorum

F®T

selami hocam kesme içinde bir sayaç yapsanız ve bu sayaç değerine göre duty on of f değerini çıkış pinine atasanız.sizin kodu çalıştırdım sonunda hesaplar süper fakat kare dalga sürekli %50 on %50 off olarak oluşuyor duty ve frekans ayarlanamıyor.

şöyle bir mantık olurmu.

Context Save ' Save any variables used in the interrupt

If TMR0IF = 1 Then ' Is it a Timer1 overflow interrupt?

SAYAC=SAYAC+1   ' sayaç  zaten kesme süresine göre çalışacak hız olarak

If SAYAC<ton  Then  'duty on değeri hesapta ne ise buna göre pin on olacak
PORTB.0=1
EndIf

If SAYAC>ton And SAYAC<tof Then  burdada duty on ve duty off arasındaki değer kadar pin off olacak
PORTB.0=0
EndIf

If SAYAC=duty  Then SAYAC=0  ton+toff değeri ile sayaç eş ise zaten toplam duty olmuş sayaç sıfırlayarak tekrar baştan 2. peryodu devam edecek.


TIMER=buraya tımer hesaplanan değeri eşlense.bu değer tmr0 a yüklense
         
TMR0IF = 0 ' Clear the Timer1 Overflow flag

EndIf '

Context Restore ' Restore any variables and exit the interrupt
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

F®T

Ayrıca bir örnekte şöyle bir tanımlaam var.

Dim TIMER0REG As TMR0L.Word
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Hattuşa

#13
ferrit ustam;
sizin söylediğiniz şöyle bir şeymi?
1 adc kanalı ile frekansı belirlesek ve belirlenen süre kadar kesmeye gitse, kesmeye gittiği anda bir pini high yapsak ve kesme içerisinde bir sayaç saydırsak ve sayaç değeri istenen noktaya geldiğinde high yaptığımız pini lowa çekip peryodu oluştursak mı? demek istiyorsunuz?
eğer öyle ise sizin kesme içerisinde ki sayaç sadece kesmeye girdiğinde sayan bir sayıcı olur, arka planda sayım yapmaz.
aslında sizin anlatmak istediğinizi yani o sayacı ben arka planda sayan prascaler olarak düşündüm. yani prascalarler arka planda sayabilen bir sayaçtırlar. kesme oranına ve büyüklüğüne göre arka planda sayabiliyorlar. 16 bitlik bir prascalari tmr lerle bir değer verdiğimizde o değeri alırlar ve bölme oranına göre 65535 e kadar sayarlar 65535 olduklarında kesmeye girerek sayma süresini bize bildirirler. tabi yanlış düşünüyorsam ETE hocam düzeltsin. zira bize bu şekilde öğretti. en azından ben öyle anladım.

bu arada az önce bilboard üzerinde 16f628a yı kurdum timer1 i 1/8 oranında ayarlayıp,butonlarla devreyi kurdum. devre çalışıyor duty,cycle doğru çalışıyor, oluşturulan frekansta doğru çalışıyor. tabi hesapladığım değerler 1/8 e uymadığı için farklı frekans aralığında çalışıyor.
ama çalışıyor. biraz dolambaçlı birmantıkta olsa çok hafif derecede duty değeri ile oynadığımda frekansta kayma oluyor.

tabi birde hatamı tespit ettim.



ust ve alt değerlerimi belirlerken öncesinde ben


UST =(dUtYAdIm *hZ)/100


yaptığım için word değişkeninde taşmalar oluyormuş aşağıdaki şekilde yaptığımda düzeldi.


UST =hZ/100 *dUtYAdIm


tabi şu da var. bu isis adamı verem edebiliyor. zira herşeyi dosdoğru göstermiyor. bazen sahaya inmek gerekiyormuş


F®T

Selami hocam aynı dediğiniz gibi düşündüm.
Sizin dediğinizde güzel.Fakat ben her 100 mikro saniyede bir kesme oluşturup kesme içi sayacı çalıştırıp karşılaştırma ile duty oluşturdum.
Atıyorum frekansı ayarladık.10 hz peryod 100 ms yapıyor.Duty değeri 100 mikro saniye adımlarla ayarlanırsa 1000 adet adım oluşuyor.
Neden.Çözünürlüğü yüksek bir frekans ve  bir duty oluşturmayı düşündüğüm için.
Senin ayarlamanda bu adımlar daha kaba olaucak gibi. ;)

Ayrıca sahaya inmek iyidir.Bende arasıra halı sahaya gidiyorum bu yaştan sonra.Ama spor iyidir.Adamı zinde tutar.Bu tip işlerde iyidir.Kafayı zinde tutar. ;D

Hesaplamalarda float değişken kullanıp bir denermisin Frekans ve duty oranını noktalık olarakta hassas ayarlayabiliyormusun? 8)
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Powered by EzPortal