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.

TMS320F28377S: Deanband Issue by using Cycle-by-Cyle Trip Event (ADC feed Comp) to set PWM low

Part Number: TMS320F28377S
Dear Community,
I need your help. I´m very new at programming at this language and for me it is very difficult to understand all about the controller correlation. I started with some examples, but there are for me some missing informations at some places.
Now I got a PwmA that
-goes high at Zero (every cylce)
-goes off when the Comparator stae is high
-->this happens at choosen DAC Value

The PwmB is the other Way Arround
-goes off at Zero (every cylce)
-goes high when the Comparator stae is high
-->this happens at choosen DAC Value

Both PWM Highs are disconnected through a Deadband.
I know the PWMs are normally inverted by using the Deadband-Feature. But after adding the Event to switch off at a specified ADC-Value through the Comparator both PWMs are inverting again. So I started inverting the commands for PWMs and now both acting like i want it.
Picture 2

But now I recognized that there is a big missbehavior in the Deadband.
How Can I solve this and stop this kind of oscialtion?
Picture 1
Must I switch again the Polarity of the commands for that?

Thank you in adavance!!!

The whole Code will be inserted at the End and this starts now.

////////////////////////////////////////////////////////////////////////////////////////////////////

//###########################################################################
//
// FILE:   epwm_trip_zone.c
//
// TITLE:  ePWM module using Trip-Zone submodule.
//
//! \addtogroup cpu01_example_list
//! <h1> EPWM Trip Zone Module (epwm_trip_zone)</h1>
//!
//! This example configures ePWM1 and ePWM2 as follows
//!  - ePWM1 has TZ1 as one shot trip source
//!  - ePWM2 has TZ1 as cycle by cycle trip source
//!
//! Initially tie TZ1 high. During the test, monitor ePWM1 or ePWM2
//! outputs on a scope. Pull TZ1 low to see the effect.
//!
//!  \b External \b Connections \n
//!  - EPWM1A is on GPIO0
//!  - EPWM2A is on GPIO2
//!  - TZ1 is on GPIO12
//!
//! This example also makes use of the Input X-BAR. GPIO12 (the external
//! trigger) is routed to the input X_BAR, from which it is routed to TZ1.
//!
//! The TZ-Event is defined such that EPWM1A will undergo a One-Shot Trip
//! and EPWM2A will undergo a Cycle-By-Cycle Trip.
//!
//              _____________             __________________
//              |           |             |                |
//  GPIO12 -----| I/P X-BAR |-----TZ1-----| ePWM TZ Module |-----TZ-Event
//              |___________|             |________________|
//
//
//
//###########################################################################
// $TI Release: F2837xS Support Library v210 $
// $Release Date: Tue Nov  1 15:35:23 CDT 2016 $
// $Copyright: Copyright (C) 2014-2016 Texas Instruments Incorporated -
//             http://www.ti.com/ ALL RIGHTS RESERVED $
//###########################################################################

//
// Included Files
//
#include "F28x_Project.h"

//
// Defines
//
#define EXTTrig     // Leave Uncommented for Testing with External Trigger.
                    // Comment for Testing with ePWM Trigger.
#define DB_UP          1

//definitions for selecting DACH reference
#define REFERENCE_VDDA     0
#define REFERENCE_VDAC     1
//definitions for COMPH input selection
#define NEGIN_DAC          0
#define NEGIN_PIN          1
//definitions for CTRIPH/CTRIPOUTH output selection
#define CTRIP_ASYNCH       0
#define CTRIP_SYNCH        1
#define CTRIP_FILTER       2
#define CTRIP_LATCH        3

//
// Globals
//
//Uint32  EPwm6TZIntCount;
Uint32  EPwm2TZIntCount;
Uint16 EPwm2_DB_Direction;

//
// Function Prototypes
//
//void InitEPwm6Example(void);
void InitEPwm2Example(void);
//raus gestrichen
//void InitTzGpio(void);
//__interrupt void epwm6_tzint_isr(void);
__interrupt void epwm2_tzint_isr(void);
void InitEPwmGpio_TZ(void);
void InitCMPSS(void);

