Elektronik / Elektronik Kaynakları/

PICBasic Dersleri PIC Basic Pro ile PIC Programlama 11

Sponsorlu Bağlantılar

PWM kullanımı İngilizce isminin karşılığı olarak Puls Genişliği Ayarlaması yada Pals genişliği ayarı şeklinde Türkçe’mize tercüme edilebilir bu terim. Kare dalga şeklindeki bir sinyalin bir periyodunda hem HIGH hemde LOW seviyesinin olduğunu hepimiz biliyoruz.

picbasic_pwm

Bir peryodun süresi sabit kalmak şartı ile high yada low seviyelerinin değiştirilmesi işlemine PWM (Pals Width Modulation) denilmektedir. Olayı daha iyi anlayabilmeniz için konuyu biraz daha açmakta fayda görüyorum. Elimizde frekansı 100 Hz olan bir kare dalga sinyali olduğunu düşünelim. Bu 1 saniyede 100 defa HIGH ve 100 defa LOW sinyali demek olacaktır. 100 Hz lik sinyalin 1 peryot zamanı; T=1 / F ile bulunur.

Bu şekilde hesaplanırsa sonuç saniye cinsinden, T=1000/F şeklinde hesaplanır ise sonuç milisaniye cinsinden T=1000000/F şeklinde hesaplanır ise sonuç mikro saniye cinsinden hesaplanmış olur. Buna göre T süresi 100 Hz için 10 ms olarak hesaplanır.

Yukarıdaki şekilde High ve Low süreleri birbirine eşit olduğu için High süresi=5 ms. Ve Low süresi= 5 ms olduğu kolaylıkla görülebilir. 1 saniye=1000 ms olduğu için bu sinyalde 1 sn içinde 1000/10 =100 defa High ve 100 defa Low sinyali elde edilmektedir.

Bu 100 Hz.lik sinyal ile bir NPN transistor ü sürdüğümüzü varsayalım. Bu durumda transistor ün (B)eys ucu saniyede 100 defa High seviyesi görecek ve buna bağlı olarak saniyede 100 defa bu transistör iletime geçecektir. transistor ün iletimde kalma süresi 1 sn içinde 100 x 5=500 ms yani yarım saniye olacaktır.

Toplam 10 ms lik süreyi değiştirmeden High süresini 7 ms ve Low süresinide (10-7=3) 3 ms yapar isek pals genişliği ile oynamış oluruz. Bu durumda transistor ün iletimde kalma süresi; 100 x 7 = 700 ms ye ye çıkacak ve low da kalma süresi ise 300 ms olacaktır. Görüldüğü üzere pals genişliğini artırarak transistor ün iletimde kalma süresini artırabiliyoruz. Aynı şekilde bu genişliği azaltarak transistor ün iletimde kalma süresini azaltabiliriz.

Buraya kadar Pals genişliği ile oynamanın bize ne kazandırdığını anlatmaya çalıştım. İşte bu özellikten yararlanarak muhtelif cihazlarda gerilim kontrolü yapabiliriz. Özellikle DC motorların devirlerini bu yöntemle kolaylıkla kontrol edebiliriz.

Bu kadar teorik bilgiden sonra PWM sinyalinin nasıl oluşturulabileceği konusunu biraz araştıralım.

Pic Basic Pro kullanarak PWM sinyali elde etmenin değişik usulleri vardır. Bunların en başında bir çıkış portu belirleyip bu porta sırası ile HIGH sonra LOW sinyallerini vermek gelir. Tabiiki arada sinyalin peryoduna göre gerekli gecikmeleride koymak gerekir. İşin kolay anlaşılabilmesi için öncelikle yukarıda konuştuğumuz 100 Hz lik bir PWM sinyalini oluşturmaya çalışalım.

Çıkış Portumuz PortB.0 olsun.

BASLA:
HIGH PORTB.0
PAUSE 5
LOW PORTB.0
PAUSE 5
GOTO BASLA

Şeklinde yazılacak kısa bir kod bize PortB.0 dan çıkan 100 Hz lik bir PWM sinyali çıkartır. Görüldüğü gibi High ve Low süreleri bir birine eşit olarak 5 ms. Verildi. Duty denilen High süresi yüzde cinsinden 50 oranında bize iş süresi yani transistorü iletimde tutacak süreyi verecektir. Bu nedenle bu süreye %50 lik Duty Cycle (Duty saykıl yada Duty çevrimi) denir.

Buna pals genişliğimiz %50 de diyebilirsiniz. Şimdi Programımızı şu şekilde değiştirelim;

BASLA:
HIGH PORTB.0
PAUSE 8
LOW PORTB.0
PAUSE 2
GOTO BASLA

