avatar_elektro77

16F1938 ECCP MODÜL KULLANIMI

Başlatan elektro77, 26 Ocak 2022, 14:46:16

elektro77

Merhabalar;
16f1938 de bulunan 3 adet eccp özelliğine aşağıdaki açıklamayı baz alarak bacic ile yapılmış bir örnek gösterebilir misiniz lütfen. Konu 3 faz motor sürücüde ıgbt leri sürmekle ilgili.
Alıntı Yap3 ECCP modülü olan bir MCU kullanmalısın. Örnek 16F1938. Bunun üzerinde 3 ECCP, 2 CCP modülü var. ECCP modülleriyle 3 adet halfbridge oluşturup, bunların çıkışlarıyla güç elemanlarını süreceksin. PWM frekansı, sürücü polaritesi, deadtime v.s. bu modüllerle yapacaksın.

CCP modülü tek porttan PWM çıkışı sağlar. Bununla ekstra elemanlarla fullbridge-halfbridge sürersin ama deadtime sorunu çıkar.

ECCP modüllerinde fullbridge için 4, halfbridge için 2 çıkış vardır. Yani deadtime v.s. kullanabilirsin. Deadtime da ise, ECCP üstündeki ilgili registere istediğin değeri verirsin, modül PWM sinyallerini o deadtime'da üretir.

SPWM frekansını, PWM frekansını değiştirerek değil, tablodaki duty değerlerini tetikleyen timer'ın zamanını değiştirerek yapacaksın. (Bunun sırası daha sonra gelir).

SPWM genliğini ise, tablodaki elemanların değeriyle oynayarak yapacaksın. Örnek: tablodan okuduğun her değeri ikiye bölerek uygularsan çıkıştaki gerilimin yarıya düştüğünü göreceksin.

Bu tablolar örnek sinüs dalgası, sen kendin istediğin gibi tablo yapıp çıkışta karedalga, üçgen, testere üretebilirsin. yazan: picproje Pkelle   
C dilinde yazılmış bir örnek
3 faz spwm üretmek için 120 derece faz farkı bulunan 3 tablo yapmalısınız. 

const int16 PHASE1[64]={128,141,153,165,177,188,199,209,219,227,234,241,246,250,254,
255,256,255,254,250,246,241,234,227,219,209,199,188,177,165,153,141,128,115,103,91,79,68,57,47,37,29,22,15,
10,6,2,1,0,1,2,6,10,15,22,29,37,47,57,68,79,91,103,115};

const int16 PHASE2[64]={17,11,7,3,1,0,0,2,4,8,13,19,26,35,44,53,64,75,87,99,111,124,136,149,161,173,185,196,
206,215,224,232,239,245,249,253,255,256,256,254,252,248,243,237,230,221,212,203,192,
181,169,157,145,132,120,107,95,83,71,60,50,41,32,24};

const int16 PHASE3[64]={239,232,224,215,206,196,185,173,161,149,136,124,111,99,87,75,64,53,44,35,26,19,13,8,
4,2,0,0,1,3,7,11,17,24,32,41,50,60,71,83,95,107,120,132,145,157,169,181,192,203,212,
221,230,237,243,248,252,254,256,256,255,253,249,245};

timer interrupt ruitini buna benzer:
PWM1=PHASE1[INDEX];
set_pwm1_duty(PWM1);
 
PWM2=PHASE2[INDEX];
set_pwm2_duty(PWM2);
 
PWM3=PHASE3[INDEX];
set_pwm3_duty(PWM3);

if (INDEX == 63) INDEX=0;
else  INDEX++;

int cikis

16f1938 datasheet
http://ww1.microchip.com/downloads/en/devicedoc/40001574c.pdf

3faz motor sürücü güç elemanları temel yapısı:


"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

