top of page

DC Motor Uygulamaları

C2000 ailesinden TMS320F28044 ile

PID ile DC Motor Hızı Kontrolü

Bu uygulamada, BC547 NPN bipolar transistör kullanılarak bir DC motorun hızı kontrol edilmiştir. Kontrol işlemi, TMS320F mikrodenetleyici ve bir potansiyometre aracılığıyla gerçekleştirilmiştir.

transistr1.gif
motor.jpg

Potansiyometreden okunan değerlere göre değişken duty cycle'a sahip bir PWM sinyali üretilmiştir. Bu PWM sinyali, transistörün gate bacağındaki sinyali kontrol ederek kollektör-emitter arasındaki akımı değiştirir. Bu akım değişimi ise DC motorun hızını kontrol etmek için kullanılır.

İlk olarak PID kontrolü sağlamadan uygulamayı gerçekleştirelim:

Yukarıdaki videoda da görüldüğü gibi potansiyometre ile çok düşük duty cycle'a sahip PWM sinyallerine geçildiğinde motor durmaktadır. Bunun nedeni düşük duty cycle değerlerinde base akımının eşik değerini aşamamasıdır. 

Bu gibi sıkıntıları önlemek ve sistemi daha verimli çalıştırmak için PID kontrol ekledik. Böylece potansiyometreden okunan değerler, base akımının eşik değerini her zaman aşacak şekilde ve motor hızının üst limiti belirlenecek şekilde ayralanmış oldu.

Potansiyometreden okunan değer için motorun alt ve üst hız limiti PID sayesinde belirlendi.

H-Bridge ile DC Motor Yönü Kontrolü

