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: Phase-shift PWM, missing pulse

Part Number: TMS320F28379D
Other Parts Discussed in Thread: SYSCONFIG

Hi,
I am running a DC/DC converter with phaseshift control between ePWM1 and ePWM2, 50% duty-cycle with TBPRD=2000 and CMPA=1000.
When loading the phase shift I am missing one PWM cycle everytime TBPHS pass 1000.

ePWM2 looks like:

I have tried to avoid jumping over 1000 but instead increment TBPHS when passing 1000 but that does not make any difference, still missing one cycle.
If the synchronizing pulse comes when TBPHS equals 1001, I thought TBCTR should be at 1000 (last TBPHS value) and set the output high but that doesn't seem to be the case.
The function that sets TBPHS is not running synchronized with TBCTR but it seems to be the same behavior independent of when the TBPHS is set.
Can you enlighten me what I should do or think?

  • Hi Kenneth,

    I looks to me like there is a missing action when the sync pulse occurs with certain values. One known issue that can happen is when a sync pulse occurs, the TBCTR can jump over CMPA and miss the Action Qualifier that you have set on CMPA (this depends on things like TBPHS value, counter direction, and your CMPA value etc.). Could you send your EPWM configuration code so I can take a better look? Are you changing TBPHS of both EPWM1 and EPWM2? And is the issue only seen on EPWM2?

    Best Regards,

    Allison

  • Hi Allison and thank you for your reply,

    I´m only changing TBPHS on EPWM2 and the issue only occur there.

    Below is my initiation code for EPWM1 and EPWM2, created by SysConfig:

    EPWM_setEmulationMode(PWM_Prim1_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setClockPrescaler(PWM_Prim1_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    EPWM_setTimeBasePeriod(PWM_Prim1_BASE, 2000);
    EPWM_setTimeBaseCounter(PWM_Prim1_BASE, 0);
    EPWM_setTimeBaseCounterMode(PWM_Prim1_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setCountModeAfterSync(PWM_Prim1_BASE, EPWM_COUNT_MODE_UP_AFTER_SYNC);
    EPWM_disablePhaseShiftLoad(PWM_Prim1_BASE);
    EPWM_setPhaseShift(PWM_Prim1_BASE, 0);
    EPWM_forceSyncPulse(PWM_Prim1_BASE);
    EPWM_setSyncOutPulseMode(PWM_Prim1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO);
    EPWM_setSyncPulseSource(PWM_Prim1_BASE, HRPWM_PWMSYNC_SOURCE_ZERO);
    EPWM_setCounterCompareValue(PWM_Prim1_BASE, EPWM_COUNTER_COMPARE_A, 1000);
    EPWM_setCounterCompareShadowLoadMode(PWM_Prim1_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareValue(PWM_Prim1_BASE, EPWM_COUNTER_COMPARE_B, 1000);
    EPWM_setCounterCompareShadowLoadMode(PWM_Prim1_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim1_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_enableTripZoneAdvAction(PWM_Prim1_BASE);
    EPWM_setTripZoneAdvAction(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZB_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZB_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZA_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZA_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionA(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionA(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionB(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionB(PWM_Prim1_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_enableTripZoneSignals(PWM_Prim1_BASE, EPWM_TZ_SIGNAL_DCAEVT1);
    EPWM_setDeadBandDelayPolarity(PWM_Prim1_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    EPWM_setDeadBandDelayMode(PWM_Prim1_BASE, EPWM_DB_RED, true);
    EPWM_setRisingEdgeDelayCount(PWM_Prim1_BASE, 50);
    EPWM_setDeadBandDelayMode(PWM_Prim1_BASE, EPWM_DB_FED, true);
    EPWM_setFallingEdgeDelayCount(PWM_Prim1_BASE, 50);
    EPWM_setEmulationMode(PWM_Prim2_BASE, EPWM_EMULATION_FREE_RUN);
    EPWM_setClockPrescaler(PWM_Prim2_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);
    EPWM_setPeriodLoadMode(PWM_Prim2_BASE, EPWM_PERIOD_DIRECT_LOAD);
    EPWM_setTimeBasePeriod(PWM_Prim2_BASE, 2000);
    EPWM_setTimeBaseCounter(PWM_Prim2_BASE, 0);
    EPWM_setTimeBaseCounterMode(PWM_Prim2_BASE, EPWM_COUNTER_MODE_UP_DOWN);
    EPWM_setCountModeAfterSync(PWM_Prim2_BASE, EPWM_COUNT_MODE_UP_AFTER_SYNC);
    EPWM_enablePhaseShiftLoad(PWM_Prim2_BASE);
    EPWM_setPhaseShift(PWM_Prim2_BASE, 0);
    EPWM_setSyncOutPulseMode(PWM_Prim2_BASE, EPWM_SYNC_OUT_PULSE_DISABLED);
    EPWM_setSyncPulseSource(PWM_Prim2_BASE, HRPWM_PWMSYNC_SOURCE_ZERO);
    EPWM_setCounterCompareValue(PWM_Prim2_BASE, EPWM_COUNTER_COMPARE_A, 1000);
    EPWM_setCounterCompareShadowLoadMode(PWM_Prim2_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setCounterCompareValue(PWM_Prim2_BASE, EPWM_COUNTER_COMPARE_B, 1000);
    EPWM_setCounterCompareShadowLoadMode(PWM_Prim2_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(PWM_Prim2_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_enableTripZoneAdvAction(PWM_Prim2_BASE);
    EPWM_setTripZoneAction(PWM_Prim2_BASE, EPWM_TZ_ACTION_EVENT_DCAEVT1, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(PWM_Prim2_BASE, EPWM_TZ_ACTION_EVENT_DCAEVT2, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZB_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZB_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZA_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvAction(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_TZA_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionA(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionA(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionB(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_U, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_setTripZoneAdvDigitalCompareActionB(PWM_Prim2_BASE, EPWM_TZ_ADV_ACTION_EVENT_DCxEVT1_D, EPWM_TZ_ADV_ACTION_LOW);
    EPWM_enableTripZoneSignals(PWM_Prim2_BASE, EPWM_TZ_SIGNAL_DCAEVT1);
    EPWM_setDeadBandDelayPolarity(PWM_Prim2_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);
    EPWM_setDeadBandDelayMode(PWM_Prim2_BASE, EPWM_DB_RED, true);
    EPWM_setRisingEdgeDelayCount(PWM_Prim2_BASE, 50);
    EPWM_setDeadBandDelayMode(PWM_Prim2_BASE, EPWM_DB_FED, true);
    EPWM_setFallingEdgeDelayCount(PWM_Prim2_BASE, 50);

    I try to avoid a jump over CMPA with the following quite easy code. It runs at 5kHz and the PWM at 25kHz:


    phase = ((TimeBasePeriod * (uint32_t)Phi_prim)) / 1000;

    if ((phase > 1000) & (old_phase < 1000)){ // upcount
      phase = 1000;
    }
    old_phase = ((TimeBasePeriod * (uint32_t)Phi_prim)) / 1000;

    EPWM_setPhaseShift(PWM_Prim2_BASE, (uint16_t)phase ); // PWM_Prim2_BASE controls internal phase on primary

    Best regards

    Kenneth

  • Hi Kenneth,

    Thank you for the information and configurations. What are you using to update your TBPHS value (are you using an ISR? And what is the source of Phi_prim?). One of the workarounds suggested for missing an AQ on a changing sync pulse would be to check/compare your TBPHS and CMPA values (almost akin to how you are doing in your response above) but then use T1 and T2 action qualifier events to carry out the actions that would be missed.

    Below is a brief description to help explain. There is typically a missed AQ when:

    1. TBCTR is less than CMPA and the TBPHS value is greater than CMPA (and the counter is counting up).
      • So when a sync occurs, the TBCTR jumps from below CMPA to above CMPA and misses the action that should have occurred on CMPA-up.
      • In this case, you are skipping a CMPAU action.
    2. TBCTR is greater than CMPA and the TBPHS value is less than CMPA (and the counter is counting down)
      • So when a sync occurs, the TBCTR jumps from above CMPA to below CMPA and misses the action that should have occurred on CMPA-down. 
      • In this case, you are skipping a CMPAD action.

    In either of these cases, you would enable T1 or T2 to perform the skipped action (you can distinguish a T1-up vs T1-down action qualifier here). For example, if the first case above is true, you would select EPWMxSYNC as the T1 event source and then set the action taken on T1-up to be setting the EPWM2A high. In this way, the action from a T1-up event would supplement what the missing CMPA(up) = 1000 action would have done. 

    Keep in mind that when these conditions are not true, the T1-up/down events need to be disabled to prevent it from affecting your desired duty cycle. Let me know if you have further questions here or have made any other progress.

    Best Regards,

    Allison

  • Hi Allison,

    Thank you for your help. The T1-up/down event solved my problem.

    Best regards

    Kenneth