#1
Data sheet'e şöyle bir baktım.ECCP aslında gelişmiş Capture , Compare ve PWM modulü anlamına geliyor. Half-Bridge (yarım köprü) çalışmasını ayarlayan CCPxCON registeri olup iş genellikle push-pull sürücülerin sürülmesinde kullanılıyor. Sanırım daha ziyade motor sürücülerine uygun bir sistem.
Yarım köprü modunun auarlanması CCPxCON registerinden yapılıyor ve ayarlamayı Bit7-6 yapmakta. Ancak. Bu registerin bit7-6 da verdiği açıklamaya bakacak olursak (aşağıdaki en son satır) Yarım köprü çıkışı iki pin üzerinden yapılabiliyor ve diğer iki PxA ve PxB bu amaçla kullanılıyor ama Pxc ve PxD port pini olarak kullanılıyor diyor. Dolayısıyla 3 adet ECCP çıkış pini yerine 2 adet aktif durumda Yarım köprü modunda. Çok iyi bildiğim bir konu değil maalesef. Ancak mantığımla fikir yürütebiliyorum.

Compare mode:
Unused
If CCPxM<3:2> = 00, 01, 10:
xx = PxA assigned as Capture/Compare input; PxB, PxC, PxD assigned as port pins
If CCPxM<3:2> = 11:
00 = Single output; PxA modulated; PxB, PxC, PxD assigned as port pins
01 = Full-Bridge output forward; PxD modulated; PxA active; PxB, PxC inactive
10 = Half-Bridge output; PxA, PxB modulated with dead-band control; PxC, PxD assigned as port pins

Şayet 3 çıkışın olsaydı, CCP1CON ve CCP2CON ve CCP3CON registerlerinden modülü half bridge olarak seçecektin.
Daha sonra her bir CCP modülü için (CCPTMRS0 ve CCPTMRS1 registerlerinden) timer seçimi yapacaktın. PWMxCON registerinden Dead time aayrlaması yapacaktın.
Frekans aayrlamaları her zaman olduğu gibi çıkışlar için seçtiğin Timer'a bağlı olarak PRx registerine verilecek değerle olacak ve daha sonra timerları aktif hale getireceksin.


Ete

elektro77

#2
Ete Hocam merhabalar;
16F1938 in ayarlarını aşağıdaki şekilde yaptım. Msc de hata vermiyorlar. Yanlış veya gereksiz olan var mı kontrol edebilir misiniz lütfen?

#config
        __config _CONFIG1, _FOSC_HS
        __config _CONFIG2, _PLLEN_OFF & _LVP_OFF
#endconfig

