timer1 kesmesi

Başlatan black, 26 Eylül 2014, 16:36:05

ete

Kesme ile kare dalga oluşturmada basit olan %50 duty ile çalışmaktır. Zira her kesmede konum değiştirince çıkan sinyal %50 duty değerine sahip olur. Duty ile oynamak istersen high süresinde başka tmr1 süresi low da başka tmr1 süresi uygulaman gerekir. Bu ise biraz kafa çalıştırma ve uygun algoritma geliştirmeyi gerektirir. Şu anda şöyle yapabiliriz diyebileceğim bir yöntem aklıma gelmedi daha doğrusu basit bir şey allıma geldi ama uygulanabilirliği şüphe götürür. İstersen biraz da sen kafa yor ve nasıl aypılabileceği konusunda öneride bulun bakalım ne düşüneceksin.
Toplam peryot sabit kalacak ama arada hig ve low süreleri bir birlerine borç verecek mesele burada. Bir ip ucu vereyim. Adc ölçümü hep low süresini hesaplasın. Hig süresine sıra gelince, senin 10 kademenden birisi kadar low süresine ekleme yapılsın ama toplam 5khz lik süreyide aşmamış olalım.

Ete

Hattuşa

#16
ete hocam
sizin verdiğiniz bu kodda, frekansımız 500hz ile 5khz arasındaydı ya bu aralığı 2 katına alıp "ONdeger" değerimizi duty-cycle olarak kullanamayız mı? yani misal (olabildiği kadar zira timer helper programına hesaplatmadım) 250 hertz ile 10 khz arasına alıp, "Ondeger" değişkenimizi 10 kademeye alıp duty değişkeni olarak kullanabilirmiyiz. tabi bu seferde peryodu belirleyecek değişkeni nasıl ekleyeceğiz ona bir türlü akıl erdiremedim. yada tmr1 kesmesi içerisine pini high-low yapacak bir değişkeni nasıl ekleyebiliriz. atıyorum "ONdeger" değişkenimiz 500 hertzde 45543 değerini alıyor ya Ondeger değişkenimizin 2271. değerinde koda müdahale edip pini terslediğimizde %50-%50 olmaz mı?
....
hocam kafam durdu ben bir sigarayada daha asılayım. ;D


ete

Adc den peryot okumak ve buna uygun olarak duty değerinide yüzde cinsinden kullanarak arada low ve high süresi için timer değerlerini hesaplamak gerekir.Ama nasıl.? Epeyce kafa yormak gerekiyor.

Ete

ete

Aklıma gelen sistem şöyle,
ADC den okunan değer 500us-5000us aralığında çıkıştan alınacak frekansın peryodu olsun ama us cinsinden hesaplansın.
Duty adından bir değişken tanımlansın ve buda olması gereken duty değerini belirlesin. Gerisini aşağıdaki örnekli uyglamadan takip etmek daha kolay olacak sanırım.
Diyelimki 1KHz (1000 Hz) lik bir sinyal çıkartacağız. Bunun Duty değeri %60 olsun. Yani %40 LOW, %60 High olacak şekilde çıkacak sinyalimiz.
1Khz lik sinyalin peryodu, us cinsinden şöyle bulunur: T=1000/1=1000us dir. Bunun %60 ı ise 1000*60/100=600 us olacaktır.
Low süresi ise 1000-600=400us olacaktır.  Şimdi bunlara uygun TMR1 değerlerini hesaplayalım.
20 Mhz de bir komut çevrimi 0,2us dir (20/4=5 ve 1/5=0,2us) 600us için TMR1 sayacının 600/0,2=3000 sayması gerekecektir.
Buna 7 komut gecikmesi eklemek doğru olacaktır. Bu sayacın TMR1 sayacında belirli bir sayıdan başlayıp tam 65535 i saydıktan sonra kesme oluşturabilmesi için 65536-3000+7=62543 sayısını TMR1 e ön yükleme değeri olarak vermek ve tam 65536 da kesme oluşmasını sağlamak gerekir.
LOW için de benzer bir hesap yaparsak,
400/0,2=2000, buna 7 ekliyoruz ve 65536 dan çıkartıyoruz. Böylece LOW için TMR1 ön yükleme değeri=65536-2007=63529 olarak bulunur.
Bu durumda ilk TMR1 kesmesi çıkış LOW iken 63529 ön yükleme değeri ile çalışmaya başlayacak.
Kesme oluşunca Çıkış Toggle ile konum değiştirecek ve TMR1 ön yükleme değeri olarak 62543 verilecektir.
Toparlarsak,
1. ADC den frekansın süresi peryot olarak us cinsinden hesaplanacak.
2. Duty değeri % olarak belirlenecek.
3. Hesaplanan peryot dan HIGH süresi hesaplanacak.
4. Hesaplanan peryottan HIGH çıkartılarak LOW süresi hesaplanacak.
5. HIGH-Önyükleme=HIGH_Süresi/0,2 (veya HighSüresi*10/2)+7+1 ) hesaplanarak hesaplanan değer 65535 den çıkartılacak. Bu süre HIGH ön yükleme süresi olarak verilecek.
6. LOW Önyükleme Süresi Low_Süresi/0,2  (veya LowSüresi*10/2)+7+1) hesaplanarak 65535 den çıkartılacak.
Hepsi bu kadar.
Umarım becerirsin.

