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.
I am trying to implement the same 120 degree phase shift between epwm channels in a design as is illustrated in sprug04a figures 59 and 60 and example 13 code snip. The only difference in my design is that I am using the driver library routines instead of direct register access method and I am trying to shift phase between epwm1, epwm4, and epwm7, while keeping epwm 2 and 3 the same phase as epwm1, epwm 5 and 6 the same as epwm4, and epwm 8 and 9 the same as epwm7. I am close to successful, but not quite, in that the waveform I am getting for epwm7a/7b seems to be inverted from what I want such that 7b (the complement of 7a) looks like what I want 7a to look like. I am wondering if what I want to do is possible and I've just got some register set wrong or something similarly simple but non-obvious to me right now as a relatively new user of the epwm peripheral.
Thank you,
// ----------------------------------------------------------------------------- // FILE INFORMATION // ----------------------------------------------------------------------------- // File Name : epwm_config.c // Description : source code to setup the DSP epwm // Design Notes : Handles dev board versus proto hardware // ----------------------------------------------------------------------------- // REVISION HISTORY: // Date By Description of Change // -------- -------- ----------------------------------------------------------- // 20180314 sebeiter Original // -------- -------- ----------------------------------------------------------- #include "epwm.h" #include "peripherals.h" #define EPWM_TIMER_TBPRD 1875 // this will be 3750 counts in up-down mode or 20KHz at 150MHz/2 #define EPWM_MIN_CMPA 1250 // = 33% #define DEADBAND_1USEC 75 // // initEPWM - Configure ePWM // void EPWM_init(epwm_group_enum epwm_group) { uint32_t phase_a_base; uint32_t phase_b_base; uint32_t phase_c_base; uint16_t phase_shift_count = 0U; EPWM_SyncCountMode sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; bool phase_enable = false; switch(epwm_group) { case EPWM_GROUP_ONE: phase_a_base = EPWM1_BASE; phase_b_base = EPWM2_BASE; phase_c_base = EPWM3_BASE; phase_shift_count = 0; phase_enable = false; sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; break; case EPWM_GROUP_TWO: phase_a_base = EPWM4_BASE; phase_b_base = EPWM5_BASE; phase_c_base = EPWM6_BASE; phase_shift_count = 1250; phase_enable = true; sync_count_mode = EPWM_COUNT_MODE_DOWN_AFTER_SYNC; break; case EPWM_GROUP_THREE: phase_a_base = EPWM7_BASE; phase_b_base = EPWM8_BASE; phase_c_base = EPWM9_BASE; phase_shift_count = 1250; phase_enable = true; sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; break; default: ASSERT(FALSE); break; } EPWM_setupCommon(phase_a_base, phase_enable, phase_shift_count, sync_count_mode); EPWM_setupCommon(phase_b_base, true, 0, sync_count_mode); EPWM_setupCommon(phase_c_base, true, 0, sync_count_mode); if(epwm_group == EPWM_GROUP_ONE) { // Select INT on Time base counter zero event, // Enable INT, generate INT on 1st event EPWM_setInterruptSource(phase_a_base, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(phase_a_base); EPWM_setInterruptEventCount(phase_a_base, 1U); } } void EPWM_setupCommon(uint32_t base, bool phase_enable, uint16_t phase_shift, EPWM_SyncCountMode count_mode) { // Set-up TBCLK EPWM_setTimeBasePeriod(base, EPWM_TIMER_TBPRD); EPWM_setCountModeAfterSync(base, count_mode); EPWM_setPhaseShift(base, phase_shift); //phase_shift); EPWM_setTimeBaseCounter(base, 0U); // Set Compare values EPWM_setCounterCompareValue(base, EPWM_COUNTER_COMPARE_A, EPWM_MIN_CMPA); // Set up counter mode EPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN); if(phase_enable == true) { EPWM_enablePhaseShiftLoad(base); EPWM_setSyncOutPulseMode(base, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); } else { EPWM_disablePhaseShiftLoad(base); // was disable EPWM_setSyncOutPulseMode(base, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); } EPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // 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_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_A, false); // no swap on A S6=0 EPWM_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_B, false); // no swap on B S7=0 EPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true); // rising edge delay S1 = 1 EPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true); // falling edge delay S0 = 1 EPWM_setDeadBandDelayPolarity(base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH ); // rising edge delay not inverted S2=0 EPWM_setDeadBandDelayPolarity(base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); // falling edge delay inverted S3=1 EPWM_setRisingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); // input ePWMA to the RED S4=0 EPWM_setFallingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); // input ePWMA to the FED (AHC) S5=0 EPWM_setDeadBandControlShadowLoadMode(base, EPWM_DB_LOAD_FREEZE); // freeze shadow to active load EPWM_disableDeadBandControlShadowLoadMode(base); // the deadband value stays the same, no need to reload each period EPWM_setRisingEdgeDelayCountShadowLoadMode(base, EPWM_RED_LOAD_FREEZE); EPWM_disableRisingEdgeDelayCountShadowLoadMode(base); EPWM_setFallingEdgeDelayCountShadowLoadMode(base, EPWM_FED_LOAD_FREEZE); EPWM_disableFallingEdgeDelayCountShadowLoadMode(base); EPWM_setDeadBandCounterClock(base, EPWM_DB_COUNTER_CLOCK_FULL_CYCLE); EPWM_setRisingEdgeDelayCount(base, (uint16_t)DEADBAND_1USEC); EPWM_setFallingEdgeDelayCount(base, (uint16_t)DEADBAND_1USEC); }
OK, in the light of day, I checked my scope probes and figured out that the epwm 120 and 240 phase shifts by group does in fact work, if you put the probes on the correct pins! I also added some code for enabling the epwmxsyncin's to each group explicitly (using SysCtl_setSyncInputConfig), but it didn't seem to matter if I selected 1 or 4 as the source, perhaps because I am in "flow through" mode. But I also remember reading that chains of more than 4 should not be used, so please advise if this is not recommended use. Thanks!
// // initEPWM - Configure ePWM // void EPWM_init(epwm_group_enum epwm_group) { uint32_t phase_a_base; uint32_t phase_b_base; uint32_t phase_c_base; uint16_t phase_shift_count = 0U; EPWM_SyncCountMode sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; bool phase_enable = false; switch(epwm_group) { case EPWM_GROUP_ONE: phase_a_base = EPWM1_BASE; phase_b_base = EPWM2_BASE; phase_c_base = EPWM3_BASE; phase_shift_count = 0; phase_enable = false; sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; break; case EPWM_GROUP_TWO: phase_a_base = EPWM4_BASE; phase_b_base = EPWM5_BASE; phase_c_base = EPWM6_BASE; phase_shift_count = 1250; phase_enable = true; sync_count_mode = EPWM_COUNT_MODE_UP_AFTER_SYNC; //EPWM_COUNT_MODE_DOWN_AFTER_SYNC; SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM4, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT); break; case EPWM_GROUP_THREE: phase_a_base = EPWM7_BASE; phase_b_base = EPWM8_BASE; phase_c_base = EPWM9_BASE; phase_shift_count = 1250; phase_enable = true; sync_count_mode = EPWM_COUNT_MODE_DOWN_AFTER_SYNC; // EPWM_COUNT_MODE_UP_AFTER_SYNC; SysCtl_setSyncInputConfig(SYSCTL_SYNC_IN_EPWM7, SYSCTL_SYNC_IN_SRC_EPWM1SYNCOUT); break; default: ASSERT(FALSE); break; } EPWM_setupCommon(phase_a_base, phase_enable, phase_shift_count, sync_count_mode); EPWM_setupCommon(phase_b_base, true, phase_shift_count, sync_count_mode); EPWM_setupCommon(phase_c_base, true, phase_shift_count, sync_count_mode); if(epwm_group == EPWM_GROUP_ONE) { // Select INT on Time base counter zero event, // Enable INT, generate INT on 1st event EPWM_setInterruptSource(phase_a_base, EPWM_INT_TBCTR_ZERO); EPWM_enableInterrupt(phase_a_base); EPWM_setInterruptEventCount(phase_a_base, 1U); } }
Thanks - I guess I am still a little bit curious about "flow through" mode versus using the SYNCSOCREGS register (14.14.4 in the spruhm8g) to mux in the epwmxsyncout as the next group's syncselect. The behavior of my code doesn't change if I substitute EPWM4SYNCOUT for EPWM1SYNCOUT as the source sync input for EPWM7, but it seem like it should given the phasing between the groups? Plus the statement about not exceeding 4 modules makes me nervous that I am chaining together 9 of them. Am I misunderstanding that warning in the hardware manual?
Hi Susan,
This is just saying that you should route the sync signals via the most direct path. For example, you want not want to use EPWM1 -> EPWM4 -> EPWM7 -> EPWM8 -> EPWM9 to sync EPWM9 to EPWM1. In most use-cases the sync configurations will not violate the four module restriction.
Regards,
Kris