OSCCON =%01101000 '4 MHz
' Bit  7 0 = 4xPLL devre dışı 1= 4xPLL etkinleştirilir (konfigürasyon kelimesi 2 ayarı - PLLEN tarafından geçersiz kılınır)
' bits 6-3 = 1111=16Mhz, 1110=8MHz veya 32Mhz(4xPLL - conf word 2'ye bağlıdır) 1101=4 MHz, 1100=2MHz 1011=1MHz
' bitS 0-1 = 00= Conf word ile ayarlanan saat ,01 = Timer1 OSC , 1x = dahili Osc Block
WDTCON = %00000000 ' Bit 7,6 = 0 n/a , Bit 5-1 = watchdog zamanlayıcı periyodu seçimi , bit 0 = Watchdog zamanlayıcı biti ( WDTE) için SWDTEN etkinleştirme / devre dışı bırakma
'watchdog zamanlayıcısını 1 ms'ye ayarla ve SWDTEN bitinin ayarlanmasıyla etkinleştirme (mod Config1)'de _WDTE ayarıyla seçilir
APFCON  = %00000000 'Tümü Varsayılan - SPI kullanılırken değişiklik yok SDO1=RC2 , bit6=0 kullanın
CPSCON0 = $00       'Kapasitif Algılama Kontrolü Devre Dışı Bırak
CPSCON1 = $00       'CSC'yi Devre Dışı Bırak - CPSCON0 ile kullanılır
CM1CON0 = $00       'Karşılaştırıcıyı Devre Dışı Bırak / Temizle 1
CM1CON1 = $00       'CM1CON0 ile kullanılır
CM2CON0 = $00       'Karşılaştırıcıyı Devre Dışı Bırak / Temizle 2  CM2CON1 = ile kullanılır
CMOUT   = $00       'Karşılaştırıcılar çıkış kaydını devre dışı bırak - sadece karşılaştırıcı
SRCON1  = %00000000 'SRCON0 kaydı ile kullanılır
DACCON0 = $00       'D/A Devre Dışı Bırak
DACCON1 = $00       'D/A Devre Dışı Bırak -DACCON0 ile kullanılır 
OPTION_REG.7 = 1  'Zayıf Çekmeler devre dışı 1 = küresel devre dışı 0 = küresel etkinleştirme (her port tarafından ayarlanır - WPUB ayarları)
OPTION_REG.6 = 0  'Kesinti INT pininin Düşen Kenarında 0= düşen kenar 1= yükselen kenar
OPTION_REG.5 = 0  'TMR0 saat kaynağı - 1=T0clk pin 0=dahili saat
OPTION_REG.4 = 0  'TMR0 0=TOCKI piminin L/H 1= TOCKI piminin H/L'si
OPTION_REG.3 = 0  'TMR0 için Ön Çağırıcı Kullan 0= Evet , 1 = Hayır
OPTION_REG.2 = 1  'Timer0 ön ölçekleyici Hız Seçimi bitleri 2-0(1:256)
OPTION_REG.1 = 1  '000 = 1:2 , 001= 1:4 , 010 = 1:8 , 011 = 1:16
OPTION_REG.0 = 1  '100 = 1:32 , 101 = 1:64, 110 = 1:128 , 111 = 1:256
T1CON  =%01110100 'Timer 1 ,bit7-6 = TMR1 CLK source 00 = Instuction Clk(Fosc/4),01 =sys clk,10=ext clk,11=cap sense osc
'bit5-4 = TMR1 ön ölçek 11= 1:8 ,bit3 =0 LP kapalı,bit2=1 senkron harici CLK yok ,bit1= 0 n/a,Bit0=0 Zamanlayıcı 1 açık/kapalı
T1GCON =%00000000 'Zamanlayıcı 1 Kapı Kontrolü bit7 0= kapıdan bağımsız olarak sayar 1 = kullanımda olan kapılar, bit6 kapısı 1= Yüksek ,0=düşük
'olduğunda aktif bit5 0= geçiş modu devre dışı 1= etkin bit4 tek darbe modu 1- en 0= dis, bit 2 - durum biti,1-0 - geçit kaynağı seçimi
T2CON  =%01110011 'Zamanlayıcı 2 kapalı + 1:15 ölçek sonrası ,1:64 ön ölçek 
'( bit 7 = x, bit6-3 1110 = 1:15 ölçek sonrası, bit2=0 zamanlayıcı kapalı ,bit1-0 = ön ölçek 10 = 16 , 11 = ön ölçek 64
T4CON = %00000000 'ÖLÇÜ SONRASI 1/1,DUR,Ön ÖLÇÜ 1/1
T6CON = %00000000 'POST ÖLÇEKLEYİCİ 1/1,DUR,ÖN ÖLÇÜ 1/1
TMR0  = 0 'TMR0 MODÜL KAYDI 
TMR1H = 0 'TMR1H MODÜLÜNÜ TEMİZLE KAYIT
TMR1L = 0 'CLEAR TMR1L MODÜL KAYIT
TMR2  = 0 'CLEAR TMR2 MODÜL KAYIT
TMR4  = 0 'CLEAR TMR4 MODÜL KAYIT
TMR6  = 0 'CLEAR TMR6 MODÜL KAYIT
PR2 = 255 'Timer 2 Önyükleme Zamanı 
PR6 = 255 'Zamanlayıcı 6
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

Bir kaç satır birşey yazıp hata varmı diye kontrol ettirmen hoşuma gitmiyor.
Ben böyle bir şey hiç yapmadım. Kontrol nasıl olur sana öğreteyim.
Yazarsın kodu çalıştırırsın çalışmıyor ise sorun ararsın. Yoksa bu şekilde bir yere varman mümkün değil.
Sana söylemiştim bu işlemci aşina olduğum bir işlemci değil. Sırf soruna cevap verebilmek için o işlemciye ait data sheeti açıp her yerini kontrol etmem gerekiyor ki buda saatlerimi alır.
Neden sırf hata varmı diye böyle bir işe girişeyimki. Biraz yaptığın işe ve yetenekllerine güvenmen gerekiyor. Hata olmaz demiyorum ama bir hata var ise karşı karşıya kaldığın zaman onu aramalısın.
Ortada bir sorun yok iken hata aramak kadar zor bir iş yoktur. Bu nedenle tavsiyem yazmaya devam et ve sistemi simulasyonda da olsa çalıştırmaya çalış ki sorun var ise görebilesin.