Ete

Hattuşa

slm ete hocam;
son mesajınızda ki maddeleri tek tek uyguladım ama 6. maddenin altında ki kısmı yapamadım.
o kısımsa "Umarım becerirsin" yani beceremedim.
şimdi hocam ekran alıntısında görüldüğü üzere;
2 kanal adc yi aktif edip 1. kanalı başlangıçta yaptığımız şekliyle frekansımızı değişken hale getirdik.
ekranın 2. satırındaki ADC1 değeri frekansımızı oluşturan ADC değerimiz, altında ki FR DEG: ise frekansımızı belirleyen ve hesaplamalar sonucu kesme süremizi belirleyen değer.yani TMRL ve TMRH değerimiz.
devamındaki ADC2 ise duty değerimizi belirleyeceğimiz adc değerimiz, YUZDE olarak görünen ise hesaplanacak duty değerinin yüzdesi yani
yuzde =adc2 /11 (ben kabaca hesaplattım yani %98 lerde kalabilir)
ekranda DUTY olarak gözüken kısım ise FR DEG, yani ondeger olarak kabul ettiğimiz değerin duty süresi
duty =(ondeger /100) *yuzde

hemen altındaki cycle ise duty değerinden sonraki low süresi
cycle =ondeger -duty

ekranda herşey güzel, sorun TMR1 kesme içerisinde verilecek komutları beceremedim.

Z0_KeSMe:
        Context Save
        If INTCON.2 =1 Then
        KeS =1
       INTCON.2 =0
       EndIf
    [b]   If PIR1.0 =1 Then
       PIR1.0 =0
      If OnDeGeR =DuTy Then Toggle P1 :OnDeGeR =CyClE
      TMR1L =OnDeGeR.Byte0
      TMR1H =OnDeGeR.Byte1
      EndIf [/b]
        Context Restore


