This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

CCS/TMS320F28075: c2000 Simultaneous generation of PWM

Part Number: TMS320F28075

Tool/software: Code Composer Studio

hello All,

i am new to TI- Piccolo 32 bit Controller. I am using this for a Power Electronics control application.

here in i need to generate precise PWM signals to control a ZVS fullbride rectifier. the requirement is to generate 4 signals (PWM2A, PWM2B, PWM6A, PWM6B). PWM2B and PWM6B are complimentary signals of PWM2A and PWM6A respectively.

i have done the following code for the same:

void PWMHandler_s_vdPWM_TURN_ON(void)
{

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    PWM_Handler_init();


    PWM_Handler_config(2,PWM_BASE_FREQ_MICROSEC);
    PWM_Handler_config(6,PWM_BASE_FREQ_MICROSEC);

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1u;
    EDIS;
}

void PWM_Handler_config(Uint16 u16ChannelID, Uint16 u16Period)
{

    Uint16 PWM_TBPRD;

    (*ePWM[u16ChannelID]).TBCTL.bit.PRDLD = (Uint16)TB_SHADOW;
    PWM_TBPRD = (Uint16)((u16Period * (float)(TB_CLOCK/2)));

    (*ePWM[u16ChannelID]).TBPRD = PWM_TBPRD;
    (*ePWM[u16ChannelID]).TBCTL.bit.CTRMODE = (Uint16)TB_COUNT_UPDOWN;
    (*ePWM[u16ChannelID]).TBCTL.bit.HSPCLKDIV = (Uint16)TB_DIV1;
    (*ePWM[u16ChannelID]).TBCTL.bit.CLKDIV = (Uint16)TB_DIV1;

    /* To ensure that the PWM continues to run in software halt*/
    (*ePWM[u16ChannelID]).TBCTL.bit.FREE_SOFT = 2u;

       (*ePWM[u16ChannelID]).TBCTL.bit.PHSEN = (Uint16)TB_ENABLE;
       (*ePWM[u16ChannelID]).TBCTL.bit.SYNCOSEL = (Uint16)TB_SYNC_IN;

    //////////////////////////////////////////////////////////////////////
    (*ePWM[u16ChannelID]).ETSEL.bit.SOCAEN = 1u;
    (*ePWM[u16ChannelID]).ETPS.bit.SOCPSSEL = 1u;
    (*ePWM[u16ChannelID]).ETSOCPS.bit.SOCAPRD2 = 5u;

    ////////////////////////////////////////////////////////////////////////////

    /* PWM2 */
    if(2 == u16ChannelID){

            /* For Output A */
            EPwm2Regs.AQCTLA.bit.CAU = (Uint16)AQ_SET;        
            EPwm2Regs.AQCTLA.bit.CBU = (Uint16)AQ_NO_ACTION;    
            EPwm2Regs.AQCTLA.bit.CBD = (Uint16)AQ_CLEAR;        
            EPwm2Regs.AQCTLA.bit.CAD = (Uint16)AQ_NO_ACTION;    
            EPwm2Regs.CMPCTL.bit.SHDWAMODE = (Uint16)CC_SHADOW;        

            /* For Output B */
            EPwm2Regs.AQCTLB.bit.CAU = (Uint16)AQ_CLEAR;        
            EPwm2Regs.AQCTLB.bit.CBU = (Uint16)AQ_NO_ACTION;
            EPwm2Regs.AQCTLB.bit.CBD = (Uint16)AQ_SET;
            EPwm2Regs.AQCTLB.bit.CAD = (Uint16)AQ_NO_ACTION;
            EPwm2Regs.CMPCTL.bit.SHDWBMODE = (Uint16)CC_SHADOW;
        }
      

        /* PWM6 */
        if(6 == u16ChannelID){

            /* For Output A */
            EPwm6Regs.AQCTLA.bit.CAU = (Uint16)AQ_NO_ACTION;            
            EPwm6Regs.AQCTLA.bit.CBU = (Uint16)AQ_SET;        
            EPwm6Regs.AQCTLA.bit.CBD = (Uint16)AQ_NO_ACTION;            
            EPwm6Regs.AQCTLA.bit.CAD = (Uint16)AQ_CLEAR;        
            EPwm6Regs.CMPCTL.bit.SHDWAMODE = (Uint16)CC_SHADOW;        

            /* For Output B */
            EPwm6Regs.AQCTLB.bit.CAU = (Uint16)AQ_NO_ACTION;
            EPwm6Regs.AQCTLB.bit.CBU = (Uint16)AQ_CLEAR;
            EPwm6Regs.AQCTLB.bit.CBD = (Uint16)AQ_NO_ACTION;
            EPwm6Regs.AQCTLB.bit.CAD = (Uint16)AQ_SET;
            EPwm6Regs.CMPCTL.bit.SHDWBMODE = (Uint16)CC_SHADOW;
    }


    /* DEAD BAND INSERTION */
    (*ePWM[u16ChannelID]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    (*ePWM[u16ChannelID]).DBCTL.bit.POLSEL = DB_ACTV_HIC;
    (*ePWM[u16ChannelID]).DBCTL.bit.IN_MODE = DBA_ALL;
    (*ePWM[u16ChannelID]).DBRED.bit.DBRED = 200u;
    (*ePWM[u16ChannelID]).DBFED.bit.DBFED = 200u;


}

with this i am able to generate the required PWMs with a required dead bands between the complimentary signals. my issue is when the PWM signals start. i was hoping that all the signals would start simultaneously but i see a delay(~100ms) in the strating of Signal PWM6A and PWM6B..what i observe is that PWM2A and PWM2B starts together. Along with this the Signal PWM6B goes to high (i presume because of the dead band), but doesn't toggle for another 100ms. please find the screenshot from oscilloscope:

since i am controlling power equipment at higher voltage with these PWM's such a behavior is causing a lot of issues (high inrush etc.) at startup... can anyone please tell me what am i doing wrong here???

thanks in advance for your support,

regards

Nishant

  • hello All,

    these is small mistake in above code.. please refer to this code:

    void PWMHandler_s_vdPWM_TURN_ON(void)

    {

       EALLOW;

       CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 0;

       EDIS;

       PWM_Handler_init();

       PWM_Handler_config(1,PWM_BASE_FREQ_MICROSEC);

       PWM_Handler_config(2,PWM_BASE_FREQ_MICROSEC);

       PWM_Handler_config(6,PWM_BASE_FREQ_MICROSEC);

       EALLOW;

       CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1u;

       EDIS;

    }

    void PWM_Handler_config(Uint16 u16ChannelID, Uint16 u16Period)

    {

       Uint16 PWM_TBPRD;

       (*ePWM[u16ChannelID]).TBCTL.bit.PRDLD = (Uint16)TB_SHADOW;

       PWM_TBPRD = (Uint16)((u16Period * (float)(TB_CLOCK/2)));

       (*ePWM[u16ChannelID]).TBPRD = PWM_TBPRD;

       (*ePWM[u16ChannelID]).TBCTL.bit.CTRMODE = (Uint16)TB_COUNT_UPDOWN;

       (*ePWM[u16ChannelID]).TBCTL.bit.HSPCLKDIV = (Uint16)TB_DIV1;

       (*ePWM[u16ChannelID]).TBCTL.bit.CLKDIV = (Uint16)TB_DIV1;

       /* To ensure that the PWM continues to run in software halt*/

       (*ePWM[u16ChannelID]).TBCTL.bit.FREE_SOFT = 2u;

          if(1 == u16ChannelID)

          {

                (*ePWM[u16ChannelID]).TBCTL.bit.PHSEN = (Uint16)TB_DISABLE;

                (*ePWM[u16ChannelID]).TBCTL.bit.SYNCOSEL = (Uint16)TB_CTR_ZERO;

          }

          else

          {

                (*ePWM[u16ChannelID]).TBCTL.bit.PHSEN = (Uint16)TB_ENABLE;

                (*ePWM[u16ChannelID]).TBCTL.bit.SYNCOSEL = (Uint16)TB_SYNC_IN;

          }

       //////////////////////////////////////////////////////////////////////

       (*ePWM[u16ChannelID]).ETSEL.bit.SOCAEN = 1u;

       (*ePWM[u16ChannelID]).ETPS.bit.SOCPSSEL = 1u;

       (*ePWM[u16ChannelID]).ETSOCPS.bit.SOCAPRD2 = 5u;

       ////////////////////////////////////////////////////////////////////////////

       /* PWM2 */

       if(2 == u16ChannelID){

               /* For Output A */

               EPwm2Regs.AQCTLA.bit.CAU = (Uint16)AQ_SET;        

               EPwm2Regs.AQCTLA.bit.CBU = (Uint16)AQ_NO_ACTION;    

               EPwm2Regs.AQCTLA.bit.CBD = (Uint16)AQ_CLEAR;        

               EPwm2Regs.AQCTLA.bit.CAD = (Uint16)AQ_NO_ACTION;    

               EPwm2Regs.CMPCTL.bit.SHDWAMODE = (Uint16)CC_SHADOW;        

               /* For Output B */

               EPwm2Regs.AQCTLB.bit.CAU = (Uint16)AQ_CLEAR;        

               EPwm2Regs.AQCTLB.bit.CBU = (Uint16)AQ_NO_ACTION;

               EPwm2Regs.AQCTLB.bit.CBD = (Uint16)AQ_SET;

               EPwm2Regs.AQCTLB.bit.CAD = (Uint16)AQ_NO_ACTION;

               EPwm2Regs.CMPCTL.bit.SHDWBMODE = (Uint16)CC_SHADOW;

           }

           /* PWM6 */

           if(6 == u16ChannelID){

               /* For Output A */

               EPwm6Regs.AQCTLA.bit.CAU = (Uint16)AQ_NO_ACTION;            

               EPwm6Regs.AQCTLA.bit.CBU = (Uint16)AQ_SET;        

               EPwm6Regs.AQCTLA.bit.CBD = (Uint16)AQ_NO_ACTION;            

               EPwm6Regs.AQCTLA.bit.CAD = (Uint16)AQ_CLEAR;        

               EPwm6Regs.CMPCTL.bit.SHDWAMODE = (Uint16)CC_SHADOW;        

               /* For Output B */

               EPwm6Regs.AQCTLB.bit.CAU = (Uint16)AQ_NO_ACTION;

               EPwm6Regs.AQCTLB.bit.CBU = (Uint16)AQ_CLEAR;

               EPwm6Regs.AQCTLB.bit.CBD = (Uint16)AQ_NO_ACTION;

               EPwm6Regs.AQCTLB.bit.CAD = (Uint16)AQ_SET;

               EPwm6Regs.CMPCTL.bit.SHDWBMODE = (Uint16)CC_SHADOW;

       }

       /* DEAD BAND INSERTION */

       (*ePWM[u16ChannelID]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

       (*ePWM[u16ChannelID]).DBCTL.bit.POLSEL = DB_ACTV_HIC;

       (*ePWM[u16ChannelID]).DBCTL.bit.IN_MODE = DBA_ALL;

       (*ePWM[u16ChannelID]).DBRED.bit.DBRED = 200u;

       (*ePWM[u16ChannelID]).DBFED.bit.DBFED = 200u;

    }

    please find the Oscilloscope Output as well:

  • Hi Nishant,

    There are a couple of things you could try. 

    1. As this is a fixed frequency power stage, you can use immediate load for period. If you plan to change the frequency as well, you could do immediate load for the slave PWM period at initialization and then change it later in the code.

    2. Make sure you initialize the PWM counters for both PWMs. If they are supposed to start with a phase shift, and the counters are initialized with this phase shift in mind, please make sure to do immediate load of period for the slave PWM.

    This should solve the issue.

    Hrishi

  • hello Hrishi,

    thanks for your suggestions..
    my system requires only fixed frequency.. and i have done what you have suggested by applying apt values to A & B compare registers of the ePWM channels..

    regarding point 2... yes i am doing as you suggested..

    In the attached waveform shown above there is a delay in the starting of the signal itself.. once it starts there is no phase shift or anything... this delay is of the order of 100ms... an per my understanding i am not able to co-relate it with phase shift or any other registers.. this behaviour is only observed during the starting of the PWM... once all 4 PWM signals starts, i am able to control signals..
  • Nishant,

    Please change the shadow load behavior of the Period register for the slave PWM to immediate load 

    (*ePWM[u16ChannelID]).TBCTL.bit.PRDLD = (Uint16)TB_SHADOW;

    Immediate load will make sure that the period value takes effect at the beginning.

    Hrishi