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.

TMS320F280049C: DEADBAND with duty HRPWM

Former Member
Former Member
Part Number: TMS320F280049C

Hi,

I am working on a project with HRPWM.

In this project we want to be quite precise in the first PWM values. To do this we use the DEADBAND which allows us to use the HRPWM from 1% of the duty cycle while losing the precision at 100% of PWM

I generate a HRPMW4A and a HRPMW4B with the DEADBAND, the HRPMW4B is generated from the HRPWM4A and is inverted.

Using the HRPWM I noticed that the delay between the rising edge of PWMxA and the falling edge of PWMxB and vice versa changes if the CMPAHR or CMPBHR values are changed.
In my project I should have a delay of 100ns, this value does not change with the different values of CMPA and CMPB but by changing CMPAHR and CMPBHR it can go down to 91ns.

I have seen in other posts that the HRPWM comes after the DEADBAND which might explain why this only applies to CMPxHR and not CMPx.
Is there a way to avoid this while keeping the HRPWM for duty with the DEADBAND?

Here is my code.

//#############################################################################
//
// FILE:    gpio_ex1_setup.c
//
// TITLE:   Device GPIO Setup
//
//! \addtogroup driver_example_list
//! <h1> Device GPIO Setup </h1>
//!
//! Configures the device GPIO into two different configurations
//! This code is verbose to illustrate how the GPIO could be setup.
//! In a real application, lines of code can be combined for improved
//! code size and efficiency.
//!
//! This example only sets-up the GPIO. Nothing is actually done with
//! the pins after setup.
//!
//! \b In \b general: \n
//!  - All pullup resistors are enabled.  For ePWMs this may not be desired.
//!  - Input qual for communication ports (CAN, SPI, SCI, I2C) is asynchronous
//!  - Input qual for Trip pins (TZ) is asynchronous
//!  - Input qual for eCAP and eQEP signals is synch to SYSCLKOUT
//!  - Input qual for some I/O's and __interrupts may have a sampling window
//
//#############################################################################
//
//
// $Copyright:
// Copyright (C) 2022 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 "sfo_v8.h"

void epwm_gpio_init(void);
void epwm_init_module(void);
void hrpwm_init_module(void);

#define EPWM_CMPC_VALUE   0U                        // Set to 0 here (we want to send to the beginning of period)
#define EPWM_SYNC_EVENT_COUNT   1U                  // Send frame every period here (can go up to 15)

#define PWMCLK     100U   // PWM module clock in Mhz
#define PWM_FREQ   100U   // Transmission PWM frequency in Khz

//
//  SFO calibration flags
//
#define STATUS_SUCCESS    1
#define STATUS_FAIL       0


#define ADC_NORM   (float)0.00048828125

//
//  SFO calibration flags
//
#define STATUS_SUCCESS    1
#define STATUS_FAIL       0


float32_t duty      = 0;
uint32_t dutyFine   = 0;

uint16_t status;

//
// 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.
//
int MEP_ScaleFactor;

//
// Used by SFO library (ePWM[0] is a dummy value that isn't used)
//
volatile uint32_t ePWM[2] = {0, EPWM4_BASE};

uint16_t period = (PWMCLK / (float)PWM_FREQ) * 1000U;

//
// Main
//
void main(void)
{
    //
    // Initializes system control, device clock, and peripherals
    //
    Device_init();

    //
    // Initializes PIE and clear PIE registers. Disables CPU interrupts.
    // and clear all CPU interrupt flags.
    //
    Interrupt_initModule();

    //
    // Initialize the PIE vector table with pointers to the shell interrupt
    // Service Routines (ISR).
    //
    Interrupt_initVectorTable();

    epwm_gpio_init();

    status = SFO_INCOMPLETE;
    while(status == SFO_INCOMPLETE)
    {
        status = SFO();
        if(status == SFO_ERROR)
        {
            ESTOP0;   // SFO function returns 2 if an error occurs & # of MEP
        }              // steps/coarse step exceeds maximum of 255.
    }

    epwm_init_module();
    hrpwm_init_module();

    //
    // Enable Global Interrupt (INTM) and realtime interrupt (DBGM)
    //
    EINT;
    ERTM;

    for(;;)
    {
        dutyFine = (duty*2560);

        HRPWM_setCounterCompareValue(EPWM4_BASE, HRPWM_COUNTER_COMPARE_A, dutyFine);
        HRPWM_setCounterCompareValue(EPWM4_BASE, HRPWM_COUNTER_COMPARE_B, dutyFine);
    }
}

