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.

UCD3138: UCD3138 Training Lab 4 - Can't get Closed Loop to work

Part Number: UCD3138

Hello,

I have been trying to get the Training Lab 4 (closed loop control of DPWM's) to work for the past few days with no success. I have tried writing to various different registers etc. but cannot get closed loop control to work. I see a burst of pulses for a very short time (very narrow pulses for about 10ms's) before they completely die off. I'm not sure what I'm doing wrong, I have followed everything on the training videos word for word, including setting up the jumpers on the UCD3138 development board. Lab 2 and 3 work well, and I am able to fully control the code...so I know my development environment is set up correct. I will really appreciate some help on this as I am trying to implement this closed loop code into my project. I have attached the code below.

#define MAIN 1

#include "system_defines.h"
#include "Cyclone_Device.h"
#include "pmbus_commands.h"
#include "pmbus_common.h"
#include "pmbus_topology.h"
#include "variables.h"
#include "functions.h"
#include "software_interrupts.h"
#include "cyclone_defines.h"
#include "stdio.h"

#define PCLK_PERIOD 4.0e-9
#define PERIOD_SECONDS 10.0e-6
#define PERIOD ((int)(PERIOD_SECONDS/PCLK_PERIOD)<<4)
#define EVENT1 (int)(PERIOD*0.00)
#define EVENT2 (int)(PERIOD*0.25)
#define EVENT3 (int)(PERIOD*0.50)
#define EVENT4 (int)(PERIOD*0.75)

int ram_eadcdac;
// comment for hyperknob [min=0, max=16383, step=256]

void init_dpwm0(void)
{

Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 0; // disable locally for init
Dpwm0Regs.DPWMCTRL0.bit.CLA_EN = 1; // default is 1 - use cla

Dpwm0Regs.DPWMPRD.all = PERIOD; // use .all for all values, so that the scaling matches
Dpwm0Regs.DPWMEV1.all = EVENT1; // set EVENT 1 to 0% (start) of period
Dpwm0Regs.DPWMEV2.all = EVENT2; // set EVENT 2 to 25% of period
Dpwm0Regs.DPWMEV3.all = EVENT3; // set EVENT 3 to 50% of period
Dpwm0Regs.DPWMEV4.all = EVENT4; // set EVENT 4 to 75% of period

Dpwm0Regs.DPWMSAMPTRIG1.all = (PERIOD * 3)/4; //3/4 of period
Dpwm0Regs.DPWMCTRL2.bit.SAMPLE_TRIG_1_EN = 1; //enable 1 sample trigger
Dpwm0Regs.DPWMCTRL1.bit.EVENT_UP_SEL = 1; //update at end of period
Dpwm0Regs.DPWMCTRL0.bit.PWM_MODE = 0; //normal mode (this is NOT the default)

Dpwm0Regs.DPWMCTRL0.bit.PWM_EN = 1; // enable DPWM0 locally
}

void init_filter0(void)
{ //PID setup taken from a random topology - lab is for closing loop, not tuning parameters.

//Filter0Regs.FILTERCTRL.bit.USE_CPU_SAMPLE = 1; // enable CPU Sample
//Filter0Regs.CPUXN.bit.CPU_SAMPLE = 200; // set to 1/4
Filter0Regs.FILTERKPCOEF0.bit.KP_COEF_0 = 800;
Filter0Regs.FILTERKICOEF0.bit.KI_COEF_0 = 50;
Filter0Regs.FILTERKDCOEF0.bit.KD_COEF_0 = 1500;
Filter0Regs.FILTERKDALPHA.bit.KD_ALPHA_0 = -1;

Filter0Regs.FILTERKICLPHI.bit.KI_CLAMP_HIGH = 0x7FFFFF;
Filter0Regs.FILTERKICLPLO.bit.KI_CLAMP_LOW = 0;

Filter0Regs.FILTEROCLPHI.bit.OUTPUT_CLAMP_HIGH = 0x7FFFFF;
Filter0Regs.FILTEROCLPLO.bit.OUTPUT_CLAMP_LOW = 0;

Filter0Regs.FILTERCTRL.bit.FILTER_EN = 1;
// enable OK here, because nothing will happen until DPWM and front end are globally enabled

// Better option for handling shoot through - uses full dynamic range of filter
LoopMuxRegs.FILTERKCOMPA.bit.KCOMP0 = (PERIOD/2) >> 4; // KCOMP is at 4 ns, period is at 250 ps
Filter0Regs.FILTERCTRL.bit.OUTPUT_MULT_SEL = 0; // select half period kcomp for output multiplier
}