Görüldüğü üzere Duty değerini %50 den %80’e çıkardık. Low değeride %50 den %20 ye otomatikman düşmüş oldu. Toplam peryod 10 ms idi ve bu hiç değişmedi. Sinyalimizin şekli yaklaşık olarak şöyle oldu

picbasic_pwm_dalga

Bu anlattıklarımı gerçek program satırları şeklinde vermiyorum. İsteyen yazıp deneyebilir. Bu yazdığımız örnek program en basit PWM örneğidir. Bunu biraz daha değişken hale getirebilmek için sistemimize 2 adet buton ilave edelim ve bu butonlar yardımı ile PWM sinyalini değiştirelim.

2 adet buton dan birincisi Artır butonu olsun ve PortA.0 da bağlı olsun. İkinci butonumuz ise Azalt butonu olsun ve PortA.1 de bağlı olsun. Bu butonlar birer Pull-up direncine bağlı olsun ve butona basılınca port pinine LOW tatbik etsinler. PWM sinyalimiz yine PortB.0 dan çıksın. Buna uygun programımız aşağıdadır.

Program : Buton kontrollü PWM

‘****************************************************************
‘*  Name    : Buton-PWM.BAS                                      	*
‘*  Author  : [E T E]                                  	*
‘*  Notice  : Copyright (c) 2007 [E.T.E]                        	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 29.03.2007                                        	*
‘*  Version : 1.0                                               	*
‘*  Notes   :  *
‘*          :                                                   	*
‘****************************************************************
PortA=0 : TrisA=%00000011
PortB=0 : TrisB=%00000000

@ DEVICE PIC16F84
@ DEVICE PIC16F84, WDT_OFF
@ DEVICE PIC16F84, PWRT_OFF
@ DEVICE PIC16F84, PROTECT_OFF
@ DEVICE PIC16F84, XT_OSC 

SURE VAR BYTE
SURE=5
BASLA:
IF PORTA.0=0 THEN
SURE=SURE+1
IF SURE>10 THEN SURE=10 ‘10 MS Yİ GEÇEMİYORUZ
PAUSE 150
ENDIF

IF PORTA.1=0 THEN
SURE=SURE-1
IF SURE=255 THEN SURE=0
PAUSE 150
ENDIF 

HIGH PORTB.0
PAUSE SURE
LOW PORTB.0
PAUSE (10 - SURE)
GOTO BASLA
END

Benzeri bir sinyali üretebilecek birde Pic Basic Pro komutu bulunmaktadır. Komut; PWM Pin , Duty , Cycle şeklinde kullanılır. Pin sinyalin çıkartılacağı port pini dir. Duty 0-255 arasında bir sayı olup oransal olarak iş süresini verir. 255 değeri %100 lük duty değerine , 127 ise %50 lik duty değerine eş değerdir.

Her hangi bir % duty değerinin Duty karşılığını bulmak için Duty= %Duty x 255 / 100 formülünü kullanabilirsiniz.

Örnek olarak %60 lık bir duty sinyali yakalamak için Duty değeri ne olmalıdır dersek;
60 x 255 / 100 = 153 olarak bulunur.

Cycle ise sinyalin periyot sayısıdır. Örnek vermek gerekir ise; PWM PortB.0 , 127 , 200 komutu

PortB.0 dan %50 Duty değerinde bir sinyali 200 adet peryot olarak çıkartır. Çok kullanışlı bir komut olduğunu söyleyemem. Zira komutun sürekliliği yoktur. Her seferinden siz komutu yinelemeniz gerekir.

Bu şekilde yazılan bir programda araya ilave edilecek her komut veya her bir gecikme komutu PWM sinyalini bozacaktır. Bu nedenle çok avantajlı bir PWM üretme metodu olarak gösteremeyiz.

Peki diyelim ki geniş bir programımız var ve pwm sinyalini elde ettikten sonra arada başka işlerde yapmamız gerekiyor. Böyle bir program ihtiyacında bu sistemi kullanmamız imkansız Tabiiki. O halde ne yapmamız gerek.

Bu sorunun iki cevabı var. Birincisi TMR0 kesmesi kullanılarak gerekli PWM sinyalinin üretilmesidir. Sorunun ikinci yanıtı ise HPWM yani Donanım Özellikli PWM kullanmaktır.

Önce TMR0 kesmesi oluşturarak nasıl PWM sinyallerinin elde edileceğine bir bakalım.

Bu örneğimizde 2 KHz lik frekansa sahip bir PWM sinyali elde etmeye çalışalım. Sinyalin periyodu P=1000000/2000 eşitliğinden hesap edilecektir. (P=1/F yani 1000000/2000) Buna göre periyot 500 us olarak bulunur. Demek ki sinyalimizin Low ve High sinyalleri toplam süresi 500 us olacaktır. Sinyalin Duty oranı %50 olsun. Buna göre sinyalimizin Low süresi 250 us ve High süresi de aynı şekilde 250 us olarak bulunur. Demek ki 250 us de bir kesme oluşturabilirsek bu kesme bize 2 KHz lik bir PWM sinyalini oluşturmamızı sağlayacaktır.