hocam sizi sıktım farkındayım ama şunu yapmaya çalıştım (en azından sizin anlatımınızdan anladığım kadarıyla,
ondeger değişkeni duty değişkenine eşitlenince P1 çıkışının konunumu değiştirdim ve aynı zamanda ondeger değişkenine söylediğiniz gibi cycle değişkenine yükledim. ki P1 in konumunu tekrar değiştirebilelim. ama o kısmı beceremedim.

ete

Öncelikle ADC-0 kanalından Peryodu hesaplayalım. Frekans 500 Hz ile 5000 hz arasında idi. Min frekans Peryodu 1000/500=2ms yada 2000 us olacaktır. Maksimum Frekans Peryodu, 1000/5000=0,2ms yada 200us olacaktır.
O halde 2000-200=1800 us lik bir değişim söz konusu olacaktır. (1800/1024)*256=450 sabit çarpan olarak bulunur. Formül,
Peryot=(Ham+1)*/450+200 şeklinde bulunur. Bu formülü bu şekilde kullanırsak ADC maksimumda iken min. frekans min. da iken ise maksimum frekansı hesaplamış oluruz. Halbuki tersi olsa daha güzel olurdu. O halde;
Peryot=(1024-Ham)*/450+200 şeklinde uygularsak maksimum ADC de min peryot yani maksimum frekans hesaplamış olacağız.

Bu formül ile frekansa karşılık gelen peryodu bulduktan sonra şimdi DUTY hesabını da ADC-1 kanalından yapalım.
Maksimum değer 100 olacağına göre (100/1024)*256=25 bizim sabit çarpanımız olur. Formül ise;
Duty=(Ham+1)*/25 şeklinde hesaplanır.
Şimdi TMR1 değerlerini hesaplayalım.
Temp=Peryot*duty/100
HighYukleme=temp*10/2
HighYukleme=65535-HighYukleme+8  'buradaki 8 rakamı 7+1 dan geliyor. 1 rakamı 65536 yerine 65535 yazmak zorunluluğundan , 7 ise komut gecikmelerinden kaynaklanıyor.

Şimdide Low Yükleme Değerini hesaplayalım.
Temp=Peryot-HighYukleme
LowYukleme=Temp*10/2
LowYukleme=65535-LowYukleme+8
Bütün bu hesaplamalar programın ADC okuma kısmında yapılacaktır.
Kesme kısmında
..
..
If PIR1.0=1 then
PIR1.0=0
Toggle CIKIS
If CIKIS=1 THEN
  TMR1L=HighYukleme.Byte0
  TMR1H=HighYukleme.Byte1
Else
  TMR1L=LowYukleme.Byte0
  TMR1H=LowYukleme.Byte1
Endif
Endif
Context Restore

Hepsi bu kadar bu seferde yapamazsan bu işi yapmaktan vaz geç derim çünki artık ne yapman gerekenlerin kendisini yapıp verdim. Bu tür hesapları kendin yaparsan daha iyi öğrenirsin diye düşünüp detaya girmemiş ancak yolunuda göstermiş idim.
Çok zor olmasa gerek. Yalnızca mantık çalıştırıp neyin nerede nasıl yapılacağına anlattıklarıma bakarak karar verecektin ama sanırım temel epeyce zayıf. Her neyse bu sefer başar artık. Bak umarım başarırsın demiyorum başar artık diyorum. Zira her şey elinin altında artık.

Ete

Hattuşa

#21
Alıntı YapPeryot=(Ham+1)*/450+200 şeklinde bulunur. Bu formülü bu şekilde kullanırsak ADC maksimumda iken min. frekans min. da iken ise maksimum frekansı hesaplamış oluruz. Halbuki tersi olsa daha güzel olurdu.

hocam tam tersi derken hesaplama daha rahat olacaksa yüksekten küçüge hesaplatalım, onuda öğrenmiş oluruz.
bu arada duty değeri de dediğiniz şekliyle oluyor, ancak sanki bir yerde hata var gibi, belki isisin azizliği olabilir. hata derken verdiğiniz şekilde kesme içinde dediklerinizi aynen yazdığımda duty değerini düşüremiyorum. iflerin içindeki

  If PIR1.0 =1 Then
       PIR1.0 =0
       Toggle P1
       If P1 =1 Then
   TMR1L=loWyUkLeMe.Byte0
  TMR1H=loWyUkLeMe.Byte1     
 
Else
  TMR1L=hIgHyUkLeMe.Byte0
  TMR1H=hIgHyUkLeMe.Byte1
EndIf
EndIf


şeklinde değiştirince duty değeri düşüyor, yükseliyor ancak frekans düşmüyor. verdiğiniz şekilde de frekans sağlıklı çalışıyor ancak duty tam sağlıklı çalışmıyor.

ama şu var hocam inanın benim için çok zor olan birşeyi siz çok güzel ve basit bir şekilde yaptınız. tşk ederim.

NOT: hocam mantığını anladım artık, tşk ederim. gerisi ile ben uğraşırım eğer aşamazsam size dönerim

Hattuşa

slm ete hocam;
hocam kendimin bir eksiğini farkettim. farkedemediğim okuduklarımı anlayamayışımmış, 2 gündür yazdıklarınızı okuyup durdum. ama sonunda başardım. vermiş olduğunuz kodu kendi devreme adapte edip kodları bir kenara attım. ben buton kontrollü duty-cycle değerini 10 kademeye aldım ki böyle olmasını istiyordum. çokta güzel oldu hocam ya. inanın önceki halinden (analog yaptığım şeklinden) çok çok güzel oldu bunun için size bu tşk yazısını yazma mecburiyetinde hissettim kendimi. hocam "TEŞEKKÜR EDERİM"

bu arada hocam, sorularım bitmedi bilesiniz. şu işlemci ile yaptığımız 4 işlem üzerine bir dizi soru yağmuruna tutmayı planlıyorum. şimdilik özel hayatımda biraz yoğunluk var gene rahatsız edeceğim sizi...

Powered by EzPortal