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.

TMS320F28377D: jitter on PWM when using HR mode

Part Number: TMS320F28377D
Other Parts Discussed in Thread: C2000WARE

Tool/software:


Hello,

Currently, I have an issue with the use of HRPWMs on the comparators of a TMS320F28377D. When using them in UP and DOWN counting mode with dead bands, and PWM2/3/4/5/6/7/8 are linked to PWM1. Indeed, despite using shadow mode, the CMPA and CMPAHR registers do not seem to be loaded at the same time, which causes jitter.

To verify my current configuration and check my suspicions, I tested the example code "hrpwm_ex9_dutyhr_updown_deadband_sfo" (from C2000Ware_5_04_00_00) by slightly modifying it to highlight the issue. Specifically, I modify the register value to primarily increment the CMPAHR register and make a jump of +1 on CMPA. Here is the result in the picture:
  - In 1, you can clearly see my variation with my +1 increments,
  - In 2 and 3, the jitter.



This is really not acceptable in my product; is there a way to work around this problem?

Thank you in advance.

Best regards,  
Martial ARNAUD

PS: here the test code that allows reproducing the issue

//#############################################################################
//
// FILE:   hrpwm_dutyhr_updown_deadband.c
//
// TITLE:  HRPWM Duty Control with Up-Down, Active High Complementary Deadband.
//
//! \addtogroup driver_example_list
//! <h1>HRPWM Duty Control with AHC Deadband</h1>
//!
//! This example implements High-Resolution EPWM duty control capability. The
//! example begins with a basic Active-High Complementary (AHC) output
//! on channels A and B of the EPWM module(s) by using the Dead Band submodule
//! to apply rising and falling edge delays on channel A and B respectively.
//! High-Resolution duty control is then applied on both A/B channels of the
//! EPWM module(s). HR duty control is implemented by applying the CMPAHR
//! (for channel A) and CMPBHR (for channel B) values to control both edges of
//! both EPWM channel outputs with finer granularity. The duty cycle of the
//! EPWM module(s) are updated with calculations performed in main().
//! This example also calls the following TI's MEP Scale Factor Optimizer (SFO)
//! software library V8 functions:
//!
//! \b int \b SFO(); \n
//! - Updates MEP_ScaleFactor dynamically when HRPWM is in use
//! - Updates HRMSTEP register (exists only in EPwm1Regs register space)
//!   with MEP_ScaleFactor value
//! - Returns 2 if error: MEP_ScaleFactor is greater than maximum value of 255
//!   (Auto-conversion may not function properly under this condition)
//! - Returns 1 when complete for the specified channel
//! - Returns 0 if not complete for the specified channel
//!
//! This example is intended to explain the HRPWM capabilities. The code can be
//! optimized for code efficiency. Refer to TI's Digital power application
//! examples and TI Digital Power Supply software libraries for details.
//!
//! \b External \b Connections \n
//!  - Monitor ePWM1/2/3/4 A/B pins on an oscilloscope.
//
//#############################################################################
//
//
// $Copyright:
// Copyright (C) 2013-2024 Texas Instruments Incorporated - http://www.ti.com/
//
// Redistribution and use in source and binary forms, with or without 
// modification, are permitted provided that the following conditions 
// are met:
// 
//   Redistributions of source code must retain the above copyright 
//   notice, this list of conditions and the following disclaimer.
// 
//   Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the 
//   documentation and/or other materials provided with the   
//   distribution.
// 
//   Neither the name of Texas Instruments Incorporated nor the names of
//   its contributors may be used to endorse or promote products derived
//   from this software without specific prior written permission.
// 
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// $
//#############################################################################
//
// Included Files
//
#include "driverlib.h"
#include "device.h"
#include "board.h"
#include "sfo_v8.h"
#include "stdbool.h"

