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.

TMS320F280025C: Problem with phase shift between 3 ePWMs

Part Number: TMS320F280025C

Hi everyone ! 

I have a problem to configure my phase shift between 3 ePWM to drive 3 boost power stage.

I want 120° phase shift per EPWM (phase is an input user). I configure EPWM1 as master and EPWM2 and EPWM3 as slaves. But on my oscilloscope I see 60° per phase not 120°.  Could you explain me please ? Why it doesn't work correctly ?

Thanks.

void epwm_init(uint32_t base)
{
    float PWM_TBPRD_1;
    float PWM_TBPRD_2;
    float PWM_TBPRD_3;
    float PWM_CMPA_1;
    float PWM_CMPA_2;
    float PWM_CMPA_3;
    EPWM_ClockDivider PWM_PARAM_PRESCALER;
    EPWM_HSClockDivider PWM_PARAM_HIGHSPEEDPRESCALER;
    float TBCLK;

    if(base == myEPWM1_BASE)
    {
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);

        // Parameters
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_1);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_B, (uint16_t)PWM_CMPA_1);
        EPWM_setPhaseShift(base, 0U);
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_enableSyncOutPulseSource(myEPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
    }

    else if (base == myEPWM2_BASE)
    {
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);

        // Parameters
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_2);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_2);
        EPWM_setPhaseShift(base, 0U);
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);

        set_phase(base, PHI);

    }

    else if(base == myEPWM3_BASE)
    {
        get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);

        // Parameters
        EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_3);
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_3);

        EPWM_setPhaseShift(base, 0U);
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setTimeBaseCounter(base, 0U);

        EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
        //EPWM_enableSyncOutPulseSource(myEPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
        set_phase(base, PHI);

    }

    //EPWM_setTimeBaseCounter(base, 0U);
    EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN);

    EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);

    // Set up shadowing
    EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    // Set actions
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

    // Trip zone
    // Configure ePWM1x to output low on TZx TRIP
    EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);
    // Trigger event when DCBH is high
    EPWM_setTripZoneDigitalCompareEventCondition(base, EPWM_TZ_DC_OUTPUT_B1, EPWM_TZ_EVENT_DCXH_HIGH);
    // Configure DCBH to use TRIP4 as an input
    EPWM_enableDigitalCompareTripCombinationInput(base, EPWM_DC_COMBINATIONAL_TRIPIN4, EPWM_DC_TYPE_DCBH);
    // Enable DCB as OST
    EPWM_enableTripZoneSignals(base, EPWM_TZ_SIGNAL_DCBEVT1);
    // Configure the DCB path to be unfiltered and asynchronous
    EPWM_setDigitalCompareEventSource(base, EPWM_DC_MODULE_B, EPWM_DC_EVENT_1, EPWM_DC_EVENT_SOURCE_ORIG_SIGNAL);

    // Clear trip flags
    EPWM_clearTripZoneFlag(base, EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST);

    // Calculate delays
    get_delays_FED_RED(myEPWM1_BASE, &TBCLK);
    get_delays_FED_RED(myEPWM2_BASE, &TBCLK);
    get_delays_FED_RED(myEPWM3_BASE, &TBCLK);
}
void set_phase(uint32_t base, uint16_t phi)
{
    uint16_t phase;

    if(base == myEPWM2_BASE)
    {
        phase = ((float)phi * HWREGH(base + EPWM_O_TBPRD) / 360);
    }

    if(base == myEPWM3_BASE)
    {
        phase = ((float)phi * HWREGH(base + EPWM_O_TBPRD) * 2 / 360); 
    }

    //EPWM_selectPeriodLoadEvent(base, EPWM_SHADOW_LOAD_MODE_SYNC);
    EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
    EPWM_forceSyncPulse(base);

    EPWM_setPhaseShift(base, phase);
    EPWM_setTimeBaseCounter(base, phase);
    EPWM_enablePhaseShiftLoad(base);
}

