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: Synchronize EPWMx on EPWMy with one frequency per ePWM

Part Number: TMS320F280025C


Hi,

I have a problem, I have configured two ePWM running at different frequencies and I would like them to be in phase. I want SPWM_FOR_ADC (EPWM7_BASE) to be triggered on SPWM_U (EPWM1_BASE). I must have forgotten a configuration, can you help me please?

Thanks 

Damien

void epwm_init(uint32_t base)
{
    /**Parameters*/
    EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
    EPWM_setTimeBaseCounter(base, 0U);
    EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_4, EPWM_HSCLOCK_DIVIDER_4);
    /**Set up shadowing*/
    EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    /**Set actions
    For boost assembly*/
    EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    /**For buck assembly*/
    EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
}

void epwm_settings(uint32_t base)
{
    if((base == SPWM_U) ||
       (base == SPWM_V) ||
       (base == SPWM_W))
    {
        //for test
        EPWM_setCounterCompareValue(SPWM_U, EPWM_COUNTER_COMPARE_B, 78);
        EPWM_setCounterCompareValue(SPWM_V, EPWM_COUNTER_COMPARE_B, 78);
        EPWM_setTimeBasePeriod(base, EPWM_TBPRD);
    }
    else if(base == SPWM_FOR_ADC)
    {
        EPWM_setCounterCompareValue(SPWM_FOR_ADC, EPWM_COUNTER_COMPARE_A, 78);//CMPA_EPWM_ADC
        EPWM_setTimeBasePeriod(SPWM_FOR_ADC, 156);//EPWM_TBPRD_ADC
    }
    else if(base == SPWM_REGU)
    {
        EPWM_setTimeBasePeriod(base, EPWM_TBPRD_REGU);
        /**Initialize PWM to regulation interrupt*/
        EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, CMPA_EPWM_REGU);
        /// 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);
    }
}

