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.

AM263P4: LP-AM263P4: Issue with Complementary PWM Generation

Part Number: AM263P4
Other Parts Discussed in Thread: SYSCONFIG

Hello,

I am working with the LP-AM263P4 development board and am generating complementary PWM signals using PWM1 and PWM3.

My target configuration is:

  • PWM Frequency: 20 kHz
  • PWM Period: 50 µs

However, I am not getting the expected output. Initially, the PWM waveform matches the expected behavior, but after some time it changes unexpectedly. This pattern repeats at the same interval every time.

I have attached:

  • Output waveform screenshots
  • ti_driver_open_close.c source file

My main application code is shown below:

void configAQ(uint32_t base)
{
    EPWM_setActionQualifierAction(
        base,
        EPWM_AQ_OUTPUT_A,
        EPWM_AQ_OUTPUT_HIGH,
        EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);

    EPWM_setActionQualifierAction(
        base,
        EPWM_AQ_OUTPUT_A,
        EPWM_AQ_OUTPUT_LOW,
        EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
}

void epwm_deadband_main(void *args)
{
    /* Open drivers to open the UART driver for console */
    Drivers_open();
    Board_driversOpen();

    DebugP_log("EPWM DeadBand Test Started ...\r\n");
    DebugP_log("EPWM DeadBand Example runs for 5 Secs \r\n");

    /* Start all the EPWM Timebase Counters */
    SOC_setMultipleEpwmTbClk(gEpwmTbClkSyncDisableMask, TRUE);

    configAQ(CONFIG_EPWM1_BASE_ADDR);
    configAQ(CONFIG_EPWM3_BASE_ADDR);

    uint16_t duty, duty2;
    duty = 40;
    duty2 = 40;

    EPWM_setCounterCompareValue(
        CONFIG_EPWM1_BASE_ADDR,
        EPWM_COUNTER_COMPARE_A,
        (5000 * duty) / 100);

    EPWM_setCounterCompareValue(
        CONFIG_EPWM3_BASE_ADDR,
        EPWM_COUNTER_COMPARE_A,
        (5000 * duty2) / 100);

    while(1);

    ClockP_sleep(5);

    /* Stop all the EPWM Timebase Counters */
    SOC_setMultipleEpwmTbClk(gEpwmTbClkSyncDisableMask, FALSE);

    DebugP_log("EPWM DeadBand Test Passed!!\r\n");
    DebugP_log("All tests have passed!!\r\n");

    Board_driversClose();
    Drivers_close();
}

I would appreciate your help in understanding the following:

  1. Why does the PWM waveform change periodically after initially producing the expected output?
  2. What could be causing this behavior?
  3. Is there any issue with my Action Qualifier configuration or the overall PWM setup?
  4. How can I fix this issue to obtain a stable 20 kHz complementary PWM output?

Additionally, I have another question:

  • How can I independently control each PWM module (for example, PWM1 and PWM3) instead of operating them only as complementary outputs? I would appreciate any guidance or example demonstrating how to control each PWM separately.

Thank you for your support.
ANBURAJA A

 

Note:
0 is PWM1 A , 1 is PWM1 B

2 is PWM3 A, 3 is PWM3 B

pwm2.pngpwm.png

ti_drivers_config.c ti_drivers_open_close.c 

  • Hello,

    First, PWM1 and PWM3 are separate ePWM modules. Complementary outputs are normally generated using the A and B outputs of the same ePWM module, for example EPWM1A and EPWM1B, with the dead-band submodule generating the complementary signal. EPWM1 and EPWM3 do not need to operate as a complementary pair.


    In the current code, the ePWM time-base clocks are started before the Action Qualifier and compare values are updated:

    SOC_setMultipleEpwmTbClk(gEpwmTbClkSyncDisableMask, TRUE);
    
    configAQ(CONFIG_EPWM1_BASE_ADDR);
    configAQ(CONFIG_EPWM3_BASE_ADDR);

    It is recommended to keep TBCLK disabled while configuring TBPRD, CMPA, Action Qualifier, dead-band, phase, and synchronization settings. Start the counters only after both modules have been completely configured.

    Starting TBCLK before changing the configuration can cause an initial partial or unexpected PWM cycle, although it should not normally cause a continuous periodic change.

    Action Qualifier settings are defined twice. The Action Qualifier is configured once by SysConfig in ti_drivers_open_close.c and then overwritten again by configAQ().
    The generated configuration currently uses:

    EPWM_AQ_OUTPUT_HIGH on up-count CMPA
    EPWM_AQ_OUTPUT_LOW on down-count CMPA

    However, configAQ() changes this to:

    EPWM_AQ_OUTPUT_LOW on up-count CMPA
    EPWM_AQ_OUTPUT_HIGH on down-count CMPA

    The code after while(1) is unreachable
    The following code will never execute:

    while(1);
    
    ClockP_sleep(5);
    SOC_setMultipleEpwmTbClk(gEpwmTbClkSyncDisableMask, FALSE);
    
    

    The infinite loop prevents the application from reaching ClockP_sleep() or stopping the PWM. This is not the source of a periodic waveform change, but the code should be cleaned up based on whether the PWM should operate continuously or for five seconds.


    To generate complementary signals from one module, configure EPWMxA as the source waveform and use the dead-band module to produce EPWMxA and EPWMxB.

    Best Regards,

    Masoud

  • Hello,

    Thank you for your response and for the clarification.

    I understand that ePWM1 and ePWM3 are independent ePWM modules, and that complementary outputs are normally generated using EPWMxA and EPWMxB of the same module through the dead-band submodule. My intention is to use EPWM1A/EPWM1B and EPWM3A/EPWM3B as two independent PWM modules.

    Regarding your comments:

    1. TBCLK configuration

      I understand that TBCLK should remain disabled while configuring TBPRD, CMPA, Action Qualifier, dead-band, synchronization, and other ePWM settings, and should only be enabled after the configuration is complete. I will modify my initialization sequence accordingly.

    2. Action Qualifier configuration

      I also noticed that the Action Qualifier is configured by SysConfig in ti_drivers_open_close.c, and then overwritten by my configAQ() function. I will keep only one configuration to avoid conflicts.

    3. Infinite loop

      I agree that the code after while(1) is unreachable, and I will clean this up depending on whether the PWM is intended to run continuously or for a limited duration.

    However, I still have one concern regarding the waveform behavior.

    Even after considering the above points, the PWM output initially appears correct and then changes periodically before returning to the expected waveform, repeating at a fixed interval. Since the compare values are written only onceI would not during initialization and are never updated afterward, expect the waveform to change during runtime.

    Could you please help me understand:

    • Is there any background process, synchronization event, or shadow-register reload mechanism that could periodically modify the PWM output?

    • Could the SysConfig-generated initialization be reconfiguring the ePWM registers after startup?

    • Are there any additional ePWM registers (such as shadow-load, synchronization, phase loading, trip-zone, or event-trigger settings) that I should verify to identify the cause of this periodic behavior?

    Additionally, I have a few questions regarding ePWM control:

    1. I am currently using:

      SOC_setMultipleEpwmTbClk(gEpwmTbClkSyncDisableMask, TRUE);
      

      As I understand it, this enables the time-base clocks for all ePWM modules included in gEpwmTbClkSyncDisableMask. Is there a way to enable the TBCLK for only one specific ePWM module (for example, only ePWM1 or only ePWM3) instead of enabling all modules together?

    2. Is it possible to independently control the A and B outputs of the same ePWM module? For example, can I configure EPWM0B to generate PWM while keeping EPWM0A continuously LOW (or disabled)? Likewise, can I enable only EPWM0A while keeping EPWM0B disabled?

    3. If independent control of EPWMxA and EPWMxB is supported, could you please recommend the appropriate configuration (Action Qualifier, Dead-Band, Output Swap, GPIO configuration, or any other required settings), or point me to an SDK example demonstrating this use case?

    Finally, for my application I would like to control ePWM1 and ePWM3 independently (different duty cycles and potentially different frequencies), rather than using them as a complementary pair. Is there a recommended SDK example or reference project that demonstrates configuring and controlling multiple independent ePWM modules simultaneously?

    Thank you for your assistance and guidance.

  • Hello,

    All EPWM are independent by nature and you can configure them separately. For best practice, you can create a sync out source from one of them and sync the rest of EPWM with that.

    Regarding the periodic waveform change, there is no background process in the SDK that periodically reconfigures the ePWM registers after initialization. Similarly, SysConfig only generates the initialization code and does not continue modifying the ePWM configuration at runtime. Since your compare values are written only once, the waveform should remain stable unless some other part of the application is modifying the ePWM registers or an external event is affecting the module.

    Regarding your additional questions:

    1. SOC_setMultipleEpwmTbClk() enables the TBCLK for all ePWM modules included in the mask. There is currently no API to enable TBCLK for only a single ePWM module, as the TBCLK synchronization is controlled globally for the selected modules.

    2. Yes, EPWMxA and EPWMxB can be controlled independently. If you do not use the dead-band module, both outputs have independent Action Qualifier settings. For example, you can configure EPWMxB to generate a PWM waveform while forcing EPWMxA low (or vice versa) using the Action Qualifier continuous software force or by configuring the AQ actions appropriately.

    3. For independent PWM generation on multiple modules (such as ePWM1 and ePWM3), simply configure each ePWM module independently with its own TBPRD, CMPA, AQ, and synchronization settings. The epwm_up_aq SDK example is a good starting point, and you can extend it to multiple ePWM instances

    Best,

    Masoud