250 us de bir kesme oluşturmanın yolu ise TMR0 sayacına bir ön değer verip 256 değerine ulaştığı zaman (255 den tekrar sıfır değerine geçerken) kesme oluşturmaktan geçer. Bu açıkladıklarımızı bir program olarak düşünür isek;

PROGRAM- TMR0 kesmesi ile PWM sinyali oluşturmak


‘****************************************************************
‘*  Name    : PWM-TMR0.BAS                                      	*
‘*  Author  : [E T E]                                	*
‘* Notice  : Copyright (c) 2007 [ETE]                          	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 13.04.2007                                        	*
‘*  Version : 1.0                                               	*
‘*  Notes   : *
‘*          :                                                   	*
‘****************************************************************
PORTA=0:portb=0
TRISB=%00000000   ‘
TRISA=%00000000   ‘
‘—————————————————————–
@ DEVICE pic16F628 ‘işlemci  16F628
@ DEVICE pic16F628, WDT_OFF  ‘Watch Dog timer kapalı
@ DEVICE pic16F628, PWRT_ON  ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF ‘Kod Koruma kapalı
@ DEVICE pic16F628, MCLR_off  ‘MCLR pini kullanılmıyor.
@ DEVICE pic16F628,  INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak
‘—————————————————————–
‘————————————————————————-
ON INTERRUPT GoTo KESME  ‘kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10001000 ‘Pull  up dirençleri İPTAL- Bölme oranı 1/1
INTCON=%10100000 ‘Kesmeler  aktif ve TMR0 kesmesi aktif
TMR0=28
CMCON=7 ‘16F628 de komparatör pinleri iptal hepsi giriş çıkış
‘—————————————————————————-

‘—————————————————————————–
CLEAR ‘tüm değişkenler  sıfırlandı
‘PAUSE 200

‘—————————————————————————–

BASLA:

GOTO BASLA

DISABLE
KESME:
PORTA.0=1-PORTA.0
@ nop
@ nop
TMR0=28
INTCON.2=0 ‘TMR0 Kesme bayrağı sıfırlanıyor
RESUME
ENABLE

END

Program içindeki ve özellikle kesme bölümünde verilen komutların ASM karşılıklarının her birinin 1us gecikme daha doğrusu komut işleme süresi vardır. Dolayısıyla bu komutların toplamı ciddi bir gecikmeye sebep olurlar. Bu durumda gerçek 2 KHz lik bir sinyal elde edebilmek için komut gecikmelerinide hesaba katmak gerekir.

Dolayısıyla oluşacak kesmeyi her 250 us de bir değilde daha kısa sürede yapıp komutlarla birlikte bu süreyi 250 us olarak yakalamak gerekecektir. Bu durumda TMR0 değerini azaltmamız gerekir. Normalde 256-250=6 değeri ile TMR0 ın 2 KHz lik sinyali oluşturması beklenirken komut gecikmelerinden dolayı bu süre 1,8 KHz dolayında çıkar.

Bunu önlemek için TMR0 ön yükleme değerini 6 dan 28’e yükseltmemiz gerekir. Böylece istediğimiz sinyali yakalamış oluruz. Programda yer alan @ NOP ifadeleri frekansın ince ayarı için kullanılmıştır.
Bize lazım olacak gerçek TMR0 değerini nasıl bulacağız?. Bu normalde hesap yolu ile bulunabilir. Ancak komutların ASM karşılıklarını tespit etmek ve bunların komut sürelerini bulmak gerçekten zor bir iştir. O yüzden daha kolay bir yol tarif edeceğim.

Devrenizi isis de kurun ve PWM çıkış pinine bir frekans sayıcı bağlayın. Devreyi çalıştırın. Elde ettiğiniz frekansı Frekans sayıcı gösterecektir. Beklediğinizden daha küçük ise TMR0 ön yükleme değerini artırın. Beklediğinizden daha büyük ise TMR0 ön yükleme değerini azaltın. Böylece uygun TMR0 değerini kısa sürede bulabilirsiniz.

Şimdi değişik bir örnek daha yapalım. Elimizde 3 adet led olduğunu ve bu ledlerin PortA.0, PortA.1 ve PortA.2 pinlerine bağlı olduklarını düşünelim.

Bu ledlerin her birine ayrı ayrı olarak vereceğimiz PWM sinyali ile yakıp söndürelim. Ancak her birini bağımsız olarak parlaklığını ayarlayalım. Bunun için pic frekansını 20 MHz olarak kullanacağız. Burada temel mantığımız birim duty cycle değerine karşılık bir kesme oluşturmak ve her bir led için verilen duty değeri kadar kesme sayıp sinyali çıkışlara uygulamak olacaktır.

