avatar_Hattuşa

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

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

F®T

Hocam ben hala ekranda ayarlanan frekansı osilaskop ve frekansmetre ile alabilmiş değilim.Ekranda frekans 10 hz ama frekansmetrede 1 hz.Ayrıca sürekli 1 hz görünüyor.Bana kalırsa hesaplamalar ile ilgili bir sorun var.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

ete

#16
Bu projede yoğun matematik kullanılması gerekiyor. Çünki herşey hesaplanacak değerlerle ayarlanması gerekiyor.
Bu nedenle program yazmadan önce kağıt üzerinde bazı hesaplamalar yapmak daha doğru olurdu.
Benden örnek istedin ama örnek yerine senaryo versem daha çok işine yarar diye düşünüyorum.
Önce 1 hz lik sinyalin değerlerine bakalım; TMR0 kullanacağız 16 bit modunda olacak ve 1/16 bölme oranı ile çalışacağız.
1 Hz , peryodu 1.000.000 us (Low+High süresi) ,bunun için sayacımızın 62500 us sayması gerekiyor (16*62500=1.000.000) diyelimki %50 duty oranı kullanıyoruz. Bu durumda sayacımızın önce 31250 sayıp çıkışın konum değiştirmesi ve ardından yeniden bir 31.250 sayıp yeniden konum değiştirmesi gerekiyor. Peki 31250 sayması için ön yükleme değerimiz ne olmalı 65535-31500=34285 olması gerekiyor.
Birde 10 Hz değerlerine bakalım;
10 Hz, peryodu 100.000 us, sayacımızın 6250 sayması gerekir. %50 duty oranı ile bu değer 3125 olması gerekiyor ve sonuçta bu değer için ön yükleme değerimiz 62410 olması gerekir.
Şimdi program senaryosuna geçebiliriz. Frekansı ADC0 kanalına bağlı pot ile ayarlamayı düşünüyoruz. O halde pot maksimum ve minimum değerleri arasında bana 1 Hz ile 10 Hz lik sinyali oluşturacak önyükleme değerini vermesi gerekir. Bunun üzerinden ben duty değerlerine göre HIGH ve LOW sürelerinin ön yükleme değerlerini hesaplamalıyım.
10 Hz de ön yükleme değerimiz 59286 dır. 1 Hz de ise 3016 dır. Bu ikisinin farkı bana potdan okuma aralığını verecek ve hesaplanan değer 3016 eklenecektir.  59286-3016= 56270 .
O halde potun ADC karşılığı 0-1023 aralığında değişirken benim bu değerimde 0-56270 aralığında değişmesi gerekecektir.
Bu durumda hesaplayacağım değer;
56270/1023=55,00488759 gibi küsüratlı bir değer çıkıyor. Protonda bu rakam ile ADC den okunan değeri çarpınca (yapabiliyor isen) direk ihtiyacın olan değeri hesaplarsın. PBP da ben şöyle yaparım. bu sayıyı 266 ile çarparsam bana 14081 gibi bir değer verir Bu benim 32 bit çarpanım olur. Böylece toplam peryot için ön yükleme değerim
(HAM*/14081)+3016 hesabı ile bulunmuş olur. 
Daha sonra Duty oranı hesabına geçelim. Pot dan Okunacak değer 0-1023 arasında değişiyor hesap bana bunu 0-100 olarak verecek. O halde (100/1023)*256=25,0244 ve bu değeri 2503 olarak alıp sonucu 100 e böleceğiz.
Şimdi senaryoya geçelim ve asılhesaplamaları orada yapalım.

1. Önce POT_Önyükleme değer için ADC okunur. Buradan toplam önyükleme değeri bulunur. Buna peryot diyelim
    Pot değeri arttıkça frekansın artması için okunan değeri 1023 den çıkartmamız gerekir.
    HAM=1023-HAM
    Peryot=(HAM*/14081)+3016
2. SOnra Duty oranı potdan okunur.
    Duty= (HAM*/2503)/100
3. Şimdi High peryodu için parametreleri hesaplayalım.
    Toplam_Sayan=65535-Peryot  'bu değer toplam peryot için işlemcinin sayacağı TMR0 miktarıdır.
    Bunu Duty oranı ile çarparsak bize HIGH süresinin sayılacak miktarını verir.
    HIGH_SAYAN=(Toplam_SAYAN*DUTY)/100
    LOW_SAYAN=TOPLAM_SAYAN-HIGH_SAYAN
    HIGH_ONYUKLE=65535-HIGH_SAYAN
    LOW_ONYUKLE=65535-LOW_SAYAN

