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.
Hello,
I want to use HRPWM for my application and it requires 6 PWM outputs A and B are inverted versions of one another.
My question is regarding the Jitter on the channels with regards to syncing
I am not changing the period but the duty cycle will be changed during every pwm cycle, from the datasheet note it seems that only phase or period control will introduce the jitter.
However in the driverlib function setMEPcontrolMode it is set as Period and Duty control. Does this mean that the jitter will be introduced with duty control as well?
I have followed the HRPWM examples for HRPWM_EX3_PRDUPDOWN_SFO_V8.c
I however am not using the SFO and am just manually converting the fractional to the correct CMPA:HR value.
When I scope the outputs of the 3 waveforms with CMPA:HR cycling between all steps I do not see any changes in the waveform.
I leave EPWM1A alone and cycle EPWM2A and EPWM3A throught he CMPA:HR values and see no difference in the edge compared to EPWM1A
This is my initialization code
// Set-up TBCLK // set period to shadow load EPWM_setPeriodLoadMode(base, EPWM_PERIOD_DIRECT_LOAD); // set base period uint16_t HR_PERIOD = (uint16_t)UP_DOWN_PERIOD; EPWM_setTimeBasePeriod(base,HR_PERIOD); // Set-up TBCLK EPWM_setCounterCompareValue(base,EPWM_COUNTER_COMPARE_A,3U); // Set up shadowing to load on 0 EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(base, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // set phase shift to 0 HRPWM_setPhaseShift(base, 0U); // disable phase shift load HRPWM_disablePhaseShiftLoad(base); // reset time base counter HRPWM_setTimeBaseCounter(base, 0U); // Set up counter mode HRPWM_setTimeBaseCounterMode(base, EPWM_COUNTER_MODE_UP_DOWN); // set to count up down // configure clock pre-scaling HRPWM_setClockPrescaler(base, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); // Enable shadow mode for compare value HRPWM_setActionQualifierShadowLoadMode(base, EPWM_ACTION_QUALIFIER_A,EPWM_AQ_LOAD_ON_CNTR_ZERO); //HRPWM_setActionQualifierShadowLoadMode(base, EPWM_ACTION_QUALIFIER_B,EPWM_AQ_LOAD_ON_CNTR_ZERO); // Set actions // When EPWM1_A hits the compare value on an up count set output A low HRPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); // When EPWM1_A hits the compare value on a down count set output A high HRPWM_setActionQualifierAction(base, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); // When EPWM1_A hits the compare value on an up count set output B high //EPWM_setActionQualifierAction(base, //EPWM_AQ_OUTPUT_B, //EPWM_AQ_OUTPUT_HIGH, //EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); // When EPWM1_A hits the compare value on a down count set output B low //EPWM_setActionQualifierAction(base, //EPWM_AQ_OUTPUT_B, //EPWM_AQ_OUTPUT_LOW, //EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA); // Deadband Configuration // Use EPWMA as the input for both RED and FED HRPWM_setRisingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); HRPWM_setFallingEdgeDeadBandDelayInput(base, EPWM_DB_INPUT_EPWMA); // Set the RED and FED values HRPWM_setFallingEdgeDelayCount(base, 10); // TI used a value of 200 in there example code: Deadband needs to be 2.0us => 10ns*200=2us HRPWM_setRisingEdgeDelayCount(base, 10); // Invert only the Falling Edge delayed output (AHC) HRPWM_setDeadBandDelayPolarity(base, EPWM_DB_RED, EPWM_DB_POLARITY_ACTIVE_HIGH); HRPWM_setDeadBandDelayPolarity(base, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW); // Use the delayed signals instead of the original signals HRPWM_setDeadBandDelayMode(base, EPWM_DB_RED, true); HRPWM_setDeadBandDelayMode(base, EPWM_DB_FED, true); // DO NOT Switch Output A with Output B HRPWM_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_A, false); HRPWM_setDeadBandOutputSwapMode(base, EPWM_DB_OUTPUT_B, false); ////////////// // Initialize HRPWM extension. HRPWM_setHiResTimeBasePeriodOnly(base,(uint16_t)MEP_SCALE_FACTOR); //ASSUMPTION 55 MEP STEPS PER PWM HRPWM_setHiResCounterCompareValueOnly(base,HRPWM_COUNTER_COMPARE_A,1U); HRPWM_setCounterCompareShadowLoadEvent(base, HRPWM_CHANNEL_A,HRPWM_LOAD_ON_CNTR_ZERO); HRPWM_setCounterCompareShadowLoadEvent(base, HRPWM_CHANNEL_B,HRPWM_LOAD_ON_CNTR_ZERO); //set HRPWM to control both edges of period HRPWM_setMEPEdgeSelect(base, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE); HRPWM_setMEPControlMode(base, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); HRPWM_setMEPEdgeSelect(base, HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE); HRPWM_setMEPControlMode(base, HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL); // Set high resolution MEP (Micro Edge Positioner) step //MEP steps applied = TEPWMCLK /180 ps = 200Mhz^-1/180ps = 28 HRPWM_setMEPStep(base, MEP_SCALE_FACTOR); // Enables MEP (Micro Edge Positioner) automatic scale mode. HRPWM_disableAutoConversion(base); // enable HR period control HRPWM_disablePeriodControl(base);
This is followed by some syncing
EPWM_setSyncOutPulseMode(EPWM1_BASE, EPWM_SYNC_OUT_PULSE_ON_COUNTER_ZERO); EPWM_setSyncOutPulseMode(EPWM2_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); EPWM_setSyncOutPulseMode(EPWM3_BASE, EPWM_SYNC_OUT_PULSE_ON_EPWMxSYNCIN); //EPWM_enablePhaseShiftLoad(EPWM1_BASE); EPWM_enablePhaseShiftLoad(EPWM2_BASE); EPWM_enablePhaseShiftLoad(EPWM3_BASE);
Any help would be appreciated.
Cheers,
Kip
Hi Chris,
Due to the US Holidays please expect a reply by January 4th.
Best Regards,
Marlyn
Seems like your specific application shouldn't run into a jitter issue.
Why are you not using the SFO library?
But here is some driverlib based code for the HRPWM I wrote some time ago to show the HRPWM slide between different duty values.
Take a look at this and diff it with your code and see what the differences could be:
// // Included Files // #include "driverlib.h" #include "device.h" #include "SFO_V8.h" #define EPWM_TIMER_TBPRD 100UL #define MIN_HRPWM_DUTY_PERCENT 4.0/((float32_t)EPWM_TIMER_TBPRD)*100.0 // // Defines // #define LAST_EPWM_INDEX_FOR_EXAMPLE 5 // // Globals // float32_t dutyFine = MIN_HRPWM_DUTY_PERCENT; uint16_t status; int MEP_ScaleFactor; // Global variable used by the SFO library // Result can be used for all HRPWM channels // This variable is also copied to HRMSTEP // register by SFO() function. volatile uint32_t ePWM[(PWM_CH + 1)] = {0, EPWM1_BASE, EPWM2_BASE, EPWM3_BASE, EPWM4_BASE}; // // Function Prototypes // void initHRPWM(uint32_t period); void initEPWMGpio(void); void error(void); //__interrupt void epwm1ISR(void); //__interrupt void epwm2ISR(void); //__interrupt void epwm3ISR(void); //__interrupt void epwm4ISR(void); // // Main // void main(void) { uint16_t i = 0; // // Initialize device clock and peripherals // Device_init(); // // Disable pin locks and enable internal pull ups. // Device_initGPIO(); // // Initialize PIE and clear PIE registers. Disables CPU interrupts. // Interrupt_initModule(); // // Initialize the PIE vector table with pointers to the shell Interrupt // Service Routines (ISR). // Interrupt_initVectorTable(); // // Assign the interrupt service routines to ePWM interrupts // //Interrupt_register(INT_EPWM1, &epwm1ISR); //Interrupt_register(INT_EPWM2, &epwm2ISR); //Interrupt_register(INT_EPWM3, &epwm3ISR); //Interrupt_register(INT_EPWM4, &epwm4ISR); initEPWMGpio(); // // CHANGE XBAR inputs from using GPIO0 // if EPWM SYNCIN is enabled, EXTSYNCIN1 and EXTSYNCIN2 will use // GPIO0 (which is the output of EPWM1). // Pick and unused GPIO // XBAR_setInputPin(XBAR_INPUT5, 50); XBAR_setInputPin(XBAR_INPUT6, 50); // // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor. // HRMSTEP must be populated with a scale factor value prior to enabling // high resolution period control. // while(status == SFO_INCOMPLETE) { status = SFO(); if(status == SFO_ERROR) { error(); // SFO function returns 2 if an error occurs & # of MEP } // steps/coarse step exceeds maximum of 255. } // // Disable sync(Freeze clock to PWM as well) // SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_GTBCLKSYNC); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); initHRPWM(EPWM_TIMER_TBPRD); // // Enable sync and clock to PWM // SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); // Enable ePWM interrupts // //Interrupt_enable(INT_EPWM1); //Interrupt_enable(INT_EPWM2); //Interrupt_enable(INT_EPWM3); //Interrupt_enable(INT_EPWM4); // // Enable Global Interrupt (INTM) and realtime interrupt (DBGM) // EINT; ERTM; for(;;) { // // Sweep DutyFine // for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < 99.9; dutyFine += 0.01) { DEVICE_DELAY_US(1000); for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++) { float32_t count = (dutyFine * (float32_t)(EPWM_TIMER_TBPRD << 8))/100; uint32_t compCount = (count); HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_A, compCount); HRPWM_setCounterCompareValue(ePWM[i], HRPWM_COUNTER_COMPARE_B, compCount); } // // Call the scale factor optimizer lib function SFO() // periodically to track for any change due to temp/voltage. // This function generates MEP_ScaleFactor by running the // MEP calibration module in the HRPWM logic. This scale // factor can be used for all HRPWM channels. The SFO() // function also updates the HRMSTEP register with the // scale factor value. // status = SFO(); // in background, MEP calibration module // continuously updates MEP_ScaleFactor if (status == SFO_ERROR) { error(); // SFO function returns 2 if an error occurs & # // of MEP steps/coarse step } // exceeds maximum of 255. } } } // // epwm1ISR - ePWM 1 ISR // //__interrupt void epwm1ISR(void) //{ // EPWM_clearEventTriggerInterruptFlag(EPWM1_BASE); // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); //} // // epwm2ISR - ePWM 2 ISR // //__interrupt void epwm2ISR(void) //{ // EPWM_clearEventTriggerInterruptFlag(EPWM2_BASE); // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); //} // // epwm3ISR - ePWM 3 ISR // //__interrupt void epwm3ISR(void) //{ // EPWM_clearEventTriggerInterruptFlag(EPWM3_BASE); // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); //} // // epwm4ISR - ePWM 4 ISR // //__interrupt void epwm4ISR(void) //{ // EPWM_clearEventTriggerInterruptFlag(EPWM4_BASE); // Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); //} void initEPWMGpio(void) { // // Configure GPIO0/1 as ePWM1A/1B pins respectively // GPIO_setPadConfig(0, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_0_EPWM1A); GPIO_setPadConfig(1, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_1_EPWM1B); // // Configure GPIO2/3 as ePWM2A/2B pins respectively // GPIO_setPadConfig(2, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_2_EPWM2A); GPIO_setPadConfig(3, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_3_EPWM2B); // // Configure GPIO4/5 as ePWM3A/3B pins respectively // GPIO_setPadConfig(4, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_4_EPWM3A); GPIO_setPadConfig(5, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_5_EPWM3B); // // Configure GPIO6/7 as ePWM4A/4B pins respectively // GPIO_setPadConfig(6, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_6_EPWM4A); GPIO_setPadConfig(7, GPIO_PIN_TYPE_STD); GPIO_setPinConfig(GPIO_7_EPWM4B); } void initHRPWM(uint32_t period) { uint16_t j; // // ePWM channel register configuration with HRPWM // ePWMxA / ePWMxB toggle low/high with MEP control on Rising edge // for (j=1;j<LAST_EPWM_INDEX_FOR_EXAMPLE;j++) { EPWM_setEmulationMode(ePWM[j], EPWM_EMULATION_FREE_RUN); // // Set-up TBCLK // EPWM_setTimeBasePeriod(ePWM[j], period-1); EPWM_setPhaseShift(ePWM[j], 0U); EPWM_setTimeBaseCounter(ePWM[j], 0U); // // set duty 50% initially // HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_A, (period/2 << 8)); HRPWM_setCounterCompareValue(ePWM[j], HRPWM_COUNTER_COMPARE_B, (period/2 << 8)); // // Set up counter mode // EPWM_setTimeBaseCounterMode(ePWM[j], EPWM_COUNTER_MODE_UP); EPWM_disablePhaseShiftLoad(ePWM[j]); EPWM_setClockPrescaler(ePWM[j], EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1); EPWM_setSyncOutPulseMode(ePWM[j], EPWM_SYNC_OUT_PULSE_DISABLED); // // Set up shadowing // EPWM_setCounterCompareShadowLoadMode(ePWM[j], EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO); EPWM_setCounterCompareShadowLoadMode(ePWM[j], EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO); // // Set actions // EPWM_setActionQualifierAction(ePWM[j], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(ePWM[j], EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO); EPWM_setActionQualifierAction(ePWM[j], EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA); EPWM_setActionQualifierAction(ePWM[j], EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB); HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE); HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL); HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO); HRPWM_setMEPEdgeSelect(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE); HRPWM_setMEPControlMode(ePWM[j], HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL); HRPWM_setCounterCompareShadowLoadEvent(ePWM[j], HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO); HRPWM_enableAutoConversion(ePWM[j]); // // Turn off high-resolution period control. // HRPWM_disablePeriodControl(ePWM[j]); HRPWM_disablePhaseShiftLoad(ePWM[j]); // // Interrupt where we will change the Compare Values // Select INT on Time base counter zero event, // Enable INT, generate INT on 1st event // //EPWM_setInterruptSource(ePWM[j], EPWM_INT_TBCTR_ZERO); //EPWM_enableInterrupt(ePWM[j]); //EPWM_setInterruptEventCount(ePWM[j], 1U); } } // // error - Halt debugger when called // void error (void) { ESTOP0; // Stop here and handle error }
Thanks, I was able to cross reference some mistakes I had made and got it working with your code as the base line.
I was also able to integrate the SFO library into my project.
Cheers.