İşte programımız;

‘****************************************************************
‘* Name    : KESMETMR0.BAS                                      *
‘*  Author  : [E T El]                                	*
‘*  Notice  : Copyright (c) 2005 [ETE]                          	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 23.04.2005                                        	*
‘*  Version : 1.0                                               	*
‘*  Notes   : *
‘*          :                                                   	*
‘****************************************************************
PORTA=0:portb=0
TRISB=%00000000   ‘
TRISA=%00000000   ‘
‘—————————————————————–
@ DEVICE pic16F628 ‘işlemci  16F628
@ DEVICE pic16F628, WDT_OFF  ‘Watch Dog timer kapalı
@ DEVICE pic16F628, PWRT_ON  ‘Power on timer açık
@ DEVICE pic16F628, PROTECT_OFF  ‘Kod koruma kapalı
@ DEVICE pic16F628, MCLR_off ‘MCLR pini kullanılmıyor.
@ DEVICE pic16F628,  INTRC_OSC_NOCLKOUT ‘Dahili osilatör kullanılacak
‘—————————————————————–
‘————————————————————————-
ON INTERRUPT GoTo KESME  ‘kesme oluşursa KESME adlı etikete git.
OPTION_REG=%10001000 ‘Pull  up dirençleri İPTAL- Bölme oranı 1/1
INTCON=%10100000 ‘Kesmeler  aktif ve TMR0 kesmesi aktif
‘TMR0=6
CMCON=7 ‘16F628 de komparatör pinleri iptal hepsi giriş çıkış
‘—————————————————————————-
DUTY_A VAR BYTE
DUTY_B VAR BYTE
DUTY_C VAR BYTE
LEDA VAR BYTE
LEDB VAR BYTE
LEDC VAR BYTE
‘—————————————————————————–
‘—————————————————————————–

BASLA:
DUTY_A=80
DUTY_B=30
DUTY_C=10
GOTO BASLA

DISABLE
KESME:
LEDA=LEDA+1
IF (PORTA.0=1 AND LEDA=DUTY_A) OR (PORTA.0=0 AND LEDA=100-DUTY_A) THEN
PORTA.0=1-PORTA.0
LEDA=0
ENDIF
LEDB=LEDB+1
IF (PORTA.1=1 AND LEDB=DUTY_B) OR (PORTA.1=0 AND LEDB=100-DUTY_B) THEN
PORTA.1=1-PORTA.1
LEDB=0
ENDIF

LEDC=LEDC+1
IF (PORTA.2=1 AND LEDC=DUTY_C) OR (PORTA.2=0 AND LEDC=100-DUTY_C) THEN
PORTA.2=1-PORTA.2
LEDC=0
ENDIF

TMR0=254
INTCON.2=0 ‘TMR0 Kesme bayrağı  sıfırlanıyor
RESUME
ENABLE
END

Programda her bir led e ait duty değerleri program içinde sabit olarak verilmiştir. Her bir led için birer buton kullanarak bu Duty seviyeleri ayarlanabilir. Bunu da sizler yaparsınız artık.

Şimdi önceki bölümde açıkladığımız sorunun ikinci cevabına gelelim. İkinci cevap Donanım özellikli PWM kullanmak idi. HPWM ana programdan bağımsız olarak geri planda çalışabilen bir özellik olup yazacağınız programdan kesinlikle etkilenmez. Siz başka işler yaparken sinyal sürekli olarak ilgili pin den çıkar.

Bu özelliğe sahip olan pic lerin kiminde tek bir PWM çıkışı (örnek PIC16F628) kiminde ise 2 adet PWM çıkışı (örnek PIC16F876 veya PIC16F877) kiminde ise 3 adet PWM çıkışı bulunabilmektedir.

Pwm çıkışı birden fazla olan piclerde tüm çıkışlar için uygulanacak frekans daima tektir ve PR2 registeri ile belirlenir. Çıkışların Duty Cycle değerleri bağımsız olarak değiştirilebilirler.

HPWM özelliğinin her picde bulunmadığını söylemiş idik. Bu özelliğe sahip tanıdık picler den bazılarını burada sayalım ve her birinde PWM sinyalinin hangi pin den alındığını belirtelim. 16F628 de yalnızca 1 kanal HPWM bulunmaktadır. Çıkış pini zorunlu olarak CCP1 özelliği olan PortB.3 pinidir. Bu pin değiştirilemez.

PIC16F876 da 2 adet HPWM kanalı bulunmaktadır. Çıkış pinleri PortC.2 ve PortC.1 pinleridir.

PIC16F877 de yine 2 adet HPWM kanalı bulunmaktadır. Çıkış Pinleri PortC.2 ve PortC.1 pinleridir.

