Other Parts Discussed in Thread: CONTROLSUITE, TIDM-HV-1PH-DCAC
I am attempting to synchronize EPWM1-3 for a three-phase 208V inverter application. I followed the example code provided in ControlSuite (VSI - 1phase HP DC/AC), a modified the EPWM setup scripts. However, when I think I setup the EPWM IAW Chapter 14 of spruhm8g.pdf, I see a 20 ns delay in EPWM 2 and 3 from EPWM 1 (scope plot shown below, and option 1 in code snippet). Is this considered synchronized? If not, did I not setup the EPWM registers correctly?
Also, when I setup the register in an alternative form (option 2 in code snippet), similar to that provided in the f803xPWM.h file that accompanies the three-phase motor control kit, I can get the three PWM pulses to line up exactly, but it doesn't appear to be IAW with the f28337xD documentation.
Both cases give the correct output duty cycle and frequency. Any insight is appreciated.
void setup3PPWM(uint16_t inv_pwm_no, uint16_t pwm_period_ticks, uint16_t pwm_dbred_ticks, uint16_t pwm_dbfed_ticks)
{
EALLOW;
// PWM clock on F2837x is divided by 2
// ClkCfgRegs.PERCLKDIVSEL.bit.EPWMCLKDIV = 1
////////////////////////////////////////////
// Time Base SubModule Registers
////////////////////////////////////////////
(*ePWM[inv_pwm_no]).TBCTL.bit.PRDLD = TB_SHADOW;
(*ePWM[inv_pwm_no]).TBPRD = pwm_period_ticks >>1; // PWM frequency = 1 / period
(*ePWM[inv_pwm_no]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no]).TBCTR = 0;
(*ePWM[inv_pwm_no]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
(*ePWM[inv_pwm_no]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
(*ePWM[inv_pwm_no]).TBCTL.bit.CLKDIV = TB_DIV1;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.PRDLD = TB_SHADOW;
(*ePWM[inv_pwm_no+1]).TBPRD = pwm_period_ticks >>1; // PWM frequency = 1 / period
(*ePWM[inv_pwm_no+1]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no+1]).TBCTR = 0;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.CLKDIV = TB_DIV1;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.PRDLD = TB_SHADOW;
(*ePWM[inv_pwm_no+2]).TBPRD = pwm_period_ticks >>1; // PWM frequency = 1 / period
(*ePWM[inv_pwm_no+2]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no+2]).TBCTR = 0;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.HSPCLKDIV = TB_DIV1;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.CLKDIV = TB_DIV1;
//Option 1 - Similar to TI documentation for f28377D
(*ePWM[inv_pwm_no]).TBCTL.bit.PHSEN = TB_DISABLE;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.PHSEN = TB_ENABLE;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.PHSEN = TB_ENABLE;
// configure PWM 2 and 3 as slaves and let it pass the sync in pulse from PWM1
(*ePWM[inv_pwm_no]).TBCTL.bit.SYNCOSEL = TB_CTR_ZERO; // sync "down-stream" - like example document, but gives phase delay on scope
(*ePWM[inv_pwm_no+1]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // - like example document, but gives phase delay on scope
(*ePWM[inv_pwm_no+2]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // - like example document, but gives phase delay on scope
//Option 2 - similar to f2803xPWM.h with 3-phase motor control kit
//(*ePWM[inv_pwm_no]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // all set equal - pass through - this is how motor controller did it
//(*ePWM[inv_pwm_no+1]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // all set equal - pass through - this is how motor controller did it
//(*ePWM[inv_pwm_no+2]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN; // all set equal - pass through - this is how motor controller did it
//(*ePWM[inv_pwm_no]).TBCTL.bit.PHSEN = TB_DISABLE;
//(*ePWM[inv_pwm_no+1]).TBCTL.bit.PHSEN = TB_DISABLE;
//(*ePWM[inv_pwm_no+2]).TBCTL.bit.PHSEN = TB_DISABLE;
(*ePWM[inv_pwm_no]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no+1]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no+2]).TBPHS.bit.TBPHS = 0;
(*ePWM[inv_pwm_no]).TBCTL.bit.PHSDIR = TB_UP;
(*ePWM[inv_pwm_no+1]).TBCTL.bit.PHSDIR = TB_UP;
(*ePWM[inv_pwm_no+2]).TBCTL.bit.PHSDIR = TB_UP;
////////////////////////////////////////////
// Counter Compare Submodule Registers
////////////////////////////////////////////
(*ePWM[inv_pwm_no]).CMPA.bit.CMPA = 0; // set duty 0% initially
(*ePWM[inv_pwm_no]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
(*ePWM[inv_pwm_no]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD; //TLB Sample twice?
(*ePWM[inv_pwm_no+1]).CMPA.bit.CMPA = 0; // set duty 0% initially
(*ePWM[inv_pwm_no+1]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
(*ePWM[inv_pwm_no+1]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
(*ePWM[inv_pwm_no+2]).CMPA.bit.CMPA = 0; // set duty 0% initially
(*ePWM[inv_pwm_no+2]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;
(*ePWM[inv_pwm_no+2]).CMPCTL.bit.LOADAMODE = CC_CTR_ZERO_PRD;
////////////////////////////////////////////
// Action Qualifier SubModule Registers
////////////////////////////////////////////
(*ePWM[inv_pwm_no]).AQCTLA.bit.CAU = AQ_CLEAR; // CTR = CMPA@UP , turn B on (GND out)
(*ePWM[inv_pwm_no]).AQCTLA.bit.CAD = AQ_SET; // CTR = CMPA@Down , turn B off (V out)
(*ePWM[inv_pwm_no+1]).AQCTLA.bit.CAU = AQ_CLEAR; // CTR = CMPA@UP , turn B on (GND out)
(*ePWM[inv_pwm_no+1]).AQCTLA.bit.CAD = AQ_SET; // CTR = CMPA@Down , turn B off (V out)
(*ePWM[inv_pwm_no+2]).AQCTLA.bit.CAU = AQ_CLEAR; // CTR = CMPA@UP , turn B on (GND out)
(*ePWM[inv_pwm_no+2]).AQCTLA.bit.CAD = AQ_SET; // CTR = CMPA@Down , turn B off (V out)
// to start don't configure the PWM to do anything
//(*ePWM[inv_pwm_no]).AQCTLA.all = 0;
//(*ePWM[inv_pwm_no+1]).AQCTLA.all = 0;
//(*ePWM[inv_pwm_no+2]).AQCTLA.all = 0;
////////////////////////////////////////////
// Active high complementary PWMs - Set up the deadband
////////////////////////////////////////////
(*ePWM[inv_pwm_no]).DBCTL.bit.IN_MODE = DBA_ALL;
(*ePWM[inv_pwm_no]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
(*ePWM[inv_pwm_no]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
(*ePWM[inv_pwm_no]).DBRED = pwm_dbred_ticks;
(*ePWM[inv_pwm_no]).DBFED = pwm_dbred_ticks;
(*ePWM[inv_pwm_no+1]).DBCTL.bit.IN_MODE = DBA_ALL;
(*ePWM[inv_pwm_no+1]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
(*ePWM[inv_pwm_no+1]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
(*ePWM[inv_pwm_no+1]).DBRED = pwm_dbred_ticks;
(*ePWM[inv_pwm_no+1]).DBFED = pwm_dbred_ticks;
(*ePWM[inv_pwm_no+2]).DBCTL.bit.IN_MODE = DBA_ALL;
(*ePWM[inv_pwm_no+2]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
(*ePWM[inv_pwm_no+2]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
(*ePWM[inv_pwm_no+2]).DBRED = pwm_dbred_ticks;
(*ePWM[inv_pwm_no+2]).DBFED = pwm_dbred_ticks;
EDIS;
}