//
// Main
//
void main(void)
{
//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the F2837xS_SysCtrl.c file.
//
    InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the F2837xS_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
    InitGpio();

//
// enable PWM1, and PWM2
//
    //CpuSysRegs.PCLKCR2.bit.EPWM6=1;
    CpuSysRegs.PCLKCR2.bit.EPWM2=1;

//
// For this case just init GPIO pins for ePWM1, ePWM2, ePWM3
//
    InitEPwmGpio_TZ();
    //raus gestrichen
    //InitTzGpio();

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
    DINT;

//
// Initialize the PIE control registers to their default state.
// The default state is all PIE interrupts disabled and flags
// are cleared.
// This function is found in the F2837xS_PieCtrl.c file.
//
    InitPieCtrl();

//
// Disable CPU interrupts and clear all CPU interrupt flags:
//
    IER = 0x0000;
    IFR = 0x0000;

//
// Initialize the PIE vector table with pointers to the shell Interrupt
// Service Routines (ISR).
// This will populate the entire table, even if the interrupt
// is not used in this example.  This is useful for debug purposes.
// The shell ISR routines are found in F2837xS_DefaultIsr.c.
// This function is found in F2837xS_PieVect.c.
//
    InitPieVectTable();

//
// Interrupts that are used in this example are re-mapped to
// ISR functions found within this file.
//
    EALLOW; // This is needed to write to EALLOW protected registers
    //PieVectTable.EPWM6_TZ_INT = &epwm6_tzint_isr;
    PieVectTable.EPWM2_TZ_INT = &epwm2_tzint_isr;
    EDIS;   // This is needed to disable write to EALLOW protected registers

//
// Step 4. Initialize the Device Peripherals:
//
    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =0;
    EDIS;

    //InitEPwm6Example();
    InitEPwm2Example();
    // Configure Comparator COMP1H to accept POS input from pin and NEG input
    // from DAC
    //
    InitCMPSS();

    EALLOW;
    CpuSysRegs.PCLKCR0.bit.TBCLKSYNC =1;
    EDIS;

//
// Step 5. User specific code, enable interrupts:
//
    //EPwm6TZIntCount = 0;
    EPwm2TZIntCount = 0;

//
// Enable CPU INT2 which is connected to EPWM1-3 INT:
//
    IER |= M_INT1;

//
// Enable EPWM INTn in the PIE: Group 3 interrupt 1-3
//
    //PieCtrlRegs.PIEIER2.bit.INTx6 = 1;
    PieCtrlRegs.PIEIER2.bit.INTx2 = 1;

//
// Enable global Interrupts and higher priority real-time debug events:
//
    EINT;  // Enable Global interrupt INTM
    ERTM;  // Enable Global realtime interrupt DBGM

//
// Step 6. IDLE loop. Just sit and loop forever (optional):
//
    for(;;)
    {
        asm ("  NOP");
    }
}

//
// epwm1_tzint_isr - EPWM1 TZ ISR
//
/*__interrupt void epwm6_tzint_isr(void)
{
    EPwm6TZIntCount++;

    //
    // To Re-enable the OST Interrupt, do the following:
    // EALLOW;
    // EPwm1Regs.TZCLR.bit.OST = 1;
    // EPwm1Regs.TZCLR.bit.INT = 1;
    // EDIS;
    //

    //
    // Acknowledge this interrupt to receive more interrupts from group 2
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}
*/
//
// epwm2_tzint_isr - EPWM2 TZ ISR
//
__interrupt void epwm2_tzint_isr(void)
{
	//zusatz-->wird nicht gebraucht
    //GpioDataRegs.GPATOGGLE.bit.GPIO11 = 1;



    EPwm2TZIntCount++;

    //
    // Clear the flags - we will continue to take
    // this interrupt until the TZ pin goes high
    //
    EALLOW;
    EPwm2Regs.TZCLR.bit.CBC = 1;
    EPwm2Regs.TZCLR.bit.INT = 1;
    EDIS;

    //
    // Acknowledge this interrupt to receive more interrupts from group 2
    //
    PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
}


