Help to look at the following code of the ADC module settings, as well as the back of the voltage control code where there is a problem, the code can not realize the PI control please help you to solve it!
After running, it
<code>#include "DSP2833x_Device.h" /* DSP2833x Headerfile Include File */
#include "DSP2833x_Examples.h" /* DSP2833x Examples Include File */
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <math.h>
#define BUFFER_LENGTH 4096
#define CURRENT_SCALE_FACTOR 0.00054
#define VOLTAGE_SCALE_FACTOR 0.0405
#define VREF 3.3 //Reference voltage for the ADC
#define SYSTEM_CLOCK 200E6 // 200MHz
#define TBCLK 100E6 // 100MHz
#define PWM_CARRIER 100E3 // 100kHz
// Global variable for this example
Uint16 Sample1=0, Sample2=0; // 실제 Sensing이 된 ADC 변수
Uint16 ADC_cnt=0, ADC_cnt2=0, ADC_data0=0, ADC_data1=0, ADC_flag=0; // ADC Calibaraion를 위한 변수 설정
float32 I_osum=0., I_oavg=0.;
Uint16 Fil_cnt=0;
Uint16 I_Fil=0, I_inFil=0;
Uint16 Runflag=0, Trip_cnt=0; //여러 제어Mode 및 OpenLoop가 가능하도록 설정. Runflag 값을 변경하여 동작을 다음과 같이 설정 할 수 있다.
// 0 : 평상시(동작안함), 1 : 투스위치 Openloop Test,
// 2 : 투스위치 VoltageControl, 3 : 스위치 1개 Openloop Test, 4 : 디지털 제어
Uint16 EPwm1IsrTicker = 0;
Uint16 BackTicker;
Uint16 AdcisrTicker; // ADC 인터럽트 서비스 루틴 호출 횟수 계수(S/W카운터)
Uint16 VoltageTicker;
float32 Adc_Result;
float32 AdcOffset;
float64 V_o=0., offset_0=0., I_o=0., offset_1=0.; // ADC Calibaraion 및 출력전압 센싱값 변수 설정
float32 V_err=0., V_ref=0; // PI제어를 위한 오차 및 출력전압 Reference
float32 Kv_pi =0., V_pterm=0., V_iterm=0. ; // PI제어기의 P제어기 수행후 값(V_pterm),
float32 V_in_REF=0;
float32 Anti_Err=0;
float32 IntegV_err=0;
float32 Integerr=0;
float32 Antierr=0;
// I제어기 수행 후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p1=0, K_i1=0, K_a1=0; // Voltage Control의 게인
float32 Io_f=0., Vo_f=0.; // 전류 Filter 변수 설정
float32 test_value=0.;
float32 out_sat=0.0;
float32 out_pi=0.0;
float32 PwmDutyRatio;
float32 FallingEdgeDelay;
float32 RisingEdgeDelay;
float32 DBPer=0.0;
/*★*/
float32 I_err=0., I_ref=0.4; // PI제어를 위한 오차 및 입력 전류 Reference
float32 Ki_pi =0., I_pterm=0., I_iterm=0.; // PI제어기의 P제어기 수행후 값(V_pterm), I제어기 수행후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p2=4.0, K_i2=100.0; // Current Control의 게인
float32 PwmDutyRatioA = 0.0;
////////////////////////////inverter
// Global variables used in inverter
void epwm1module(void); // epwm1module 함수 불러오기
void epwm2module(void); // epwm2module 함수 불러오기
void epwm3module(void); // epwm3module 함수 불러오기
interrupt void epwm1isr(void); // Interrupt 불러오기(epwm1isr)
interrupt void ADCIsr(void); //Interrupt ADC
void main(void)
{
InitSysCtrl();
InitEPwmGpio();
DINT;
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1isr; // PIE Vector Table 설정
PieVectTable.EPWM2_INT = &epwm1isr;
PieVectTable.EPWM3_INT = &epwm1isr;
PieVectTable.ADCINT = &epwm1isr;
PieVectTable.EPWM1_TZINT = &epwm1isr;
PieVectTable.EPWM2_TZINT = &epwm1isr;
EDIS;
InitAdc();
AdcRegs.ADCREFSEL.bit.REF_SEL = 0;
AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; // ADCCLK = HSPCLK/(ADCCLKPS*2)/(CPS+1)
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.CPS = 0; // ADCCLK = 100MHz/(1*2)/(0+1) = 50MHz
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 샘플/홀드 사이클 = ACQ_PS + 1 = 16 (ADCCLK기준)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 샘플링 모드 선택 (0:순차 샘플링 Sequence, 1:동시 샘플링 Simultaneous)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 시퀀스 모드 설정: 직렬 시퀀스 모드 (0:병렬 모드, 1:직렬 모드)
AdcRegs.ADCTRL1.bit.SUSMOD=0; // 시작점을 EPWM과 동기화
AdcRegs.ADCMAXCONV.all = 0x1; // ADC를 사용할 개수
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // ADC 순서 설정
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // ADC 순서 설정
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM_SOCA로 ADC 시퀀스 시동
EPwm3Regs.ETSEL.bit.SOCAEN = 1; // EPWM 3번에 동기화 신호 Enable
EPwm3Regs.ETSEL.bit.SOCASEL = 2; // SOCA의 동기화 시점을 PRD와 동일하게 설정
EPwm3Regs.ETPS.bit.SOCAPRD = 1; // SOCA의 동기화 횟수를 EPWM과 동일하게 설정
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Carrier 파형을 Up 으로 설정
EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBCTL.bit.CLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // (100MHz/100KHz)-1 = 999 𝑇_𝑃𝑊𝑀=2∗𝑇𝐵𝑃𝑅𝐷∗ 𝑇_𝑇𝐵𝐶𝐿𝐾
EPwm3Regs.TBCTR = 0x0000; // 초기 Counter Clear
// PIE의 ADC 인터럽트 활성화
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // PIE 인터럽트(ADCINT) 활성화
IER |= M_INT1; // CPU 인터럽트(INT1) 활성화
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
PieCtrlRegs.PIEIER2.bit.INTx2 = 1; // TZ int2
IER |= M_INT2; // CPU 인터럽트(INT1) 활성화
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
epwm1module();
epwm2module();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
// Enable CPU INT3 which is connected to EPWM1-3 INT:
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
IER |= M_INT3;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
BackTicker = 0;
for(;;)
{
BackTicker++;
}
}
// DC_DC
void epwm1module(void)
{
/* Setup Counter Mode and Clock */
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm1Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm1Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm1Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm1Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm1Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm1Regs.DBCTL.bit.IN_MODE = 0;
EPwm1Regs.DBCTL.bit.OUT_MODE = 0;
EPwm1Regs.DBCTL.bit.POLSEL = 0;
EPwm1Regs.DBFED = 1; // Falling Deadtime 설정
EPwm1Regs.DBRED = 1; // Rising Deadtime 설정
/* Set Interrupts */
EPwm1Regs.ETSEL.bit.INTSEL = 1; // EPWM 인터럽트 옵션 - CTR이 PRD일때 동기화
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event EPwm1Regs.
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 이벤트 트리거 Enable
EPwm1Regs.ETSEL.bit.SOCASEL = 2; // SCCA 트리거 조건 : 카운터 주기 일치 시 (읽는 시점이라고 생각하시면 됩니다)
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // SOCA 이벤트 분주 설정 : 트리거 조건 한번 마다 (샘플링을 EPWM주파수에 동기화를 시켰다고 보시면 됩니다.)
EALLOW;
EDIS;
}
void epwm2module()
{
/* Setup Counter Mode and Clock */
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm2Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm2Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm2Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm2Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm2Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm2Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm2Regs.DBCTL.bit.IN_MODE = 0;
EPwm2Regs.DBCTL.bit.OUT_MODE = 0;
EPwm2Regs.DBCTL.bit.POLSEL = 0;
EPwm2Regs.DBFED = 1; // Falling Deadtime 설정
EPwm2Regs.DBRED = 1; // Rising Deadtime 설정
}
interrupt void epwm1isr(void)
{
EPwm1IsrTicker++;
if (PwmDutyRatioA >= 0.8)
{
PwmDutyRatioA = 0.8;
}
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm2Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm1Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
interrupt void Adcisr(void)
{
if(AdcisrTicker==10)
{
AdcOffset = ((3.3 * (float32)(AdcRegs.ADCRESULT0)) / 4096); //Offset value before startup
}
AdcisrTicker++;
if (AdcisrTicker > 10000)
AdcisrTicker = 11;
Adc_Result = ((3.3 * (float32)(AdcRegs.ADCRESULT0) / 4096) - AdcOffset) * 10;
}
void voltageController(void) // Voltage Control Mode
{
////////////// Deadtime 설정 ///////////////
EPwm1Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm1Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm1Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
EPwm2Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm2Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm2Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
////////////// PI 제어기 설정 /////////////////
if(Adc_Result<4.0)
{
PwmDutyRatio=0.416;
return;
}
V_err=V_ref-Adc_Result;
Antierr=V_err-K_a1*(out_pi-out_sat);
Integerr +=K_i1*Antierr;
out_pi=Integerr + K_p1*V_err;
if(out_pi>0.8)
out_sat=0.8;
else if(out_pi<0.1)
out_sat=0.1;
else
out_sat=out_pi;
PwmDutyRatio=out_sat;
VoltageTicker++;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.CMPA.half.CMPA = (EPwm2Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
}
</code>
<code>#include "DSP2833x_Device.h" /* DSP2833x Headerfile Include File */
#include "DSP2833x_Examples.h" /* DSP2833x Examples Include File */
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <math.h>
#define BUFFER_LENGTH 4096
#define CURRENT_SCALE_FACTOR 0.00054
#define VOLTAGE_SCALE_FACTOR 0.0405
#define VREF 3.3 //Reference voltage for the ADC
#define SYSTEM_CLOCK 200E6 // 200MHz
#define TBCLK 100E6 // 100MHz
#define PWM_CARRIER 100E3 // 100kHz
// Global variable for this example
Uint16 Sample1=0, Sample2=0; // 실제 Sensing이 된 ADC 변수
Uint16 ADC_cnt=0, ADC_cnt2=0, ADC_data0=0, ADC_data1=0, ADC_flag=0; // ADC Calibaraion를 위한 변수 설정
float32 I_osum=0., I_oavg=0.;
Uint16 Fil_cnt=0;
Uint16 I_Fil=0, I_inFil=0;
Uint16 Runflag=0, Trip_cnt=0; //여러 제어Mode 및 OpenLoop가 가능하도록 설정. Runflag 값을 변경하여 동작을 다음과 같이 설정 할 수 있다.
// 0 : 평상시(동작안함), 1 : 투스위치 Openloop Test,
// 2 : 투스위치 VoltageControl, 3 : 스위치 1개 Openloop Test, 4 : 디지털 제어
Uint16 EPwm1IsrTicker = 0;
Uint16 BackTicker;
Uint16 AdcisrTicker; // ADC 인터럽트 서비스 루틴 호출 횟수 계수(S/W카운터)
Uint16 VoltageTicker;
float32 Adc_Result;
float32 AdcOffset;
float64 V_o=0., offset_0=0., I_o=0., offset_1=0.; // ADC Calibaraion 및 출력전압 센싱값 변수 설정
float32 V_err=0., V_ref=0; // PI제어를 위한 오차 및 출력전압 Reference
float32 Kv_pi =0., V_pterm=0., V_iterm=0. ; // PI제어기의 P제어기 수행후 값(V_pterm),
float32 V_in_REF=0;
float32 Anti_Err=0;
float32 IntegV_err=0;
float32 Integerr=0;
float32 Antierr=0;
// I제어기 수행 후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p1=0, K_i1=0, K_a1=0; // Voltage Control의 게인
float32 Io_f=0., Vo_f=0.; // 전류 Filter 변수 설정
float32 test_value=0.;
float32 out_sat=0.0;
float32 out_pi=0.0;
float32 PwmDutyRatio;
float32 FallingEdgeDelay;
float32 RisingEdgeDelay;
float32 DBPer=0.0;
/*★*/
float32 I_err=0., I_ref=0.4; // PI제어를 위한 오차 및 입력 전류 Reference
float32 Ki_pi =0., I_pterm=0., I_iterm=0.; // PI제어기의 P제어기 수행후 값(V_pterm), I제어기 수행후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p2=4.0, K_i2=100.0; // Current Control의 게인
float32 PwmDutyRatioA = 0.0;
////////////////////////////inverter
// Global variables used in inverter
void epwm1module(void); // epwm1module 함수 불러오기
void epwm2module(void); // epwm2module 함수 불러오기
void epwm3module(void); // epwm3module 함수 불러오기
interrupt void epwm1isr(void); // Interrupt 불러오기(epwm1isr)
interrupt void ADCIsr(void); //Interrupt ADC
void main(void)
{
InitSysCtrl();
InitEPwmGpio();
DINT;
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1isr; // PIE Vector Table 설정
PieVectTable.EPWM2_INT = &epwm1isr;
PieVectTable.EPWM3_INT = &epwm1isr;
PieVectTable.ADCINT = &epwm1isr;
PieVectTable.EPWM1_TZINT = &epwm1isr;
PieVectTable.EPWM2_TZINT = &epwm1isr;
EDIS;
InitAdc();
AdcRegs.ADCREFSEL.bit.REF_SEL = 0;
AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; // ADCCLK = HSPCLK/(ADCCLKPS*2)/(CPS+1)
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.CPS = 0; // ADCCLK = 100MHz/(1*2)/(0+1) = 50MHz
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 샘플/홀드 사이클 = ACQ_PS + 1 = 16 (ADCCLK기준)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 샘플링 모드 선택 (0:순차 샘플링 Sequence, 1:동시 샘플링 Simultaneous)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 시퀀스 모드 설정: 직렬 시퀀스 모드 (0:병렬 모드, 1:직렬 모드)
AdcRegs.ADCTRL1.bit.SUSMOD=0; // 시작점을 EPWM과 동기화
AdcRegs.ADCMAXCONV.all = 0x1; // ADC를 사용할 개수
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // ADC 순서 설정
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // ADC 순서 설정
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM_SOCA로 ADC 시퀀스 시동
EPwm3Regs.ETSEL.bit.SOCAEN = 1; // EPWM 3번에 동기화 신호 Enable
EPwm3Regs.ETSEL.bit.SOCASEL = 2; // SOCA의 동기화 시점을 PRD와 동일하게 설정
EPwm3Regs.ETPS.bit.SOCAPRD = 1; // SOCA의 동기화 횟수를 EPWM과 동일하게 설정
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Carrier 파형을 Up 으로 설정
EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBCTL.bit.CLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // (100MHz/100KHz)-1 = 999 𝑇_𝑃𝑊𝑀=2∗𝑇𝐵𝑃𝑅𝐷∗ 𝑇_𝑇𝐵𝐶𝐿𝐾
EPwm3Regs.TBCTR = 0x0000; // 초기 Counter Clear
// PIE의 ADC 인터럽트 활성화
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // PIE 인터럽트(ADCINT) 활성화
IER |= M_INT1; // CPU 인터럽트(INT1) 활성화
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
PieCtrlRegs.PIEIER2.bit.INTx2 = 1; // TZ int2
IER |= M_INT2; // CPU 인터럽트(INT1) 활성화
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
epwm1module();
epwm2module();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
// Enable CPU INT3 which is connected to EPWM1-3 INT:
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
IER |= M_INT3;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
BackTicker = 0;
for(;;)
{
BackTicker++;
}
}
// DC_DC
void epwm1module(void)
{
/* Setup Counter Mode and Clock */
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm1Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm1Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm1Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm1Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm1Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm1Regs.DBCTL.bit.IN_MODE = 0;
EPwm1Regs.DBCTL.bit.OUT_MODE = 0;
EPwm1Regs.DBCTL.bit.POLSEL = 0;
EPwm1Regs.DBFED = 1; // Falling Deadtime 설정
EPwm1Regs.DBRED = 1; // Rising Deadtime 설정
/* Set Interrupts */
EPwm1Regs.ETSEL.bit.INTSEL = 1; // EPWM 인터럽트 옵션 - CTR이 PRD일때 동기화
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event EPwm1Regs.
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 이벤트 트리거 Enable
EPwm1Regs.ETSEL.bit.SOCASEL = 2; // SCCA 트리거 조건 : 카운터 주기 일치 시 (읽는 시점이라고 생각하시면 됩니다)
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // SOCA 이벤트 분주 설정 : 트리거 조건 한번 마다 (샘플링을 EPWM주파수에 동기화를 시켰다고 보시면 됩니다.)
EALLOW;
EDIS;
}
void epwm2module()
{
/* Setup Counter Mode and Clock */
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm2Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm2Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm2Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm2Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm2Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm2Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm2Regs.DBCTL.bit.IN_MODE = 0;
EPwm2Regs.DBCTL.bit.OUT_MODE = 0;
EPwm2Regs.DBCTL.bit.POLSEL = 0;
EPwm2Regs.DBFED = 1; // Falling Deadtime 설정
EPwm2Regs.DBRED = 1; // Rising Deadtime 설정
}
interrupt void epwm1isr(void)
{
EPwm1IsrTicker++;
if (PwmDutyRatioA >= 0.8)
{
PwmDutyRatioA = 0.8;
}
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm2Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm1Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
interrupt void Adcisr(void)
{
if(AdcisrTicker==10)
{
AdcOffset = ((3.3 * (float32)(AdcRegs.ADCRESULT0)) / 4096); //Offset value before startup
}
AdcisrTicker++;
if (AdcisrTicker > 10000)
AdcisrTicker = 11;
Adc_Result = ((3.3 * (float32)(AdcRegs.ADCRESULT0) / 4096) - AdcOffset) * 10;
}
void voltageController(void) // Voltage Control Mode
{
////////////// Deadtime 설정 ///////////////
EPwm1Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm1Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm1Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
EPwm2Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm2Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm2Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
////////////// PI 제어기 설정 /////////////////
if(Adc_Result<4.0)
{
PwmDutyRatio=0.416;
return;
}
V_err=V_ref-Adc_Result;
Antierr=V_err-K_a1*(out_pi-out_sat);
Integerr +=K_i1*Antierr;
out_pi=Integerr + K_p1*V_err;
if(out_pi>0.8)
out_sat=0.8;
else if(out_pi<0.1)
out_sat=0.1;
else
out_sat=out_pi;
PwmDutyRatio=out_sat;
VoltageTicker++;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.CMPA.half.CMPA = (EPwm2Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
}
</code>
#include "DSP2833x_Device.h" /* DSP2833x Headerfile Include File */
#include "DSP2833x_Examples.h" /* DSP2833x Examples Include File */
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <math.h>
#define BUFFER_LENGTH 4096
#define CURRENT_SCALE_FACTOR 0.00054
#define VOLTAGE_SCALE_FACTOR 0.0405
#define VREF 3.3 //Reference voltage for the ADC
#define SYSTEM_CLOCK 200E6 // 200MHz
#define TBCLK 100E6 // 100MHz
#define PWM_CARRIER 100E3 // 100kHz
// Global variable for this example
Uint16 Sample1=0, Sample2=0; // 실제 Sensing이 된 ADC 변수
Uint16 ADC_cnt=0, ADC_cnt2=0, ADC_data0=0, ADC_data1=0, ADC_flag=0; // ADC Calibaraion를 위한 변수 설정
float32 I_osum=0., I_oavg=0.;
Uint16 Fil_cnt=0;
Uint16 I_Fil=0, I_inFil=0;
Uint16 Runflag=0, Trip_cnt=0; //여러 제어Mode 및 OpenLoop가 가능하도록 설정. Runflag 값을 변경하여 동작을 다음과 같이 설정 할 수 있다.
// 0 : 평상시(동작안함), 1 : 투스위치 Openloop Test,
// 2 : 투스위치 VoltageControl, 3 : 스위치 1개 Openloop Test, 4 : 디지털 제어
Uint16 EPwm1IsrTicker = 0;
Uint16 BackTicker;
Uint16 AdcisrTicker; // ADC 인터럽트 서비스 루틴 호출 횟수 계수(S/W카운터)
Uint16 VoltageTicker;
float32 Adc_Result;
float32 AdcOffset;
float64 V_o=0., offset_0=0., I_o=0., offset_1=0.; // ADC Calibaraion 및 출력전압 센싱값 변수 설정
float32 V_err=0., V_ref=0; // PI제어를 위한 오차 및 출력전압 Reference
float32 Kv_pi =0., V_pterm=0., V_iterm=0. ; // PI제어기의 P제어기 수행후 값(V_pterm),
float32 V_in_REF=0;
float32 Anti_Err=0;
float32 IntegV_err=0;
float32 Integerr=0;
float32 Antierr=0;
// I제어기 수행 후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p1=0, K_i1=0, K_a1=0; // Voltage Control의 게인
float32 Io_f=0., Vo_f=0.; // 전류 Filter 변수 설정
float32 test_value=0.;
float32 out_sat=0.0;
float32 out_pi=0.0;
float32 PwmDutyRatio;
float32 FallingEdgeDelay;
float32 RisingEdgeDelay;
float32 DBPer=0.0;
/*★*/
float32 I_err=0., I_ref=0.4; // PI제어를 위한 오차 및 입력 전류 Reference
float32 Ki_pi =0., I_pterm=0., I_iterm=0.; // PI제어기의 P제어기 수행후 값(V_pterm), I제어기 수행후 값 (V_iterm), 두 값을 더한 최종 출력값 (V_pi)
float32 K_p2=4.0, K_i2=100.0; // Current Control의 게인
float32 PwmDutyRatioA = 0.0;
////////////////////////////inverter
// Global variables used in inverter
void epwm1module(void); // epwm1module 함수 불러오기
void epwm2module(void); // epwm2module 함수 불러오기
void epwm3module(void); // epwm3module 함수 불러오기
interrupt void epwm1isr(void); // Interrupt 불러오기(epwm1isr)
interrupt void ADCIsr(void); //Interrupt ADC
void main(void)
{
InitSysCtrl();
InitEPwmGpio();
DINT;
InitPieCtrl();
// Disable CPU interrupts and clear all CPU interrupt flags:
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.EPWM1_INT = &epwm1isr; // PIE Vector Table 설정
PieVectTable.EPWM2_INT = &epwm1isr;
PieVectTable.EPWM3_INT = &epwm1isr;
PieVectTable.ADCINT = &epwm1isr;
PieVectTable.EPWM1_TZINT = &epwm1isr;
PieVectTable.EPWM2_TZINT = &epwm1isr;
EDIS;
InitAdc();
AdcRegs.ADCREFSEL.bit.REF_SEL = 0;
AdcRegs.ADCTRL3.bit.ADCCLKPS = 1; // ADCCLK = HSPCLK/(ADCCLKPS*2)/(CPS+1)
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.CPS = 0; // ADCCLK = 100MHz/(1*2)/(0+1) = 50MHz
// ADC 주기 설정 Code
AdcRegs.ADCTRL1.bit.ACQ_PS = 15; // 샘플/홀드 사이클 = ACQ_PS + 1 = 16 (ADCCLK기준)
AdcRegs.ADCTRL3.bit.SMODE_SEL = 0; // 샘플링 모드 선택 (0:순차 샘플링 Sequence, 1:동시 샘플링 Simultaneous)
AdcRegs.ADCTRL1.bit.SEQ_CASC = 1; // 시퀀스 모드 설정: 직렬 시퀀스 모드 (0:병렬 모드, 1:직렬 모드)
AdcRegs.ADCTRL1.bit.SUSMOD=0; // 시작점을 EPWM과 동기화
AdcRegs.ADCMAXCONV.all = 0x1; // ADC를 사용할 개수
AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // ADC 순서 설정
AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // ADC 순서 설정
AdcRegs.ADCTRL2.bit.EPWM_SOCA_SEQ1 = 1; // ePWM_SOCA로 ADC 시퀀스 시동
EPwm3Regs.ETSEL.bit.SOCAEN = 1; // EPWM 3번에 동기화 신호 Enable
EPwm3Regs.ETSEL.bit.SOCASEL = 2; // SOCA의 동기화 시점을 PRD와 동일하게 설정
EPwm3Regs.ETPS.bit.SOCAPRD = 1; // SOCA의 동기화 횟수를 EPWM과 동일하게 설정
EPwm3Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Carrier 파형을 Up 으로 설정
EPwm3Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBCTL.bit.CLKDIV = 0; // EPWM3번의 CLK 분주
EPwm3Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // (100MHz/100KHz)-1 = 999 𝑇_𝑃𝑊𝑀=2∗𝑇𝐵𝑃𝑅𝐷∗ 𝑇_𝑇𝐵𝐶𝐿𝐾
EPwm3Regs.TBCTR = 0x0000; // 초기 Counter Clear
// PIE의 ADC 인터럽트 활성화
PieCtrlRegs.PIEIER1.bit.INTx6 = 1; // PIE 인터럽트(ADCINT) 활성화
IER |= M_INT1; // CPU 인터럽트(INT1) 활성화
PieCtrlRegs.PIEIER2.bit.INTx1 = 1;
PieCtrlRegs.PIEIER2.bit.INTx2 = 1; // TZ int2
IER |= M_INT2; // CPU 인터럽트(INT1) 활성화
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
EDIS;
epwm1module();
epwm2module();
EALLOW;
SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 1;
EDIS;
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
// Enable CPU INT3 which is connected to EPWM1-3 INT:
PieCtrlRegs.PIEIER3.bit.INTx1 = 1;
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;
PieCtrlRegs.PIEIER3.bit.INTx3 = 1;
IER |= M_INT3;
// Enable global Interrupts and higher priority real-time debug events:
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
BackTicker = 0;
for(;;)
{
BackTicker++;
}
}
// DC_DC
void epwm1module(void)
{
/* Setup Counter Mode and Clock */
EPwm1Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm1Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm1Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm1Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm1Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm1Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm1Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm1Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm1Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm1Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm1Regs.DBCTL.bit.IN_MODE = 0;
EPwm1Regs.DBCTL.bit.OUT_MODE = 0;
EPwm1Regs.DBCTL.bit.POLSEL = 0;
EPwm1Regs.DBFED = 1; // Falling Deadtime 설정
EPwm1Regs.DBRED = 1; // Rising Deadtime 설정
/* Set Interrupts */
EPwm1Regs.ETSEL.bit.INTSEL = 1; // EPWM 인터럽트 옵션 - CTR이 PRD일때 동기화
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_1ST; // Generate INT on 1st event EPwm1Regs.
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // SOCA 이벤트 트리거 Enable
EPwm1Regs.ETSEL.bit.SOCASEL = 2; // SCCA 트리거 조건 : 카운터 주기 일치 시 (읽는 시점이라고 생각하시면 됩니다)
EPwm1Regs.ETPS.bit.SOCAPRD = 1; // SOCA 이벤트 분주 설정 : 트리거 조건 한번 마다 (샘플링을 EPWM주파수에 동기화를 시켰다고 보시면 됩니다.)
EALLOW;
EDIS;
}
void epwm2module()
{
/* Setup Counter Mode and Clock */
EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count 방식 설정 (Up방식으로)
EPwm2Regs.TBCTL.bit.HSPCLKDIV = 0; // EPWM Clock 설정
EPwm2Regs.TBCTL.bit.CLKDIV = 0; // EPWM Clock 설정
/* Setup Phase */
EPwm2Regs.TBPHS.half.TBPHS = 0; // 위상을 얼만큼 이동시키는지 설정
EPwm2Regs.TBCTL.bit.PHSEN = 0; // 위상을 이동 시킬지 말지를 결정 (0:Disable , 1:Enable)
// Setup Period (Carrier Frequency)
EPwm2Regs.TBPRD = (TBCLK/PWM_CARRIER)-1; // Set Timer Period, (100MHz/100KHz)-1 = 999
EPwm2Regs.TBCTR = 0; // Clear Counter
/* Set Compare Value */
EPwm2Regs.CMPA.half.CMPA = 0; // 비교기의 +레퍼런스 설정 (초기조건 - 0으로 설정)
/* Setup shadowing */
EPwm2Regs.TBCTL.bit.PRDLD = TB_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // 원신호를 보호해주는 Shadow 레지스터 설정
EPwm2Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; // Shadow 레지스터에서 로드하는 시점을 설정
EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // 동기화 시점을 설정 (카운터가 Zero일 경우 동기화), 위상을 사용하지 않아 크게 의미가 없는 코드
/* Set actions */
EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.AQCTLA.bit.ZRO=AQ_SET; // Carrier가 zero일때 high신호로
/* Set Dead-time */
EPwm2Regs.DBCTL.bit.IN_MODE = 0;
EPwm2Regs.DBCTL.bit.OUT_MODE = 0;
EPwm2Regs.DBCTL.bit.POLSEL = 0;
EPwm2Regs.DBFED = 1; // Falling Deadtime 설정
EPwm2Regs.DBRED = 1; // Rising Deadtime 설정
}
interrupt void epwm1isr(void)
{
EPwm1IsrTicker++;
if (PwmDutyRatioA >= 0.8)
{
PwmDutyRatioA = 0.8;
}
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm2Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA;
EPwm1Regs.ETCLR.bit.INT = 1;
PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
}
interrupt void Adcisr(void)
{
if(AdcisrTicker==10)
{
AdcOffset = ((3.3 * (float32)(AdcRegs.ADCRESULT0)) / 4096); //Offset value before startup
}
AdcisrTicker++;
if (AdcisrTicker > 10000)
AdcisrTicker = 11;
Adc_Result = ((3.3 * (float32)(AdcRegs.ADCRESULT0) / 4096) - AdcOffset) * 10;
}
void voltageController(void) // Voltage Control Mode
{
////////////// Deadtime 설정 ///////////////
EPwm1Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm1Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm1Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
EPwm2Regs.DBCTL.bit.IN_MODE = 0; // EPWMxA is the source for both falling-edge & rising-edge delay
EPwm2Regs.DBCTL.bit.OUT_MODE = 3; // Dead-band is fully enabled for both rising-edge delay on EPWMxA and falling-edge delay on EPWMxB
EPwm2Regs.DBCTL.bit.POLSEL = 2; // Active High Complementary (AHC). EPWMxB is inverted
////////////// PI 제어기 설정 /////////////////
if(Adc_Result<4.0)
{
PwmDutyRatio=0.416;
return;
}
V_err=V_ref-Adc_Result;
Antierr=V_err-K_a1*(out_pi-out_sat);
Integerr +=K_i1*Antierr;
out_pi=Integerr + K_p1*V_err;
if(out_pi>0.8)
out_sat=0.8;
else if(out_pi<0.1)
out_sat=0.1;
else
out_sat=out_pi;
PwmDutyRatio=out_sat;
VoltageTicker++;
EPwm1Regs.AQCTLA.bit.CAU = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm1Regs.AQCTLA.bit.ZRO = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm1Regs.CMPA.half.CMPA = (EPwm1Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
EPwm2Regs.AQCTLA.bit.CAU = AQ_SET; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 High신호로
EPwm2Regs.AQCTLA.bit.CAD = AQ_CLEAR; // Carrier가 올라가면서 레퍼런스와 만나는 지점에서 Low신호로
EPwm2Regs.CMPA.half.CMPA = (EPwm2Regs.TBPRD + 1) * PwmDutyRatioA; // 비교기와 최종 레퍼런스 비교
}
can realize PI control, voltage control mode, and can output the control result on the SC450 control board.
New contributor
Xingyi Li is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.