void epwm_gpio_init(void)
{
    //
    // GPIO EPWM INIT
    //
    GPIO_setPadConfig(6, GPIO_PIN_TYPE_STD);
    GPIO_setPadConfig(7, GPIO_PIN_TYPE_STD);

    GPIO_setPinConfig(GPIO_6_EPWM4_A);                     //
    GPIO_setPinConfig(GPIO_7_EPWM4_B);                     //

}

void epwm_init_module(void)
{
    EPWM_setPeriodLoadMode(EPWM4_BASE, EPWM_PERIOD_DIRECT_LOAD);

    //
    // Set-up TBCLK
    //
    EPWM_setTimeBasePeriod(EPWM4_BASE, (period - 1U));

    //
    // Set Compare values
    //
    EPWM_setCounterCompareValue(EPWM4_BASE, EPWM_COUNTER_COMPARE_A, 0); //(period / 2)

    EPWM_setCounterCompareValue(EPWM4_BASE, EPWM_COUNTER_COMPARE_B, 0); //(period / 2)

    //
    // Set up shadowing
    //
    EPWM_setCounterCompareShadowLoadMode(EPWM4_BASE, EPWM_COUNTER_COMPARE_A, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    EPWM_setCounterCompareShadowLoadMode(EPWM4_BASE, EPWM_COUNTER_COMPARE_B, EPWM_COMP_LOAD_ON_CNTR_ZERO);

    //
    // Set phase shift value to zero & disable phase shift loading & sync
    // output.
    //
    EPWM_setPhaseShift(EPWM4_BASE, 0U);
    EPWM_disablePhaseShiftLoad(EPWM4_BASE);

    //
    // Set time base counter value to zero.
    //
    EPWM_setTimeBaseCounter(EPWM4_BASE, 0U);

    //
    // Set emulation mode to free run.
    //
    EPWM_setEmulationMode(EPWM4_BASE, EPWM_EMULATION_FREE_RUN);


    //
    // Set counter mode to up-counter.
    //
    EPWM_setTimeBaseCounterMode(EPWM4_BASE, EPWM_COUNTER_MODE_UP);

    //
    // Configure TBCLK. TBCLK = EPWMCLK/(highSpeedPrescaler * pre-scaler)
    //
    EPWM_setClockPrescaler(EPWM4_BASE, EPWM_CLOCK_DIVIDER_1, EPWM_HSCLOCK_DIVIDER_1);

    //
    // Configure Action Qualifier
    //
    //
    // Enable shadow mode for CMPA & CMPB values.
    //
    EPWM_setActionQualifierShadowLoadMode(EPWM4_BASE, EPWM_ACTION_QUALIFIER_A, EPWM_AQ_LOAD_ON_CNTR_ZERO);
    EPWM_setActionQualifierShadowLoadMode(EPWM4_BASE, EPWM_ACTION_QUALIFIER_B, EPWM_AQ_LOAD_ON_CNTR_ZERO);

    //
    // Action for ePWM4A output. Set output to high when TBCTR = 0.
    // Set output to low when TBCTR = CMPA value.
    //
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);

    //
    // Action for ePWM4B output. Set output to high when TBCTR = 0.
    // Set output to low when TBCTR = CMPB value.
    //
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_HIGH, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_LOW, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);

    //
    //
    // DEAD BAND
    //
    //

//    EPWM_enableRisingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
//    EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO);
//    EPWM_setRisingEdgeDelayCount(EPWM4_BASE, 10);

//    EPWM_enableFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
//    EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);
//    EPWM_setFallingEdgeDelayCount(EPWM4_BASE, 10);
}