Şimdi gelelim HPWM özelliğinin nasıl kullanılacağına. Önce yine biraz bilgi vermem gerekecek.
HPWM işlemi pic içinde bazı registerler yardımı ile yönlendirilmektedir. Sinyalin frekansı PR2 (Timer-2 periyot registeri) tarafından belirlenmektedir.

Aynı zamanda Timer-2 bölücüsü de frekansın belirlenmesinde yada hesaplanmasında etkin rol oynamaktadır. Timer-2 bölücüsü değerleri T2CON registeri tarafından tutulmaktadır.

PWM Periyot(Zaman) = [(Pr2+1)*4*Tosc*TMR2 Bölücü Değeri]

Formülü ile hesaplanmaktadır. PWM Frekansı ise

F(PWM) = 1 / PWM Peryot

Şeklinde hesaplanmaktadır.

HPWM sinyalinin açılması her kanala ait CCP1CON registerinin 2 ve 3. bitleri tarafından organize edilmekte olup bu iki bit değeri 1 ise sinyal (var) açık 0 ise sinyal (yok) kapalı olmaktadır.

HPWM normalde 10 bitlik bir duty değerine sahiptir. Bu yüksek çözünürlükte bir Duty değeridir.

Duty değeri ;

PWM(Duty) = (CCPR1L) * Tosc * (TMR2 Bölücü Değeri) formulü ile hesaplanmaktadır.

Duty (Ham Değeri) =(PR2+1) * 4 * %Duty formülü ile de direkt Duty registerine yazılacak olan değer hesaplanır. Verilen bu değerler 4 MHz frekanslar için geçerlidir.

Bu kadar bilgi verdikten sonra ilk programımızı yazalım; Yazacağımız program;

4 MHz kristal frekansında çalışan 1 adet 16F628 in CCP1 pininden 20 KHz frekansa sahip ve Duty değeri %50 olan bir HPWM sinyali çıkartılması konusunda olacaktır. Bir programda HPWM sinyalinin açılabilmesi için aşağıdaki işlemlerin yerine getirilmesi gerekmektedir.

1. PR2 registerine değer vererek PWM frekansını belirleyin.

2. 10 Bitlik Ham Duty değerini hesaplayın ve bu değerin ilk iki bitini CCP1CON.4 ile CCP1CON.5 registerine yazın. Kalan 8 biti ise CCPR1L registerine yazın ve böylece Duty cycle değerini belirleyin.

3. CCP1 pin ini çıkış olarak ayarlayın

4. T2Con registerinde bölücü değerini ayarlayın

5. CCP1CON registerinin 2 ve 3. bitlerini 1 yaparak PWM sinyalini ilgili pin den çıkartın

Şimdi bu dediklerimizi bir programa uygulayalım.

1. PR2 Değerini 20 KHz için hesaplamamız gerekiyor. Frekansı 20 KHz olan bir sinyalin peryodu;
T=1000000/20000 = 50 us olarak bulunur. Bunu formülümüzde yerine koyar isek;
PWM Periyot(Zaman) = [(Pr2+1)*4*Tosc*TMR2 Bölücü Değeri]
50 =(PR2+1) x 4 x ¼ x 1 = PR2+1 PR2=50-1 = 49 olarak bulunur. (4MhZ içindir)

2. 10 Bitlik Duty(Ham) değeri için duty oranı %50 olduğunu düşünerek şöyle hesap edebiliriz.
Duty (Ham Değeri) =(PR2+1) * 4 * %Duty
Duty-Ham=(49+1) x 4 x 50/100 = 100 olarak bulunur. Bulunan değerin ilgili registerlere yazılması işi için;
CCP1CON.4=Duty-Ham.0
CCP1CON.5=Duty-Ham.1
CCPR1L=Duty-Ham>>2
Şeklinde yapılır.

3. CCP1 pini çıkış olarak ayarlanmalıdır. 16F628 de bu portB.3 pini olduğuna göre; TRISB=%00000000 şeklinde bir komut ile yada TRISB.3=0 şeklinde bir komut ile bu işlemde ayarlanır.

4. 20 KHz sinyal için bölme oranını 1/1 olarak aldık dolayısıyla ;
T2CON=%00000100 komutu ile hem bölme oranını1/1 yaptık hemde TMR 2 zamanlayıcısını aktif hale getirdik (Bit-2 bu işi yapmaktadır burada 1 olarak verilmiştir).

5. Son olarak da PWM sinyalinin açılması için;
CCP1CON.2=1
CCP1CON.3=1
Komut dizisi ile sinyal açılır.

Program : HPWM – 16F628


