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: HRPWM DeadBande not working

Former Member
Former Member
Part Number: TMS320F280049C


Hi,

I am working on a project with HRPWM, in this project we want to have a precise duty cycle but the 3 starting cycles present a problem.

To avoid this we thought to use the DeadBande but it is not working on my project.

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);

#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();

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


    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_HRPWM);

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_TBCLKSYNC);

    SysCtl_enablePeripheral(SYSCTL_PERIPH_CLK_EPWM4);

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

    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_ZERO);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPA);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPA);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_UP_CMPB);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_B, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_DOWN_CMPB);
    EPWM_setActionQualifierAction(EPWM4_BASE, EPWM_AQ_OUTPUT_A, EPWM_AQ_OUTPUT_NO_CHANGE, EPWM_AQ_OUTPUT_ON_TIMEBASE_PERIOD);

    //
    //
    // DEAD BAND
    //
    //
    EPWM_setDeadBandDelayPolarity(EPWM4_BASE, EPWM_DB_FED, EPWM_DB_POLARITY_ACTIVE_LOW);

    EPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_RED, true);
    EPWM_setRisingEdgeDelayCount(EPWM4_BASE, 1000);
    EPWM_enableRisingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
    EPWM_setRisingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_RED_LOAD_ON_CNTR_ZERO);

    EPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_FED, true);
    EPWM_setFallingEdgeDelayCount(EPWM4_BASE, 1000);
    EPWM_enableFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
    EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);


    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);
    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_HIGH);
    EPWM_enableTripZoneSignals(EPWM4_BASE, EPWM_TZ_SIGNAL_OSHT1);

    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_TZA, EPWM_TZ_ACTION_LOW);         //When it trips
    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_TZB, EPWM_TZ_ACTION_HIGH);        //When it trips
    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_DCAEVT1, EPWM_TZ_ACTION_LOW);     //When event occurs (if trip not enabled)
    EPWM_setTripZoneAction(EPWM4_BASE, EPWM_TZ_ACTION_EVENT_DCBEVT1, EPWM_TZ_ACTION_HIGH);    //When event occurs (if trip not enabled)
    EPWM_selectDigitalCompareTripInput(EPWM4_BASE, EPWM_DC_TRIP_TRIPIN4, EPWM_DC_TYPE_DCAH);
    EPWM_setTripZoneDigitalCompareEventCondition(EPWM4_BASE, EPWM_TZ_DC_OUTPUT_A1, EPWM_TZ_EVENT_DCXH_HIGH);
    EPWM_selectDigitalCompareTripInput(EPWM4_BASE, EPWM_DC_TRIP_TRIPIN4, EPWM_DC_TYPE_DCBH);
    EPWM_setTripZoneDigitalCompareEventCondition(EPWM4_BASE, EPWM_TZ_DC_OUTPUT_B1, EPWM_TZ_EVENT_DCXH_HIGH);
    EPWM_enableTripZoneSignals(EPWM4_BASE, EPWM_TZ_SIGNAL_DCAEVT1 | EPWM_TZ_SIGNAL_DCBEVT1);
}

//
// End of File
//

Thank you in advance for your answer !

Lorend Dalloshi

  • Yes unfortunately the HR DEADBAND cannot skip the 3 Cycle limitation either. There isn't a workaround using deadband. What exactly is your application? Maybe we can find an alternate solution.

  • Former Member
    0 Former Member in reply to Nima Eskandari

    I would like to have an accurate duty cycle but currently I cannot be accurate between 0% and 0.3% because of this limitation. By using the DeadBand I thought I could access this range of duty cycle by losing the possibility to reach 100% of the duty cycle.

    Thanks for your answer.

    Dalloshi Lorend

  • Former Member
    0 Former Member in reply to Former Member

    I found the problem, it is in the initialization of the deadbande.

    in my code i used to initialize like this 

        EPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_FED, true);
        EPWM_setFallingEdgeDelayCount(EPWM4_BASE, 1000);
        EPWM_enableFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
        EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);

    but the shadowload set the register to 0 to make it work i had to initialize like this

        EPWM_setDeadBandDelayMode(EPWM4_BASE, EPWM_DB_FED, true);
        EPWM_enableFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE);
        EPWM_setFallingEdgeDelayCountShadowLoadMode(EPWM4_BASE, EPWM_FED_LOAD_ON_CNTR_ZERO);
        EPWM_setFallingEdgeDelayCount(EPWM4_BASE, 1000);
        

    Dalloshi Lorend