//
// Defines
//
// The below TBPRD, RED, and FED values are programmed in SysConfig. Note
// that the HRPWM edges must be placed outside of the 3-clock-cycle restricted
// areas. Please see your device technical reference manual for details on this
// HRPWM duty cycle range limitation.
//
#define EPWM_TIMER_TBPRD            100UL // Time-Base Period
#define EPWM_RED                    10UL  // Rising Edge Delay
#define EPWM_FED                    10UL  // Falling Edge Delay

//
// In this example, we want to increment the CMPx values to update the HRPWM
// duty cycle during run-time. While varying CMPx, TBPRD should remain
// greater than or equal to CMPx + RED/2 and TBPRD should remain greater
// than or equal to CMPx + FED/2, otherwise one of the channels will be
// demanded low for longer than the full EPWM period. In this PWM 
// configuration, the desired CMPx range is:
// - The minimum CMPx value should be larger than the FED/2.
// - The maximum CMPx value should be smaller than (TBPRD - (RED/2)).
// These min and max values are converted to percentages to be used in main().
//
#define MIN_HRPWM_DUTY_PERCENT      ((float32_t)EPWM_FED/2)/((float32_t)EPWM_TIMER_TBPRD)*100.0
#define MAX_HRPWM_DUTY_PERCENT      ((float32_t)EPWM_TIMER_TBPRD - EPWM_RED/2)/((float32_t)EPWM_TIMER_TBPRD)*100.0

#define LAST_EPWM_INDEX_FOR_EXAMPLE    5

#define CMP_INIT_VALUE  0x4DE1
#define CMP_FINAL_VALUE 0x4E10

//
// Globals
//
float32_t dutyFine = 50.0; // Start the duty cycle at 50%

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[] =
    {0, myEPWM1_BASE, myEPWM2_BASE, myEPWM3_BASE, myEPWM4_BASE};


float32_t count;
uint32_t compCount;
uint32_t hrCompCount;

//
// Function Prototypes
//
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);

    //
    // Disable sync (Freeze clock to PWM as well)
    //
    SysCtl_disablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    //
    // Initialize EPWM modules and change EXTSYNCIN XBAR Inputs from GPIO0.
    //
    Board_init();


    //
    // 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.
    }

    //
    // 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 real-time interrupt (DBGM)
    //
    EINT;
    ERTM;

    // Initialize comparator value
    compCount = CMP_INIT_VALUE;

    for(;;)
    {
      HRPWM_setCounterCompareValue(ePWM[1], HRPWM_COUNTER_COMPARE_A, compCount);
      HRPWM_setCounterCompareValue(ePWM[1], HRPWM_COUNTER_COMPARE_B, compCount);
      HRPWM_setCounterCompareValue(ePWM[2], HRPWM_COUNTER_COMPARE_A, compCount);
      HRPWM_setCounterCompareValue(ePWM[2], HRPWM_COUNTER_COMPARE_B, compCount);

      status = SFO(); // In the background, the 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 the maximum
      }

      // Start to update comparator value 
      if(compCount != CMP_FINAL_VALUE)
      {
          compCount++;
      }
      else if (compCount == CMP_FINAL_VALUE)
      {
          compCount = CMP_INIT_VALUE;
      }
    }
    //     //
    //     // Sweep dutyFine from the minimum to maximum duty percentages.
    //     //
    //     for(dutyFine = MIN_HRPWM_DUTY_PERCENT; dutyFine < MAX_HRPWM_DUTY_PERCENT; dutyFine += 0.0001)
    //     {
    //         DEVICE_DELAY_US(1000);
    //         for(i=1; i<LAST_EPWM_INDEX_FOR_EXAMPLE; i++)
    //         {
    //             count = ((100.0 - dutyFine) * (float32_t)(EPWM_TIMER_TBPRD << 8))/100.0;
    //             compCount = (count);
    //             hrCompCount = (compCount & (0x000000FF));
    //             if (hrCompCount == 0)
    //             {
    //                 //
    //                 // Add 1 so that CMPxHR is never equal to 0.
    //                 //
    //                 compCount |= 0x00000001;
    //             }
    //             //
    //             // Update CMPA/B and their HR components.
    //             //
    //             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 the background, the 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 the 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);
