Şimdi Ara

PWM Hesabı ve Kodlanması (Çözüldü)

Daha Fazla
Bu Konudaki Kullanıcılar: Daha Az
2 Misafir - 2 Masaüstü
5 sn
15
Cevap
0
Favori
9.584
Tıklama
Daha Fazla
İstatistik
  • Konu İstatistikleri Yükleniyor
0 oy
Öne Çıkar
Sayfa: 1
Giriş
Mesaj
  • Dikkat: Sorun çözüldü. Cevapları dördüncü sorunun altında belirttim.
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    XT kristal osilatör f = 4mhz kullandığımızı varsayalım.
    (Ccs C dilinde ve PIC C derleyicisinde çalışıyoruz)

    PWM, timer2 ile çalıştığına göre kodumuz:
    setup_timer2(T2_DIV_BY_Bölme Oranı,PR2,Postscale); olmalıdır.

    setup_timer2(T2_DIV_BY_16,254,1); kullandığımızı varsayalım. Buradan,
    Bölme oranı (prescale) = 16
    PR2 = 254
    Kesmeye geçme sayacı (Postscale) = 1 (ilk sorum burada: postscale timer2 kesmesi için kullanılıyor ancak benim programımda kesme olmayacak, bu durumda PWM'i kesmeye girmeden kullanabilir miyim ?)


    PWM periyodu = (PR2+1 ) x 4 x Osilatör Periyodu x TMR2 Bölme Oranı (ikinci sorum: bu hesap 10bitliğe göre mi ayarlanmıştır ? 4 ile çarpılmasaydı 8bitlik hesap mı yapmış olurduk?)

    Yani,
    Tpwm = (PR2+1) x 4 x Tosc x (TMR2 prescale) buradan,
    Tpwm = (254+1) x 4 x (1/4 000 000) x 16
    = 4080 us

    Dolayısıyla sinyalin grafiği şu şekilde olacaktır:
     PWM Hesabı ve Kodlanması (Çözüldü)



    Bu şekilde çalışırken sinyalin 2040uS süresince iş-görev (duty) yaptığını görüyoruz.
    Bu çalışma aralığını %50 oranına çekmek istersem yani 1020us yapmak istersek;

    10 bitlik Duty değeri için:
    Darbe Genişliği (pulse width) = Görev (duty) Değeri x Tosc x (TMR2 Bölme Oranı)

    İstediğimiz darbe genişliğimiz = 1020us
    = 1020/1 000 000

    Yani,
    1020/1 000 000 = Duty x (1/4 000 000) x 16 denkleminden Duty bilinmeyenini çekersek:
    Duty = 255 çıkar.
    Bu hesabı 10bitlik duty değerine göre yapmış olduk.

    8bitlik duty değeri için formül:
    Darbe Genişliği (pulse width) = Görev (duty) Değeri x Tosc x (TMR2 Bölme Oranı) x 4


    Pwm değerini ya 8 bitlik yazım ile ya da 10 bitlik yazım ile değiştirebiliriz. (gerçi 8bitlik yazsak bile, PIC iki sıfır kaydırarak bu değeri 10bitliğe çeviriyor)
    10 bitlik tanımlama için "gorev" adında geçiş değişkeni tanımlıyorum:

    int16 gorev = 255
    set_pwm_duty(gorev);

    8 bitlik tanımlamada ise girdiğimiz sayı PIC iki sıfır kaydırarak bu değeri 10bit'e çevirdiği için 4 ile çarpılacak
    Yani,
    gorev = gorev/4 ise:

    set_pwm_duty(63,75); olur.

    Üçüncü sorum: Tpwm hesabı 10bitlik kullanıma göre uygulanıyorsa 8bitlik tanımlama(set_pwm_duty(63,75)) yapmamız yanlış olmaz mı ?

    Şuradan:
    http://www.acroname.com/robotics/info/concepts/pwm.html

    görülebileceği gibi görev çevrimi (duty cycle):

    Duty Cycle = Pulse Width/Tpwm olur.

    Yukarıdaki formüllere göre gerekli sadeleştirmeler yapıldığında:
    Duty Cycle = Duty/(PR2+1)x4 olur.

    PR2 = 254 seçilmişti ve
    Duty = 255 bulunmuştu. Buradan:

    Duty Cycle = 255/(254+1)x4
    = 1/4
    = %25 olur.

    Sinyalin çalışma süresinin toplam PWM periyoduna oranı 1/4 çıkıyor. Yani hesapların doğruluğunu sağlıyor.

    Yeni sinyalin grafiği:
     PWM Hesabı ve Kodlanması (Çözüldü)


    Gelelim dördüncü soruya:

    PWM ile motor sürmeye kalkarsak %100 (ideal varsayalım) hızla çalışan bir motoru pwm(gorev) veya pwm(63,75) ile %50 çalışır hale -daha doğru bir söylemle Rpm hızında dönen bir motorun Rpm/2 hızında dönmesini- sağlayabilir miyiz ?

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Sonunda cevaplarımı elde ettim. Buraya da son durumu güncelleyeyim:

    1) Postscaler'in PWM üzerinde bir etkisi yok. Datasheet'lerden de kolaylıkla bulunabilir. Postscale timer2 kesmesi için kullanılan bir değer. PR2 değeri sınırına ulaşıp her sıfırlanışında 1 postscale değeri artıyor. Örneği PR2 değerini 50 girdik. Postscale değerini 3 girdik. Timer2 sıfırdan saymaya başlıyor. 50 olduğunda sıfırlanıyor ve postscale 1 değer artıyor. Bu işlem iki kez daha tekrarlanınca Postcale bizim belirlediğimiz 3 değerine ulaşıyor ve Timer2 kesmesi oluşuyor. Ben programda kesme kullanmayacağım için gireceğim değerin program üzerinde bir etkisi yok.
    2) PR2 değeri 0xff şeklinde 16bitlik olarak dahi belirtilebiliyor. Dolayısıyla formül 8bitlik veya 10bitlik diyemeyiz. Datasheet'te de bu formül belirtilmiş. PR2'e ne değer girersek girelim 10bit üzerinden hesap yaptığımız için (örneğin 0xff = 255 deyip PR2=255 yazıyoruz) 10bitlik bir hesap yapıyoruz. Söylemeyi unutmuşum, 16F877A kullanıyorum. Datasheet'te bu PIC'in çözünürlüğü 10bit verilmiş zaten.
    3) İşte en büyük problemim set_pwm_duty() fonksiyonunun nasıl çalıştığıyla ilgiliydi.

    Öyle bir fonksiyon oluşturmuş ki adamlar duty parametresine girilen değer 255'den büyükse derleyici bunu 10bit algılıyor, eğer 255 ve altında bir değer girilmişse derleyici bunu 8bit kabul ediyor.

    set_timer2(T2_DIV_BY_1,249,1); belirledik diyelim.

    255'den küçük bir değer girdiğimizde yani 8bitlik bir değer girdiğimizde

    Duty Cycle = Duty/(PR2+1) olacaktır.

    Örneğin set_pwm_duty(125) için Duty Cycle = 125/250 = 1/2 = %50 çıkar.


    Ancak değer hem 255'den küçükse hem de bu değer 10bitlik olarak kullanılmak isteniyorsa:

    1)10bitlik bir değer için int16 diye bir değişken ile bu değeri girebiliriz.
    int16 gorev = 125;

    Duty Cycle = Duty/(PR2+1)x4 demiştim. Buradaki Duty değeri girilen değerin 10bitlik olması gerekiyor. Bunu tanımlayabilmek için de int16 kullanıyoruz. Aslında çözünürlüğü 10bit'e çıkarmış olduk.

    Duty Cycle = 125/1000 = %12.5 Bu kez PWM oranı %12.5 olur.

    veya aşağıdaki iki şekilde de bu işlemi yapabiliriz.
    2)set_pwm_duty(125L);
    3)set_pwm_duty((long)125);

    kaynak:
    http://www.ccsinfo.com/forum/viewtopic.php?t=31674
    http://www.ccsinfo.com/forum/viewtopic.php?t=28761
    http://www.ccsinfo.com/forum/viewtopic.php?t=24403


    4) Üçüncü sorumun cevabına göre bu cevap ta kendiliğinden beliriyor. set_pwm_duty() fonksiyonu kaç bitlik kullanılırsa motorun yüzde hesabı da ona göre çıkıyor.



    < Bu mesaj bu kişi tarafından değiştirildi KeanAtay -- 2 Aralık 2013; 1:33:26 >







  • Yapay Zekanın Yanıtı

    PWM Hesabı ve Kodlaması

    PWM Duty Cycle Nedir?

    Darbe Genişlik Modülasyonu (PWM), bir elektrik sinyalinin görev döngüsünü değiştirerek bir çıkış gücünü kontrol etmek için kullanılan bir tekniktir. Görev döngüsü, sinyalin devrede olduğu zamanın toplam süreye oranıdır.

    PWM Duty Cycle Hesaplama

    PWM görev döngüsü, aşağıdaki formül kullanılarak hesaplanabilir:

    Görev Döngüsü = Açık Süre / (Açık Süre + Kapalı Süre)

    PWM Hesaplama

    PWM hesaplaması, istenen çıkış gücünü elde etmek için gereken görev döngüsünün belirlenmesini içerir. Görev döngüsü genellikle yüzde olarak ifade edilir ve 0 ile 100 arasında değerler alabilir.

    PWM Kodlaması

    PWM sinyali, bir mikrodenetleyici veya özel bir PWM IC kullanılarak kodlanabilir. Kodlama, açık ve kapalı sürelerin ayarlanmasını ve böylece istenen görev döngüsünün oluşturulmasını içerir.

    PWM, motor kontrolü, güç kaynakları ve dijital-analog dönüştürücüler gibi çok çeşitli uygulamalarda kullanılır. Uygun şekilde hesaplanmış ve kodlanmış bir PWM sinyali, hassas ve verimli güç kontrolü sağlayabilir.

    Yapay Zekanın Yanıtını Genişlet
  • 1)pwm modunda postscaler kullanılmaz,ürünün datasheetinde pwm şemasından görebilirsiniz.
    2)periyot 8 bitliktir.2 bitlik bir sayı ile 8 bitlik bir sayıyı çarparsak 10 bit elde ederiz öyle düşünebilirsin.o yüzden 4 ile çarpılmıştır.10 bit olan max çözünürlüktür.
    3)8 bitlik hesaba göre max 255 yazılabilir.yanlış olmaz.tekrak söylüyorum 10 bit olan çözünürlüktür
    4)pwm frekansları ile hızın sabit bir fonksiyon doğrultusunda çalıştığını bilmiyorum ama %100 olarak pwm verilirse pure dc elde edilir.sen onu yarıya bölüyorsun ordan hesap et
  • faruk_ultras F kullanıcısına yanıt
    1-) Postscaler burada etki etmiyor. Şemada da yok fakat bu durumda setup_timer2 kodunu nasıl yazmam gerekecek. Postscaler değerini 0'mı yazmam gerek ?
    örneğin : setup_timer2(T2_DIV_BY_16,254,0);

    2-) Cümleyi tam anlayamadım. Yani 4 ile çarpılarak 10 bit'e mi geçilmiş ? Yani 8bitlik olan periyot 4 ile çarpılarak 10bitliğe çevriliyor. Değilse neden duty için girdiğimiz değer 10bitliğe dönüştürülüyor? Yoksa çözünürlükle mi karıştırıyorum ?


    Diğer cevaplarda sıkıntı yok da çözünürlüğü biraz açabilirsek sevinirim.



    < Bu mesaj bu kişi tarafından değiştirildi KeanAtay -- 1 Aralık 2013; 1:21:34 >
  • KeanAtay kullanıcısına yanıt
    tamam işte postscaler kullanılmıyorsa seni hiç etkilemez o.istediğin değeri yaz.
    tekrar edersek;kafanı hiç karıştırma.10 bit olan durum çözünürlüktür.
    duty için girdğin değer pr2'dir.o değer tmr2 register'ı ile karşılaştırılır ondan sonrada ccp registeri ile karşılaştırılır.tmr2 ile ccp registerlerı 10 bitliktir.şemada var zaten görürsün

    direk motoru sürer geçerim diyorsan duty 4 ile çarpılmış gibi bilgileri öğrenmene gerek yok tahminimce
  • faruk_ultras F kullanıcısına yanıt
    Vereceğim Duty periyodunun Pwm periyodundan büyük olmaması için bu hesapları yapıyorum. T periyotluk bir Pwm'e T+x periyotluk Duty verirsem sıkıntı olur haliyle.

    Yalnız şuraya takıldım
    quote:

    duty için girdiğin değer pr2'dir


    setup_timer2(T2_DIV_BY_16,254,0); derken PR2'i 254 verdik, set_pwm_duty(150); derken de duty'i 150 veriyoruz. Bunlar farklı şeyler değil mi ? Sonradan PR2 duty'de yazdığım değeri mi alıyor yoksa ?

    4'le çarpılmış kısmı set_pwm_duty(a) kısmına %50 lik bir sürüş için ne yazmam gerektiğini bilmeyişimden dolayı kafamı karıştırıyor. Direkt duty(255) yazarsam bu sayı 8bitlik mi yoksa 10bitlik mi ? Yani 255 yazarken % 100 çalışmasını istediğim halde bu yanlışlık yüzünden daha farklı bir % ile sürüş almış olurum. Bundan dolayı takıldım bu noktaya.

    Mesela böyle bir sorun burada da yaşanmış :http://www.ccsinfo.com/forum/viewtopic.php?p=102995




  • KeanAtay kullanıcısına yanıt
    255*4*4.000.000*16 bu senin periyodun.bunu 1e bölersen frekansı bulursun.hız için bu frekanstan gidebilirsin

    pr2 değerini değiştirirsen senin duty cycle'ın ve frekansın değişecektir.

    oynaman gereken pr2 değeri.ama pwm modülü hakkında bilgilerini artırmanı tavsiye ederim.denetleyicinin datasheet'ini aç orda aradıklarının cevapları var.
  • faruk_ultras F kullanıcısına yanıt
    Şimdi hepten karıştı.

    Birbirimizi anlamıyoruz galiba:
    Madem PR2 ile oynuyoruz neden kodlamalarda hep set_pwm_duty ile hız ayarlaması yapıyoruz. Bu mantığa göre zaten set_timer2 koduyla PR2'yi değiştirebiliriz set_pwm_duty koduna hiç ihtiyaç kalmaz.

    Ben PR2'e 254 atarak zaten belirli bir periyot hesabı yaptım. Duty'nin %100 çalışır durumunda iken bu aralıkların nasıl olduğunu yukarıdaki grafikte gösterdim. Tam şekilde çalışırken sinyalin şekli yukarıdaki gibiydi. Fakat madem %50 hızda sürmek istiyorum öyleyse bu sinyalin yarısın iş yapmasını istiyorum dedim.

    Bunun için tekrar PR2 değiştirirsem yeni hesaplar ve yeni grafikler çıkar.

    Yarıya indirmek için duty() içerisine bir değer giriyorum ve iş yapma süresini değiştiriyorum.

    Ccs C kitaplarında, yazılarında ve diğer forumlardaki gördüğüm örneklerde de hep set_pwm_duty() ile çalışma %'si değiştiriliyor. PR2'e dokunan yok.

    Ha iç blok şemasında bu değişiklik PR2 ile yapılıyor olabilir orasıyla henüz ilgilenmiyorum. Kafama takılan nokta duty içerisine atacağım sayıyı nasıl yazmam gerekiyor ? Ne şekilde yazarsam 8bitlik olur ne şekilde yazarsam 10bitlik olur.

    Bunun içinde yukarıda örnek verdim. Doğrudan içerisine 100,200,250 gibi bir sayı girersek PIC bunu 8bitlik algılıyor. Dolayısıyla 255 üzerinde bir sayı giremiyoruz. 10bitlik girmek için int16 kullanmak gerekiyor. Fakat burda şöyle bir sıkıntıyla karşılaştım.

    Yukarıdaki formüllerin neye göre ayarlandığını bilmediğimden, duty değerini int16 olarak da versem düz sayı girip 8bitlik de versem aynı işlem gerçekleşir mi ?

    Yine de teşekkür ediyorum verdiğiniz cevaplar birçok eksiği doldurdu fakat bazı yerler bulanık halen.




  • KeanAtay kullanıcısına yanıt
    prensip olarak low level assembly öğrenmeden yani donanıma hakim olmadan high level programlama yapılmasına karşıyım.aslında sorun yok kardeşim.set_pwm duty komutu işi kolaylaştırıyor.oraya 0'dan 255'e yazabiliyorsun.mesela oraya 127 yazarsan %50lilk duty cycle elde ediyorsun.başka bişeylede uğraşmıyorsun.set_pwm__duty foksiyonunun girdisi 8 bitlikse başka bi sayı yazamazsınki.tabiki 8 bit algılar.

    "Ccs C kitaplarında, yazılarında ve diğer forumlardaki gördüğüm örneklerde de hep set_pwm_duty() ile çalışma %'si değiştiriliyor. PR2'e dokunan yok. " burda yanlışın var.setup_Timer2 derken pr2 başta ayarlanıyor.ona göre işlem yapıyor program.
    donanım seviyesine inersen sorununu çözersin.
  • faruk_ultras F kullanıcısına yanıt
    İşte setup_timer2 derken PR2 ayarlanıyor onu kast etmek istemiştim ama ifade edememişim. Yani sonradan PR2 ile oynamıyoruz bunu demek istemiştim. Siz yukarıda PR2 ile ilgili değişiklikten bahsedince kafam karıştı her neyse.

    Datasheet'i inceledim az önce. Hem timer2'i hem de PWM modülünün şemasını inceledim. PR2'nin yazımında problem yok hatta 16bitlik bile tanımlayabiliyormuşuz, 0xff gibi.

    PIC ile henüz amatör olarak uğraşıyorum, PIC dersini seneye göreceğiz. C++ bilgim olduğu için Ccs C ile başladım direkt olaya. Assembly'e düzenli kaynak bulamadım. Fakat zamanla Ccs C'nin berbat bir olduğunu düşünmeye başladım. Çok kasıntı bir dil. Altı üstü duty içerisine sayı girip pwm yüzdesini değiştireceğim ancak 255 den yukarı yazarsam 10bit algılıyor, 255 den aşağı yazarsam kaydırma yapmıyor 8bit alıyor sayıyı. Aslında bakarsak set_pwm duty fonksiyonunun nasıl kullanıldığına dair bilgi arıyorum. Yukarıdaki diğer sorularımı cevapladınız problem kalmadı teşekkür ederim. Şu fonksiyonu araştırayım benhttps://www.ccsinfo.com/forum/viewtopic.php?p=139759 gerçekten sinir etti.




  • KeanAtay kullanıcısına yanıt
    iyi çalışmalar kardeşim
  • faruk_ultras F kullanıcısına yanıt
    Teşekkür ederim.
  • 1) Postscaler'in PWM üzerinde bir etkisi yok. Datasheet'lerden de kolaylıkla bulunabilir. Postscale timer2 kesmesi için kullanılan bir değer. PR2 değeri sınırına ulaşıp her sıfırlanışında 1 postscale değeri artıyor. Örneği PR2 değerini 50 girdik. Postscale değerini 3 girdik. Timer2 sıfırdan saymaya başlıyor. 50 olduğunda sıfırlanıyor ve postscale 1 değer artıyor. Bu işlem iki kez daha tekrarlanınca Postcale bizim belirlediğimiz 3 değerine ulaşıyor ve Timer2 kesmesi oluşuyor. Ben programda kesme kullanmayacağım için gireceğim değerin program üzerinde bir etkisi yok.
    2) PR2 değeri 0xff şeklinde 16bitlik olarak dahi belirtilebiliyor. Dolayısıyla formül 8bitlik veya 10bitlik diyemeyiz. Datasheet'te de bu formül belirtilmiş. PR2'e ne değer girersek girelim 10bit üzerinden hesap yaptığımız için (örneğin 0xff = 255 deyip PR2=255 yazıyoruz) 10bitlik bir hesap yapıyoruz. Söylemeyi unutmuşum, 16F877A kullanıyorum. Datasheet'te bu PIC'in çözünürlüğü 10bit verilmiş zaten.
    3) İşte en büyük problemim set_pwm_duty() fonksiyonunun nasıl çalıştığıyla ilgiliydi.

    Öyle bir fonksiyon oluşturmuş ki adamlar duty parametresine girilen değer 255'den büyükse derleyici bunu 10bit algılıyor, eğer 255 ve altında bir değer girilmişse derleyici bunu 8bit kabul ediyor.

    set_timer2(T2_DIV_BY_1,249,1); belirledik diyelim.

    255'den küçük bir değer girdiğimizde yani 8bitlik bir değer girdiğimizde

    Duty Cycle = Duty/(PR2+1) olacaktır.

    Örneğin set_pwm_duty(125) için Duty Cycle = 125/250 = 1/2 = %50 çıkar.


    Ancak değer hem 255'den küçükse hem de bu değer 10bitlik olarak kullanılmak isteniyorsa:

    1)10bitlik bir değer için int16 diye bir değişken ile bu değeri girebiliriz.
    int16 gorev = 125;

    Duty Cycle = Duty/(PR2+1)x4 demiştim. Buradaki Duty değeri girilen değerin 10bitlik olması gerekiyor. Bunu tanımlayabilmek için de int16 kullanıyoruz. Aslında çözünürlüğü 10bit'e çıkarmış olduk.

    Duty Cycle = 125/1000 = %12.5 Bu kez PWM oranı %12.5 olur.

    veya aşağıdaki iki şekilde de bu işlemi yapabiliriz.
    2)set_pwm_duty(125L);
    3)set_pwm_duty((long)125);

    kaynak:
    http://www.ccsinfo.com/forum/viewtopic.php?t=31674
    http://www.ccsinfo.com/forum/viewtopic.php?t=28761
    http://www.ccsinfo.com/forum/viewtopic.php?t=24403


    4) Üçüncü sorumun cevabına göre bu cevap ta kendiliğinden beliriyor. set_pwm_duty() fonksiyonu kaç bitlik kullanılırsa motorun yüzde hesabı da ona göre çıkıyor.




  • Merhaba benimde bir sorum peki PIC16f877a kullanarak böyle iki sinyal üretmek istiyorum. PWM sinyalin duty cycle'nı %50-%100 arası nasıl yaparım.
     PWM Hesabı ve Kodlanması (Çözüldü)



    < Bu mesaj bu kişi tarafından değiştirildi Usein -- 9 Kasım 2014; 22:13:13 >
  • Usein U kullanıcısına yanıt
    Merhaba,
    Vermiş olduğunuz sinyaller arasında faz farkı var. Biri diğerinin önünde gidiyor. PIC'de Timer2 ayarlaması bütün PWM'ler için geçerli. Yani tek bir Timer2 değeri girerek hem CCP1 hem de CCP2 pinlerini ayarlıyoruz. Böyle bir sinyal üretiminin nasıl yapılacağını bilmiyorum. Aynı entegrede iki PWM çıkışı var ama Timer2 ile ayarlanacak periyot her ikisi için de aynı olacağı için iki sinyal de aynı fazda olacaktır. Bu sorunun cevabını bilmiyorum.

    %50-%100 yapmak için:
    set_pwm_duty(125) yazarsanız %50
    set_pwm_duty(254) yazarsanız %100

    görev çevrimi alırsınız.
  • KeanAtay kullanıcısına yanıt
    %50-%100 derken ben 2. yani faz farkı olan sinyali demek istemiştim.Projedeki hocam pwm ayarını 50-100 arasında yapabiliecek mod olabilir belki araştır dedi.Pwmde böyle bir mod varmı ki internette bulamadım da hiç.
  • 
Sayfa: 1
- x
Bildirim
mesajınız kopyalandı (ctrl+v) yapıştırmak istediğiniz yere yapıştırabilirsiniz.