I am trying to use the EPWM module to generate double pulse waveforms for driving a power FET test rig. Based on my understanding of this controller family, the appropriate way to do this is in software using interrupts (ie INT_EPWMx) that are triggered by the timebase counter being equal to some CMPx - this should correspond to a rising or falling edge of the PWM waveform.
I am currently stuck on getting two pulses of different widths to repeat in a periodic fashion (pulse 1 has width a, and pulse 2 has width b). I am trying to do this by changing the duty cycle of the EPWM back and forth from one value to another. Forcing the EPWM low for isolated double pulses is a problem I will solve later - probably via trip zone interrupts.
Here is a minimal version of the logic I would like to implement - this is based on the epwm_ex11_configure_signal example in c2000 ware.
#include "driverlib.h" #include "device.h" #include "board.h" uint32_t epwm1IntCount; EPWM_SignalParams pwmSignal1 = {10000, 0.5f, 0.5f, true, DEVICE_SYSCLK_FREQ, SYSCTL_EPWMCLK_DIV_2, EPWM_COUNTER_MODE_UP_DOWN, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1}; EPWM_SignalParams pwmSignal2 = {10000, 0.25f, 0.5f, true, DEVICE_SYSCLK_FREQ, SYSCTL_EPWMCLK_DIV_2, EPWM_COUNTER_MODE_UP_DOWN, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1}; // Interrupt Prototype __interrupt void modDutyCycle(void); void main(void) { // Initialize needed components epwm1IntCount = 0U; Device_init(); Device_initGPIO(); Interrupt_initModule(); Interrupt_initVectorTable(); Board_init(); SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); EPWM_configureSignal(myEPWM1_BASE, &pwmSignal1); // Set EPWM EPWM_configureSignal(myEPWM1_BASE, &pwmSignal1); SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC); //Interrupts Interrupt_enable(INT_EPWM1); EPWM_enableInterrupt(myEPWM1_BASE); EPWM_setInterruptSource(myEPWM1_BASE, EPWM_INT_TBCTR_D_CMPA); EPWM_setInterruptEventCount(myEPWM1_BASE, 1U); Interrupt_register(INT_EPWM1, &modDutyCycle); EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM for(;;) { asm ("NOP"); } } __interrupt void modDutyCycle(void) { if (epwm1IntCount > 0U) { EPWM_configureSignal(myEPWM1_BASE, &pwmSignal1); epwm1IntCount = 0U; } else { EPWM_configureSignal(myEPWM1_BASE, &pwmSignal2); epwm1IntCount++; } EPWM_clearEventTriggerInterruptFlag(myEPWM1_BASE); Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP3); }
This works if I modify the duty cycle for the first time to the new value and stop cycling through the interrupts (I get pulse width b), but if I continue cycling the EPWM stops outputting any signal at all as measured on an oscilloscope. I have looked through the program flow using breakpoints in debug mode and confirmed that my EPWM_INT_TBCTR_D_CMPA is indeed being properly triggered and cleared each cycle, and that the logical flow of my program snippet is correct.
What am I missing here? Is the configure signal function in ex11 doing something I'm not aware of/something not appropriate for implementing this? This is seems to be an issue stemming from being unfamiliar with this family of controllers as opposed to a fundamental logic/programming problem.