Damien

  • You can see an other function to calculate TBPRD en CMPA for frequency and duty cycle desired. I'm sorry for my english level ! If I understand correctly TBPHS max = TBPRD max and I determines these values. TBPRD and CMPA are correct. 

    For example if I want 90° phase shift between PWM1 and PWM2 and 180° between PWM1 and PWM3

    => TBPHS (master PWM1) = 0

    => TBPHS (slave PWM2) = ((Phase = 90°) * TBPRD) / 360 ; in my case TBPRD = 156 so TBPHS = 39

    => TBPHS (slave PWM3) = ((Phase = 180°) * TBPRD) / 360 in my case TBPRD = 156 so TBPHS = 78

    Can you help me please ? Where is my mistake ? 

    Thanks

    Damien

    void set_phase(uint32_t base, uint16_t phi)
    {
        uint16_t phase;
    
        if(base == myEPWM2_BASE)
        {
            phase = ((float)phi * HWREGH(base + EPWM_O_TBPRD) / 360);
        }
    
        if(base == myEPWM3_BASE)
        {
            phase = ((float)phi * HWREGH(base + EPWM_O_TBPRD) * 2 / 360);
        }
    
        //EPWM_selectPeriodLoadEvent(base, EPWM_SHADOW_LOAD_MODE_SYNC);
        EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
        EPWM_forceSyncPulse(base);
    
        EPWM_setPhaseShift(base, phase);
        EPWM_setTimeBaseCounter(base, phase);
        EPWM_enablePhaseShiftLoad(base);
    }
    *TBPRD_boost_3 = PWM_Freq_TBCLK / (PWM_FREQ * 2);
    *CMPA_boost_3 = ((float) (100 - duty_boost_3) / 100) * (*TBPRD_boost_3);

    void epwm_init(uint32_t base)
    {
        float PWM_TBPRD_1;
        float PWM_TBPRD_2;
        float PWM_TBPRD_3;
        float PWM_CMPA_1;
        float PWM_CMPA_2;
        float PWM_CMPA_3;
        EPWM_ClockDivider PWM_PARAM_PRESCALER;
        EPWM_HSClockDivider PWM_PARAM_HIGHSPEEDPRESCALER;
        float TBCLK;
    
        if(base == myEPWM1_BASE)
        {
            get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
    
            // Parameters
            EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_1);
            EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_B, (uint16_t)PWM_CMPA_1);
            EPWM_setPhaseShift(base, 0U);
            EPWM_disablePhaseShiftLoad(base);
            EPWM_setTimeBaseCounter(base, 0U);
            EPWM_enableSyncOutPulseSource(myEPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
        }
    
        else if (base == myEPWM2_BASE)
        {
            get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
    
            // Parameters
            EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_2);
            EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_2);
            EPWM_setPhaseShift(base, 0U);
            EPWM_disablePhaseShiftLoad(base);
            EPWM_setTimeBaseCounter(base, 0U);
            EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
    
            set_phase(base, PHI);
    
        }
    
        else if(base == myEPWM3_BASE)
        {
            get_pwm_clock_from_freq(base , &PWM_TBPRD_1 , &PWM_TBPRD_2 , &PWM_TBPRD_3 , &PWM_CMPA_1 , &PWM_CMPA_2 , &PWM_CMPA_3 , &PWM_PARAM_PRESCALER , &PWM_PARAM_HIGHSPEEDPRESCALER, &TBCLK);
    
            // Parameters
            EPWM_setTimeBasePeriod(base, (uint16_t)PWM_TBPRD_3);
            EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, (uint16_t)PWM_CMPA_3);
    
            EPWM_setPhaseShift(base, 0U);
            EPWM_disablePhaseShiftLoad(base);
            EPWM_setTimeBaseCounter(base, 0U);
    
            EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
    
            set_phase(base, PHI);
    
        }
    
        //EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN);
    
        EPWM_setClockPrescaler(base, PWM_PARAM_PRESCALER, PWM_PARAM_HIGHSPEEDPRESCALER);
    
        // Set up shadowing
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    
        // Set actions
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    
        // Trip zone
        // Configure ePWM1x to output low on TZx TRIP
        EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
        EPWM_setTripZoneAction(base, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_LOW);
        // Trigger event when DCBH is high
        EPWM_setTripZoneDigitalCompareEventCondition(base, EPWM_TZ_DC_OUTPUT_B1, EPWM_TZ_EVENT_DCXH_HIGH);
        // Configure DCBH to use TRIP4 as an input
        EPWM_enableDigitalCompareTripCombinationInput(base, EPWM_DC_COMBINATIONAL_TRIPIN4, EPWM_DC_TYPE_DCBH);
        // Enable DCB as OST
        EPWM_enableTripZoneSignals(base, EPWM_TZ_SIGNAL_DCBEVT1);
        // Configure the DCB path to be unfiltered and asynchronous
        EPWM_setDigitalCompareEventSource(base, EPWM_DC_MODULE_B, EPWM_DC_EVENT_1, EPWM_DC_EVENT_SOURCE_ORIG_SIGNAL);
    
        // Clear trip flags
        EPWM_clearTripZoneFlag(base, EPWM_TZ_INTERRUPT | EPWM_TZ_FLAG_OST);
    
        // Calculate delays
        get_delays_FED_RED(myEPWM1_BASE, &TBCLK);
        get_delays_FED_RED(myEPWM2_BASE, &TBCLK);
        get_delays_FED_RED(myEPWM3_BASE, &TBCLK);
    }
    

  • Hi, If you are using the up-down count mode you PWM cycle would be double of the configured period value. Hence you need to scale the phase shift accordingly.
    Note that you can also set the counter direction (using PHSDIR bit) during the phase synchronization.
    So, for the phase where you need 240deg you'll have to flip the direction using PHSDIR.

  • Hi ,

    Thanks for your reply. If I understand correctly we must reverse the direction because the value of TBPHS will exceed the max TBPRD ? Is it possible to flip the direction by driverlib function ? Or only by bit-field ?

    Thanks 

    Damien

  • Hi,

    You can use the driverlib function PWM_setPhaseDir to set the phase direction upon sync.

  • Hi,

    I don't find your function but this function "EPWM_setCountModeAfterSync(myEPWM3_BASE, EPWM_COUNT_MODE_UP_AFTER_SYNC)". It doesn' work, when I want 180° on ePWM2 ° and naturally phase > 180° on ePWM3

    Can you explain to me in my case how I must proceed to have a phase greater  on EPWM2 and EPWM3 on up and down count mode ?

    Thanks

    Damien

  • You can see a screen shot. Why when I set phase = 120° ePWM2 is OK with correct phase shift with ePWM1 and ePWM3 isn't OK ? Can you explain me more please ?

    Thanks

    My code : 

    void set_phase(uint32_t base, uint16_t phi)
    {
        uint16_t phase;
    
        if(base == myEPWM2_BASE)
        {
            //EPWM_setCountModeAfterSync(base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
            phase = ((float)phi * HWREGH(base + EPWM_O_TBPRD) * 2 / 360); // *2 to adapt scale on UP and DOWN Count mode
        }
    
        if(base == myEPWM3_BASE)
        {
            //EPWM_setCountModeAfterSync(base, EPWM_COUNT_MODE_UP_AFTER_SYNC);
            phase = ((float)phi * 2 * HWREGH(base + EPWM_O_TBPRD) * 2 / 360);
        }
    
        EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_SOFTWARE);
        EPWM_forceSyncPulse(base);
    
        EPWM_setPhaseShift(base, phase);
        EPWM_setTimeBaseCounter(base, phase);
        EPWM_enablePhaseShiftLoad(base);
    }

  • Hi,

    For the PWM3 you need to set the PHSDIR. Looks like this function is supposed to set the bit but it is commented out.

       //EPWM_setCountModeAfterSync(base, EPWM_COUNT_MODE_UP_AFTER_SYNC);

    This determines what direction the counter will count after the sync for EPWM3. Please set the direction and phase as needed based on the phase shift desired.

  • Hi  ,

    I apologize for the late response, finally I set the TBCTR register on Up count Mode because it doesn't work anyway with the count mode after synhro.

    I keep going on my project and I will come back to this problem later.

    Thank you !

    Damien

  • Hi,

    Thank you. We'll close this thread for now and you can start a new thread later if you see any issue again.