void epwm_set_phase(uint32_t base, uint16_t phi)
{
    /**Configure ePMWs*/
    // Todo comments to explain
    if(phi == 0)
    {
        EPWM_disablePhaseShiftLoad(base);
        EPWM_setPhaseShift(base, phi);
        EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
    }
    else
    {
        uint16_t tbphs = epwm_get_tbphs_from_phi(base, phi);
        EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
        EPWM_enablePhaseShiftLoad(base);
        EPWM_selectPeriodLoadEvent(base, EPWM_SHADOW_LOAD_MODE_SYNC);
        EPWM_setPhaseShift(base, tbphs);
        EPWM_setTimeBaseCounter(base, tbphs);
    }
}

  • I think there is a problem with the generation of the SYNC pulse ?

  • Hello Damien,

    Assuming that each of these functions is being called correctly during initialization, the first thing I'd notice here would be that if you'd like your ePWM signals to be in-phase, i.e. phase shift zero, then your epwm_set_phase function doesn't know how to handle that. It appears to assume that a shift of zero is only for the primary ePWM, not the secondary. If this is not the source of the issue, I'd suggest using CCS' debug view to look at the contents of the time-base control register and seeing if the settings shown there match up with what you're telling your device to do.

    Finally, if none of the above assists, let me know what behavior you do see in your ePWM waveforms instead of what you want to see.

    Hope this helps,

    Jason Osborn

  • Hi Jason,

    I explain myself a little better, in fact I have configured three ePWM modules which are SPWM_U, SPWM_V and SPWM_W which work at the same frequency (40kHz) and each one out of phase of 120degrees with regard to SPWM_U (EPWM1_BASE) which the master. This works fine but then I added another ePWM at 20kHz frequency which is SPWM_FOR_ADC (EPWM7_BASE) and I want it to be in phase with EPWM1_BASE and visually on the oscilloscope they are not. I only observe them in phase if I run them at the same frequency. I think there is a SYNC pulse problem? Because I set the pulse generation to 0 and if they don't have the same frequency the switch to will not be done at the right time for SPWM_FOR_ADC ?

    Thanks

    Damien

  • in my code if I comment epwm_set_phase  function in the hand, it still doesn't work. I did this to try to isolate the problem as well as possible. Here is my code in main : the epwm_set_phase function is commented

        /**
         * ePWM initialization with phase shift
         */
        epwm_init(SPWM_U);               <-
        //epwm_init(SPWM_V);
        //epwm_init(SPWM_W);   
        epwm_init(SPWM_FOR_ADC);         <-
    
        epwm_settings(SPWM_U);           <-
        //epwm_settings(SPWM_V);
        //epwm_settings(SPWM_W);
        epwm_settings(SPWM_FOR_ADC);     <-
    
        //epwm_set_phase(SPWM_U, 0);
        //epwm_set_phase(SPWM_U, EPWM_PHI);
        //epwm_set_phase(SPWM_U, EPWM_PHI << 1);
        //epwm_set_phase(SPWM_FOR_ADC, 0);
    void epwm_init(uint32_t base)
    {
        /**Parameters*/
        EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP);
        EPWM_setTimeBaseCounter(base, 0U);
        EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_4, EPWM_HSCLOCK_DIVIDER_4);
        /**Set up shadowing*/
        EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
        /**Set actions
        For boost assembly*/
        EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
        EPWM_setActionQualifierAction(base, SPWM_TOP, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
        /**For buck assembly*/
        EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
        EPWM_setActionQualifierAction(base, SPWM_BOT, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    }
    
    void epwm_settings(uint32_t base)
    {
        /// To force command MOS ePWM at a low state.
        if((base == SPWM_U) ||
           (base == SPWM_V) ||
           (base == SPWM_W))
        {
            //for test
            EPWM_setCounterCompareValue(SPWM_U, EPWM_COUNTER_COMPARE_B, 78);
            EPWM_setCounterCompareValue(SPWM_V, EPWM_COUNTER_COMPARE_B, 78);
            EPWM_setTimeBasePeriod(base, EPWM_TBPRD);//EPWM_TBPRD
    
            /*EPWM_setActionQualifierContSWForceAction(SPWM_U, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);
            EPWM_setActionQualifierContSWForceAction(SPWM_V, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);*/
            EPWM_setActionQualifierContSWForceAction(SPWM_W, SPWM_BOT, EPWM_AQ_SW_OUTPUT_LOW);
            EPWM_setActionQualifierContSWForceAction(SPWM_U, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
            EPWM_setActionQualifierContSWForceAction(SPWM_V, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
            EPWM_setActionQualifierContSWForceAction(SPWM_W, SPWM_TOP, EPWM_AQ_SW_OUTPUT_LOW);
        }
        else if(base == SPWM_FOR_ADC)
        {
            EPWM_setCounterCompareValue(SPWM_FOR_ADC, EPWM_COUNTER_COMPARE_A, 155);//CMPA_EPWM_ADC
            EPWM_setTimeBasePeriod(SPWM_FOR_ADC, 311);//EPWM_TBPRD_ADC
        }
        else if(base == SPWM_REGU)
        {
            EPWM_setTimeBasePeriod(base, EPWM_TBPRD_REGU);
            /**Initialize PWM to regulation interrupt*/
            EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, CMPA_EPWM_REGU);
            /// 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);
        }
    }
    

    epwm_set_phase function :

    void epwm_set_phase(uint32_t base, uint16_t phi)
    {
        /**Configure ePMWs*/
        // Todo comments to explain
        if(phi == 0)
        {
            EPWM_disablePhaseShiftLoad(base);
            EPWM_setPhaseShift(base, phi);
            EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO);
        }
        else
        {
            uint16_t tbphs = epwm_get_tbphs_from_phi(base, phi);
            EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);
            EPWM_enablePhaseShiftLoad(base);
            EPWM_selectPeriodLoadEvent(base, EPWM_SHADOW_LOAD_MODE_SYNC);
            EPWM_setPhaseShift(base, tbphs);
            EPWM_setTimeBaseCounter(base, tbphs);
        }
    }

    Thanks

  • I'm sorry I can't put you the oscillogram, but I see the signal SPWM_FOR_ADC which is sometimes in advance on EPWM_BASE (SPWM_U) and sometimes in delay

  • Hello Damien,

    To clarify, when you say that you want a 20kHz signal to be in-phase with a 40kHz signal, what exactly do you mean?

    Regards,

    Jason Osborn

  • I understand your uncertainty, I explain my use. I am setting up a digital control, the signals EPWM1_BASE, EPWM2_BASE and EPWM4_BASE are used to control the semi conductors and I synchronize the ADC SOC on a signal ePWM7_BASE which has a frequency twice less high to give me more time for the control. But it doesn't work very well because this signal SPWM_FOR_ADC is not synchronized on EPWM1_BASE.

  • I want the two signals to be synchronized with each other, no time lag.

  • Hello Damien,

    To clarify what I meant, at no point do you declare that EPWM1 is the sync source for EPWM7. If you run the epwm_set_phase() function you've written on EPWM7 with a phase shift of 0, it just sets EPWM7's syncout signal. Again, if you have the opportunity, please go through CCS' debug functionality and use the expressions window to look through the relevant registers- it can be very useful as a step one for debugging to see what exactly is not being set!

    Regards,

    Jason Osborn

  • Ok I have to use this function even when the phase shift is zero ?

    EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1);

    Unfortunately I can't run my code tonight as I'm not at work.

    Tell me if I'm wrong: in my case, I have to set the Sync out signal on ePWM1 via EPWM_enableSyncOutPulseSource(base, EPWM_SYNC_OUT_PULSE_ON_CNTR_ZERO) and then set the Sync in source on EPWM7 via EPWM_setSyncInPulseSource(base, EPWM_SYNC_IN_PULSE_SRC_SYNCOUT_EPWM1) ?

    Regards,

    Damien

  • Damien,

    In theory, no, if these signals are never altered after initialization, but I do so for safety regardless. Your summary appears accurate, recalling that EPWM7 must also have the PHSEN bit set.

    If you continue having issues, I would first ensure that your 'EPWM_TBPRD' value is properly twice of the value you are assigning to the period of EPWM7. Next, I would make sure that your CMPx values and AQ settings are properly configured to give you the behavior you want. If you continue having issues after all of that, please provide the waveforms for your signals and the contents of the relevant registers.

    Regards,

    Jason Osborn