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.

TMS320F28069: DAC/Ramp Generator

Part Number: TMS320F28069
Other Parts Discussed in Thread: CONTROLSUITE

Hi,

I am trying to implement a ramp generator ( saw tooth type) using the DAC sub-module for peak current mode DC converter slope compensation, based on the info discussed in this app note:

http://www.ti.com/lit/an/sprabe7a/sprabe7a.pdf

I have written the code, but I  need to test it. Can anyone tell me how to view the ramp on the scope or on the emulator( I know there is a feature for graphing data while in debug mode).

I need to make sure that the ramp starts as soon as PWM1 goes high and keep decreasing by the slope value I set till it gets to zero by the end of each PWM cycle.

Thank you!

  • farid,

    There's no direct means of seeing the ramp generator on the scope. You can indirectly measure it by routing the comparator output to a GPIO pin, driving a known DC voltage, and measuring the time between the start of EPWM period vs when the comparator output trips.

    -Tommy
  • Thanks! That was my plan B.

  • One more related question:

    I need to update the value of CompxRegs.RAMPMAXREF_SHDW each PWM cycle. Would that be an issue if it gets updated in the mid of a PWM cycle, what I mean is: would the previous value gets overwritten, or this value will be overwritten only at the end of PWM cycle? if this is the case, would it help if I generate an interrupt at the beginning of each PWM cycle where I update CompxRegs.RAMPMAXREF_SHDW?
  • farid,

    The SHADOW registers are designed specifically to buffer mid-cycle updates of values.  The SHADOW registers are ignored by the ramp generator until a PWMSYNC event is received, which prompts the hardware to copy the SHADOW values into the ACTIVE registers where they can take effect.

    -Tommy

  • Hi,
    I tried verifying that my ramp is working properly. With the scope I was looking at COMP1OUT while I am changing input voltage on the non-inverting pin of comparator1. I set Comp1Regs.RAMPMAXREF_SHDW= 65472 ( I assume this corresponds to 3.3V) , and Comp1Regs.RAMPDECVAL_SHDW = 20;

    I kept changing the DC voltage for Comp1A pin. I was able to notice that the PWMA duty cycle keeps increasing as I decrease the DC voltage., but COMP1OUT output stays low. The only time COMP1OUT goes high is when my DC input at Comp1A pin is around 3.3V which is the value I set for RAMPMAXREF_SHDW.

    I was expecting to see the output of COMP1OUT toggles PWM every cycle( based on the DC input voltage at Comp1A , so that I can measure /verify the slope of my ramp.

    Can anyone tells me why this is happening. Thank you!

    Below is the code for my configuration:

    EALLOW;
    Comp1Regs.COMPCTL.bit.COMPDACEN = 1; // Power up Comparator locally
    Comp1Regs.COMPCTL.bit.COMPSOURCE = 0; // Connect the inverting input to internal DAC
    Comp1Regs.DACCTL.bit.FREE_SOFT = 0; /* Emulation mode behavior, stop immediately */
    Comp1Regs.DACCTL.bit.DACSOURCE = 1; // 0 - DACVAL; 1 - Internal ramp for slope compensation

    Comp1Regs.COMPCTL.bit.QUALSEL = 0; // Comparator output must be active for 4 consecutive clocks before resetting the RAMP
    Comp1Regs.DACCTL.bit.RAMPSOURCE = 0; // 0 - PMW1; 1 - PWM2,...so on
    Comp1Regs.RAMPDECVAL_SHDW = slopeval;
    EPwm1Regs.HRPCTL.bit.PWMSYNCSEL = 1; // PWM SYNC generated at CTR = ZRO for synchronizing internal ramp
    Comp1Regs.COMPCTL.bit.CMPINV = 0; // Comparator Output passed

    Comp1Regs.RAMPMAXREF_SHDW= 65472;
    EDIS;


    EALLOW;
    EPwm1Regs.TZSEL.bit.DCAEVT2 = 1; /* Digital compare, output A, cycle by cycle */
    EPwm1Regs.TZCTL.bit.TZA = TZ_FORCE_LO; /* EPWM1A will go low */
    EPwm1Regs.TZCTL.bit.TZB = TZ_NO_CHANGE; /* EPWM1B has no action */

    EPwm1Regs.DCTRIPSEL.bit.DCAHCOMPSEL = DC_COMP1OUT;
    EPwm1Regs.TZDCSEL.bit.DCAEVT2 = TZ_DCAH_HI;

    EPwm1Regs.DCACTL.bit.EVT2SRCSEL = DC_EVT2; /* DCAEVT2 = DCAEVT2 (not filtered) */
    EPwm1Regs.DCACTL.bit.EVT2FRCSYNCSEL = DC_EVT_ASYNC; /* Take async path */
    EPwm1Regs.DCFCTL.bit.PULSESEL = 0; /* Time-base counter equal to period (TBCTR =TBPRD) */
    EPwm1Regs.DCFCTL.bit.BLANKINV = 0; /* Blanking window inverted */
    EPwm1Regs.DCFCTL.bit.BLANKE = 0;//1; /* Blanking Window Enable */
    EPwm1Regs.DCFCTL.bit.SRCSEL = 0; /* Source Is DCAEVT1 Signal */
    EDIS;
    EPwm1Regs.DCFWINDOW = 0; /* 0 length blanking window */
    EPwm1Regs.DCFOFFSET = 0; //25; /* 420ns blanking window offset & then blanking window begins */
    EDIS;
  • Can anyone comment on my question above please!
  • farid,

    Are you also initializing the ADC? I have an impression that the comparator shares some resources with the ADC so they may both need to be powered up to work.

    If that doesn't work, it might be easier to debug the comparator by setting RAMPDECVAL to 0 so that it's given a static DAC reference value.

    -Tommy
  • Yes, I am using this ADC as well. I am calling the function below in main().

    void InitAdc(void)
    {
    extern void DSP28x_usDelay(Uint32 Count);

    // *IMPORTANT*
    // The Device_cal function, which copies the ADC calibration values from TI reserved
    // OTP into the ADCREFSEL and ADCOFFTRIM registers, occurs automatically in the
    // Boot ROM. If the boot ROM code is bypassed during the debug process, the
    // following function MUST be called for the ADC to function according
    // to specification. The clocks to the ADC MUST be enabled before calling this
    // function.
    // See the device data manual and/or the ADC Reference
    // Manual for more information.

    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.ADCENCLK = 1;
    (*Device_cal)();
    EDIS;

    // To powerup the ADC the ADCENCLK bit should be set first to enable
    // clocks, followed by powering up the bandgap, reference circuitry, and ADC core.
    // Before the first conversion is performed a 5ms delay must be observed
    // after power up to give all analog circuits time to power up and settle

    // Please note that for the delay function below to operate correctly the
    // CPU_RATE define statement in the F2806x_Examples.h file must
    // contain the correct CPU clock period in nanoseconds.
    EALLOW;
    AdcRegs.ADCCTL1.bit.ADCBGPWD = 1; // Power ADC BG
    AdcRegs.ADCCTL1.bit.ADCREFPWD = 1; // Power reference
    AdcRegs.ADCCTL1.bit.ADCPWDN = 1; // Power ADC
    AdcRegs.ADCCTL1.bit.ADCENABLE = 1; // Enable ADC
    AdcRegs.ADCCTL1.bit.ADCREFSEL = 0; // Select interal BG
    EDIS;

    DELAY_US(ADC_usDELAY); // Delay before converting ADC channels

    EALLOW;
    AdcRegs.ADCCTL2.bit.CLKDIV2EN = 1;
    EDIS;

    DELAY_US(ADC_usDELAY); // Delay before converting ADC channels

    /* Configure ADC */
    EALLOW;
    AdcRegs.INTSEL1N2.bit.INT1E = 1; /* Enabled ADCINT1 */
    AdcRegs.INTSEL1N2.bit.INT1CONT = 0; /* Disable ADCINT1 Continuous mode */
    AdcRegs.INTSEL1N2.bit.INT1SEL = 0; /* setup EOC0 to trigger ADCINT1 to fire */
    AdcRegs.ADCSOC0CTL.bit.CHSEL = 0xA; /* Set SOC0 channel select to ADCINB2 */
    AdcRegs.ADCSOC0CTL.bit.TRIGSEL = ADCTRIG_EPWM1_SOCB; //6; /* Set SOC0 start trigger on EPWM1B, due to round-robin SOC0 converts first then SOC1 */
    AdcRegs.ADCSOC0CTL.bit.ACQPS = 6; /* Set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0; /* Configure early interrupts */
    EDIS;

    /* Configure ADC */
    EALLOW;
    AdcRegs.INTSEL1N2.bit.INT2E = 1; /* Enabled ADCINT2 */
    AdcRegs.INTSEL1N2.bit.INT2CONT = 0; /* Disable ADCINT2 Continuous mode */
    AdcRegs.INTSEL1N2.bit.INT2SEL = 1; /* setup EOC1 to trigger ADCINT2 to fire */
    AdcRegs.ADCSOC1CTL.bit.CHSEL =0xA; /* Set SOC1 channel select to ADCINB0 */
    AdcRegs.ADCSOC1CTL.bit.TRIGSEL= ADCTRIG_EPWM2_SOCB; /* Set SOC1 start trigger on EPWM1B, due to round-robin SOC0 converts first then SOC1 */
    AdcRegs.ADCSOC1CTL.bit.ACQPS = 6; /* Set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0; /* Configure early interrupts */
    EDIS;

    EALLOW;
    AdcRegs.INTSEL3N4.bit.INT3E = 1; /* Enabled ADCINT3 */
    AdcRegs.INTSEL3N4.bit.INT3CONT = 0; /* Disable ADCINT3 Continuous mode */
    AdcRegs.INTSEL3N4.bit.INT3SEL = 2; /* setup EOC2 to trigger ADCINT1 to fire */
    AdcRegs.ADCSOC2CTL.bit.CHSEL = 0xA; /* Set SOC2 channel select to ADCINB1: Channel 9*/
    AdcRegs.ADCSOC2CTL.bit.TRIGSEL= ADCTRIG_EPWM3_SOCB; /* Set SOC2 start trigger on EPWM3B, due to round-robin SOC0 converts first then SOC1 */
    AdcRegs.ADCSOC2CTL.bit.ACQPS = 6; /* Set SOC2 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1) */
    AdcRegs.ADCCTL1.bit.INTPULSEPOS = 0; /* Configure early interrupts */
    EDIS;
    }
  • Hi,
    I set to Comp1Regs.RAMPMAXREF_SHDW= 19840( about a 1V) and RAMPDECVAL to 0. I slowly kept increasing voltage at V+ of the comparator. Then I noticed that when this V+ voltage reaches 1V. COMP1OUT signals goes high and PWM1 becomes low. I also noticed that when V+=0.9V, PWM1 Duty Cycles becomes around 5 percent( I dont know how to explain that). My understanding is that PWM1 is supposed to be ON or OFF in this test case scenario depending on the value of V+ ( below1V or above 1V).
    Still this does does not explain to me why COMP1OUT does not toggle cycle by cycle.

    Thanks!
  • farid,

    The analog comparator operates independently of the EPWM so its trip status (COMP1OUT) will not be affected by EPWM cycle boundaries.

    In your initialization code, the comparator output is configured to be a cycle-by-cycle trip source, which means that the trip status will self-clear at the beginning of each EPWM cycle.

    I believe that you are seeing the comparator output a constant trip when V+ > 0.9V. At the beginning of each EPWM cycle, the CBC trip is cleared, which allows the EPWM1A output to be active until the comparator trip is qualified by the DC submodule, which then asserts the CBC trip for the remainder of the EPWM cycle. Depending on your PRD, this could look like a 5% duty cycle.

    -Tommy
  • Hi Tommy,

    What I understand from you reply is that COMP1OUT will not toggle at each PWM cycle?

    I just need to verify that the ramp is slowing down according to the decrement value I set with RAMPDECVAL. I wanna make sure also that the ramp starts decreasing at rising edge of each PWM cycle. To have all this, I am wondering if I can plot the data of RAMPSTS register using the graph feature in the debug mode?

    Or there is any other way to verify the slope of the ramp? how to calculate RAMPDECVAL? for a 200KHz PWM for 90MHz system clock?

    Thanks!
  • farid,

    Correct, the COMP1OUT output will only change when V+ and V- cross each other.

    I have not done this myself, but you should be able to read back the values of RAMPSTS and DACVAL using the CPU while the ramp generator is decrementing.  So if you want to prove the ramp generator behavior, you can set an EPWM CMP interrupt a few cycles before the end of a cycle and then use a CPU loop in the ISR to store a buffer of TBCTR vs RAMPSTS vs DACVAL values so that you can trace the sequence of events offline.

    To calculate the RAMPDECVAL, you would probably want to determine the desired slope in mV/us terms first.  The 10b DAC would give you an LSB step of VDDA/2^10, so about 3.2mV per step.  The ramp generator decrements at SYSCLK so you would have one decrement operation about every 11.1ns with a 90MHz SYSCLK.

    -Tommy

  • Hi,

    Just to double check! I read at this app note: "Digital Peak Current Mode Control With Slope Compensation Using the TMS320F2803x"  that Each step of the discrete ramp requires three instructions to complete.Is this still the case for TMS320F28069. You mentioned above that each decrement takes one system clock cycle.

    Is there any example code I can refer to for Ramp slope compensation?

    Thanks,

    Farid

  • Farid,

    I think the reason for the three instruction cycles is because they are using the CLA to generate the slope rather than the tightly coupled ramp generator hardware of the comparator:

    The Biricha code uses the Control Law Accelerator (CLA) of the TMS320F2803x to implement the slope compensation. The CLA is an integrated floating-point core that allows high speed, real-time control algorithms to be executed in parallel with the main CPU.

    It sounds reasonable for the CLA to take three cycles to calculate the next DAC code and write the value to the DACVAL register.

    There is a PCMC implementation example for the HVPSFB kit, but it can be a little difficult to follow:

    \controlSUITE\development_kits\HVPSFB_v1.1\HVPSFB_PCMC\

    -Tommy

  • Thank you so much that's explains a lot to me now.

    When I set: Comp1Regs.RAMPDECVAL_SHDW = 20; This value of 20 does it get subtracted each clock cycle from the 10 bits DAC value representing the peak value of the ramp(Vpp), or from the scaled value of the ramp( VPP*64)?
  • Farid,

    The value of RAMPDECVAL is subtracted from RAMPSTS every clock cycle.  Only the upper 10-bits of the RAMPSTS register are mapped to the DACVAL register.

    From the TRM:

    -Tommy

  • Appreciate it!