HPWM komutunun kullanım şekli

Başlatan DigMan, 12 Nisan 2019, 16:36:33

DigMan

Ete hocam, arkadaşlar merhaba,

Bir hpwm sorunum var. çok araştırdım, bu komutun nasıl kullanıldığına dair net bir bilgi yok ortalıkta. kendi denemelerimle, internetteki örnekler farklılık gösterebiliyor. Mesela timer ayarı yapmadan, sadece ccp1_pin = portc.2 yaparak hpwm 1, dutyA, 2000 komutuyla 0-5V arası değerler alabiliyorum lakin hpwm komutunu döngü içinde kullanmazsam olmuyor.

Önce ne yapmak istediğimi anlatayım:

program başında pwm ile ilgili tanımları yaptıktan sonra, ana döngüye gelmeden önce hpwm 1, dutyA, 2000 komutunu kullanarak pwm i maximum değerde(dutyA = 255) çalıştırmak istiyorum.

daha sonra bu dutyA değerini ana döngüde ve programın çeşitli yerlerinde değiştirerek (dutyA = 0 veya dutyA = 50 veya dutyA = 150) gibi yaparak arka planda çalışan pwm çıkışımı değiştirmek istiyorum.

Bu mümkün müdür? değilse başka bir yolu var mıdır?
Bir de bu hpwm komutunun en doğru kullanım şekli nedir? hpwm kullanmak için yapacağımız en sade ayarlar nelerdir?

Not: kullandığım program ve MCU: Proton Plus ve 18F2620

Yardımlarınızı rica ediyorum..


ete

Konuya HPWM komutu nedir onu açıklayarak başlayayım. Türkçe karşılığı Donanımsal Puls Width Modulation  sinyali olarak açıklanabilir.  Elbette bu komut donanımsal PWM özelliği olan pic işlemcilerde kullanılabilecek bir komuttur. Bu nedenle nerede kullanılacak ise önce data sheete bakılmalı bu özellik var ise kullanılmalıdır.
Komutun özelliğini açıkladıktan sonra parametrelerine bakalım.
HPWM KanalNo, Duty_Değeri (0-255) , Frekans şeklinde parametreleri mevcut.
Kanal numarası yime işlemciye ait özel bir durumdur. İşlemcide kaç kanal HPWM var ise kanal numarasıda o sayıda değişebilir. Örnek vermek gerekirse 16F628 de yalnızca 1 kanal vardır ve kanal numarası yalnızca 1 olabilir. 16F877 de iki kanal vardır ve kanal numarası 1 veya 2 olabilir.
Diğer parametre ise Duty değeridir. Bu değer 0-255 arasında değer alır ve 0=%0 ve 255=%100 duty değerinin karşılığı olur. Doğal olarak da 127=%50 duty karşılığı olan rakamdır. Ne yazıkki bu komut 8 bit çözünürlük kullanmaktadır. Halbuki işlemcilerin çoğu belkide tamamı (8 bitlik PWM si olan duymadım henüz) 10 bit çözünürlük kullanmakta ancak bu komut ile 10 bitlik çözünürlük kulanılamamaktadır. Bu nedenle bu komutu pek sevmem ve kullanmam. Register ayarları ile PWM sinyalini açarım ve daima 10 bit çözünürlük kullanırım.

Son parametremiz frekans tır. Frekans değeri min değer olarak Osilatör frekansına bağlı olarak sınırlı dır. 4 Mhze imn frekans 147 hz maksimum 32767 hz olabilmektedir.
Bu açıklamalara bakarak 2Khz lik bir sinyali %50 duty değeri ile oluşturabilmek için verilmesi gereken komut;
HPWM 1,127,2000 şeklinde olacaktır.
Komutu döngü içerisinde kullanmaz isem olmuyor cümlesinden bir anlam çıkartamadım. Olmayan nedir? Bu komut geri planda çalışan ana programdan bağımsız donanımsal PWM sinyalini çıkartır ve bir döngü içerisinde çalışması gerekmez.
Döngüsel çalışma zorunluluğu olan komut yazılımsa PWM komutu olup PWM pin,Duty,Cycle şeklind eparametreleri alır. Bu sinyal yazılımla oluşturulduğu için frekans ayarlaması yapılamaz ve sürekliliği ancak döngü kurularak sağlanabilir. Bu ikisini karıştırıyor olmayasın?

