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.

TMS320F28035: Issue with high resolution phase shift in up direction

Part Number: TMS320F28035
Other Parts Discussed in Thread: C2000WARE

Hi,

I have an issue with high-resolution PWM phase-shift on the TMS320F28035. It seems to be in the wrong phase direction when configured in up direction

I want to configure PWM with a high-resolution phase shift with the following configuration:

  • PWM1:
    • Counter in up-down mode
    • Fixed duty cycle = 50% (CMPA=Period/2)
  • PWM2:
    • Counter in up-down mode
    • Fixed duty cycle = 50% (CMPA=Period/2)
    • High-resolution phase shift
    • Phase direction : up

With “high” phase values (e.g. phase=0.01), the phase direction is in up mode as expected. But the “small” variations of phase shift (e.g. phase=0.001) are not in up direction but are in down direction.The high-resolution phase shift always works in down direction whatever the PHSDIR register value . If I configure the phase shift direction in down mode, everything is correct.

Here is the configuration of PWM 1 & 2:

(*ePWM[n]).TBCTL.bit.PRDLD = TB_IMMEDIATE;          // set Immediate load

(*ePWM[n]).TBPRD = Period;

(*ePWM[n]).TBCTR = 0;

(*ePWM[n]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;

 

(*ePWM[n]).TBPHS.half.TBPHS = 0;

(*ePWM[n]).TBCTL.bit.PHSEN = TB_DISABLE;

 

(*ePWM[n]).TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;        //used to sync EPWM(n+1)

(*ePWM[n]).TBCTL.bit.HSPCLKDIV = TB_DIV1;

(*ePWM[n]).TBCTL.bit.CLKDIV = TB_DIV1;

 

// Counter Compare SubModule Registers

(*ePWM[n]).CMPA.half.CMPA = Period/2;               // Fix duty at 50%

 

// Action Qualifier SubModule Registers

(*ePWM[n]).AQCTLA.bit.CAU = AQ_SET;

(*ePWM[n]).AQCTLA.bit.CAD = AQ_CLEAR;

 

// DeadBand Control Register

(*ePWM[n]).DBCTL.bit.IN_MODE = DBA_ALL;

(*ePWM[n]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

(*ePWM[n]).DBCTL.bit.POLSEL = DB_ACTV_HIC;          // Active Hi Complimentary

(*ePWM[n]).DBRED = 120;                              // dummy value for now

(*ePWM[n]).DBFED = 120;                              // dummy value for now

 

// ePWM(n+1) init.  EPWM(n+1) is a slave

//Time Base SubModule Register

(*ePWM[n+1]).TBCTL.bit.PRDLD = TB_SHADOW;

(*ePWM[n+1]).TBPRD = Period;

(*ePWM[n+1]).TBPRDHR = 0;

(*ePWM[n+1]).TBPHS.half.TBPHS = 0;                  // zero phase initially

(*ePWM[n+1]).TBPHS.half.TBPHSHR = (0<<8);           // zero phase initially

(*ePWM[n+1]).TBCTR = 0;

(*ePWM[n+1]).TBCTL.bit.CTRMODE = TB_COUNT_UPDOWN;

(*ePWM[n+1]).TBCTL.bit.PHSDIR = TB_UP;

(*ePWM[n+1]).TBCTL.bit.PHSEN = TB_ENABLE;

(*ePWM[n+1]).TBCTL.bit.SYNCOSEL = TB_SYNC_IN;       // Sync "flow through" mode

(*ePWM[n+1]).TBCTL.bit.HSPCLKDIV = TB_DIV1;

(*ePWM[n+1]).TBCTL.bit.CLKDIV = TB_DIV1;

 

// Counter compare submodule registers

(*ePWM[n+1]).CMPA.half.CMPA = Period/2;                    // Fix duty at 50%

(*ePWM[n+1]).CMPA.half.CMPAHR = 0;

(*ePWM[n+1]).CMPCTL.bit.SHDWAMODE = CC_SHADOW;

(*ePWM[n+1]).CMPCTL.bit.LOADAMODE = CC_CTR_PRD;

// Action Qualifier SubModule Registers

(*ePWM[n+1]).AQCTLA.bit.CAU = AQ_SET;

(*ePWM[n+1]).AQCTLA.bit.CAD = AQ_CLEAR;

 

(*ePWM[n+1]).DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;

(*ePWM[n+1]).DBRED = 120;                                   // dummy value for now

(*ePWM[n+1]).DBFED = 120;                                   // dummy value for now

 

//     Enable HiRes option

EALLOW;

(*ePWM[n+1]).HRCNFG.all = 0x0;

(*ePWM[n+1]).HRCNFG.bit.EDGMODE = HR_BEP;

(*ePWM[n+1]).HRCNFG.bit.CTLMODE = HR_PHS;

(*ePWM[n+1]).HRCNFG.bit.HRLOAD = HR_CTR_ZERO_PRD;

(*ePWM[n+1]).HRPCTL.bit.HRPE = 0;

(*ePWM[n+1]).HRMSTEP = 111;

 

//  ePWM Type 1 can auto convert the value in CMPAHR,

//  TBPHSHR or TBPRDHR to a scaled micro-edge dealy value.

(*ePWM[n+1]).HRCNFG.bit.AUTOCONV = 1;

(*ePWM[n+1]).HRPCTL.bit.TBPHSHRLOADE = 1;

(*ePWM[n+1]).TBCTL.bit.SWFSYNC = 1;

EDIS;

Is there any mistakes in the PWM configuration?

Best regards

  • Hi Fabien,

    Thanks for posting on E2E Forums!

    The PWM configuration looks correct. By high and small phase values, do you mean to say that the variation in the HR Phase values are not as per the expectations? I am unable to understand the description. Can you please elaborate a little?

    Regards,

    Aditya

  • Hi Aditya,

    Here are some measurements of the phase in 3 configurations:

    - Up direction and high resolution (in blue) => the issue I try to explain in my previous message

    - Down direction and high resolution (in orange) => correct

    - Up direction without high resolution (in grey) => correct

    I hope it's more understandable with these measures.

    Regards,

    Fabien

  • Hi Fabien,

    (*ePWM[n+1]).HRMSTEP = 111;

     

    //  ePWM Type 1 can auto convert the value in CMPAHR,

    //  TBPHSHR or TBPRDHR to a scaled micro-edge dealy value.

    (*ePWM[n+1]).HRCNFG.bit.AUTOCONV = 1;

    Any reason to write both the HRMSTEP as well as the AUTOCONV bit? The AUTOCONV bit once enabled automatically scales the TBPHSHR for HR output. For auto-conversion, you'll need to call the SFO library as well.

    Can you check  by resolving this?

  • Hi Aditya,

    There is no reason for writing the HRMSTEP, it is a copy from an old code. I deleted the line (*ePWM[n+1]).HRMSTEP = 111; but it doesn't change anything.

    I call the SFO v6 library in Main.c :

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    #include "PeripheralHeaderIncludes.h"
    #include "DSP2803x_EPWM_defines.h"
    #include "DPlib.h"
    #include "IQmathLib.h"
    #include "DCDC66-Settings.h"
    #include "DCDC66-GlobalVariables.h"
    #include "SFO_V6.h"
    #include "DSP2803x_Device.h"
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

    Regards

  • Fabien,

    I am not sure what the issue could be exactly here, hence will try to recreate this on my end. I am out of office for a couple of days so may not be able to provide an immediate check.

    By the way, I see you have used SWFSYNC set with the PWM initialization itself? Is this desired?

    Also, SFO has to be calibrated in the code. You can check that in any of the C2000Ware examples. Although, I don't think that would matter in this case, but you can add that incase you haven't.

  • Hi Aditya,

    I don't know why SWFSYNC = 1. I try with SWFSYNC = 0 but it doesn't change anything.

    In the main.c the SFO is called (copy from an old code, I didn't made any changes):

    Fullscreen
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    void C0(void)
    {
    // loop rate synchronizer for C-tasks
    if(CpuTimer2Regs.TCR.bit.TIF == 1)
    {
    CpuTimer2Regs.TCR.bit.TIF = 1; // clear flag
    //-----------------------------------------------------------
    LED_Debug(); // TOGGLE DEBUG LED
    status = SFO_INCOMPLETE;
    // Calling SFO() updates the HRMSTEP register with calibrated MEP_ScaleFactor.
    // MEP_ScaleFactor/HRMSTEP must be filled with calibrated value in order to
    // use in equations below.
    while (status== SFO_INCOMPLETE){ // Call until complete
    status = SFO();
    if (status == SFO_ERROR) {
    EALLOW;
    EPwm1Regs.HRMSTEP=111;
    EDIS;
    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

  • I don't know why SWFSYNC = 1. I try with SWFSYNC = 0 but it doesn't change anything.

    The software sync is the signal that triggers the instant as to when the phase sync should occur. Ideally speaking, this is a one-time signal when you wish to consider a specific phase shift and should not be present in the initialization of the code. You can check the implementation in TRM.