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.

TMS320F28379D: TMS320F28379D: PWM Duty cycle extending while rotating phase shift

Part Number: TMS320F28379D
Other Parts Discussed in Thread: C2000WARE

Hi Sir/Madam,

Each line cycle , 50Hz AC input voltage .I am having zero crossover signal , at 20ms(50Hz), which is interrupt to DSP.  For first  20ms ,I want to keep phase sequence PWM1,PWM2,PWM3,PWM4. For next 20ms I want to keep PWM2,PWM3,PWM4,PWM1. For next 20ms I want to keep  PWM3,PWM4,PWM1,PWM2. For next 20ms PWM4,PWM1,PWM2,PWM3. Like this 4 intervals will continue in DSP firmware.

In up-down count mode with 6250 (1milli second) as period, I tried phase shifts 4167(333 uS), 6250 (500 uS),8333 (666 uS), 10416 (833 uS) in rotation mode. I am observing correct amount of phase lead on oscilloscope between PWMs. But while doing that ,I am gettting duty cycle extended for one switching cycle,every 80ms.

While searching the solution I came across Allison Nguyen's solution/workaround.

TMS320F28379D: PWM Duty extending in multi-phase variable frequency operation

She has provided solution in epwm_ex3_synchronization_MODIFIED.c file .  But seems it is not working for me.

What could be the reason? or do you have some other work around.

Thanks and Regards,