Gelelim 10 bitlik Çözünürlükte donanımsal PWM sinyali kullanmaya.
Öncelikle size hangi frekans gerekiyor ona karar vermeniz lazım. Diyelimki 10Khz lik frekans çıkartacağım.
Osilatör frekansım 4 Mhz olsun. Data sheet de pek çok hesaplama verilmiş bu sinyalin nasıl olacağına dair. Bununla ilgili bir ders notu da yayınladım zaten Burada detaya girmek istemiyorum. Sadece kolay yolunu anlatacağım. PicMultiCalc isimli kısa programı arayın internette ve sürekli elininizin altında tutun. Çalıştırın program çok seçenekli menüsünde birde PWM Calc seçeneği mevcut. Tıklayın ekrana OSC frekansı seçimi,  Duty oranı seçimi ve Sinyal Frekansı seçimi gibi kutuları olan bir ekran gelecektir. İlgili yerleri doldurun. Unutmayın genelde bu sinyal Timer2 kullanılarak oluşturulur. Bunun bir kontrol registeri vardır T2CON şeklinde bu registerde yer alan bölme oranı gerekli frekansın oluşturulmasında rol oynar. Ayrıca b komut PR2 isimli registeride kullanır. Sonuçta girdiğiniz değerlere karşılk bu küçük program size alternatifli bir liste verir.
Alternatifler genellikle çözünürlük üzerinden oluşturulur. Örneğimizde 10Khz lik sinyal için alınan alternatifler şunlar olur;
-10 Khz sinyal  Bölme oranı=1/1 , Çözünürlük 9 bit ,  Max Duty Değeri 400 (%100 için) ve Duty adımları %0,25
-10 Khz sinyal  Bölme oranı=1/4 , Çözünürlük 8 bit ,  Max Duty Değeri 100 (%100 için) ve Duty adımları %1
son alternatifi dikkate almıyorum çünki bana çok düşük bir çözünürlük veriyor.
Birinci alternatifi tercih edersem en altta bana 1/1 bölme oranı ile PR2=99 vermem gerektiği ,
İkinci alternatifi tercih edersem bana 1/4 bölme oranı ile PR2=24 kullanmam gerektiği gösterilmiş durumda.
Tabiiki tercihim en yüksek çözünürlük olacağı için 1 ci alternatifi uygulayacağım.
Programın baş taraflarına ;
PR2=99
T2CON=%00000100 'ilk 2 bit bölme oranını belirliyor %000000xx yani xx bitleri 00=1/1 , 01=1/4 %10=1/16 bölme oranı
şeklinde komutları verdikten sonra
CCP1CON=%00001100  komutunu sinyali aktif hale getirmek için veriyoruz.
Şu anda sinyalimiz aktif ancak her hangi bir duty değeri vermediğimiz için sinyal çıkmayacaktır.
%50 oranında duty verebilmemiz için (Duty=200) vermemiz gerekcektir. Ama size daha kolay bir yol önereyim. Duty değerini %duty olarak kullanın. Bu durumda Duty=50 değerini verelim.
x=((PR2+1)*DUTY)/25   '......bu formül % duty değerinden olması gereken duty rakamını hesaplar. Bütün OSC frekanslar için geçerlidir. (Örneğimizde X=(100*50/25)=200 olarak hesaplanırki bu max değeri 400 olan sinyalin %50 si için 200 olması demektir.
CCP1CON.4=X.0
CCP1CON.5=X.1
CCPR1L=x>>2     
         
bu son satırıda verdinizmi artık %50 duty değerine sahip 10Khz lik sinyaliniz CCP1 pininden çıkmış olur.
Yapmanız gereken formül ve altındaki satırları bir alt programa yerleştirip duty değeri değiştireceğiniz zaman (Duty=20 gibi) bu alt programa yönlendirmek olacaktır.
Bir kere alıştınızmı bu komut dizisini kullanmanın kolay olduğunu söyleyebilirim.