void hrpwm_init_module(void)
{
    //
    // Initialize HRPWM extension.
    //
    HWREGH(EPWM4_BASE + EPWM_O_CMPA) = (1U << 8U);
    HRPWM_setCounterCompareShadowLoadEvent(EPWM4_BASE, HRPWM_CHANNEL_A, HRPWM_LOAD_ON_CNTR_ZERO);

    HWREG(EPWM4_BASE + EPWM_O_CMPB) |= (1U << 8U);
    HRPWM_setCounterCompareShadowLoadEvent(EPWM4_BASE, HRPWM_CHANNEL_B, HRPWM_LOAD_ON_CNTR_ZERO);

    //
    // Configure MEP edge & control mode for channel A & B. MEP Edge control is
    // on falling edge. Control mode is duty control.
    //
    HRPWM_setMEPEdgeSelect(EPWM4_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_CTRL_FALLING_EDGE);
    HRPWM_setMEPControlMode(EPWM4_BASE, HRPWM_CHANNEL_A, HRPWM_MEP_DUTY_PERIOD_CTRL);


    HRPWM_setMEPEdgeSelect(EPWM4_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_CTRL_FALLING_EDGE);
    HRPWM_setMEPControlMode(EPWM4_BASE, HRPWM_CHANNEL_B, HRPWM_MEP_DUTY_PERIOD_CTRL);

    //
    //Enable Automatic Conversion mode
    //
    HRPWM_enableAutoConversion(EPWM4_BASE);

    //
    // Disable high-resolution period control.
    //
    HRPWM_disablePeriodControl(EPWM4_BASE);

    //
    //
    //DEADBANDE
    //
    //
    HRPWM_setDeadBandDelayPolarity(EPWM4_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);

    HRPWM_setDeadbandMEPEdgeSelect(EPWM4_BASE, HRPWM_DB_MEP_CTRL_RED_FED);

    HRPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_RED, true);
    HRPWM_setRisingEdgeDelayLoadMode(EPWM4_BASE, HRPWM_LOAD_ON_CNTR_ZERO);

    HRPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_FED, true);
    HRPWM_setFallingEdgeDelayLoadMode(EPWM4_BASE, HRPWM_LOAD_ON_CNTR_ZERO);




    HRPWM_setRisingEdgeDelay(EPWM4_BASE, 1280);
    HRPWM_setFallingEdgeDelay(EPWM4_BASE, 1280);


}

//
// End of File
//

Thank you in advance for your answer !

Lorend Dalloshi

  • Hello Lorend,

    What is the behavior you're trying to avoid?

    Regards,
    Jason Osborn

  • Former Member
    0 Former Member in reply to Jason Osborn

    Hello Jason,

    In my project I want to generate a HRPWMA and a HRPWMB.

    I want  to generate the HRPWMB by inverting the HRPWMA using the DEADBAND.

    So my HRPWMA would be the signal Rising Edge Delayed and my PWMB would be the signal Failling Edge Delayed.

    If I don't use the HRPWM it's works fine but if i use it the delay between the two signal changes when i change the value of CMPxHR, which is not the case when i change the value of CMPA.

    I have noticed that the value of the HRPWM i send to PWMA is not inverted in the PWMB.

    For exemple i can get 15.52% duty on the PWMA and 85.42% on the PWMB instead of 85.48%.

    How I understand it it's that the HRPWM comes after the DEADBAND.

    So my questions are :

    1. Does the HRPWM come after the DEADBAND ? If not when does it come ?

    2. Is this a normal behavior ?

    3. Is there a way to invert the signal HRPWMB (PWMB with High Resolution) ?

    4. Is there a way for the DEADBAND to include the HRPWM value for the delay and the inversion ?

    Best Regards,

    Lorend Dalloshi

  • Hello Lorend,

    Thank you for the clarifications, I think I should be able to help you now!

    So, I'll answer them in order as best I can.

    1. The easiest way to put it is that the HRPWM is integrated with the Deadband- essentially, the DB is part of the way that the HRPWM operates. See figure 18-84 in section 18.15.1.1 of the device's TRM.
    2. Yes. CMPxHR is utilized to generate the HR behavior of the HRPWM- so CMPAHR affects the ePWMA signal, and CMPBHR affects ePWMB. The two are not just HR versions of the CMPx values. I believe this is described in the TRM in the HRPWM section.
    3. Yes! When using HRDB (see 4), there's a setting to invert PWMB. This should be based on PWMA, but if it appears it's not, try setting ePWMA as the source for ePWMB in the regular DB.
    4. Yes! Take a look at the High-Resolution Deadband, described in section 18.15.1.6 Deadband High Resolution Operation of the TRM.

    I hope all of that helps,

    Jason Osborn