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.

How to calculate Reference for 2P2Z module

dear all,

I need to set the reference so that i get 80% duty cycle in the first phase. then i set the reference to 0 so that i get 0% duty cycle. But i do not understand how to calculate & set the reference.

i found that the output never falls completely to zero.

Can anybody tell how to calculate the reference to get proper duty cycle.

my code:

//_IQn(A)=A*(2^n)
//eg. if A=800, then IQ14(A)=(2^14)*800=16384*800=13107200
//DSP2803x_Headers_nonBIOS.cmd

//====================================================================================include file
#include "DSP28x_Project.h" // Device Headerfile and Examples Include File
#include <string.h>
#include <stdint.h>

#include "DSP2803x_EPwm_defines.h"
#include "DPlib.h"
#include "IQmathLib.h"
#include "Weldcntlr_Settings.h"

//=====================================
#define dead_angle_us 10

//====================================================================================variable definition

//--------------------------------------------------------------------------------------
// C address variables for use with ASM module terminals
long AdcNetBus[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // used as consecutive addresses for ADC_Rslts
long IrefNetBus1=0,IrefNetBus2=0; // used as address for Iref1
long UoutNetBus1=0,UoutNetBus2=0; // used as address for Uout1

#pragma DATA_SECTION(CNTL_2P2Z_CoefStruct1, "CNTL_2P2Z_Coef");
#pragma DATA_SECTION(CNTL_2P2Z_CoefStruct2, "CNTL_2P2Z_Coef");

struct CNTL_2P2Z_CoefStruct CNTL_2P2Z_CoefStruct1;
struct CNTL_2P2Z_CoefStruct CNTL_2P2Z_CoefStruct2;

// ADC configuration variables
int ChSel[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int TrigSel[16]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int ACQPS[16]={6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6};

//---------------------------------------------------------------------------
// Used to indirectly access all EPWM modules
volatile struct EPWM_REGS *ePWM[] =
{ &EPwm1Regs, //intentional: (ePWM[0] not used)
&EPwm1Regs,
&EPwm2Regs,
&EPwm3Regs,
&EPwm4Regs
};

long Iset1=0,Iset2=0; // Control loop 1 target
int16 Gui_Iset1=0,Gui_Iset2=0; //Q15

// Boost channel 1 2P2Z Control loop gains
long Pgain1=50; //50
long Igain1=1; //
long Dgain1=20; //

//Scaling Constants (values found via spreadsheet; exact value calibrated per board)
int16 K_Vin=19439; // 0.593 in Q15
int16 K_Vout=20452; // 0.625 in Q15
int16 iK_Iset=24824; //24824; // 1.515 in Q14
int16 K_Iout=21627; // 0.660 in Q15

// These are defined by the linker (see F2808.cmd)
extern Uint16 RamfuncsLoadStart;
extern Uint16 RamfuncsLoadSize;
extern Uint16 RamfuncsRunStart;

//====================================================================================DPLIB pointer definition
extern long *ADCDRV_1ch_Rlt1;
extern long *ADCDRV_1ch_Rlt2;

extern long *CNTL_2P2Z_Ref1, *CNTL_2P2Z_Fdbk1, *CNTL_2P2Z_Out1;
extern long *CNTL_2P2Z_Coef1;

extern long *CNTL_2P2Z_Ref2, *CNTL_2P2Z_Fdbk2, *CNTL_2P2Z_Out2;
extern long *CNTL_2P2Z_Coef2;

extern long *PWMDRV_ComplPairDB_Duty1;
extern long *PWMDRV_ComplPairDB_Duty2;

// Voltage terminal pointers
extern long *ADCDRV_1ch_Rlt9;
extern long *ADCDRV_1ch_Rlt10;
extern long *ADCDRV_1ch_Rlt11;
extern long *ADCDRV_1ch_Rlt12;

//====================================================================================function definition
// ---------------------------------- USER -----------------------------------------
void ADC_SOC_CNF(int ChSel[], int Trigsel[], int ACQPS[], int IntChSel, int mode);
void PWM_ComplPairDB_CNF(int16 n, int16 period, int16 mode, int16 phase);
void PWM_ComplPairDB_UpdateDB (int16 n, int16 DbRed, int16 DbFed);


//======================================================================
void main(void)
{
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// DeviceInit(); // Device Life support & GPIO
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

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

EALLOW;
//-------------------------------------------------output
GpioCtrlRegs.GPADIR.bit.GPIO0=1;
GpioCtrlRegs.GPADIR.bit.GPIO1=1;
GpioCtrlRegs.GPADIR.bit.GPIO2=1;
GpioCtrlRegs.GPADIR.bit.GPIO3=1;

GpioCtrlRegs.GPAMUX1.bit.GPIO0=1; //ePWM selected
GpioCtrlRegs.GPAMUX1.bit.GPIO1=1; //ePWM selected
GpioCtrlRegs.GPAMUX1.bit.GPIO2=1; //ePWM selected
GpioCtrlRegs.GPAMUX1.bit.GPIO3=1; //ePWM selected

//-------------------------------------------------
EDIS;

DINT;

InitPieCtrl();

IER = 0x0000;
IFR = 0x0000;

InitPieVectTable();


memcpy((uint16_t *)&RamfuncsRunStart,(uint16_t *)&RamfuncsLoadStart, (unsigned long)&RamfuncsLoadSize);

InitFlash();


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


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// Step 5. User specific code,
// Only used if running from FLASH
// Note that the variable FLASH is defined by the build configuration
// #ifdef FLASH
// Copy time critical code and Flash setup code to RAM
// The RamfuncsLoadStart, RamfuncsLoadSize, and RamfuncsRunStart
// symbols are created by the linker. Refer to the linker files.
// memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);

// Call Flash Initialization to setup flash waitstates
// This function must reside in RAM
//InitFlash(); // Call the flash wrapper init function
// #endif //(FLASH)
//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
// ---------------------------------- USER -----------------------------------------
// 2 pole / 2 Zero compensator coefficients (B2, B1, B0, A2, A1) are mapped to the
// simpler 3 coefficients P, I, D to allow for trial & error intuitive tuning via
// CCS WatchWindow or GUI Sliders. Note: User can modify if needed and assign full
// set of 5 coef.

// Boost channel 1 2P2Z Coefficient init
CNTL_2P2Z_CoefStruct1.b2 = _IQ16(Dgain1);
CNTL_2P2Z_CoefStruct1.b1 = _IQ16(Igain1 - Pgain1 - Dgain1);
CNTL_2P2Z_CoefStruct1.b0 = _IQ16(Pgain1 + Igain1 + Dgain1);
CNTL_2P2Z_CoefStruct1.a2 = _IQ26(0.0);
CNTL_2P2Z_CoefStruct1.a1 = _IQ26(1.0);
CNTL_2P2Z_CoefStruct1.max = _IQ14(DMAX);
CNTL_2P2Z_CoefStruct1.min = _IQ14(DMIN);

// Boost channel 2 2P2Z Coefficient init
CNTL_2P2Z_CoefStruct2.b2 = _IQ16(Dgain1);
CNTL_2P2Z_CoefStruct2.b1 = _IQ16(Igain1 - Pgain1 - Dgain1);
CNTL_2P2Z_CoefStruct2.b0 = _IQ16(Pgain1 + Igain1 + Dgain1);
CNTL_2P2Z_CoefStruct2.a2 = _IQ26(0.0);
CNTL_2P2Z_CoefStruct2.a1 = _IQ26(1.0);
CNTL_2P2Z_CoefStruct2.max = _IQ14(DMAX);
CNTL_2P2Z_CoefStruct2.min = _IQ14(DMIN);


//==================================================================================
// INCREMENTAL BUILD OPTIONS - NOTE: select via ProjectSettings.h
//==================================================================================

// ---------------------------------- USER -----------------------------------------
#define prd 1200 // 1200 Period count = 50 KHz @ 60 MHz
//#define prd 600 // 600 Period count = 100 KHz @ 60 MHz
//#define prd 300 // 300 Period count = 200 KHz @ 60 MHz
//#define prd 200 // 200 Period count = 300 KHz @ 60 MHz
//#define prd 150 // 150 Period count = 400 KHz @ 60 MHz

#define Iout1R AdcResult.ADCRESULT1 //Q12
#define Vout1R AdcResult.ADCRESULT9 //Q12
#define Iout2R AdcResult.ADCRESULT2 //Q12
#define Vout2R AdcResult.ADCRESULT10 //Q12
#define VinR AdcResult.ADCRESULT12 //Q12

// ADC Channel Selection
ChSel[0] = 2; // Dummy read for first sample bug //ADCINA2
// ChSel[1] = 1; // A2 - Iout1 - blue //ADCINA1
ChSel[1] = 2; // A2 - Iout1 - blue //ADCINA2
ChSel[2] = 1; // A2 - Iout1 - blue //ADCINA1

// ADC Trigger Selection
TrigSel[0] = ADCTRIG_EPWM1_SOCA; // ePWM1, ADCSOCA //ADCTRIG5 – ePWM1, ADCSOCA
// TrigSel[1] = ADCTRIG_EPWM2_SOCA; // ePWM2, ADCSOCA //ADCTRIG7 – ePWM2, ADCSOCA
TrigSel[1] = ADCTRIG_EPWM1_SOCA; // ePWM1, ADCSOCA //ADCTRIG5 – ePWM1, ADCSOCA
TrigSel[2] = ADCTRIG_EPWM2_SOCA; // ePWM2, ADCSOCA //ADCTRIG7 – ePWM2, ADCSOCA

//adc2 will be triggered by EPWM1_SOCA & EPWM2_SOCA signal

// void ADC_SOC_CNF(int ChSel[], int Trigsel[], int ACQPS[], int IntChSel, int mode)
ADC_SOC_CNF(ChSel, TrigSel, ACQPS, 16, 0);

// void PWM_ComplPairDB_CNF(int16 n, int16 period, int16 mode, int16 phase)
PWM_ComplPairDB_CNF(1, prd, 1, 0);
PWM_ComplPairDB_CNF(2, prd, 0, 0);

// void PWM_ComplPairDB_UpdateDB(int16 n, int16 dbRED, int16 dbFED)
PWM_ComplPairDB_UpdateDB(1,5,4);
PWM_ComplPairDB_UpdateDB(2,5,4);

// Configure ePWMs to generate ADC SOC pulses
EPwm1Regs.ETSEL.bit.SOCAEN = 1; // Enable ePWM1 SOCA pulse
EPwm1Regs.ETSEL.bit.SOCASEL = ET_CTR_PRD; // SOCA from ePWM1 Zero event
EPwm1Regs.ETPS.bit.SOCAPRD = ET_3RD; // Trigger ePWM1 SOCA on every 3rd event

// Configure ePWMs to generate ADC SOC pulses
EPwm2Regs.ETSEL.bit.SOCAEN = 1; // Enable ePWM2 SOCA pulse
EPwm2Regs.ETSEL.bit.SOCASEL = ET_CTR_PRD; // SOCA from ePWM1 Zero event
EPwm2Regs.ETPS.bit.SOCAPRD = ET_3RD; // Trigger ePWM1 SOCA on every 3rd event

DPL_Init(); // DPL ASM ISR init

//----------------------------------------------------------------------// Closed-Loop Current
// Lib Module connection to "nets"
//----------------------------------------

// Boost 1 connections
CNTL_2P2Z_Ref1 = &IrefNetBus1; // point to Iref1
ADCDRV_1ch_Rlt1 = &AdcNetBus[1];
CNTL_2P2Z_Fdbk1 = &AdcNetBus[1]; // point to Iout1
CNTL_2P2Z_Coef1 = &CNTL_2P2Z_CoefStruct1.b2; // point to first coeff of 1st loop
CNTL_2P2Z_Out1 = &UoutNetBus1; // point to 2P2Z Uout1
PWMDRV_ComplPairDB_Duty1 = &UoutNetBus1;

// Boost 2 connections
CNTL_2P2Z_Ref2 = &IrefNetBus2; // point to Iref1
ADCDRV_1ch_Rlt2 = &AdcNetBus[2];
CNTL_2P2Z_Fdbk2 = &AdcNetBus[2]; // point to Iout1
CNTL_2P2Z_Coef2 = &CNTL_2P2Z_CoefStruct2.b2; // point to first coeff of 1st loop
CNTL_2P2Z_Out2 = &UoutNetBus2; // point to 2P2Z Uout1
PWMDRV_ComplPairDB_Duty2 = &UoutNetBus2;

// Voltage connections
ADCDRV_1ch_Rlt9 = &AdcNetBus[9];
ADCDRV_1ch_Rlt10 = &AdcNetBus[10];
ADCDRV_1ch_Rlt11 = &AdcNetBus[11];
ADCDRV_1ch_Rlt12 = &AdcNetBus[12];

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
//=================================================================================
// INTERRUPT & ISR INITIALISATION (best to run this section after other initialisation)
//=================================================================================
EALLOW;
PieVectTable.EPWM1_INT = &DPL_ISR; // Map Interrupt
PieVectTable.EPWM2_INT = &DPL_ISR; // Map Interrupt

PieCtrlRegs.PIEIER3.bit.INTx1 = 1; // Enable EPWM1 int in PIE group 3
PieCtrlRegs.PIEIER3.bit.INTx2 = 1;

// Configure ISR trigger
EPwm1Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // INT on Period event
EPwm1Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm1Regs.ETPS.bit.INTPRD = ET_3RD; // Generate ISR INT on every 3rd event

// Configure ISR trigger
EPwm2Regs.ETSEL.bit.INTSEL = ET_CTR_PRD; // INT on Period event
EPwm2Regs.ETSEL.bit.INTEN = 1; // Enable INT
EPwm2Regs.ETPS.bit.INTPRD = ET_3RD; // Generate ISR INT on every 3rd event

// Enable Peripheral, global Ints and higher priority real-time debug events:
IER |= M_INT3; // Enable CPU INT3 connected to EPWM1-6 INTs:

EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM

//configure one shot s/w force TRIP ZONE
EPwm1Regs.TZSEL.bit.OSHT1=TZ_ENABLE;
EPwm1Regs.TZCTL.bit.TZA=TZ_FORCE_LO;

EPwm2Regs.TZSEL.bit.OSHT1=TZ_ENABLE;
EPwm2Regs.TZCTL.bit.TZA=TZ_FORCE_LO;

EDIS;


//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
while(1){

Gui_Iset1 =8000;
Iset1 = ((long)Gui_Iset1*(long)iK_Iset) >> 5;
Gui_Iset2 =8000;
Iset2 = ((long)Gui_Iset2*(long)iK_Iset) >> 5;
IrefNetBus1 = Iset1;
IrefNetBus2 = Iset2;

DELAY_US(2000000);

Gui_Iset1 =0;
Iset1 = ((long)Gui_Iset1*(long)iK_Iset) >> 5;
Gui_Iset2 =0;
Iset2 = ((long)Gui_Iset2*(long)iK_Iset) >> 5;
IrefNetBus1 = Iset1;
IrefNetBus2 = Iset2;

DELAY_US(2000000);

}

//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
}

  • Tapas,

    Please can you provide more information about what you are doing?  

    From the code it looks like two independent boost converters, but in current mode control.  It also seems there is a GUI involved.  Please could you elaborate which reference?  Thanks.

    Regards,

    Richard

  • dear Richard,

    Thank you very much for your reply. Actually there is no GUI involved. I found the equation from one of the sample projects (LED boost) in Control Suite. Right now I am just trying to implement the 2P2Z module & verify the PWM duty cycle properly changes with reference. I am using a current feedback from LED & physically connected to ADCIN1. Now in s/w module connection, the current feedback is connected to ADCDRV_1ch_1 block. the output from this block (ADCDRV_1ch_Rlt1) is connected to the feedback (CNTL_2P2Z_Fdbk1) of CNTL_2P2Z_1 block. The output of this block (CNTL_2P2Z_Out1) is connected to (PWMDRV_ComplPairDB_Duty1) input of PWMDRV_ComplPairDB_1 block. I am getting complemented waveform in EPWM1A & EPWM1B. Now my question is:

    1. What value should i provide to Ref (CNTL_2P2Z_Ref1) of CNTL_2P2Z_1 block to get maximum & 50% output in LED. I mean how to calculate that?

    2. on the other hand what should i provide in the ref. to completely turn off the LED. In my application even if i put 0 in ref the LED glowing with very low intensity. How to turn off completely?

    Tapas

  • DMIN and DMAX are used to saturate the controller output. I don’t see the equations for DMIN and DMAX in your code, but if DMIN is greater than ‘0’ the controller output will never be zero.

    I don’t know exactly what you try to accomplish, is it you want to merge two feedback signals, current and voltage?

  • Tapas,

    Can you just confirm your setup is similar to Figure 19 in the application note which describes the color LED kit?

    www.ti.com/.../sprabr7.pdf

    You are operating in closed loop, in which case 2P2Z will force the duty cycle to take whatever value it needs to regulate the loop. If you want to verify operation of the PWM and LED string, I recommend first running in open loop (build level 1 in the above document) and checking the feedback is correct. Section 7.4 describes this. An Iref reference of 0.5 should correspond to 50% duty. Check also that 0% duty corresponds to the LED fully off.

    In build level 2 you close the loop. From this point onwards the Iref reference value corresponds to a current set point. The soft start module sets controls ramp-up and ramp-down, so in steady state Iset and Iref will be the same. There is a note in the document that you should not increase the Iset beyond 0.100. The implication is that this value corresponds to the maximum rated current of 350mA. Logically 50% brightness is Iset = 0.05. If I get confirmation on this I will post back.

    An Iref or Iset of 0.0 should give zero output. In your case I'm guessing there is a small offset in the feedback path which results in a non-zero current at zero set-point. What is the ADCDRV_1ch_Rlt1 variable in this condition?

    Regards,

    Richard