Ete

DigMan

Ete hocam, emek ve sabır dolu detaylı anlatımınız için çok teşekkür ederim, hemen deneyeceğim.

. Kağan

#3
HPWM kullanımını denemek istedim. Fakat bir sorunla karşılaştım. Sinyal Frekansı mHZ lere çıkınca kare dalga testere dişi dalgaya dönüşüyor gibi görünüyor(ısıs'te).
Gerçekte de böyle oluyormu? Birde altta eklediğim kodda simulasyonda  ilk başlarda sinyal oluşuyor ama daha sonra sinyal bozuluyor gibi görünüyor.

#header
  errorlevel -306  ; Crossing page boundry
#ENDHEADER

;****************************************************************


;----[16F887 Hardware Configuration]--------------------------------------------
#IF __PROCESSOR__ = "16F887"
  #DEFINE MCU_FOUND 1
#CONFIG
cfg1 = _HS_OSC                ; HS oscillator: High-speed crystal/resonator on RA6/OSC2/CLKOUT and RA7/OSC1/CLKIN
cfg1&= _WDT_OFF              ; WDT disabled and can be enabled by SWDTEN bit of the WDTCON register
cfg1&= _PWRTE_OFF            ; PWRT disabled
cfg1&= _MCLRE_OFF            ; RE3/MCLR pin function is digital input, MCLR internally tied to VDD
cfg1&= _CP_ON                ; Program memory code protection is disabled
cfg1&= _CPD_ON                ; Data memory code protection is enabled
cfg1&= _BOR_OFF              ; BOR disabled
cfg1&= _IESO_OFF              ; Internal/External Switchover mode is disabled
cfg1&= _FCMEN_OFF            ; Fail-Safe Clock Monitor is disabled
cfg1&= _LVP_OFF              ; RB3 pin has digital I/O, HV on MCLR must be used for programming
cfg1&= _DEBUG_OFF            ; In-Circuit Debugger disabled, RB6/ICSPCLK and RB7/ICSPDAT are general purpose I/O pins
  __CONFIG _CONFIG1, cfg1

cfg2 = _BOR40V                ; Brown-out Reset set to 4.0V
cfg2&= _WRT_OFF              ; Write protection off
  __CONFIG _CONFIG2, cfg2

#ENDCONFIG

#ENDIF

;----[Verify Configs have been specified for Selected Processor]----------------
;      Note: Only include this routine once, after all #CONFIG blocks
#IFNDEF MCU_FOUND
  #ERROR "No CONFIGs found for [" + __PROCESSOR__ +"]"
#ENDIF


'*************************************
'ISLEMCI TANIMLAMALARI

DEFINE OSC 20          'KRİSTAL FREKANSI
DEFINE ADC_BITS 10
DEFINE ADC_CLOCK 2    '20mhz DIS KRISTAL KULLANILIYOR
DEFINE ADC_SAMPLEUS 15

'*************************************

ADCON1 = %10000000 'SAGA YASLANIK sonuç almak için
ADCON0 = %10000000 'FOSC/32
CM1CON0 = 7
CM2CON0 = 7
TRISA = %00000000  'PORTLAR CIKIS KONUMUNDA VE KAPALI
PORTA = 0          'HEPSI I/O PORT
TRISB = %00000000  'LCD UCLARI VE PROGRAMLAMA UCLARI
PORTB = 0          'HEPSI I/O PORT
TRISC = %00000000  'PORTLAR CIKIS KONUMUNDA VE KAPALI
PORTC = 0          'HEPSI I/O PORT
TRISD = %00000000  'PORTLAR CIKIS KONUMUNDA VE KAPALI
PORTD = 0          'HEPSI I/O PORT
TRISE = %00000000  'PORTLAR CIKIS KONUMUNDA VE KAPALI
PORTE = 0          'HEPSI I/O PORT
ANSELH = 0        'AN8-9-10-11-12-13  DIGITAL GIRIS CIKIS OLACAK CUNKU ORADA LCD BAGLI
ANSEL = 0          'HEPSİ DIGITAL GIRIS CIKIS OLACAK.ANALOG KANAL KULLANIMI YOK.

PSTRCON = %00010011 'PULSE STEERING MODE ACIK VE KANAL STRA ile STRB AKTIF

T2CON=%00000110    'ilk 2 bit bölme oranını belirliyor %000000xx yani xx bitleri 00=1/1 , 01=1/4 %10=1/16 bölme oranı
                  'şeklinde komutları verdikten sonra
CCP1CON=%00001100  'TUM KANALLARDAN AYNI Sinyali aktif hale getirmek için veriyoruz.

Pause 100 ' 100 ms AÇILIŞ GECİKMESİ

DEFINE LCD_DREG PORTB      'LCD data bacakları hangi porta bağlı? LCD nin D0 D1 D2 D3
DEFINE LCD_DBIT 0          'LCD data bacakları hangi bitten başlıyor? ***
DEFINE LCD_RSREG PORTB    'LCD RS Bacağı Hangi Porta bağlı ?       
DEFINE LCD_RSBIT 4        'LCD RS bacağı Hangi Bite bağlı ?        4 ***
DEFINE LCD_EREG PORTB      'LCD Enable Bacağı Hangi Porta bağlı?
DEFINE LCD_EBIT 5          'LCD Enable Bacağı Hangi bite bağlı ?    5
DEFINE LCD_BITS 4          'LCD 4 bit mi yoksa 8 bit olarak bağlı?
DEFINE LCD_LINES 4
'*************************************
'PORT TANIMLAMALARI (DIGITAL PORTLAR)

BUZZER          VAR PORTD.2  'CIKIS -
LOW BUZZER

LED2            VAR PORTA.4  'CIKIS -
LOW LED2

BUTON1          VAR PORTD.6  'GIRIS
BUTON2          VAR PORTD.5  'GIRIS


'*************DEGISKEN TANIMLAMALARI***********
X      VAR BYTE 
DUTY    VAR WORD     
SET    VAR BYTE
SET1    VAR BYTE
MOD_SEC VAR BIT
DRM    VAR BIT
CIKIS  VAR BYTE
ONDA_CIKIS VAR WORD
KURUL  VAR BYTE
I      VAR WORD

'*************'*************'*************
MOD_SEC = 1
DRM = 1


LCDOUT $FE,1   
LCDOUT $FE, $80, "  a  "
LCDOUT $FE, $C0, "    b  "
LCDOUT $FE, $94, "        c"
PAUSE 100

'------------B A Ş L A N G I Ç ---------------   
READ 0,SET
READ 1,SET1
pause 100
   

'***********Program Başlangıcı***********

SET=30 : WRITE 0,SET
SET1=5: WRITE 1,SET1
PAUSE 100


'-----------2Mhz %50 kare dalga için-----------------
DUTY=50  '%DEĞER
PR2=155

'*************BASLA**********************
BASLA:



x=((PR2+1)*DUTY)/25  'bu formül % duty değerinden olması gereken duty rakamını hesaplar. Bütün OSC frekanslar için geçerlidir. (Örneğimizde X=(100*50/25)=200 olarak hesaplanırki bu max değeri 400 olan sinyalin %50 si için 200 olması demektir.
CCP1CON.4=X.0    'CCP1CON <5: 4> DEGERI "X" DEN ALIYOR
CCP1CON.5=X.1    'CCP1CON <5: 4> DEGERI "X" DEN ALIYOR
CCPR1L=x>>2      'CCPR1L  <7: 0> DEGERI "X" DEN ALIYOR


IF MOD_SEC=0 THEN  : TOGGLE DRM : PAUSE 100 : GOTO BTN_KNTRL


Goto BASLA
'*************BITTI**********************


'*************ALT PROGRAMLAR**********************
BTN_KNTRL:
  LCDOUT $FE,1
  LCDOut $FE,$80, "DUTY    :", DEC3 CIKIS,  ",", DEC2 ONDA_CIKIS," kHZ"
  LCDOUT $FE,$C0, "DUTY SET:", DEC3 SET,    ",", DEC2 SET1, " kHZ"
  LCDOUT $FE,$94, "--------------------"
  LCDOUT $FE,$D4, "Azal  KAYDET    Art"
  pause 100
  i=0
  BUTTON BUTON1, 0,100,100,i,1,ARTI
  i=0                                                     
  BUTTON BUTON2, 0,254,255,i,1,EKSI
  i=0
  IF MOD_SEC=0 THEN
  PAUSE 300
  BUTTON MOD_SEC, 0,254,0,i,1,CIK
  ENDIF
  GOTO BTN_KNTRL
 
CIK:

IF MOD_SEC=0 THEN
WRITE 0,SET
WRITE 1,SET1
PAUSE 100
TOGGLE DRM
ENDIF
IF DRM=0 THEN BASLA


ARTI:
 
SET1=SET1+1
IF SET1=10 THEN SET1=0:SET=SET+1
IF SET=100 THEN SET=0
GOTO BTN_KNTRL

EKSI:
SET1=SET1-1
IF SET1=255 THEN SET1=9:SET=SET-1
IF SET=255 THEN SET=100:SET1=0
GOTO BTN_KNTRL

END

ete

#4
Frekansın program içindeki açıklamana bakılırsa 2 Mhz olması gerekiyor ama verdiğin ayarlar 2Mhz için değil maalesef.

Öncelikle verdiğin değerlere bakalım. Kim belirliyor frekansı ?, PR2 değeri, Osilatör frekansı, ve Timer2 bölme oranı belirliyor.
Frekans formülümüz şöyle;
Önce Peryodu buluyoruz. Formülümüz,  Peryot=[(Pr2)+1]*4*Tosc*Presecaler şeklinde  (Datasheet Sayfa 129 da PWM peryot başlığı altında)
Pr2=155 alınmış, Tosc=1/20Mhz=0,05  ve Prescaler ise 16 olacak.
F=1/T olduğundan formülü direk Frekans bazında da yazabiliriz.
Fpwm=Fosc/[(Pr2)+1]*4*Presecaler 
Şİmdi Frekansı hesaplayabiliriz. Fpwm=20.000.000 /((155)+1)*4*16)=2003 Hz olarak hesaplanır. Siz bunu 2003Khz gibi algıladınız her halde.