void init_loop_mux(void)
{
LoopMuxRegs.DPWMMUX.bit.DPWM0_FILTER_SEL = 0; // use filter 0 for DPWM 0
LoopMuxRegs.SAMPTRIGCTRL.bit.FE0_TRIG_DPWM0_EN = 1; // use DPWM0 for filter0 sample trigger
}

void global_enable(void)
{
union GLBEN_REG glben_store; // collect global enable bits for simultaneous use
glben_store.all = 0;
glben_store.bit.DPWM0_EN = 1;
glben_store.bit.FE_CTRL0_EN = 1;
LoopMuxRegs.GLBEN = glben_store;
}

void init_front_end0(void)
{
FeCtrl0Regs.EADCDAC.bit.DAC_VALUE = 0;
FeCtrl0Regs.EADCCTRL.bit.AFE_GAIN = 2;
}

void main()
{
// enable JTAG
MiscAnalogRegs.IOMUX.all = 0;

//---------------------------------------------------------------------------
// IMPORTANT: READ BELOW, OR CODE MAY NOT EXECUTE CORRECTLY
//---------------------------------------------------------------------------
// tie pin FAULT3 to ground for normal operation
// tie pin FAULT3 to 3.3V to clear checksum
//if(GioRegs.FAULTIN.bit.FLT3_IN == 1)
{
//clear_integrity_word();
}

#if (UCD3138|UCD3138064)
MiscAnalogRegs.CLKTRIM.bit.HFO_LN_FILTER_EN = 0;
MiscAnalogRegs.CSTRIM.bit.RESISTOR_TRIM =23; //28;
#endif

init_pmbus(0x58); // initialize PMBus handler
init_dpwm0(); // initialize DPWM0
init_filter0();
init_loop_mux();
init_front_end0();
global_enable();
ram_eadcdac = 1000;//FeCtrl0Regs.EADCDAC.bit.DAC_VALUE; //initialize hyperknob

/* GioRegs.FAULTINTENA.bit.FLT2_INT_EN = 1;
GioRegs.FAULTDIR.bit.FLT2_DIR = 0;
GioRegs.FAULTIN.bit.FLT2_IN = 0; //1 - Fault pin must be driven High. 0 - Driven Low to trigger Interrupt
GioRegs.FAULTINTPOL.bit.FLT2_INT_POL = 0; //Interrupt will be generated on 1 = Rising Edge, 0 = Falling Edge

disable_interrupt();
disable_fast_interrupt(); //make sure fast interrupt is disabled
write_reqmask( CIMINT_ALL_FAULT_PIN); //enable pwm2cmp and DPWM0 interrupt(End of 16th period)(int-priority29)
write_firqpr (CIMINT_ALL_FAULT_PIN); // DPWM0 interrupt(End of 16th period) is mapped to FIQ
enable_fast_interrupt();
enable_interrupt();

MiscAnalogRegs.GLBIOEN.bit.DPWM1A_IO_EN = 1;
MiscAnalogRegs.GLBIOOE.bit.DPWM1A_IO_OE = 1;
MiscAnalogRegs.GLBIOVAL.bit.DPWM1A_IO_VALUE = 0;*/


for(;;)
{
pmbus_handler();
FeCtrl0Regs.EADCDAC.bit.DAC_VALUE = ram_eadcdac+1; //put hyperknob value into register
}
}


//#pragma INTERRUPT(c_int00,RESET)

void c_int00(void)
{
main();
}

  • I assume that you are putting some non-zero value into the EADCDAC.bit.DACVALUE? If you leave a zero in there, I would expect no pulses, since you're trying to put nothing out.

    If you put a non-zero value into DACVALUE, and still don't get pulses, then I'd suggest putting lab 3 back in and varying the pulse width to vary the voltage output. You should be able to see the voltage on the EAP0 pin going up and down as you change the pulse width in the open loop mode. That's the big reason we use open loop. We test the device configuration and the external hardware in detail before we close the loop.

    If that's working, then go back to lab 4 and use the memory debugger to look at the inputs and outputs of the filter, and the EADC raw value to see where the breakdown is.