//
// InitEPwm2Example - Initialize EPWM2 configuration
//
void InitEPwm2Example()
{
    //
    // Enable TZ1 as one cycle-by-cycle trip sources
    //
    EALLOW;
    //Für komplettes PWM-Modul
    EPwm2Regs.TZSEL.bit.CBC1 = 1;

    //
    // Set TZA
    //
    EPwm2Regs.TZCTL.bit.TZA = TZ_FORCE_LO;
    //
    EPwm2Regs.TZCTL.bit.TZB = TZ_FORCE_HI;
    //
    // Enable TZ interrupt
    //
    //Für komplettes PWM-Modul
    EPwm2Regs.TZEINT.bit.CBC = 1;
    EDIS;

    EPwm2Regs.TBPRD = 250;                       // Set timer period
    EPwm2Regs.TBPHS.bit.TBPHS = 0x0000;           // Phase is 0
    EPwm2Regs.TBCTR = 0x0000;                     // Clear counter

    //
    // Setup TBCLK
    //
    EPwm2Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP;//UP;//UPDOWN; // Count up
    EPwm2Regs.TBCTL.bit.PHSEN = TB_DISABLE;        // Disable phase loading
    EPwm2Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1;//TB_DIV4;        // Clock ratio to SYSCLKOUT
    EPwm2Regs.TBCTL.bit.CLKDIV = TB_DIV1;//TB_DIV4;          // Slow just to observe on
                                                   // the scope.

    //
    // Setup compare
    //
    EPwm2Regs.CMPA.bit.CMPA = 0;

    // Set actions
    //
    EPwm2Regs.AQCTLB.bit.ZRO =AQ_CLEAR;
	EPwm2Regs.AQCTLA.bit.ZRO =AQ_SET;
    // Set actions
    //
/*
    EPwm2Regs.AQCTLA.bit.CAU = AQ_CLEAR;             // Set PWM2A on CAU
    EPwm2Regs.AQCTLA.bit.CAD = AQ_SET;           // Clear PWM2A on CAD
    EPwm2Regs.AQCTLB.bit.CBU = AQ_SET; //Clear PWM2B on CAU
    EPwm2Regs.AQCTLB.bit.CBD = AQ_CLEAR;//Set PWM2B on CAD
*/

    /////////////////////////////////////////////////////////////////////////////////
    //Hinzufügen der Deadband Einstellungen
    //Dreht alle PWm EInstellungen um
        // Active Low complementary PWMs - setup the deadband
        //
        EPwm2Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
        EPwm2Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;//DB_ACTV_LOC;
        EPwm2Regs.DBCTL.bit.IN_MODE = DBA_ALL;
        EPwm2Regs.DBRED.bit.DBRED = 2;//EPWM2_MIN_DB;
        EPwm2Regs.DBFED.bit.DBFED = 2;//EPWM2_MIN_DB;
        EPwm2_DB_Direction = DB_UP;
        //
        // Interrupt where we will modify the deadband
        //
        EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_ZERO;     // Select INT on Zero event
        EPwm2Regs.ETSEL.bit.INTEN = 1;                // Enable INT
        EPwm2Regs.ETPS.bit.INTPRD = ET_3RD;           // Generate INT on 3rd event
        //////////////////////////////////////////////////////////////////////////
//Einstellungen für die Weiterleitung aus der x-Bar ins Trip-Zone-Sub-Modul
/////////////////////////////////////////////////////////////////////////////////
        EALLOW;
        //
        //Configure DCB to be TRIP4
        //
        //EPwm8Regs.TZDCSEL.bit.DCBEVT1 = TZ_DCBH_HI;
        EPwm2Regs.TZDCSEL.bit.DCBEVT2 = TZ_DCBH_HI;//Abänderung in CBC
        //Hier kann noch die Polarität eingestellt werden und was so passiert

        //EPwm8Regs.DCTRIPSEL.bit.DCBHCOMPSEL = 0xF;
        EPwm2Regs.DCTRIPSEL.bit.DCBHCOMPSEL = 0xF;//kann so bleiben alle Trips sind aktiv
        //EPwm8Regs.DCBHTRIPSEL.bit.TRIPINPUT4 = 1;
        EPwm2Regs.DCBHTRIPSEL.bit.TRIPINPUT4 = 1; //Input 1 selected as combinational ORed input to DCBH mux

        //
        //Configure DCB as OST
        //
        //EPwm8Regs.TZSEL.bit.DCBEVT1 = 1;
        //Enable DCBEVT2 as a CBC trip source for this ePWM module
        EPwm2Regs.TZSEL.bit.DCBEVT2 = 1;//Abänderung in CBC
        //Erweiterung um A
        EPwm2Regs.TZSEL.bit.DCAEVT2 = 1;
        //noch möglich --> Enable TZ1 as a CBC trip source for this ePWM module

        //
        //Configure DCB path to be unfiltered & async
        //
        //EPwm8Regs.DCBCTL.bit.EVT1SRCSEL = DC_EVT1;
        EPwm2Regs.DCBCTL.bit.EVT2SRCSEL = DC_EVT2;//Abänderung in CBC
        //Erweiterung um A
        EPwm2Regs.DCACTL.bit.EVT2SRCSEL = DC_EVT2;
        //EPwm8Regs.DCBCTL.bit.EVT1FRCSYNCSEL = DC_EVT_ASYNC;
        EPwm2Regs.DCBCTL.bit.EVT2FRCSYNCSEL = DC_EVT_ASYNC; //Abänderung in CBC
        //Erweiterung um A
        EPwm2Regs.DCACTL.bit.EVT2FRCSYNCSEL = DC_EVT_ASYNC;

        CpuSysRegs.PCLKCR0.bit.TBCLKSYNC = 1;

        //
        //Configure TRIP4 to be CTRIP1H
        //
        EPwmXbarRegs.TRIP4MUX0TO15CFG.bit.MUX0 = 0;

        //
        //Enable TRIP4 Mux for Output
        //
        EPwmXbarRegs.TRIP4MUXENABLE.bit.MUX0 = 1;

        //
        // Clear trip flags
        //
        //EPwm8Regs.TZCLR.bit.OST = 1;
        EPwm2Regs.TZCLR.bit.DCBEVT2 = 1;
        //Erweiterung um A
        EPwm2Regs.TZCLR.bit.DCAEVT2 = 1;
        //EPwm8Regs.TZCLR.bit.INT = 1;
        EPwm2Regs.TZCLR.bit.INT = 1;
        //NOTE: No further EPWMx_TZINT PIE interrupts will be generated
        //until the flag is cleared. If the TZFLG[INT] bit is cleared and any of
        //the other flag bits are set, then another interrupt pulse will be
        //generated. Clearing all flag bits will prevent further interrupts.

        //
        //Enable DCB interrupt
        //
        //EPwm8Regs.TZEINT.bit.OST = 1;
        EPwm2Regs.TZEINT.bit.DCBEVT2 = 1;
        //Erweiterung um A
        EPwm2Regs.TZEINT.bit.DCAEVT2 = 1;
        EDIS;
/////////////////////////////////////////////////////////////////////////////////
}