Şimdi gelelim 2 Mhz Frekans elde etmek için hangi parametreleri kullanacağımıza,
Frekans formülünden PR2 parametresini çeker isek ve Fpwm değeri olarak 2.000.000 Hz alırsak,
PR2=(20.000.000)/(2.000.000*4*16)
Pr2=10/64 gibi bir rakam elde ederizki bu değer 1 den küçük olduğu için paydanın küçülmesini gerektirir. Burada oynayabileceğimiz tek parametre Bölme oranıdır ve öyle görünüyorki onu 1 olarak almamız gerekecek.
Bu durumda Frekans, F=10/4 şeklinde hesaplanmış olacak ve PR2=2 olarak bulunacaktır.
Maksimum Duty değerini ise şöyle bulabiliriz.
x=((PR2+1)*DUTY)/25 formülünde Duty yerine 100 (yani %100) yazarsak,
X=((2+1)*100)/25=12 gibi bir değer bulunur.
%50 duty için aynı hesabı yaparsak,
X=((2+1)*50)/25= 6 değeri bulunmuş olur.

Gelelim frekansın kare dalgamı yoksa testere dişi dalgamı olduğuna. Elbette çıkan dalga kare olması gerekir.
İsis gösteremiyor olabilir. Gerçeğini gözlemlemek lazım.
20Mhz frekans ta bu işlemci en fazla zaten 2,5 Mhz frekans üretebilir.

