Haberler:

Foruma Resim Yükleme ve Boyut Sınırlaması ( ! )  https://bit.ly/2GMFb8H

Ana Menü

dspic30f2023-pwm ve CCS

Başlatan jackal183, 03 Temmuz 2011, 21:38:26

iyildirim

Evet, bu işlemciler SMPS serisi olarak geçiyor. Zaten üzerindeki modüllerin özellikleri de smps için üretildiklerini gösteriyor.

Benim gördüğüm, diğer serilerden en önemli farkları PWM ve ADC  modülleri. Ayrıca üzerinde 4 adet de komparator var.
PWM modülünün en önemli farkı, period ve duty çözünürlüğünün  çok iyi olması. ADC de 30f lerdeki en hızlı ADC.

Ayrıca diğerlerinden farklı olarak , (diğerleri derken CCP modülleri değil MC pwm'i kastediyorum) PWM darbesi ile ADC sample anını senkronlama, komparatorlarla PWM darbesini sonlandırma gibi özellikleri var. MC serilerinde de PWM fault girişleriyle bu var ancak modülün tamamı için geçerli olacak şekilde. Bunlarda her bir PWM generatörü (4 adet) için ayrı ayrı yapılabiliyor. Birde 4 adet PWM generatörü olduğu için 4 farklı period ve duty destekleniyor.

Tabii bir de çeşitli formlar da PWM üretmek vs. de mümkün..  Complementary, push-pull vs.

Bana göre tek sıkıntısı da düşük frekanslara inilememesi.

Gerçi MC serilerinde de çok düşük frekansa inilemiyor. En düşük neydi hatırlamıyorum ama 33FJ256MC710 da da  50 Hz'lik servo besleyebileceğim bir frekansa inememiştim. 8 kanal PWM üretme işini OC kullanarak yapmıştım.

Bu arada OC kullanmanın herhangi bir mahsuru yok.  Elimdeki dandik scop ile baktığımda OC ile üretilen PWM'in MC veya SMPS ile üretilenden bir farkını göremedim. Zaten datasheet lerde de CCP modülü glicth engellenmiştir gibi ifadeler var.
Örneğin servo için 50-100 hz pwm oluşturmak gibi bir işde CCP modülü kullanmanın herhangi bir dezavantajı yok.
Ancak SMPS veya motor kontrolü gibi konularda akım, gerilim, ters akım vs. bir sürü şeyi çok hızlı bir şekilde kontrol etmek sözkonusu olduğunda CCP modülü bu iş için üretilmiş PWM modüllerinin yanına bile yaklaşamaz..

PWM1H ve PWM1L pinlerine gelirsek,
Her bir PWM generatöründeki pinler Low ve High olarak isimlendirilmiş bir çift. Bunların istediğimiz herhangi birini aktif yapıp PWM ile sürülmesini sağlayabiliyoruz. Kullanmadığımız pin varsa GPIO olarak ne ayarlı ise o oluyor. Yine aktif PWM darbesinin low veya high olduğunu da söyleyebiliyoruz.

Verilen örnekte pinlerin her ikisinde de PWM darbesi olacak.
Bu seçilen PWM moduna ve diğer bazı şeylere bağlı.

Eğer PWM modu olarak independent seçili ise her iki pindede puls olacaktır.
complemantary seçili ise low pinde puls,  (dead time vs ye de bağlı olarak ) high pin de puls olmadığında olacak. Dead time gözönüne alınmazsa daima biri high iken diğeri low olacak..
Push-pull da ise sırayla bir high, bir low pinde puls oluyor. Yani pin olarak bakınca bir pwm darbesi boş geçiliyor.

Yeri gelmişken,
Ayrıca overwrite denilen bir özellik daha var. Bunun için de her bir pwm generatöründe OVRDAT ve OVREN  adında her pin için iki ayrı register var.
OVRDAT, OVREN 1 olduğunda pine sıfırmı birmi basılacağı söylüyor. Aynı şekilde fault girişleri aktif olduğunda pinlere ne basılacağı da ayrıca söylenebiliyor.

Örneğin bir H köprü ile hız kontrollü bir DC motor sürelim.
PWM1 köprünün sol yarımı, pwm2 sağ yarımı olsun. Highlar üst low lar da alt mosları kontrol etsin.
Motor bir yöne dönerken sadece PWM1H ile PWM2L çalışacak. 1L ve 2H duracak.
Bunun için

2020-2023 de
IOCON1bits.OVRDAT = IOCON2bits.OVRDAT = 0b00; tanımlayıp,  sonrasında

bir yön için
IOCON1bits.OVRENH = IOCON2bits.OVRENL = 0;
IOCON2bits.OVRENH = IOCON1bits.OVRENL = 1;

diğer yön için de
IOCON1bits.OVRENH = IOCON2bits.OVRENL = 1;
IOCON2bits.OVRENH = IOCON1bits.OVRENL = 0;
demek yeterli.
Aynı şekilde decay akımlarını kontrol etmek için de overwrite registerleri kullanmak işi kolaylaştırıyor.  Örneğin darbe kesildiğinde oluşan ters akımı hızlı sönümlendirmek için yukarıdaki örnek kullanılabileceği gibi yavaş sönümlendirmek için alt mosu sürekli açık tutup alt moslarda akımı çevirerek sönümlendirmek de mümkün..

MC serilerinde overwrite registerleri tek bir register içerisinde tüm kanalların bitleri olacak şekilde tanımlı olduğu için yön, decay vs. gibi kontrolleri duruma - hıza bağlı indekslenmiş arraylarda kontrol edilebiliyor, ve bana göre motor kontrolu açısından daha mantıklı ve verimli..

Çok uzattım.. Konu-soruda biraz dağıldı..

Sadede gelirsek tüm bu nedenlerden dolayı SMPS veya MC PWM modülleri varken özellikle motor kontrolü vs. gibi konularda CCP modülü kullanmak çok da verimli değil deyip bitireyim..


GreeN

Gerçekten çok aydınlatıcı oldu. Olaya vakıf olduğunuz belli , zaman ayırdığınız için teşekkür ederim.
Terörü Lanetliyoruz.

jackal183

hocam ADC'yi denedim bu kez 2020 elime geçti ve bunun datasheeti daha aydınlatıcı ve verdikleri sample code da güzel çalışıyor, yardımlarınız için teşekkür ederim

jackal183

#18
hocam bugün de pwm ile uğraştım pwm üretmeyi başardım ancak bir sorum var, garip geldi biraz, datasheette şöyle bir formül verilmiş;



ve yine datasheette formül ile ilgili olan PTPER registerı için "PTPER<15:3>: The Primary Time Base Period (PTPER) register holds the 13-bit value that specifies the counting period for the primary PWM time base." şeklinde bir açıklama var. buradan ne anlamalıyım son 3 bitin 0 ya da 1 olması önemsizse eğer, o zaman PTPER=FFFF yazsam da sonuç aynı olacak PTPER=FFF8 yazsam da aynı olacak? o zaman hesaplama yaparken 0 ile mi 1 ile mi hesap yapacağız?

formüle göre PLL=32, CLOCK=15 MHz diyelim, PTPER registeri 65536( son 3 biti 1 olarak alırsak) olur. o zaman elde edebileceğimiz minimum frekans;

frekans= 32*2*15*1000000/65536= 14648 hz yapar. CLOCK=4 MHz alırsak da frekans=3906 Hz eder. ancak verilen bilgilerde bu dspicin 50 hz'e kadar düşebildiği yazıyor, nasıl düşecek? PLL değerini 1 almayı düşündüm, ancak PLL değerini enable etmek gerekiyormuş datasheette yazdığına göre;
"The Phase-Locked Loop (PLL) must be enabled for the Power Supply PWM module to function. This is achieved by setting the FNOSC<1:0> bits in the FOSCSEL configuration register." e verdiği örnekte de PLL=32 almış, peki bu PLL=1 nasıl yapacam böyle birşey mümkün mü?

yukarıda eklediğim resim görünmüyor, bahsettiğim formül burda sayfa 27 de http://ww1.microchip.com/downloads/en/DeviceDoc/70270C.pdf

iyildirim

Datasheet'de verilen formül doğru.. Oluşturduğun PWM'e scop la bakma şansın olduysa sende görmüşşündür..

PTPER registerine değer yüklerken son üç bite değer atanıp tanmadığına hiç takılmadım. İşlemlerde çıkan değer ne ise onu kullandım.
Zaten son üç bitin karşılığı 8ns.   
Aslında burada söylenen şey de frekans çözünürlüğünün 8ns ve katları şeklinde gittiği.. Duty ise 1 ns çözünürlükte ayarlanabiliyor.
Datasheet'in 24. sayfasındaki şekile bakılırsa daha rahat anlaşılabilir.

Bu şekilde 960khz frekans da bile çalışılsa 10 bitlik duty çözünürlüğü elde edilmiş oluyor. 960khz den bir düşük frekans ise 959khz gibi birşey. Yani ayarlayamadığımız şey frekansın 959500hz olması.

50Hz'e inmek gibi birşeyi denemedim. Ancak 2020 lerde SMPS pwm moülünün bu kadar düşük frekansla çalışılabileceğini sanmıyorum. Sanırım ancak işlemcinin hızı da düşürülerek yapılabilir ki çok da anlamlı olmaz.. pll kullanmayınca olacakmış gibi ama sizinde yaptığınız alıntı da yazdığı gibi pll olmadan pwm modülü de çalışmıyor.

Datasheetlerde çeşitli hatalar ve çelişkilerde var. Örneğin endüstriyel ve extended olanların karşılaştırıldığı tabloda I/P için fpwm 480mhz deniyor. aslında 960mhz. Extended olanlarda ise 480. Her ikisini de kullandığım için eminim..

Ayrıca 2020-2023 ilk smps serileri. Bolca da hataları da var. Herhangi bir saçmalıkla karşılaşınca Errata  dökümanlarına bakmak adetim oldu..





jackal183

scop ile baktım verilen formül doğru evet, ancak ben 2020 ile hem 100 khz hem de 1 khz lik iki farklı pwm oluşturmak istiyorum, 100 khzde sorun yok zaten datasheettte verilen örnek direk 100 khz verilmiş temiz çalışıyor, ancak bu formüle göre 1 khz asla üretemem. PLL kullanmadan deneyeceğim, bakalım oluyor mu, hocam bu errata dökümanları nedir peki? bir de bu PLL=32 sabit midir, değiştirelebilir mi?

iyildirim

İki farklı frekansda PWM üretmek için en az bir pwm generatörünü ITB  = 1 şeklinde, independent time base modunda kullanmak gerekli. Bu durumda da  periodu Phase registeri ile belirlemek gerekli.
Sıkıntı 1 khz olmasında. Açıkçası 30F lerle pek fazla uğraşmadım. En çok kullandığım 2020 oldu. Onda da 20khz ve üzeri frekanslarla uğraştım. 1khz'e inermi bilmiyorum.

2020 nin oscillator ile ilgili datasheetlerinde belki cevabı vardır.

necati

bu hatayı nicin veriyor
*** Error 128 "C:\Program Files\PICC\Devices\30F4013.h" Line 11(9,21): A #DEVICE required before this line

#include <30F4013.h>
#DEVICE ADC=10
#FUSES NOWDT                     //No Watch Dog Timer
#FUSES XT_PLL8                   //XT Crystal Oscillator mode with 8X PLL
#FUSES NOCKSFSM                  //Clock Switching is disabled, fail Safe clock monitor is disabled
#FUSES BORV27                    //Brownout reset at 2.7V
#FUSES NOBROWNOUT                //No brownout reset
#FUSES PROTECT                   //Code protected from reads
#FUSES MCLR
#use delay(clock=80000000)

#use standard_IO(B)
//  Main code here
#include <Recon40.h>
//#include <math.h>
//#include <float.h>
/******  LCD Defines ********/
#define LCD_BL pin_f5
#define LCD_ENABLE_PIN  PIN_d1                                  ////
#define LCD_RS_PIN      PIN_b12                                    ////
#define LCD_RW_PIN      PIN_f1                                  ////
#define LCD_DATA4       PIN_b11                                   ////
#define LCD_DATA5       PIN_d0                                  ////
#define LCD_DATA6       PIN_f0                                 ////
#define LCD_DATA7       PIN_f4 
#include <LCD.C>


#use rs232(UART1,baud=115200,parity=N,bits=8)
/******* Global Vars ****************/
unsigned int16 heartbeat;
unsigned int16 ADC0,ADC1; //,Vd1,Vd2;
float Vd1,Vd2;
char adcCH;
char disp[12];

#int_TIMER1
void  TIMER1_isr(void)
{
 heartBeat++;
 //if (heartBeat == 0xFFFF)
// output_toggle(LCD_BL);
// output_toggle(LCD_ENABLE_PIN);
 //output_toggle(LCD_RS_PIN);
 //output_toggle(LCD_RW_PIN);
 //output_toggle(LCD_DATA4);
 //output_toggle(LCD_DATA5);
// output_toggle(LCD_DATA6);
// output_toggle(LCD_DATA7);
  adcCH++;
  if (adcCH>=2) adcCH = 0;
  set_adc_channel(adcCH);
  if (adcCH==0) ADC0 = read_adc();
  else ADC1 = read_adc();
  Delay_us(2);
 
 
}




   


void main()
{
   setup_spi(SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4);

   setup_timer2(TMR_INTERNAL |TMR_DIV_BY_64 ,0);
   setup_timer4(TMR_DISABLED |TMR_DIV_BY_1 ,0);
   setup_timer3(TMR_DISABLED |TMR_DIV_BY_1 ,0);
   setup_timer5(TMR_DISABLED |TMR_DIV_BY_1 ,0);


   setup_timer1(TMR_INTERNAL|TMR_DIV_BY_8);
   enable_interrupts(INT_TIMER1);
   enable_interrupts(INTR_GLOBAL);
  setup_adc_ports(sAN0 | sAN1, VSS_VDD);
  setup_adc(ADC_CLOCK_DIV_8 | ADC_TAD_MUL_4);
   
  // setup_adc_ports(sAN0 | sAN1, VSS_VDD);
 //  setup_adc(ADC_CLOCK_DIV_4 | ADC_TAD_MUL_2);
   lcd_init();

   // TODO: USER CODE!!
   output_high(LCD_BL);
   printf(lcd_putc,"\f dsPIC LCD\n");
   printf(lcd_putc,"Float & Int");
   delay_ms(3000);
    printf(lcd_putc,"\f..Ready\n");
    delay_ms(1000);
   while(1) {
   Vd1=(float)(ADC0*5)/1024;
   Vd2= (float)(ADC1*5)/1024;
 
   lcd_gotoxy(0,2);
   printf(lcd_putc,"%Lu        ",ADC0);
   lcd_gotoxy(8,2);
   printf(lcd_putc,"%Lu        ",ADC1);
   // this block resets the dsPiC
  /* delay_ms(500);
   sprintf(disp,"%f",Vd1);
   
   lcd_gotoxy(0,2);
   printf(lcd_putc,disp);
   delay_ms(100);
   sprintf(disp,"%f",Vd2);
   lcd_gotoxy(8,2);
   printf(lcd_putc,disp); */
    /* delay_ms(500);
   sprintf(disp,"%f",Vd1);
   /*****   This block resets the dsPIC toor****/
   delay_ms(1000);
   printf(lcd_putc,"\f");
   lcd_gotoxy(0,2);
   printf(lcd_putc,"V0:%f",Vd1);
   delay_ms(100);
   lcd_gotoxy(9,2);
   printf(lcd_putc,"V1:%f",Vd2);
   delay_ms(1000);
   
   
   }

}

[email]entegreterbiyecisi@yahoo.com[/email]

sadogan

Derleyici versiyonundan kaynaklanıyor. 5.106 ile derlediginde aynı hatayı alıyorum 5.103 de sıkıntı yok.
http://www.ccsinfo.com/devices.php?page=versioninfo
5.107 de düzeltilmiş.