//}



//
// Error - Halt debugger when called
//
void error (void)
{
    ESTOP0;         // Stop here and handle error
}

  • Hello,

    I will take a look and reply within a few days.

  • Hello Stevan,

    Thank you very much for your help. I look forward to your response.

  • Hello Martial,

    Are you just modifying the duty cycle in your application and using high-resolution register CMPAHR? Are you using by any-chance HR Deadband or HR Period sub-modules? 

  • Hello,

    As explained in my question, I am using the example code "hrpwm_ex9_dutyhr_updown_deadband_sfo" (from C2000Ware_5_04_00_00) without any configuration modifications, except for my specific processing in "hrpwm_dutyhr_updown_deadband.c".

    However, in my product, I update the duty cycle only through the CMPA/CMPAHR and CMPB/CMPBHR registers. Initially, I had HR only on the period and the comparators (which caused a jitter problem), so I tried all possible HR configurations to eliminate the issue but without success.

    Is there a better way to update the duty cycle than using the comparator values? Even if it requires changing the approach, I am open to any configuration that would eliminate this jitter.

    Here are my final requirements for my product:

    • High precision on the duty cycle,
    • Use of multiple PWM modules with complementary A and B signal generation,
    • Deadbands between A and B,
    • Synchronization of all PWMs to PWM1,
    • Phase shift between PWM modules.
  • Hello,

    Thank you for providing more details. Within what range would you need to modify your duty cycle? Duty cycle range limitations are illustrated in Figure 15-86 to Figure 15-89 of device TRM: https://www.ti.com/lit/ug/spruhm8k/spruhm8k.pdf

    This limitation imposes a duty cycle limit on the MEP. For example, precision edge control is not available all the way down to 0% duty cycle when HRPE (period-control) mode is enabled.

  • Hello,

    I am familiar with Figures 15-86 and 15-89, and normally this is not the issue. In our product, the duty cycle is adjustable only between 5% and 95%, but in most cases, it is between 40% and 60%.

    Having provided our requirements at the end of my last message above, could you please provide me with an example code that meets these criteria?

    Best regards,
    Martial

  • Hello Martial,

    This should be feasible to do with using CMPAHR method. I will check our C2000Ware examples to replicate the same problem and get back to you. 

  • Hello,

    Ok thanks.

    Remember that I am using the example code "hrpwm_ex9_dutyhr_updown_deadband_sfo" (from C2000Ware_5_04_00_00) without any configuration modifications, except for my specific processing in "hrpwm_dutyhr_updown_deadband.c" (attached to initial question).

    Best regards

  • Hello Martial,

    I ran hrpwm_ex9_dutyhr_updown_deadband_sfo from C2000Ware driverlib examples and I have not captured any jitters. I also checked your code and saw that changes you made could cause unnecessary jitter. One of the issues is that in your code CMPxHR can be value of zero and that should not be the case, which would cause jitter.

    Please refer to the C2000Ware example 9 since it achieves precise duty control, has deadband module activated, high-resolution period and complementary PWM modules. 

    Just a note, if you're using high-resolution period, user need to enable TBPHSHRLOADE bit also if they want to control phase in conjunction with the high-resolution period feature. This bit and the TBCTL[PHSEN] bit must be set to 1 when high-resolution period is enabled for up-down count mode even if TBPHSHR = 0x0000

    Would you want to use regular phase shift, or high-resolution phase shift? If you want to use high-resolution phase shift with high-resolution period, you would need to use TRREM register. Please refer to the HRPWM section of TRM for more detail: https://www.ti.com/lit/ug/spruhm8k/spruhm8k.pdf.

    Best regards