‘****************************************************************
‘* Name    : HPWM.BAS                                      	*
‘*  Author  : [ETE-EROLEC-ERO]                                  	*
‘*  Notice  : Copyright (c) 2007 [E.T.E]                        	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 11.04.2007                                        	*
‘*  Version : 1.0                                               	*
‘*  Notes   : *
‘*          :                                                   	*
‘****************************************************************
@ DEVICE pic16F628
@ DEVICE pic16F628, WDT_off
@ DEVICE pic16F628, PWRT_On
@ DEVICE pic16F628, PROTECT_OFF
@ DEVICE pic16F628, MCLR_off
@ DEVICE pic16F628, INTRC_OSC_NOCLKOUT
PORTA=0:TRISA=0
PORTB=0:TRISB=0
CMCON=7
T2CON =%00000100 ‘Bölücü 1/1 olarak verildi ve TMR2 aktif hale  getirildi.
PR2=49 ‘PWM-Peryot= (49+1) x 4 x ¼ x 1 =50 us  ve F=1000/50 = 20 KHz PWM  frekansı dır. 

CCP1CON.2=1 ‘bu  iki komut ile PWM sinyali açılmış olacaktır
CCP1CON.3=1

End

Buraya kadar vermiş olduğumuz program satırları ile CCP1 pini olan PortB.3 den 20 KHz frekansa sahip ve Duty cycle değeri %50 olan bir sinyal çıkartılmış olacaktır.

Bu sinyalin kapatılması için ;
CCP1CON.2=0
CCP1CON.3=0

Komutlarını vermemiz yeterli olacaktır.

Duty % değerini değiştirmek ister isek;
PWM (Ham Değeri) =(PR2+1) * 4 * %Duty formülünü kullanacağız.
Diyelimki Duty % sini %80 olarak ayarlayacağız.

Duty(Ham)=(49+1) x 4 x (80/100) = 160 yani Duty-Ham=160 olarak bulunur.
O halde Duty (ham) değerinin verilmesi için;

CCP1CON.4=DUTY-Ham.0
CCP1CON.5=DUTY-Ham.1
CCPR1L=DUTY-Ham>>2

Bu üç satır komut ile yeni duty değeri verilerek Duty oranı %80 olarak uygulanmış olacaktır.

Bu kadar anlatımdan sonra muhtelif programlar geliştirilebilir.

Örneğin ADC girişi olan bir pic kullanarak AN0 dan 1K lık bir pot kullanarak HPWM sinyalinin frekansını değiştirebilmemiz mümkün olabilir. Hatta ikinci bir pot kullanarak sinyalin Duty değerinide değiştirmek mümkün olabilir.

Bu şekilde bir program yazmadan önce frekansın aralığının tespit edilmesi gerekmektedir.
Örneğin Minimum 1 KHz ve maksimum 10 KHz olacak ve Duty değeri hep %50 de kalacak bir sinyali üretmeye çalışalım. Amacımız Pot değeri minimumda iken çıkan frekansımızın 1 KHz seviyesinde , pot değerimiz maksimumda olduğu zamanda çıkan frekansımızın 10 KHz seviyesinde olmasını sağlamak olacaktır.

Bu iş için Pic16F876 kullanacağız. Minimum frekans için PR2 değerimiz ;

T=1000/1 = 1000 us olarak bulunur. Bunu formülümüzde yerine koyar isek;
PWM Periyot(Zaman) = [(Pr2+1) x 4 x Tosc x TMR2 Bölücü Değeri]
1000 =(PR2+1) x 4 x ¼ x 1 = PR2+1 PR2=1000-1 = 999 olarak bulunur.

Bu durumda PR2 registeri 8 bitlik bir register olduğu için elde ettiğimiz 999 değerini kullanmamız mümkün değildir. Bu durumda bölücü kullanmamız gerekecektir. Elimizdeki bölücü alternatifleri 4 ve 16 dır. Bölücü olarak 4 kullandığımızı düşünerek hesabımızı bu değere göre yeniden yapalım;

1000=(PR2+1) x 4 x ¼ x 4 eşitliğinden;
PR2+1= 1000/4 ve PR2+1=250 ve sonuçta PR2=249 olarak bulunur.

Görüldüğü gibi bölücüyü rasgele seçmiyoruz. Bize 8 bitlik bir PR2 değeri verecek şekilde uygun bir bölücü seçiyoruz sonuçta.

Şimdide maksimum frekans değerimiz olan 10KHz için PR2 değerini hesaplayalım.
T=1000000/10000= 100 us olarak bulunur.
100 = (PR2+1) x 4 x ¼ x 4 (aynı bölücü oranını kullanacağız)
PR2=25-1=24 olarak bulunur.

ADC kanalı ile okunan pot değerinin nasıl frekansı belirleyen PR2 değerine dönüştürüleceğini görelim. Yani pot dan okuyacağımız değeri PR2 ye verilecek değere çevirmemiz gerekecektir.

