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.
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);
Hi Tron, are observed output's frequency deviations reproducible? or, are they different every time you run it? Maybe is not the issue, but to get very low PWMs you are probably loading high counts, so worthy to check if there is any overflow going on.
In any case, it might be worthy to double check how frequencies are being divided and whether the values to reach those lower frequency counts would fit within the register for the PWM load.
thank you,
Paula
Hi Paula. Thanks for the reply. yes, they're reproducible. I've ensured I'm not getting an overflow - my code (you can see it above) ensures that the period value is selected to be less than 65,535 to ensure there is no overflow.
When I write the tbFreq, prdVal, outputFreq, and compVals to debug console when configuring the module, they all match what I'd expect. But the actual output frequently deviates from the set output frequency, still.
Hi Tron, I colleague was able to get 50Hz at 50% duty cycle in another board (AM263x), which has similar EPWM than AM243x LP. I will try to reproduce his findings in an AM243x LP tomorrow and update you.
thank you,
Paula
Hello Tron,
We can do one test here.
I am suspecting that this issue will arise when not selecting proper scaling factors.
For your use case, you need 50 Hz and 200 Hz signals.
In this case, we can try to configure the maximum scaling factor to achieve low frequencies.
So, you can take the same MCU+SDK code in any PWM example.
In that, I will just update the below parameters,
#define APP_EPWM_OUTPUT_FREQ (1U * 50U) //For 50 HZ
#define APP_EPWM_OUTPUT_FREQ (1U * 200U) //For 200Hz
* TB frequency in Hz, so that a /4 divider is used */
#define APP_EPWM_TB_FREQ ((CONFIG_EPWM0_FCLK / (128U * 14U))
Now, we are selecting The scaling factor value is 1792.
The base clock value of the PWM module is 250000000, then it will be divide to 1792, approximately. It will come around 139508Hz frequency, which is given to the PWM module.
Next we will calculate period value, you need 50 and 200 Hz.
TPRD = (139508/50)/2 for the UP+DOWN counter use case, then the value is 1395.
For 200Hz
TPRD = (139508/200)/2 for the UP+DOWN counter use case, and the value is 348.
Above two period values with in the 16 bit and so, your application should work , can you please try and send the test results?
Regards,
S.Anil.
Anil, thanks, I was able to get 50Hz and 200Hz with above configuration.
Tron, 5-cents comment =), test needs to be run using "release" binaries. By mistake, I was using "debug" binaries and scope outputs were wrong for me.