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.

TMS320F28384D: Question about duty of PWM.

Part Number: TMS320F28384D

Hi

The duty of the PWM signal must be zero, but a full duty occurs.

The program code does not allow more than 95% of duty to occur, but it does occur 100%.

Occurs at random. What's the reason?


The following is the application information:

*Solar Inverter 33kw

 input: 650V 

 output : 220Vac 33KW

Thanks

  • Note please.
    If Ramf is used during an MCU function, the frequency of occurrence is reduced to 1/10.

  • Hey David,

    I've seen an issue similar to this. The cause was related to an ISR that did not have enough time to execute. Could you share more information on your EPWM configuration?

    Thank you,

    Luke

  • Hey Luke,

    ePWM Setting.

    please check.

    Thank you,

    void fx_Init_INVEPwmSetting(Uint16 Module,Uint16 Freq, Uint16 Position, Uint16 DBR_Value, Uint16 DBF_Value, Uint16 Ctrl_Mode)
    {
    // Setup TBCLK
    EPWM[Module]->TBPRD = __divf32( PWM_CLOCK,(Freq*2) ); // Freq:16kHz, PWM_CLOCK:100MHz
    if(Position == PWM_TOP)
    {
    EPWM[Module]->TBPHS.bit.TBPHS = 0x0000; //(Phase is 0)
    EPWM[Module]->TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading(0x0)
    }
    else //if(Position == PWM_BOT)
    {
    EPWM[Module]->TBPHS.bit.TBPHS = __divf32( PWM_CLOCK,(Freq*2) ); // (Phase is 0)
    EPWM[Module]->TBCTL.bit.PHSEN = TB_ENABLE; // Enable phase loading(0x0)
    }
    EPWM[Module]->TBCTR = 0x0000; // Counter Clear


    EPWM[Module]->CMPA.bit.CMPA = 0; // Duty-ratio : 0 %
    EPWM[Module]->CMPB.bit.CMPB = 0; // Duty-ratio : 0 %

    // Setup counter mode
    EPWM[Module]->TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN; // Counter mode(CTR mode) : Up-Down count Mode

    EPWM[Module]->TBCTL.bit.PRDLD = TB_SHADOW; // 0x0
    EPWM[Module]->TBCTL.bit.HSPCLKDIV = TB_DIV1; // High speed Time-Base Clock prescale : /1
    EPWM[Module]->TBCTL.bit.CLKDIV = TB_DIV1; // Time-Base Clock prescale : /1 TBCLK = SYSCLK / (HSPCLKDIV * CLKDIV)


    EPWM[Module]->CMPCTL.bit.SHDWAMODE = CC_SHADOW; // (Enable Shadow Register & Function)
    EPWM[Module]->CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPWM[Module]->CMPCTL.bit.LOADAMODE = CC_CTR_ZERO; 
    EPWM[Module]->CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;


    EPWM[Module]->AQCTLA.bit.CAU = AQ_CLEAR; 
    EPWM[Module]->AQCTLA.bit.CAD = AQ_SET; 


    EPWM[Module]->DBCTL.bit.OUT_MODE= DB_FULL_ENABLE;
    EPWM[Module]->DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPWM[Module]->DBRED.bit.DBRED = DBR_Value; // Rising dead time = (1 / TBCLK) * DBRED @ TBCLK = 200Mhz
    EPWM[Module]->DBFED.bit.DBFED = DBF_Value; // Falling dead time = (1 / TBCLK) * DBFED

    if(Ctrl_Mode == YES)
    {
    EPWM[Module]->EPWMSYNCOUTEN.bit.ZEROEN = SYNC_OUT_SRC_ENABLE; // TBCTR = 0x0000 event to set the EPWMxSYNCOUT signal.

    EPWM[Module]->ETSEL.bit.INTSEL = ET_CTR_PRD;
    EPWM[Module]->ETSEL.bit.INTEN = 1;
    EPWM[Module]->ETPS.bit.INTPRD = ET_1ST;
    }
    else
    {
    EPWM[Module]->EPWMSYNCINSEL.bit.SEL = SYNC_IN_SRC_SYNCOUT_EPWM1;
    EPWM[Module]->ETSEL.bit.INTEN = 0;
    }
    }

  • Hi Park,

    What is the rationale behind this section of your code?

    EPWM[Module]->TBPHS.bit.TBPHS = __divf32( PWM_CLOCK,(Freq*2) ); // (Phase is 0)
    EPWM[Module]->TBCTL.bit.PHSEN = TB_ENABLE; // Enable phase loading(0x0)

    I suspect that after the down count CMPA event is triggered and your output is set, a sync signal is resetting your counter to be your timebase period, which skips the clear event that would have occurred on up count CMPA. Is this scenario possible in the context of your system?

    Thank you,

    Luke

  • Hi Luke,

    ----------------------------------------------------------------------------------------------------------------------------

    EPWM[Module]->TBPHS.bit.TBPHS = __divf32( PWM_CLOCK,(Freq*2) ); // (Phase is 0)
    EPWM[Module]->TBCTL.bit.PHSEN = TB_ENABLE; // Enable phase loading(0x0)

    ----------------------------------------------------------------------------------------------------------------------------

    The above content was used so that ePWMa and ePWMb are 180 degrees out of phase.

    After removing the above content, I did a test, same result.

    With Ramfunc it happens less often.

    Therefore, I am trying to add the following content and test it, but I would like to inquire if you are using it well.

    The priority has been changed as follows.

    Thank you,

    ----------------------------------------------------------------------------------------------------------------------------

    #define INT1PL 2 // Group1 Interrupts (PIEIER1) // XINT1, XINT2, TIMER0
    #define INT2PL 1 // Group2 Interrupts (PIEIER2) // EPWM_TZ
    #define INT3PL 3 // Group3 Interrupts (PIEIER3) // PWM
    #define INT4PL 4 // Group4 Interrupts (PIEIER4) // ECAP
    #define INT5PL 0 // Group5 Interrupts (PIEIER5) // EQEP
    #define INT6PL 0 // Group6 Interrupts (PIEIER6) // SPI
    #define INT7PL 0 // Group7 Interrupts (PIEIER6) // DMA
    #define INT8PL 0 // Group8 Interrupts (PIEIER6) // I2C
    #define INT9PL 5 // Group9 Interrupts (PIEIER9) // SCI/CAN
    #define INT10PL 0 // Group10 Interrupts (PIEIER6) // ADC_EVT
    #define INT11PL 0 // Group11 Interrupts (PIEIER6) // CLA
    #define INT12PL 0 // Group12 Interrupts (PIEIER6) //
    #define INT13PL 6 // INT13 (TINT1) // TIMER1
    #define INT14PL 7 // INT14 (TINT2) // TIMER2
    #define INT15PL 4 // DATALOG //
    #define INT16PL 4 // RTOSINT //

    __interrupt void epwm1_isr(void)
    {
    // TIME_CHECK_HIGH;
    //--------------------------------------------------------------------------------------------
    // Set interrupt priority:
    //--------------------------------------------------------------------------------------------
    volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER3.all;
    IER |= M_INT3;
    IER &= MINT3; // Set "global" priority
    PieCtrlRegs.PIEIER3.all &= MG3_1; // Set "group" priority
    PieCtrlRegs.PIEACK.all = 0xFFFF; // Enable PIE interrupts
    __asm(" NOP");
    EINT;

    *

    *

    DINT;
    EPwm1Regs.ETCLR.bit.INT = 1;
    PieCtrlRegs.PIEIER3.all = TempPIEIER;

    }

    __interrupt void cpu_timer1_isr(void)
    {
    //--------------------------------------------------------------------------------------------
    // Set interrupt priority:
    //--------------------------------------------------------------------------------------------
    IER &= MINT13; // Set "global" priority
    EINT;

    *

    *

    DINT;

    }

    __interrupt void cpu_timer2_isr(void)
    {
    //--------------------------------------------------------------------------------------------
    // Set interrupt priority:
    //--------------------------------------------------------------------------------------------
    IER &= MINT14; // Set "global" priority
    EINT;

    *

    *

    DINT;

    }

    ----------------------------------------------------------------------------------------------------------------------------

  • Hi Park,

    I may need to consult with one of our PIE experts to determine the possible cause of your problem. I will try to get back to you by tomorrow morning.

    --Luke

  • Hi Park,

    Are there any instances in your application where you are updating your ePWM configuration during runtime, such as updating the CMPA or PRD values? Are you using shadow or active loading during those cases?

    I noticed after your 100% duty cycle occurs, the duty cycle is 0 after that period. Are there cases where your CMPA value may be set to 0 or PRD? This may cause a missed CMPA up-count event depending on your configuration.

  • Hi Luke,

    Updating the CMPA value at runtime.

    And SHDWAMODE is enabled.

    The CMPA value may be 0 depending on the PWM switching scheme.

    Below is the PWM output program.

    Should I use a different method if it can cause problems?

    void fx_INV_PWM(void)
    {
    if(PWM_L1 > 0)
    {
    EPwm6Regs.CMPA.bit.CMPA = 0;
    EPwm5Regs.CMPA.bit.CMPA = PWM_L1;
    }
    else
    {
    EPwm5Regs.CMPA.bit.CMPA = 0;
    EPwm6Regs.CMPA.bit.CMPA = -PWM_L1;
    }

    if(PWM_L2 > 0)
    {
    EPwm4Regs.CMPA.bit.CMPA = 0;
    EPwm3Regs.CMPA.bit.CMPA = PWM_L2;
    }
    else
    {
    EPwm3Regs.CMPA.bit.CMPA = 0;
    EPwm4Regs.CMPA.bit.CMPA = -PWM_L2;
    }

    if(PWM_L3 > 0)
    {
    EPwm2Regs.CMPA.bit.CMPA = 0;
    EPwm1Regs.CMPA.bit.CMPA = PWM_L3;
    }
    else
    {
    EPwm1Regs.CMPA.bit.CMPA = 0;
    EPwm2Regs.CMPA.bit.CMPA = -PWM_L3;
    }
    }

  • Hey Park,

    Could you try changing your LOADAMODE to load CMPA on CTR = PRD to see if this issue still persists? I am not sure if this behavior is defined explicitly in TRM, but I believe the cause of this behavior is that you are loading a CMPA value of 0 at the same time your counter equals 0. You also have an action qualifier event on both CTR = CMPA count-up mode and count down mode, I will have to dig deeper into the TRM to determine the priority and timing of each of these events. Does your application require that CMPA is only updated on CTR = 0? If so there may be other workarounds for this such as disabling the PWM when a duty cycle of 0% is desired.

  • Hi Park,

    From the TRM:

    "If the Counter-Compare A Register (CMPA) or Counter-Compare B Register (CMPB) is set to a value of 0 and the action qualifier action on AQCTLA and AQCTLB is configured to occur in the same instant as a shadow to active load (that is, CMPA=0 and AQCTLA shadow to active load on TBCTR=0 using AQCTL register LDAQAMODE and LDAQAMODE bits), then both events enter contention and it is recommended to use a Non-Zero Counter-Compare when using Shadow to Active Load of Action Qualifier Output A/B Control Register on TBCTR = 0 boundary."

    It appears this behavior isn't defined, and you have two events conflicting with eachother (LOAD CMPA on CTR = 0 and CTR = CMPA).