Pot değeri 0 iken okunacak ADC ham değerimiz 0 olacaktır. Bu konumda frekansımız 1 KHz olsun istiyoruz.

O halde bizim minimum PR2 değerimiz 249 olacaktır.

Pot değeri 1 K iken okunacak Ham ADC değeri 1023 olacak ve buna karşılık olarak PR2 değerimizde 24 olacaktır.

Şimdi bu değerleri bir eşitlik haline getirelim.

Pot değeri 1K-0 K arasında ADC değeri 1023 – 0 arasında yani 1024 adet değişecektir. Buna karşılık olarak PR2 değeri ise 249-24 = 225 birim değişecektir. Okunan her bir ADC değerine karşılık elde edilecek PR2 değeri 225/1024 eşitliği ile bulunur. Bu işlemi daha az ondalıklı yapabilmek için eşitliğin 256 ile çarpılmış halini kullanacağız. O halde formülümüz;

(225/1024) x 256 = 56,25 olacaktır. Yine ondalıklı işlemi azaltmak için bu değeri 5625 kabul edecek ve çıkan sonucu 100 e böleceğiz. O halde formülümüzün son hali

PR2 = ((ADC+1)*/5625) /100+249 şeklinde olacaktır. Burada çıkan sonuca 249 ekledik. Bunun sebebi frekansımızın 1 KHz den az olamayacağı içindir.

Ancak bu formülü kullanmamız pratik olarak mümkün değildir. Nedeni ise pot ile yaptığımız ayarlarda pot değerini min. Değere yani sıfıra getirdiğimiz zaman okuyacağımız ADC değeri 0 olacaktır. Formülden hesaplayacağımız PR2 değeri ise 249 olacaktır. Bu doğru. Ancak pot değerini maksimumuma yani 1K ya çıkardığımız zaman okuyacağımız ADC değeri 1023 olacaktır.

Bu durumda hesaplamamız gereken PR2 değeri de 24 olmalıdır. Hesaplayalım bakalım ne bulacağız.

PR2= ((1023+1)*/5625)/100+249= 474 olarak bulunur. Bu ise yanlış bir değerdir. Bunun sebebi , pot değerinin azalması ile PR2 değerinin artması (ters orantı) pot değerinin artması ile PR2 değerinin azalmasıdır. Bu gibi durumlarda işlemin tersi yapılır.

Şöyle, Okunan ADC değeri 1024 den çıkartılarak formül kullanılır.

PR2=((1024-ADC)*/5625)/100+24
Burada işlemin tersini aldığımız için 249 yerine 24 ekleyeceğiz. Şimdi hesapları kontrol edelim.

Pot min değerde iken HAM=0 olacak ve sonuç;
PR2=((1024×5625)/256)/100+24 = 249 bulunacaktır.
Pot maksimum değerde iken HAM=1023 bulunacak ve sonuç
PR2=((1024-1023)x5625)/256)/100+24 = 24 bulunacaktır.
Böylece hesaplama mantığımızın doğru olduğunu anlayacağız.

Şimdi anlattıklarımızı program olarak yazalım.

İşte programımız;

‘****************************************************************
‘*  Name    : HPWM-2.BAS                                      	*
‘*  Author  : [E.T.E]                                           	*
‘*  Notice  : Copyright (c) 2007 Ete]                           	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 18.03.2007                                        	*
‘*  Version : 1.0                                               	*
‘* Notes   :  *
‘*          :                                                   	*
‘****************************************************************
‘OPTION_REG =%00111111
PORTA=0:TRISA=%00000001
PORTB=0:TRISB=%00000000
PORTC=0:TRISC=%00000000
PORTD=0:TRISD=%00000000
ADCON1= %10001110 ‘
T2CON = %00000101
PR2=249
‘—————————————————————–
@ DEVICE PIC16F877
@ DEVICE PIC16F877, WDT_OFF
@ DEVICE PIC16F877, PWRT_OFF
@ DEVICE PIC16F877, PROTECT_OFF
@ DEVICE PIC16F877, XT_OSC
‘—————————————————————–
DEFINE OSC 4


‘**************** ADC chanel setting  ************************
DEFINE ADC_BITS 10 ‘ ADCIN    çözünürlük  (Bits)
DEFINE ADC_CLOCK 1 ‘ ADC  clock kaynağı  (Fosc/8)
DEFINE ADC_SAMPLEUS 3 ‘ ADC  örnekleme zamanı (uSec)

 
‘****************HPWM PRESETİNG*********************
DEFINE CCP1_REG   PORTC  ‘Hpwm 1 pin port
DEFINE CCP1_BIT     2 ‘Hpwm 1  pin bit
DEFINE CCP2_REG   PORTC  ‘Hpwm 2 pin port

DEFINE CCP2_BIT     1 ‘Hpwm 2 pin bit


