Part Number: MCU-PLUS-SDK-AM243X
Hi,
I'm trying to work with asymmetric ePWM (I wanted symmetric, but I couldn't get >50% duty cycle for some reason with counter values > 0.5*prdValue being ignored and the prd action set to do nothing). It works fine for high frequencies, but as I get lower there's a significant error in the actual output frequency. Set to 200Hz it's about 37.5% greater, at 50Hz it's 42% and at 10Hz it's about 70% greater than it should be. I've confirmed the tbFreq and prdVal match up with the target outputFreq. Is there something I'm missing in the ePWM configuration that might be causing it to lose precision at low frequencies?
Most PWM signals I need are 200Hz and 50Hz, so I'm wondering if it will be better to use a software PWM task and timers instead, but I'd prefer to offload the processing from the R5F core.
I've stripped out some of my code to show it below:
void updateEpwmOutputFreq(epwmPort, newOutputFreq) {
outputFreq = newOutputFreq;
scaleFactor = 0U;
do {
scaleFactor++;
tbFreq = fclk / scaleFactor;
prdVal = tbFreq / outputFreq;
} while (prdVal > 65535U);
compVal[0] = (prdVal * dutyCycle[0]) / 100U;
compVal[1] = (prdVal * dutyCycle[1]) / 100U;
}
/* Configure Time base submodule */
EPWM_tbTimebaseClkCfg(epwmBaseAddr, tbFreq, fclk);
EPWM_tbPwmFreqCfg(epwmBaseAddr, tbFreq, outputFreq, EPWM_TB_COUNTER_DIR_UP, EPWM_SHADOW_REG_CTRL_ENABLE);
EPWM_tbSyncDisable(epwmBaseAddr);
EPWM_tbSetSyncOutMode(epwmBaseAddr, EPWM_TB_SYNC_OUT_EVT_SYNCIN);
EPWM_tbSetEmulationMode(epwmBaseAddr, EPWM_TB_EMU_MODE_FREE_RUN);
/* Configure counter compare submodule */
EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_A, compVal[0], EPWM_SHADOW_REG_CTRL_ENABLE, EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO, TRUE);
EPWM_counterComparatorCfg(epwmBaseAddr, EPWM_CC_CMP_B, compVal[1], EPWM_SHADOW_REG_CTRL_ENABLE, EPWM_CC_CMP_LOAD_MODE_CNT_EQ_ZERO, TRUE);
/* Configure Action Qualifier Submodule for asymetric operation */
aqConfig.zeroAction = EPWM_AQ_ACTION_HIGH;
aqConfig.prdAction = EPWM_AQ_ACTION_DONOTHING;
aqConfig.cmpAUpAction = EPWM_AQ_ACTION_LOW;
aqConfig.cmpBUpAction = EPWM_AQ_ACTION_LOW;
EPWM_aqActionOnOutputCfg(epwmBaseAddr, epwmCh, &aqConfig);
/* Configure Dead Band Submodule */
EPWM_deadbandBypass(epwmBaseAddr);
/* Configure Chopper Submodule */
EPWM_chopperEnable(epwmBaseAddr, FALSE);
/* Configure trip zone Submodule */
EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_ONE_SHOT, 0U);
EPWM_tzTripEventDisable(epwmBaseAddr, EPWM_TZ_EVENT_CYCLE_BY_CYCLE, 0U);
/* Configure event trigger Submodule */
EPWM_etIntrCfg(epwmBaseAddr, EPWM_ET_INTR_EVT_CNT_EQ_ZRO, EPWM_ET_INTR_PERIOD_FIRST_EVT);
EPWM_etIntrEnable(epwmBaseAddr);