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.

TMS320F28379D: EPWM - double pulse generation

Part Number: TMS320F28379D

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.

  • Hi James,

    What am I missing here?

    The approach you took is good. What I suspect is happening here is that when you call configureSignal() within the interrupt you are actually reconfiguring your entire EPWM setup. This is not something you want to do as your EPWM is currently running. What I would suggest is for you to modify your compare values directly instead of calling configureSignal(), since that is the only part that is changing. The counter compare values can be modified through the EPWM_setCounterCompareValue() function which take in as inputs the epwm base, counter compare submodule, and the value you want for the counter compare. As an example,  EPWM_setCounterCompareValue(myEPWM1_BASE, EPWM_COUNTER_COMPARE_A, 200);

    Best Regards,

    Marlyn

  • Thanks for the pointers. Gave me a fair bit to consider as far as implementation goes moving forward. As it turns out I was missing some 

    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);
    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    statements. The EPWM_configureSignal calls were ok. Still working on the trip zone items to isolate the two pulses I want, but I'll open a new question to address that if needed. Marking this issue closed.

    James