Prashant Gugle

  • Here is link for similar issue

    TMS320F28379D: PWM Duty extending in multi-phase variable frequency operation - C2000 microcontrollers forum - C2000Tm︎ microcontrollers - TI E2E support forums

    Attached below is file

     

    // ePWM Phase Shift and T1 Workaround.
    //
    // This is the DriverLib epwm_ex3_synchronization example modified.
    //
    // This file configures EPWM1A to GPIO0 and and EPWM2A to GPIO2.
    // EPWM1A:
    //    - High on CTR = 0
    //    - Sync-Out pulse on CTR = CMPB = 500
    //    - Low on CMPA = 1000
    //    - PRD = 2000
    //
    // EPWM2A:
    //    - High on CTR = 0
    //    - Low on CMPA = 1000
    //    - PRD = 2000
    //    - TBPHS = 1500 (sync-in is EPWM1 sync-out = 500)
    //
    // The example demonstrates a missing EPWM2A action qualifier in the first cycle due to phase shift.
    // The workaround is implemented in main() by using the T1 AQ to carry out the missed action qualifier
    // due to TBPHS (1500) being greater than CMPA (1000) with phase shift (on CMPB - 500) occurring before
    // CMPA.
    //
    // To see the effect, place probes on GPIO0 and GPIO2.
    // Run the code with the workaround 'if' loop in main() commented out.
    // The result is an unwanted longer pulse in the first cycle of EPWM2A.
    // Un-comment the 'if' loop in main() and rerun to see the desired phase shift occur.
    //
    
    //
    // Included Files
    //
    #include "driverlib.h"
    #include "device.h"
    #include "board.h"
    
    #define EPWM_TIMER_TBPRD    2000
    #define EPWM_CMPA           1000
    #define EPWM_CMPB           1000
    #define EPWM_TBPHS          1500
    
    //
    // Function Prototypes
    //
    void initEPWM(uint32_t base);
    
    __interrupt void epwm1ISR(void);
    __interrupt void epwm2ISR(void);
    
    //
    // Main
    //
    void main(void)
    {
        //
        // Initialize device clock and peripherals
        //
        Device_init();
    
        //
        // Disable pin locks and enable internal pull ups.
        //
        Device_initGPIO();
    
        //
        // Initialize PIE and clear PIE registers. Disables CPU interrupts.
        //
        Interrupt_initModule();
    
        //
        // Initialize the PIE vector table with pointers to the shell Interrupt
        // Service Routines (ISR).
        //
        Interrupt_initVectorTable();
    
        //
        // Assign the interrupt service routines to ePWM interrupts
        //
        Interrupt_register(INT_EPWM1, &epwm1ISR);
        Interrupt_register(INT_EPWM2, &epwm2ISR);
    
        //
        // Configure GPIO0/1 , GPIO2/3 and GPIO4/5 and GPIO6/7 as
        // ePWM1A/1B, ePWM2A/2B, ePWM3A/3B, ePWM4A/4B pins respectively, set up output XBAR for extsyncout on GPIO24
        //
        Board_init();
    
        // Disable sync(Freeze clock to PWM as well). GTBCLKSYNC is applicable
        // only for multiple core devices. Uncomment the below statement if
        // applicable.
        //
        // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC);
        SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Initialize PWM1 without phase shift as master
        //
        initEPWM(myEPWM1_BASE);
    
        //
        // Initialize PWM2 with phase shift of 1500 TBCLKs
        //
        initEPWM(myEPWM2_BASE);
    
        EPWM_selectPeriodLoadEvent(myEPWM2_BASE, EPWM_SHADOW_LOAD_MODE_SYNC);
        EPWM_setPhaseShift(myEPWM2_BASE, EPWM_TBPHS);
        EPWM_setTimeBaseCounter(myEPWM2_BASE, 0);
    
        //
        // ePWM1 SYNCO is generated on CTR = CMPB = 500
        //
        EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_COMPARE_B);
    
        //
        // ePWM2 uses the ePWM 1 SYNCO as its SYNCIN.
        // ePWM2 SYNCO is generated from its SYNCIN, which is ePWM1 SYNCO
        //
        EPWM_setSyncOutPulseMode(myEPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN);
    
        //
        // Enable all phase shifts.
        //
        EPWM_enablePhaseShiftLoad(myEPWM2_BASE);
    
        //
        // Enable sync and clock to PWM
        //
        SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    
        //
        // Enable ePWM interrupts
        //
        Interrupt_enable(INT_EPWM1);
        Interrupt_enable(INT_EPWM2);
    
        //
        // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
        //
        EINT;
        ERTM;
    
        //
        // IDLE loop.
        //
        for(;;)
        {
            //
            // WORKAROUND LOOP. Check if TBPHS is greater than CMPA.
            // Un-comment this section to implement the workaround.
            //
    //        if(EPWM_TBPHS > EPWM_CMPA)
    //        {
    //            //
    //            // If true, then use the sync-in pulse as the T1 action qualifier event and perform the action that would be skipped by the phase shift.
    //            //
    //            EPWM_setActionQualifierT1TriggerSource(myEPWM2_BASE, EPWM_AQ_TRIGGER_EVENT_TRIG_EPWM_SYNCIN);
    //            EPWM_setActionQualifierAction(myEPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_T1_COUNT_UP);
    //        }
    //        else
    //        {
    //            //
    //            // If false, then T1 action is not needed, so do nothing on T1 events.
    //            //
    //            EPWM_setActionQualifierAction(myEPWM2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_T1_COUNT_UP);
    //        }
    
        }
    }
    
    //
    // epwm1ISR - ePWM 1 ISR
    //
    __interrupt void epwm1ISR(void)
    {
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE);
    
        //
        // Acknowledge interrupt group
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    //
    // epwm2ISR - ePWM 2 ISR
    //
    __interrupt void epwm2ISR(void)
    {
        //
        // Clear INT flag for this timer
        //
        EPWM_clearEventTriggerInterruptFlag(myEPWM2_BASE);
    
        //
        // Acknowledge interrupt group
        //
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3);
    }
    
    
    void initEPWM(uint32_t base)
    {
        //
        // Set-up TBCLK
        //
        EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD);
        EPWM_setPhaseShift(base, 0U);
        EPWM_setTimeBaseCounter(base, 0U);
    
        //
        // Set Compare values
        //
        EPWM_setCounterCompareValue(base,
                                    EPWM_COUNTER_COMPARE_A,
                                    EPWM_CMPA);
        EPWM_setCounterCompareValue(base,
                                    EPWM_COUNTER_COMPARE_B,
                                    EPWM_CMPB);
    
        //
        // Set up counter mode
        //
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
    
        EPWM_disablePhaseShiftLoad(base);
    
        EPWM_setClockPrescaler(base,
                               EPWM_CLOCK_DIVIDER_8,
                               EPWM_HSCLOCK_DIVIDER_1);
    
        //
        // Set up shadowing
        //
        EPWM_setCounterCompareShadowLoadMode(base,
                                             EPWM_COUNTER_COMPARE_A,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
        EPWM_setCounterCompareShadowLoadMode(base,
                                             EPWM_COUNTER_COMPARE_B,
                                             EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        //
        // Set actions
        //
        EPWM_setActionQualifierAction(base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(base,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_HIGH,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        EPWM_setActionQualifierAction(base,
                                      EPWM_AQ_OUTPUT_A,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base,
                                      EPWM_AQ_OUTPUT_B,
                                      EPWM_AQ_OUTPUT_LOW,
                                      EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    
    
        //
        // Interrupt where we will change the Compare Values
        // Select INT on Time base counter zero event,
        // Enable INT, generate INT on 1rd event
        //
        EPWM_setInterruptSource(base, EPWM_INT_TBCTR_ZERO);
        EPWM_enableInterrupt(base);
        EPWM_setInterruptEventCount(base, 1U);
    }
    

  • Hi Prashant,

    I have looped in the proper expert, and they should get back to you with a response in 1-2 days.

    Best Regards,

    Delaney

  • Hi Prashant

    In up-down counter mode, it is possible that action qualifier may be missed if phase shift is more than the compare register value. Can you try up count mode for EPWM counter? Please let me know if this does not work. 

    Thank you 

    Amir Hussain

  • Hi Amir,

    Even with up counter mode extended duty cycle happens, I have tried this.

    Thanks and Regards,

    Prashant Gugle

  • Hi Amir,

    When I tried with up count mode, even I am not getting correct phase shift. I tried with 12500 as time base period, and 4167, 6250,8333,10417 as phase shift values for PWM2,PWM3,PWM4 and PWM5 respectively. I should get phase value observed in oscilloscope as 330uS,500uS,660uS and 833 uS for PWM2,PWM3,PWM4 and PWM5 respectively with PWM1.

    I am getting phase values as 660uS,500uS,330uS and 160 uS.

    What could be the reason for this wrong phase values?

    I tried with C:\ti\c2000\C2000Ware_6_00_01_00\driverlib\f2837xd\examples\cpu1\epwm\epwm_ex3_synchronization.c file.

    Thanks and Regards,

    Prashant Gugle

  • Hi Amir,

    With up-down counter mode I am getting 330uS,500uS,660uS and 833 uS for PWM2,PWM3,PWM4 and PWM5 respectively with PWM1, as intended, except for extended duty cycle.

    Thanks and Regards,

    Prashant Gugle

  • Hi Prashant,

    I am looking into it. Please allow me few days to work on this.

    Thank you 

    Amir Hussain

  • Hi Amir,

    I was reading phase in leading way. If I read phase between PWM's in lagging manner then it is coming right. But when we try to rotate the phase shift, extending duty cycle is happening .

    Thanks and Regards,

    Prashant Gugle

  • Hi Prashant

    Thank you for your effort and providing additional information regarding the issue. I am working on it and respond to as you as soon as I find a solution.

    Thank you 

    Amir Hussain

  • Hi Amir,

    You found out some solution for PWM phase rotation?

    Thanks and Regards,

    Prashant Gugle

  • Prashant,

    Amir is out of office till next week. Meanwhile I can assist you.

    Solution that you are pointing has fixed master ePWM and slave ePWM, but in your case it seems role of master is rotating which may cause racing condition and that solution may not be useful for you.

    Did you try using some different unused ePWM module as master and rest all 4 of these as slave module?

    Also, out of all four module which one shows pulse extention?

    Is this 1PH interleaved PFC application? If yes is this happening at zero crossing?

    Also, the solution you mentioned above in e2e uses T1 as sync  event. Have you tried it in case you are experiencing CMPA<TBPHS phenomenon in any of your case that may cause missing the CMPA event:  TMS320F28379D: PWM Duty extending in multi-phase variable frequency operation 

    Regards,

    Sumit

  • Hi Sumit,

    I have kept PWM1 as master PWM and rotating phase of PWM3, PWM4, PWM5, PWM6, with respect to PWM1. Also tried the solution  mentioned  which uses T1 as sync event. But the issue remains the same.

    Thanks and Regards,

    Prashant Gugle

  • Prashant, 

    Please confirm my understanding is correct or not about the issue:

    So, you are having one unused dummy master pwm which is not part of actuator and you are running 4-phases interleaved operation for PFC with rotating phase shift that seems need to be 0, 90, 180, 270. But I see in your very first question, I see up-down counter mode and with phase shift counts seems different than phase shift degree mentioned here, are they not equally spread. Also, I see phase counts for 3rd and 4th phase are greater than TBPRD itself. Can you confirm that you have round of those counts considering this is up-down count mode or if its up count mode then TBPRD need to be double 12500? Also out of those 4 phases which one(4th) shows the jumping behavior or is it all of them? 

    Please confirm so that I have correct understanding.

    For now, I will consider the following based on your conversation above and explain this issue - PWM1 is master/sync PWM with up count mode with 12500 and 4 total rotating phases of PWM3, PWM4, PWM5, PWM6 with respect to PWM1. For first 20ms ,I want to keep phase sequence PWM3, PWM4, PWM5, PWM6. For next 20ms, I want to keep PWM4, PWM5, PWM6, PWM3. For next 20ms I want to keep PWM5, PWM6, PWM3, PWM4. For next 20ms PWM6, PWM3, PWM4, PWM5. Like this 4 intervals will continue in DSP firmware

    It seems to me TBPHS jump is happening during rotating phase shift operation as explained below:

    Every 80ms (full rotation cycle), one PWM undergoes the maximum phase jump - Example at the 80ms boundary:

    PWM3 was LAST (large TBPHS, e.g. 9375 for 3/4 period offset with period = 12500)
    PWM3 becomes FIRST (TBPHS = 0)
    But the reverse transition is the dangerous one. Consider PWM6 going from LAST → FIRST, or PWM3 going from FIRST → LAST

    Period = 12500
    CMPA = 6250 (50% duty, for example)

    Old TBPHS = 0 → counter runs 0..12500, hits CMPA=6250 ✓
    New TBPHS = 9375 → on sync, counter JUMPS to 9375

    So on AQ --> 9375 > CMPA (6250) → SET action at CMPA already MISSED
    Counter runs from 9375 to  12500, only CLEAR event fires → Output held HIGH for ~2 switching cycles = extended duty
    This only manifests at the 80ms boundary because that is the only time the maximum phase re-ordering occurs (the PWM rotating from last back to first, or first to last).

    Here are some suggestions to fix this:

    1. Force Output State Immediately After Phase Change (Quickest Fix)

    After writing the new TBPHS value, use the Action Qualifier Continuous Software Force to push the output to the correct idle state, then release it:

    // After writing large TBPHS to EPwm3Regs (e.g., making it the last phase)
    EPwm3Regs.AQCSFRC.bit.CSFA = 2;  // Force output A LOW immediately
    // Allow 1 ISR tick / one cycle, then release:
    EPwm3Regs.AQCSFRC.bit.CSFA = 0;  // Return to normal AQ control

    2. Update TBPHS Only at Period/Zero Event (Correct Approach)

    Never write TBPHS mid-cycle. Schedule the update to take effect at TBCNT = 0

     

    Regards,

    Sumit

  • Hi Sumit,

    I am using up-down counter with period of 6250.So total switching period as 1 milli seconds. Phase shift values are not equally spread out, to 330uS,500uS,660uS and 833 uS between PWMs(I will correct this). PWM1 is master PWM and getting above mentioned phase shift  withPWM2,PWM3,PWM4 and PWM5 respectively.

    This is happening with each PWM at every 80ms.

    I will try your solution number 1 and let you know the result.

    Thanks and Regards,

    Prashant Gugle

  • Understood. Sure, let me know how it goes.

    Regards,

    Sumit