H-Bridge, bir doğru akım (DC) motorunun yönünü değiştirmek için kullanılan bir devre türüdür. H-Bridge devresi, dört anahtar (genellikle transistörler veya MOSFET'ler) ve bunları kontrol eden bir sürücü devresinden oluşur. Bu devre, motorun ileri veya geri yönde dönmesini sağlar. Bu uygulamada anahtarlama için BC327 PNP transistör kullanılmıştır.

ezgif-4-001d73ec68.gif
H-Bridge-motor-drive-circuit-for-one-DC-motor-The-infrared-communication-module-is.png

H-Bridge devresinin çalışma prensibi, motorun iki yönde de dönmesini sağlamak için iki anahtarın aynı anda açılıp diğer iki anahtarın kapalı olmasıdır. Bu durumda, motorun bir kutbuna pozitif gerilim uygulanırken diğer kutbuna negatif gerilim uygulanır ve motor belirtilen yönde döner.

Bu uygulamadaki önemli kısım transistörlerin tetiklenmesini kontrol etmektir. H bridge devresindeki çaprazdaki transistörler aynı anda tetiklenmelidir. Yani, bir çift transistör açıkken diğer çift transistör kapalı olmalıdır. Bu, motorun belirli bir yönde dönmesini sağlar. Çaprazdaki transistörlerin aynı anda tetiklenmesi, motorun doğru yönde dönmesi için önemlidir. Tersi bir durumda, transistörlerin aynı anda kapalı veya aynı anda açık olması motorun durmasına veya arızalanmasına neden olabilir. Bunu önlemek için PWM dead time kullanılır.

PWM  dead time, H bridge devresinde kullanılan anahtar transistörlerin geçiş sürelerini kontrol etmek için kullanılan bir kavramdır. Dead time, bir transistörün kapanmasından diğerinin açılmasına geçen süreyi ifade eder. Bu süre, aynı anda iki transistörün açık olmasını önlemek için gereklidir.

Kodlar

/* * ################################# NOTLAR ########################################### * PWM frekansini TBPRD ayarlar * PWM Frekansı = EPWM_clk / (2 * TBPRD * CLKDIV * HSPCLKDIV) * * CMPA duty cyce i ayarlar * ornegin TBPRD = 5000 CMPA=2500 -> duty cycle %50 * ornegin TBPRD = 5000 CMPA=3750 -> duty cycle %25 * ornegin TBPRD = 5000 CMPA=1250 -> duty cycle %75 * #################################################################################### */ // A0 dan adc okuma yapiyorum // max -> 65520 // min ->460 // GPIO 0 dan PWM sinyali #include "DSP2804x_Device.h" // DSP2804x Headerfile Include File #include "DSP2804x_Examples.h" // DSP2804x Examples Include File #include "pid.h" pid_controller_t pid; float hata,sonuc; Uint32 cmpaCount=1500; Uint32 adcValue,adcReadDuty; // epwm struct typedef struct{ volatile struct EPWM_REGS *EPwmRegHandle; Uint16 EPwm_CMPA_Direction; Uint16 EPwm_CMPB_Direction; Uint16 EPwmTimerIntCount; Uint16 EPwmMaxCMPA; Uint16 EPwmMinCMPA; Uint16 EPwmMaxCMPB; Uint16 EPwmMinCMPB; } EPWM_INFO; EPWM_INFO epwm_info; // prototypes void Config_PWM(void); void Config_ADC(void); void Config_PID(void); __interrupt void epwm1_isr(void); void main(void){ // init-------------------------- InitSysCtrl(); InitEPwm1Gpio(); DINT; InitPieCtrl(); IER=0x0000; IFR=0x0000; InitPieVectTable(); //------------------------------- EALLOW; PieVectTable.EPWM1_INT = &epwm1_isr; EDIS; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Time Base Clock Disable EDIS; Config_PWM(); Config_ADC(); EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Time Base Clock Enable EDIS; // INT Config IER |= M_INT3; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; EINT; ERTM; for(;;) { __asm(" NOP"); } } void Config_ADC(void){ InitAdc(); // For this example, init the ADC // Configure ADC AdcRegs.ADCMAXCONV.bit.MAX_CONV1 = 3; AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x3; // Setup ADCINA3 as 1st SEQ1 conv. AdcRegs.ADCTRL1.bit.CONT_RUN = 1; AdcRegs.ADCTRL2.bit.SOC_SEQ1 =1; } void Config_PWM(void){ // Time Base Clock Config EPwm1Regs.TBPRD = 5000; // TBPRD = 5000 -> PWM Frekansini ayarlar EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Cikis fazi = 0 EPwm1Regs.TBCTR = 0x0000; // Time Base Conter = 0 // Compare Config EPwm1Regs.CMPA.half.CMPA = 2500; // cmpa_min =2500 -> duty cylei ayarlar // Counter Config EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // updown count EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // disable phase loading EPwm1Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; EPwm1Regs.TBCTL.bit.CLKDIV = TB_DIV1; // Shadow Config EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Action Qualifier Config EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up count EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A, down count // Interrupt where we will change the Compare Values EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1rd event epwm_info.EPwm_CMPA_Direction = 1; //EPWM_CMP_UP = 1 || EPWM_CMP_DOWN = 0 epwm_info.EPwmTimerIntCount = 0; // Zero the interrupt counter epwm_info.EPwmRegHandle = &EPwm1Regs; epwm_info.EPwmMaxCMPA = 3750; epwm_info.EPwmMinCMPA = 2500; } void Config_PID(void){ //pid_init(pid, kp, ki, kd, max_output, min_output) //pid_init(&pid, 1, 0, 0, 5000, 480); //pid_set_setpoint(&pid, 2500); } __interrupt void epwm1_isr(void){ // Duty Cycle kontrolü için PWM görevlerini ayarla pid_init(&pid, 1, 0, 0, 5000, 480); pid_set_setpoint(&pid, 2500); adcValue =AdcRegs.ADCRESULT1; adcReadDuty=(adcValue*1000)/65520; pid_update(&pid, adcReadDuty, 1); hata = pid.last_error; sonuc = pid.output; epwm_info.EPwmMaxCMPA = pid.output; // %25 duty cycle // epwm_info.EPwmMinCMPA = 2500; // %50 duty cycle // PWM görevlerini güncelle epwm_info.EPwmRegHandle->CMPA.half.CMPA = epwm_info.EPwmMaxCMPA; // Kesme işaretleyicisini temizle EPwm1Regs.ETCLR.bit.INT = 1; // Kesme sayacını artır epwm_info.EPwmTimerIntCount++; // Gerektiği gibi sıfırla if (epwm_info.EPwmTimerIntCount == 2) { epwm_info.EPwmTimerIntCount = 0; } // ACK kesme işaretleyicisini PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }

/* * ################################# NOTLAR ########################################### * PWM frekansini TBPRD ayarlar * PWM Frekansı = EPWM_clk / (2 * TBPRD * CLKDIV * HSPCLKDIV) * * CMPA duty cyce i ayarlar * ornegin TBPRD = 5000 CMPA=2500 -> duty cycle %50 * ornegin TBPRD = 5000 CMPA=3750 -> duty cycle %25 * ornegin TBPRD = 5000 CMPA=1250 -> duty cycle %75 * #################################################################################### */ #include "DSP2804x_Device.h" // DSP2804x Headerfile Include File #include "DSP2804x_Examples.h" // DSP2804x Examples Include File // epwm struct typedef struct{ volatile struct EPWM_REGS *EPwmRegHandle; Uint16 EPwm_CMPA_Direction; Uint16 EPwm_CMPB_Direction; Uint16 EPwmTimerIntCount; Uint16 EPwmMaxCMPA; Uint16 EPwmMinCMPA; Uint16 EPwmMaxCMPB; Uint16 EPwmMinCMPB; } EPWM_INFO; EPWM_INFO epwm_info; // prototypes void Config_PWM(void); __interrupt void epwm1_isr(void); void main(void){ // init-------------------------- InitSysCtrl(); InitEPwm1Gpio(); DINT; InitPieCtrl(); IER=0x0000; IFR=0x0000; InitPieVectTable(); //------------------------------- EALLOW; PieVectTable.EPWM1_INT = &epwm1_isr; EDIS; EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0; // Time Base Clock Disable EDIS; Config_PWM(); EALLOW; SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1; // Time Base Clock Enable EDIS; // INT Config IER |= M_INT3; PieCtrlRegs.PIEIER3.bit.INTx1 = 1; EINT; ERTM; for(;;) { __asm(" NOP"); } } void Config_PWM(void){ // Time Base Clock Config EPwm1Regs.TBPRD = 65535; // TBPRD = 6 -> PWM Frekansini ayarlar EPwm1Regs.TBPHS.half.TBPHS = 0x0000; // Cikis fazi = 0 EPwm1Regs.TBCTR = 0x0000; // Time Base Conter = 0 // Compare Config EPwm1Regs.CMPA.half.CMPA = 30000; // cmpa_min =2500 -> duty cylei ayarlar EPwm1Regs.CMPB = 30000; // Counter Config EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // updown count EPwm1Regs.TBCTL.bit.PHSEN = TB_DISABLE; // disable phase loading EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0x6; EPwm1Regs.TBCTL.bit.CLKDIV = 0x6; // Shadow Config EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; EPwm1Regs.DBCTL.bit.OUT_MODE = 3; EPwm1Regs.DBCTL.bit.POLSEL = 2; EPwm1Regs.DBCTL.bit.IN_MODE = 0; EPwm1Regs.DBRED = 50000; // Set Dead-band EPwm1Regs.DBFED = 50000; // Set Dead-band // Action Qualifier Config EPwm1Regs.AQCTLA.bit.CAU = AQ_SET; // Set PWM1A on event A, up count EPwm1Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Clear PWM1A on event A, down count EPwm1Regs.AQCTLB.bit.CBU = AQ_SET; // Set PWM1B on event B, up count EPwm1Regs.AQCTLB.bit.CBD = AQ_CLEAR; // Clear PWM1B on event B, down count // Interrupt where we will change the Compare Values EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO; // Select INT on Zero event EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1rd event epwm_info.EPwm_CMPA_Direction = 1; //EPWM_CMP_UP = 1 || EPWM_CMP_DOWN = 0 epwm_info.EPwm_CMPB_Direction = 1; epwm_info.EPwmTimerIntCount = 0; // Zero the interrupt counter epwm_info.EPwmRegHandle = &EPwm1Regs; epwm_info.EPwmMaxCMPA = 3750; epwm_info.EPwmMinCMPA = 2500; epwm_info.EPwmMaxCMPB = 3750; epwm_info.EPwmMinCMPB = 2500; } __interrupt void epwm1_isr(void){ // Duty Cycle kontrolü için PWM görevlerini ayarla epwm_info.EPwmMaxCMPA = 30000; // %25 duty cycle // epwm_info.EPwmMinCMPA = 2500; // %50 duty cycle epwm_info.EPwmMaxCMPB = 30000; // PWM görevlerini güncelle epwm_info.EPwmRegHandle->CMPA.half.CMPA = epwm_info.EPwmMaxCMPA; epwm_info.EPwmRegHandle->CMPB = epwm_info.EPwmMaxCMPB; // Kesme işaretleyicisini temizle EPwm1Regs.ETCLR.bit.INT = 1; // Kesme sayacını artır epwm_info.EPwmTimerIntCount++; // Gerektiği gibi sıfırla if (epwm_info.EPwmTimerIntCount == 2) { epwm_info.EPwmTimerIntCount = 0; } // ACK kesme işaretleyicisini PieCtrlRegs.PIEACK.all = PIEACK_GROUP3; }

bottom of page