K

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

Başlatan Kean Atay, 30 Kasım 2013, 23:16:30

Kean Atay

Dikkat: Sorun çözüldü. Cevapları dördüncü sorunun altında belirttim.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

PWM hesaplamalarında anlamadığım birkaç nokta var:

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:



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:


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 ?

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

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.

Kean Atay

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.

Powered by EzPortal