Bu kadar yüksek frekanslara PWM ile çıkmadım. Bir ara denemek isterim. Bir sonuç alırsam buraya mesaj olarak eklerim.

Ete

. Kağan

#5
Hocam sanırım simule edemiyor.
Simulation is not running in real time due to excessive CPU load.
hatası nasıl düzeltilebilir? İşlemcinin %50 sini bile kullanmıyor.


'-----------2Mhz %50 kare dalga için-----------------
CCP1CON = %00001100  'TUM KANALLARDAN AYNI Sinyali aktif hale getirmek için veriyoruz.
PSTRCON = %00010011  'PULSE STEERING MODE ACIK VE KANAL STRA ile STRB AKTIF
T2CON   = %00000100  'ilk 2 bit bölme oranını belirliyor %000000xx yani xx bitleri 00=1/1 , 01=1/4 %10=1/16 bölme oranı
                     'şeklinde komutları verdikten sonra
duty=50  ' % DEĞER
PR2=2

'*************BASLA**********************
BASLA:

x=((PR2+1)*DUTY)/25   'bu formül % duty değerinden olması gereken duty rakamını hesaplar. Bütün OSC frekanslar için geçerlidir. (Örneğimizde X=(100*50/25)=200 olarak hesaplanırki bu max değeri 400 olan sinyalin %50 si için 200 olması demektir.
CCP1CON.4=X.0    'CCP1CON <5: 4> DEGERI "X" DEN ALIYOR
CCP1CON.5=X.1    'CCP1CON <5: 4> DEGERI "X" DEN ALIYOR
CCPR1L=x>>2      'CCPR1L  <7: 0> DEGERI "X" DEN ALIYOR