Ete

elektro77

Alıntı yapılan: ete - 29 Ocak 2022, 11:23:55Bu nedenle tavsiyem yazmaya devam et ve
sistemi simulasyonda da olsa çalıştırmaya çalış ki sorun var ise görebilesin.
Anlaşıldı hocam. Kusura bakmayın. Yazmaya devam ediyorum. Bu pic i naçizane beraber öğreniriz Hocam
ne dersiniz.? Sizin motorlarla ve sürücüleri ile pek ilgilenmediğinizi biliyorum ama siz yardım etmezseniz
benim bu işi yapmam aylarımı alacak...
Saygılarımla..
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

elektro77

#5
const	int16	PHASE1[64]={128,141,153,165,177,188,199,209,219,227,234,241,246,250,254,
255,256,255,254,250,246,241,234,227,219,209,199,188,177,165,153,141,128,115,103,91,79,68,57,47,37,29,22,15,
10,6,2,1,0,1,2,6,10,15,22,29,37,47,57,68,79,91,103,115};

const	int16	PHASE2[64]={17,11,7,3,1,0,0,2,4,8,13,19,26,35,44,53,64,75,87,99,111,124,136,149,161,173,185,196,
206,215,224,232,239,245,249,253,255,256,256,254,252,248,243,237,230,221,212,203,192,
181,169,157,145,132,120,107,95,83,71,60,50,41,32,24};

const	int16	PHASE3[64]={239,232,224,215,206,196,185,173,161,149,136,124,111,99,87,75,64,53,44,35,26,19,13,8,
4,2,0,0,1,3,7,11,17,24,32,41,50,60,71,83,95,107,120,132,145,157,169,181,192,203,212,
221,230,237,243,248,252,254,256,256,255,253,249,245};

timer interrupt ruitini buna benzer:
PWM1=PHASE1[INDEX];
set_pwm1_duty(PWM1);
			
PWM2=PHASE2[INDEX];
set_pwm2_duty(PWM2);
		
PWM3=PHASE3[INDEX];
set_pwm3_duty(PWM3);

if (INDEX == 63) INDEX=0;
else  INDEX++;

int cikis

Merhabalar. kolay gelsin. Kandiliniz ve üçaylarınız mübarek olsun.
Bir timer kurup bu timer pulsleri ile, yukarıdaki c ile yapılmış tablo değerlerini çıkışa vermek işinin basic teki mantığı nedir?
"Eğer bir konuyu öğrenmek istiyorsan o konunun öğretmeni ol; daha iyi öğrenmek istiyorsan o konuda bir kitap yaz; daha da iyi öğrenmek istiyorsan yazdığın kitabi oku"

ete

#6
Gördüğüm kadarı ile bu bir data tablosu. Basic de bunun karşılığı LOOKUP komutu,
LOOKUP Index,[Constant{,Constant...}],Var
şeklinde kullanılıyor. Köşeli parantez içine orada gördüğün data ları yazacaksın.
Index bir değişken adı ve byte cinsinden olacak. Var yerine Phase1 değişkenini kullanacaksın.
Tabloda index=0 :gosub TABLO dediğinde, TABLO etiketi altında da LOOKUP komutu yer alırsa Phase1 değişkenine tablodaki ilk değer yerleşip geri döner.
Tablonun altında , PWM1=PHASE1[INDEX]; şeklindeki komut yerine PWM1=PHASE1 yazarsın olur biter.
Aslında işi daha hızlı halletmek istersen,
Phase1[64] elemanlı bir dizi değişkeni tanımlarsın.
Programda başla satırından önce,
FOR INDEX=0 to 63
LOOKUP INDEX,[xx,xx,....],PHASE[INDEX]
NEXT
şeklinde bir komut yerleştirirsen bütün data PHASE1 dizisine yerleşir. Böylece program içinde lazım olduğunda
PWM=PHASE1[INDEX] şeklinde komutu kullanırsın INDEX burada sıradaki hangi bilginin verileceğine işaret eder.
ete

Powered by EzPortal