‘******************* DEĞİŞKENLER  ********************
HAM var word
X   VAR WORD
DUTY VAR BYTE
‘—————————————————————————

CCP1CON.2=1
CCP1CON.3=1

BASLA:
DUTY=50
GOSUB POTOKU

 GOTO BASLA

POTOKU:
ADCIN 0,HAM
PR2=((1024-HAM)*/5625)/100+24

 X=(PR2+1)* DUTY /25
CCP1CON.4=X.0
CCP1CON.5=X.1
CCPR1L=x>>2
RETURN

pwm_devre

Son olarak 16F876 pic de iki HPWM kanalının açılmasını göreceğiz. Aslında tamamen 1. Kanal (CCP1) için yapılan işlemleri bu seferde ikinci kanal için yapmak gerekmektedir.

Bir önceki program örneğimizi kullanarak 1 adet pot ile iki kanala ait HPWM frekansını kontrol edeceğiz.
Burada önemli olan pwm sinyalinin nasıl açılıp nasıl kapandığını görmektir. Zira frekans her iki kanal içinde değişmez biçimde aynı olacaktır. Her iki kanalın frekansları önceden belirttiğimizi gibi aynı olmak zorundadır. Yalnızca Duty değerleri farklı olabilir.

‘****************************************************************
‘*  Name    : HPWM-3.BAS                                      	*
‘* Author  : [E.T.E]                                           	*
‘* Notice  : Copyright (c) 2007 Ete]                           	*
‘*          : All Rights Reserved                               	*
‘*  Date    : 18.03.2007                                        	*
‘*  Version : 1.0                                               	*
‘*  Notes :                                                   	*
‘*          :                                                   	*
‘****************************************************************
‘OPTION_REG =%00111111
PORTA=0:TRISA=%00000001
PORTB=0:TRISB=%00000000
PORTC=0:TRISC=%00000000
PORTD=0:TRISD=%00000000
ADCON1= %10001110 ‘
T2CON = %00000101
PR2=249
‘—————————————————————–
@ DEVICE PIC16F877
@ DEVICE PIC16F877, WDT_OFF
@ DEVICE PIC16F877, PWRT_OFF
@ DEVICE PIC16F877, PROTECT_OFF
@ DEVICE PIC16F877, XT_OSC
‘—————————————————————–
DEFINE OSC 4


‘**************** ADC chanel setting  ************************
DEFINE ADC_BITS 10 ‘ ADCIN    çözünürlük  (Bits)
DEFINE ADC_CLOCK 1 ‘ ADC  clock kaynağı  (Fosc/8)
DEFINE ADC_SAMPLEUS 3 ‘ ADC  örnekleme zamanı (uSec)


‘****************HPWM PRESETİNG*********************
DEFINE CCP1_REG   PORTC ‘Hpwm 1 pin port
DEFINE CCP1_BIT     2 ‘Hpwm 1  pin bit
DEFINE CCP2_REG   PORTC ‘Hpwm 2 pin port
DEFINE CCP2_BIT     1 ‘Hpwm 2  pin bit


‘******************* DEĞİŞKENLER  ********************
HAM var word
X   VAR WORD
DUTY VAR BYTE
‘—————————————————————————

CCP1CON.2=1 ‘birinci kanalı açtık
CCP1CON.3=1
CCP2CON.2=1 ‘ikinci kanalı açtık
CCP2CON.3=1

BASLA:
DUTY=50
GOSUB POTOKU

 GOTO BASLA

POTOKU:
ADCIN 0,HAM
PR2=((1024-HAM)*/5625)/100+24

 X=(PR2+1)* DUTY /25
CCP1CON.4=X.0
CCP1CON.5=X.1

 CCP2CON.4=X.0
CCP2CON.5=X.1

 CCPR1L=X>>2

 CCPR2L=X>>2
RETURN

Ders-11 ‘i burada bitiriyoruz. Ders içinde geçen programların dosyaları ilişikte verilmiştir. Her bir programın simülasyon dosyaları ve versiyon uyuşmazlığına karşılık sec uzantılı dosyalarıda bulunmaktadır.

Hazırlayan: Erol Tahir Erdal (ETE) PICBasic Dersleri PIC Basic Pro ile PIC Programlama 11 Kod ve isis simülasyon dosyaları: PICBasic Dersleri PIC Basic Pro ile PIC Programlama 11

Dosya indirme LINK listesi (HTML formatında) link-10193.zip şifre-pass: 320volt.com

PICBasic Dersleri PIC Basic Pro ile PIC Programlama-12 Ders-12 Devam

  • fatih

    güzel bir makale olmuş elinize sağlık

  • sabri

    çok güzel çalışmalar.her defasında kaynak olarak başvurduğum site. yapanların emeğine sağlık