IF MOD_SEC=0 THEN  : TOGGLE DRM : PAUSE 100 : GOTO BTN_KNTRL


Goto BASLA




. Kağan

Hocam birde "Hızlı yanıttan" kod içeren mesaj gönderirken hata veriyor site. Kodsuz yanıt gönderdikten sonra düzeltten kod ekleyince kabul ediyor. İkincisi, düzenlede ekrana sığdır modundan çıkıyor. Bilginize.

ete

Bu konu başlığında bir sorun var. Yanıtla butonu bu konuda çıkmıyordu. Kod renklendirme sorunu varmış Gevv öyle söyledi. Sanırım kod etiketi altından çıkartmış verdiğin kodu ve Yanıtla butonu meydana çıkmış.
Hızlı yanıt kod içermemeli yada mesaj gibi yazılmalı kod çaresi yok. Bence hızlı yanıt mantığı basitçe bir iki şey söylemek için kullanılan yanıt sistemi gibi düşünülmeli.

İşlemcinin %50 sini kullanırken "Simulation is not running in real time due to excessive CPU load." hatasını yada ikazı ile ilgili olarak %50 lik işlemci kullanımı ile programın PC işlemcisine verdiği yük farklı şeyler olsa gerek. Genellikle simulasyonun zorlanması simulasyon sonuçlarının ekrana yansıtılmasında ortaya çıkar. Bu nedenle frame sayısını azaltarak bu sorun azaltılabilir. Yukarıda System butonuna tıklayın açılan pencerede "Set Animation Options" butonuna tıklayın . Gelen ekranda en üstte "Frames per Second" seçeneği karşısında 20 görülecektir. Bu rakamı 10 a düşürüp yeniden simulasyonu başlatın

Ete

ete

#8
Bende bir deneme yaptım. Benm skop çok düzgün kare dalga gösteriyor.
Okunan frekans ise 1,666.667 Hz olarak gözüküyor.
Hep söylerim PicMultiCalc isimli ufak programı kullanın diye. Şimdi ona baktım, 20 Mhz Osc frekansında 2000 khz (yani 2 Mhz) PWM frekansı için bana PR2=2 verdi.
Frekans değeri olarak da 1.666.667 Hz gösterdiki pic de bu frekansı veriyor hemde düzgünce.
Şimdi senin ekranında bu testere dişi şeklinde görülüyor ise kullandığın simulasyonda bir sorun olması gerekir.
Bendeki simulasyon düzgün kare dalga gösteriyor.

Ete


Powered by EzPortal