Bütün hesap bu kadar. Şimdi programda çıkış pinine bir isim verilir. CIKIS diyelim. HIGH ile başlayacağız.
Program açılırken bu dediklerim Basla satırından evvel okunup HIGH Onyükleme değeri hesaplanacak ve bu TMR0L ve TMR0H registerlerine verilecek. Çıkış=HIGH yapılıp Sonra kesme aktif hale getirilip işlem başlayacak.
İlk kesme oluştu; Kesme içinde şunlar olması gerekir.
IF CIKIS=1 THEN
   CIKIS=0
   TMR0L=LOW_ONYUKLE.BYTE0
   TMR0H=LOW_ONYUKLE.BYTE1
ELSE
   CIKIS=1
   TMR0L=HIGH_ONYUKLE.BYTE0
   TMR0H=HIGH_ONYUKLE.BYTE1
ENDIF
TMR0IF=0
...

Umarım Anlaşılmıştır. Bu dediklerimi denemedim ama mantıken böyle olması gerektiğini düşünüyorum.

Ete

F®T

Ete hocam günaydın.Burda frekans ve duty ile ilgili çözünürlük adımları nasıl oluşur.Pot çözünürlüğü kadarmı.1024 adımmı.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

ete

Olayı daha iyi anlamanız için şunları düşünün;
- 1 Hz lik bir sinyal oluşturacağım.
- Duty oranım %50 olacak
Bu parametrelere dayanarak benim sinyalim;
- 500 ms HIGH verecek ve kesme oluşturup konum değiştirecek
- LOW halinde iken yine 500 ms LOW verip kesme oluşacak ve konum değiştirecek.
Peki 500 ms lik süre sonunda kesme oluşması için ne olması gerekiyor bir bakalım.
Sayac 500.000/16=31250 sayacaktır. Yada sayması gerekir. Bunu sayması için ben ön yükleme değeri olarak 65535-3125=34285 değerini TMR0 'a vermem gerekir.  Bu şekilde programı açarsam TMR0 31250 saydığı zaman 16*31250=500.000us lik süre geçmiş olacaktır. Kesme bayrağı set edilecek ve program kesmeye girecektir.
Burada çıkışa konum değiştirip bu seferde LOW süresine ait değerleri TMR0'a verirsem o süre sonunda yeniden kesme oluşur ve program kesmeye girerek çıkış orada konum değitirir. Nedir LOW değerlerimiz;
500.000 us LOW süremiz olacak bölme oramnı 16 olduğu için sayac 500.000/16=31250 sayacak demektir. Bunu sayması için ön yükleme değerimizde 65535-31250=34.285 olarak TMR0'a verilmelidir.
Bu kısa açıklama konunun daha iyi anlaşılmasını sağlar sanırım.

Ete

F®T

Gayet net açıklıyorsunuz hocam.Teşekkür ediyorum.
Kafama takılan şu, bu vermiş olduğunuz formüller , potansiyometreler ile 9.7 hz frekans ,duty on değeride %77.7 olarak ayarlanabiliyormu?Bu şekil hassas bir ayarlama yapma olanağı oluşuyormu?
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

ete

Ferit frekans çözünürlüğü elbette pot çözünürlüğü ile bağlantılı ama zaten topu topu 10 hz lik bir fark var.
Frekansda ondalıklı çözünürlük isteniyorsa olaya farklı açıdan bakmak gerekir.  Benim önerimde basit bir çözünürlik hesabı yapalım istersen.
Pot en düşük konumda yani 1Hz konumunda frekans 1 Hz olacaktır.
Şimdi potu az çevirelim. ADC den Okunan değer 1 olsun
1023-1=1022 buradan Peryot=(1022*/14081)+3016=59229 bulunur. Bu ise bize 59229 x 16= 947664 us lik bir peryot verir Buda çözünürlüğün ondalıklı değişeceğinin resmidir.

Aynı hesabı potu biraz fazla çevirerek yapalım.
ADC den 23 okuduk diyelim.  1023-23=1000 buluruz. Peryot=(1000 */ 14081)+3016=58019 bulunur.
Bu ise 58019*16=928.304us lik bir peryodu verir ki bu 1 hz den biraz fazla bir frekansa tekabül eder.
Görüldüğü üzere çözünürlük pot değerine bağlı olarak ondalıklı olarak değişecektir.

Ete

ete

Pot ile hassas ayar ancak görerek yapılır. Bir yerde bu frekansı yada Duty oranını görürsün ve fazla çevirmişim biraz düşüreyim dersin yada az çevirmişim biraz artırayım dersin. Potu çevirip frekans ve duty oranlarına Skop ile bakarsan bu dediklerini bu formüller ile yapabilirsin.

