Tool/software: Code Composer Studio
I just want to build a hysteresis controller for a single phase inverter. I use the signal generation module to produce a 80Hz 1amplitude sin signal as the current reference signal. I use ADC to read from LEM to measure the actual current signal . These two signal will produce a error signal and used to compare with up and down band . This will produce a complementary PWM combinations. Here is the question, i do able to produce the complementary PWM signals. LEM is well calibrated as well as ADC. I use a RL load and use the phase 2 and phase 3. The code seems to be everything fine and each part is well debugged and tested seperately. However, when i apply the DC-link voltage by a variable DC source, i use 2A, 20V, there is no current flow through. I don't know why, the code is given below, could anyone can have a look and give me some suggestions? I just want to use the software forced without comparator, this gonna to be next stage.
// Combined ADC and signal generation code for error identificaiton (used for the complementary PWM)
//
// ADC:
// ADC A2 SOC0----> LEM V ------> AdcResultsa1
// ADC B0 SOC0----> Vfb-bus ------> AdcResultsb1
//
// EPWM:
// EPWM4A---> 20kHz SOCA LEM and DC_link ADC
// PWM2A ---> PWMvH
// PWM2B ---> PWMvL
// PWM3A ---> PWMwH
// PWM3B ---> PWMwL
//
// ###################################################################################
//
// Included files
//
#include "F28x_Project.h"
#include "IQmathLib.h" // IQ math
#include <sgen.h> // signal generation (16bit)
//
// Function prototypes
//
void SignalGeneration(void); //
void ConfigureEPWM(void); //
void ConfigureADC(void); //
void SetupADCEPWM(void); //
interrupt void adca1_isr(void); //
interrupt void adcb1_isr(void); //
//
// Signal generation (current reference)
//
SGENT_1 sgen = SGENT_1_DEFAULTS; //
float32 SG_FINAL;//
//
// ADCa1-LEM phase u
//
float32 AdcResultsa1; //
#define ADC_OFFSET 1.65; //
#define ADC_SCALE 3/4096; //
#define ADC_GAIN 10.2852; // 10.2852 for the AC 7.2727 for the DC
float32 Adca1_ONE;
float32 Adca1_SECOND; //
volatile float32 Adca1_final; //
//
// complementary PWM calculation process
//
Uint32 SIGN;
float32 ERROR; //
//
// ADC-b0 for the DC-link voltage
//
float32 AdcResultsb1; //
//
// main code
//
void main(void)
{
// Step 1. Initialize system control
// disable the watchdog systemclock 200MHz
////////////////////////////////////////////////////////////////////////////////////
InitSysCtrl();
//
// Step 2. Initialize system GPIOs
///////////////////////////////////////////////////////////////////////////////////
InitGpio(); //
InitEPwm2Gpio();// initialize EPWM4 GPIO 2 3 4, pull-up and mux
InitEPwm3Gpio();
InitEPwm4Gpio();
//
// Step 3. Clear all interrupts, initialize PIE vector table and system interrupts
//////////////////////////////////////////////////////////////////////////////////////////
DINT; // disable all the interrupts
InitPieCtrl();
IER=0x0000;//
IFR=0x0000; //
InitPieVectTable(); //
IER |=M_INT1; // enable group 1 interrupts
EINT; // enable global interrupt INTM
ERTM; //
EALLOW; //
PieVectTable.ADCA1_INT=&adca1_isr; // function for the ADCA interrupt 1
PieVectTable.ADCB1_INT=&adcb1_isr; // function for the ADCA interrupt 2
EDIS; //
PieCtrlRegs.PIEIER1.bit.INTx1=1; // ADCA1 interrupt
PieCtrlRegs.PIEIER1.bit.INTx2=1; // ADCB1 interrupt
// Step 4. Signal generation module configuration
//////////////////////////////////////////////////////////////////////////////////////
SignalGeneration();
// Step 5. PWM configuration
////////////////////////////////////////////////////////////////////////////////////////
EALLOW; //
CpuSysRegs.PCLKCR2.bit.EPWM2=1; // enable EPWM2 3 4 clock
CpuSysRegs.PCLKCR2.bit.EPWM3=1;
CpuSysRegs.PCLKCR2.bit.EPWM4=1;
EDIS; //
EALLOW;//
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=0; //
EDIS; //
ConfigureEPWM();
EALLOW;//
CpuSysRegs.PCLKCR0.bit.TBCLKSYNC=1; //
EDIS; //
// step 6. ADC configurations
/////////////////////////////////////////////////////////////////////////////////////////
ConfigureADC();
SetupADCEPWM();
// step 7. Parameter initialization
//////////////////////////////////////////////////////////////////////////////////////////
SIGN=0; //
//
// main code
//
while(1)
{
static float32 ERROR_P= 0.3; // 0.3A
static float32 ERROR_N=-0.3; //-0.3A
static float32 CURRENT_P=3; // 3A limitation
static float32 CURRENT_L=-3; //-3A limitation
//
// signal generation module
//
sgen.calc(&sgen);
SG_FINAL =_IQ15toF(sgen.out); // convert IQ15 number to float number
ERROR= SG_FINAL - Adca1_final;
if (ERROR > ERROR_P)
{
SIGN=1;
EPwm2Regs.AQCSFRC.bit.CSFA=2; // EPWM2A set high
EPwm2Regs.AQCSFRC.bit.CSFB=1; // EPWM2B set low
EPwm3Regs.AQCSFRC.bit.CSFA=1; // EPWM3A set low
EPwm3Regs.AQCSFRC.bit.CSFB=2; // EPWM3B set high
}
else if (ERROR < ERROR_N)
{
SIGN=2;
EPwm2Regs.AQCSFRC.bit.CSFA=1; // EPWM2A set low
EPwm2Regs.AQCSFRC.bit.CSFB=2; // EPWM2B set high
EPwm3Regs.AQCSFRC.bit.CSFA=2; // EPWM3A set high
EPwm3Regs.AQCSFRC.bit.CSFB=1; // EPWM3B set low
}
else if (Adca1_final > CURRENT_P || Adca1_final < CURRENT_L)
{
SIGN=3;
EPwm2Regs.AQCSFRC.bit.CSFA=1; // continuously low 2A
EPwm2Regs.AQCSFRC.bit.CSFB=1; // continuously low 2B
EPwm3Regs.AQCSFRC.bit.CSFA=1; // continuously low 3A
EPwm3Regs.AQCSFRC.bit.CSFB=1; // continuously low 3B
}
}
}
//
// signal generation function prototype
//
void SignalGeneration(void)
{
sgen.freq=8590; // 80Hz signal
sgen.step_max=1000; // Max Freq= 302.57 Hz
sgen.alpha=0; // no phase shift
sgen.gain=0x7fff; // gain=1 in Q15
sgen.offset=0; // No dc offset
}
//
// EPWM function prototype
//
void ConfigureEPWM(void)
{
EALLOW;
//
// EPWM2 for the phase v
//
EPwm2Regs.TBCTL.bit.HSPCLKDIV=0; // divide by 1
EPwm2Regs.TBCTL.bit.CLKDIV=0; // divide by 1
EPwm2Regs.AQSFRC.bit.RLDCSF=3; // load immediately with software forced
//
// EPWM2 dead band
//
EPwm2Regs.DBCTL.bit.OUT_MODE=3; // DBM is fully enabled
EPwm2Regs.DBCTL.bit.POLSEL=2; // Active high complementary
EPwm2Regs.DBCTL.bit.IN_MODE=0; // EPWMA is the source for both falling edge and rising edge delay
EPwm2Regs.DBRED.bit.DBRED=200; // deadtime 2us
EPwm2Regs.DBFED.bit.DBFED=200; // deadtime 2us
//
// EPWM3 for the phase w
//
EPwm3Regs.TBCTL.bit.HSPCLKDIV=0; // divide by 1
EPwm3Regs.TBCTL.bit.CLKDIV=0; // divide by 1
EPwm3Regs.AQSFRC.bit.RLDCSF=3; // load immediately with software forced
//
// EPWM3 dead band
//
EPwm3Regs.DBCTL.bit.OUT_MODE=3; // DBM is fully enabled
EPwm3Regs.DBCTL.bit.POLSEL=2; // Active high complementary
EPwm3Regs.DBCTL.bit.IN_MODE=0; // EPWMA is the source for both falling edge and rising edge delay
EPwm3Regs.DBRED.bit.DBRED=200; // deadtime 2us
EPwm3Regs.DBFED.bit.DBFED=200; // deadtime 2us
//
// EPWM4 used for LEM and DC_link
//
EPwm4Regs.ETSEL.bit.SOCAEN=1; //Enable the ADC SOCA pulse
EPwm4Regs.ETSEL.bit.SOCASEL=2; //Enable SOCA when event counter equal to period
EPwm4Regs.ETPS.bit.SOCAPRD=1; // generate SOCA pulse on the first event
EPwm4Regs.TBCTL.bit.HSPCLKDIV=0; // divide by 1
EPwm4Regs.TBCTL.bit.CLKDIV=0; // divide by 1
EPwm4Regs.TBPRD=5000; // EPWMCLK 100MHz 20KHz period EPWM
EPwm4Regs.TBCTL.bit.CTRMODE=0; // up count mode
EDIS;
}
//
// ADC configuration funciton prototype
//
void ConfigureADC(void)
{
EALLOW;
//
// Adca
//
AdcaRegs.ADCCTL2.bit.PRESCALE=6; // 200MHz/4=50MHz ADCCLK
AdcSetMode(ADC_ADCA, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //
AdcaRegs.ADCCTL1.bit.INTPULSEPOS=1; //interrupt pulse generation occurs at end of conversion
AdcaRegs.ADCCTL1.bit.ADCPWDNZ=1; // power up ADC
//
// Adcb
//
AdcbRegs.ADCCTL2.bit.PRESCALE=6; // 200MHz/4=50MHz ADCCLK
AdcSetMode(ADC_ADCB, ADC_RESOLUTION_12BIT, ADC_SIGNALMODE_SINGLE); //
AdcbRegs.ADCCTL1.bit.INTPULSEPOS=1; //
AdcbRegs.ADCCTL1.bit.ADCPWDNZ=1;
DELAY_US(1000); // delay for 1ms to allow ADC time to power up
EDIS;
}
void SetupADCEPWM(void)
{
EALLOW;
//
// LEM Adca SOC0
//
AdcaRegs.ADCSOC0CTL.bit.CHSEL=2; // SOC0 for ADCA will convert pin A2 (LEM)
AdcaRegs.ADCSOC0CTL.bit.ACQPS=14; // 75ns sampling charging time
AdcaRegs.ADCSOC0CTL.bit.TRIGSEL=11; //trigger on ePWM4 SOCA
AdcaRegs.ADCINTSEL1N2.bit.INT1SEL=0; // end of SOC0 will set INT1 flag
AdcaRegs.ADCINTSEL1N2.bit.INT1E=1; // ADCAINT1 interrupt enabled
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1=1; // INT1 flag is cleared
//
// DC-link voltage Adcb SOC0
//
AdcbRegs.ADCSOC0CTL.bit.CHSEL=0; // SOC0 for ADCB will convert pin B0 (DC-link)
AdcbRegs.ADCSOC0CTL.bit.ACQPS=14; // 75ns sampling charging time
AdcbRegs.ADCSOC0CTL.bit.TRIGSEL=11; //trigger on ePWM4 SOCA
AdcbRegs.ADCINTSEL1N2.bit.INT1SEL=0; // end of SOC0 will set INT1 flag
AdcbRegs.ADCINTSEL1N2.bit.INT1E=1; // ADCbINT1 interrupt enabled
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1=1; // INT1 flag is cleared
EDIS;
}
//
// Adca1 interrupt LEM result
//
interrupt void adca1_isr(void)
{
AdcResultsa1=(_iq12)AdcaResultRegs.ADCRESULT0;
Adca1_ONE=AdcResultsa1 *ADC_SCALE;
Adca1_SECOND= Adca1_ONE - ADC_OFFSET;
Adca1_final = Adca1_SECOND* ADC_GAIN;
AdcaRegs.ADCINTFLGCLR.bit.ADCINT1=1; // INT1 flag is cleared
PieCtrlRegs.PIEACK.all= PIEACK_GROUP1;
}
//
// Adcb1 interrupt DC_link voltage result
//
interrupt void adcb1_isr(void)
{
AdcResultsb1=AdcbResultRegs.ADCRESULT0; // 16 bit ADC result
AdcbRegs.ADCINTFLGCLR.bit.ADCINT1=1; // INT1 flag is cleared
PieCtrlRegs.PIEACK.all= PIEACK_GROUP1;
}