//
// InitTzGpio - Initialize TZ GPIOs
//
/*
void InitTzGpio(void)
{
    //
    // For External Trigger, GPIO12 as the trigger for TripZone
    //
    GpioCtrlRegs.GPAPUD.bit.GPIO12 = 0;    // Enable pull-up on GPIO12 (TZ1)

    GpioCtrlRegs.GPAQSEL1.bit.GPIO12 = 3;  // Asynch input GPIO12 (TZ1)

    EALLOW;
    InputXbarRegs.INPUT1SELECT = 12;
    EDIS;

    //
    // For monitoring when the TZ Interrupt has been entered
    //

}
*/

//
// InitEPwmGpio_TZ - Initialize EPWM1A and EPWM2A GPIOs
//
void InitEPwmGpio_TZ(void)
{
    EALLOW;
    GpioCtrlRegs.GPAPUD.bit.GPIO2 = 1;    // Disable pull-up on GPIO2 (EPWM2A)
    GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 1;   // Configure GPIO2 as EPWM2A
    GpioCtrlRegs.GPAPUD.bit.GPIO3 = 1;    // Disable pull-up on GPIO3 (EPWM2B)
    GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 1;   // Configure GPIO3 as EPWM2B
    EDIS;
}

//
// End of file
//

//
// InitCMPSS - Initialize CMPSS1 and configure settings
//
void InitCMPSS(void)
{
    EALLOW;

    //
    //Enable CMPSS
    //
    Cmpss1Regs.COMPCTL.bit.COMPDACE = 1;

    //
    //NEG signal comes from DAC
    //
    Cmpss1Regs.COMPCTL.bit.COMPHSOURCE = NEGIN_DAC;

    //
    //Use VDDA as the reference for DAC
    //
    Cmpss1Regs.COMPDACCTL.bit.SELREF = REFERENCE_VDDA;

    //
    //Set DAC to midpoint for arbitrary reference
    //
    Cmpss1Regs.DACHVALS.bit.DACVAL = 1048;

    //
    // Configure CTRIPOUT path
    // Asynch output feeds CTRIPH and CTRIPOUTH
    //
    Cmpss1Regs.COMPCTL.bit.CTRIPHSEL = CTRIP_ASYNCH;
    //Cmpss1Regs.COMPCTL.bit.CTRIPOUTHSEL = CTRIP_ASYNCH;

    //
    // Configure CTRIPOUTH output pin
    // Configure OUTPUTXBAR3 to be CTRIPOUT1H
    //
    //OutputXbarRegs.OUTPUT3MUX0TO15CFG.bit.MUX0 = 0;

    //
    //Enable OUTPUTXBAR3 Mux for Output
    //
    //OutputXbarRegs.OUTPUT3MUXENABLE.bit.MUX0 = 1;
    EDIS;
}

  • Hi Basti36,

    I want to confirm the issue. The polarity of the PWMs is now correct for your application, but you are posting due to the issues with the extra pulse being created on the edges of the PWM. Is that correct?

    Can you also confirm which PWM channels correlate to the color of waveforms shown in your images?

    Regards,

    Kris

  • Hi Kris,

    Yes, the polarity of the PWMs is now correct for my application. The extra pulse being created on the edges of the PWM is the Problem. How can this be solved?
    Sorry for the confusing Post. The pasting Result wasn‘t shown on my browser and now I am only on my phone.
    Regards,

    Basti
  • Basti,

    Thanks for the clarification. I had edited my previous post afterwards so you probably didn't see it in the email notification, but can you also confirm which PWM channels correlate to the color of waveforms shown in your images?

    Thanks,
    Kris
  • Hi Kris,

    Channel 1 (yellow - Pwm2A) goes high at Zero every Cycle and goes low when the Channel 3 (blue) reaches the compare Value of 1048 (only to test the DAC). Blue is a saw-tooth input signal. The Channel 2 (red - Pwm2B) goes every Cycle at Zero on low and high at the reached Compare-Value. The System counts up from 0 to 250 for a PWM cycle of 100kHz.
    Regards,

    Basti
  • Hi Kris,
    I am still working on this Problem, but I missd to say, that this extra edge only happens when the Pwm2A switching to low with the Trip-Event.
    (Pwm2B the other Way around. Extra edge at switching to high on the Trip-Event)

    Regards

    Basti

  • I think I figured the problem out. It is caused by the asynchrony of the PWM cycle and my measured signal, what is driven by a extern function generator and trips the comparator. For this case the signal-form is worsening the result, because the saw tooth rising edge is not perfect constructed in this short time. So I tested the same with a rectangle signal form and there is no extra edge in this cases( fall; rise ).

    To prove this finally it would be helpfull to set an other GPIO high only at Zero of the PWM Cyle for a minimal time to show on an oscilloscope, dass dort ein neuer Zyklus beginnt.
    How can I do this on aeasy Way? (GPIO high signal at every cycle start.)

  • Hi Basti,

    Sounds like great progress. If EPWM3 is available, I would recommend to configure it to create your pulse. The basic idea is use EPWM2 to generate a SYNCOUT to EPWM3's SYNCIN. This will align the timers (there will be a few cycle variation for propagation delay).

    The best way to get exact results will be setup EPWM3 similar to EPWM2 to begin with to generate the same waveform. Expect to see some phase shift on EPWM3. You can then use the TBPHS register to shift EPWM3 so that they are aligned. It's usually a value of around TBPHS=3 in the slave PWM to get it aligned.

    You can now modify EPWM3's action qualifier to generate a pulse on the zero event.

    Regards,
    Kris

  • Hi Kris, there is still a problem with a the extra edge.
    Ok, the last post from me was more a thesis than a proof answer.

    But now I can say that the extra edge only happens when the PWm is forced to go low by the cycle-by-Cycle-Event triggered by the comparator.

    How can I avoid this extra edge?

    I m trying to use a blanking-window. The Window has to be set when the comparator has been triggered the event. But at the Momment I cant set the window Offset dynamicly. Is this possible or is there a other to do this and avoid these edge?

    Regards Basti

  • Basti,

    I think this is what you were saying in a previous post, but it sounds like this is an issue with the comparator momentarily activating/de-activating due to a borderline value.

    Have you tried activating the filter in the comparator trigger?

    Regards,
    Kris
  • Another option if you don't want to add delay in the reaction time from the comparator event to the change in PWM is to use the T1 and T2 events instead of a CBC trip. Take a look at the AQTSRCSEL register for further information.

    They have the same effect you are looking for, but I think are more appropriate for what you are looking to do. They can be configured to force the PWM outputs to a state just like the trip, but when the condition clears they don't release the force. It behaves just like a compare event but can be an input from the comparator.
  • Hi Kris,
    sorry for the long pause. I was working on other projects.
    Yes, it seems there is a issue with the comparator activating/deactivating due to a borderline value. But this activates a CBC-Event and this activates a Trip. The Trip sets the PWMA low und PWMB high. How it is possible that it switch once again, after setting the Outputs (all in on PWM-Cycle).

    Or a flag issue, that resets the CBC-Event direct after the set.

    The filter after the comparator is activated.

    Regards Basti
  • Hi Kris,
    the filter is the best way to prevent irregular switching while another half bridge switches.
    By the way the information in the technical references are to small for me to use it right.

    Did I understand it right? When the condition of setting clears at a CBC-event than the output also switches wthin the same PWM Periode?

    Regards Basti