Ete

F®T

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

[/quote]

Yukardaki kod ile şöyle bir deneme yapmıştım.Kesme süresini 100 mikro saniye yapmıştım.Dolayısı ile her 100 us de kesmeye girerek sayaç 1 artıyor.Çözünürlükte frekans ve duty için 100 us olarak ayarlanmış oluyor.sayaç değerine görede duty on off pine çıkış veriyor.
Bu mantık sizce nasıl ?
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Hattuşa

slm ferrit usta ve ETE hocam, akşamdan ferrit usta bana başka bir yöntem olarakta bir kesme oluşturulup bu kesme içerisinde sayaç çalıştırmakla yapılabilir mi demişti. başta bana olmaz gibi geldi. bu doğrultuda akşam buraya bişeyler yazdım. ne var ki sabah şöyle bir fikir aklıma geldi (ferrit ustanın bahsettiği yöntemle ilgili ve gayette güzel çalışıyor) dosyayı ekledim.
mantık şu;
ben timer1 kesmesi ile 500uS da bir kesme oluşacak şekilde ayarladım. yani timer1 her 500uS da bir kesmeye giriyor. çözünürlük için kesme süresi daha da kısa ayarlanabilir. herneyse; ben bu kesmenin içinde bir sayaç çalıştırdım. 1 hz in değeri 1000ms öyleyse sayacım 2000 olmalı, 10 hz in değeri 100mS sayacım 200 olmalı. bir adc kanalında 2000-200 =1800 değeri arasında bir değişim sağlarsa ben peryodumu oluştururum. başka bir adc kanalı ile de bu peryodun duty-cycle aralığını ayarladım. bu aralığı ben 100 adım olarak ayarladım ve daha hassas da olabilir.

devre bu şekli ile gayet iyi çalışıyor. deneyebilirsiniz...

ETE hocam verdiğiniz bilgiler çok değerli, aynı mantıkta düşünüyorum. benim derdim. interrupta arka planda fazla oyalanmamak adına ilk tekniği uyguladım. ferrit ustanın söylediği teknikte interrupt ile her 500uS da bir kesme ile işlemci meşgul olacak. gerçi bir işlemci için 500uS luk bir aralık epeyce uzun. hele de 64 MHZ de hissetmez bile...

sonuç olarak istediğimizi elde ettik ve bu yazılım işinde çözümsüzlük diye birşey yok. herşey insanın hayal gücü, azmi,becerisi ve bilgisi ile alakalı...

herşey için teşekkür ederim...

ete

Ferit kesme içinde çok fazla kod var ve bence bunların süresi 100us yi bile aşabilir. Kod gecikmesi bu düşündüğünü zorlar bence. Selami gibi zorunlu olarak kesme süresini artırman gerekebilir.
Ete

F®T

Evet haklısınız hocam kesme içi sayaç ve kesme süresinin küçük tutulması yaklaşımı sanırım çözünürlüğün daha iyi olmasını sağlayabilir.

Selami hocam günaydın.Sorunu çözmeden nasıl yatabildin. :o
Ama yine sabah zindeliği ile halletmişin.Eline sağlık.
Güzel bir konu oldu.
Ete hocam ve Selami hocama teşekkür ediyorum.
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Hattuşa


F®T

Selami hocam eline sağlık çok güzel bir çalışma olmuş.Bu kadar olur. ;)
"Hakk" şerleri hayr eyler Zannetme ki gayr eyler Ârif anı seyreyler Mevlâ görelim neyler Neylerse güzel eyler.

Maxim

çok güzel bir çalışma olmuş elinize sağlık.
aynı alt yapıyla 1khz-10khz yapılabilirmi sizce?

ete

Ekran değerleri ile frekans değerleri bir birleri ile örtüşmüyor. rastgele bir bilgi veriliyormuş gibi durum var.
Ya hesaplarda bir terslik var yada komut gecikmeleri işi etkiliyor.
Sistem prensibi aslında 100us lik kesmelere uygun bir sistem ama bu kadar kısa sürede bu işin yapılmasıda son derece zor. Denemek için 10 hzlik bir sinyal elde etmeye çalışın. ancak ekranda 19,2 hz gibi bir değer yazdığı zaman sinyal frekansı 10 hz ye denk geliyor. Arada büyük fark var. Bu sorunuda düzeltirsen program iyi bir referans programı olabilir.

Görünüşe bakılırsa tek doğru değer 20HZ İÇN görülüyor gerisi yanlış. 20 Hzde peryot 50ms olacak. 10 hz de peryot 100 ms olmalı.

Ete

Powered by EzPortal