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.

LAUNCHXL-F28069M: Please, any one can approve this code? Thanks. What is wrong and right?

Part Number: LAUNCHXL-F28069M
Other Parts Discussed in Thread: C2000WARE

void
AdcConversion_run(int *conv)
{
EALLOW;
AdcRegs.INTSEL1N2.bit.INT1E = 1;


AdcRegs.INTSEL1N2.bit.INT1CONT = 0;


AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;


AdcRegs.INTSEL1N2.bit.INT1SEL = 5; // EOC5 triggers ADCINT1

// Force Start SOC0-5 to begin ping-pong sampling
//
AdcRegs.ADCSOCFRC1.all = 0x003F;

//
// Wait for ADCINT1 to trigger, then add ADCRESULT0-5 registers to sum
//
while (AdcRegs.ADCINTFLG.bit.ADCINT1 == 0)
{

}

//
// Must clear ADCINT1 flag since INT1CONT = 0
//
AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
conv[0]= (int)AdcResult.ADCRESULT0;
conv[1]= (int)AdcResult.ADCRESULT1;
conv[2]= (int)AdcResult.ADCRESULT2;
conv[3]= (int)AdcResult.ADCRESULT3;
conv[4]= (int)AdcResult.ADCRESULT4;
conv[5]= (int)AdcResult.ADCRESULT5;

//
// Disable ADCINT1  to STOP 
//
AdcRegs.INTSEL1N2.bit.INT1E = 0;

AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;


AdcRegs.ADCINTOVFCLR.bit.ADCINT1 = 1;

//
// reset RR pointer to 32, so that next SOC is SOC0
//
AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 1;

while( AdcRegs.SOCPRICTL.bit.SOCPRIORITY != 1 );
AdcRegs.SOCPRICTL.bit.SOCPRIORITY = 0;

while( AdcRegs.SOCPRICTL.bit.SOCPRIORITY != 0 );
EDIS;
}

void
AdcChanSelect_run()
{
EALLOW;
AdcRegs.ADCSOC0CTL.bit.CHSEL= 3;
AdcRegs.ADCSOC1CTL.bit.CHSEL= 11;
AdcRegs.ADCSOC2CTL.bit.CHSEL= 4;
AdcRegs.ADCSOC3CTL.bit.CHSEL= 12;
AdcRegs.ADCSOC4CTL.bit.CHSEL= 5;
AdcRegs.ADCSOC5CTL.bit.CHSEL= 13;
Uint16 ACQPS_Value = 50;
AdcRegs.ADCSOC0CTL.bit.ACQPS = ACQPS_Value;
AdcRegs.ADCSOC1CTL.bit.ACQPS = ACQPS_Value;
AdcRegs.ADCSOC2CTL.bit.ACQPS = ACQPS_Value;
AdcRegs.ADCSOC3CTL.bit.ACQPS = ACQPS_Value;
AdcRegs.ADCSOC4CTL.bit.ACQPS = ACQPS_Value;
AdcRegs.ADCSOC5CTL.bit.ACQPS = ACQPS_Value;

AdcRegs.INTSEL1N2.bit.INT1E = 1;
// AdcRegs.INTSEL1N2.bit.INT2E = 1;

//
// Disable continuous sampling for ADCINT1 and ADCINT2
//
AdcRegs.INTSEL1N2.bit.INT1CONT = 0;
// AdcRegs.INTSEL1N2.bit.INT2CONT = 0;

//
// ADCINTs trigger at end of conversion
//
AdcRegs.ADCCTL1.bit.INTPULSEPOS = 1;

//
// Setup ADCINT1 and ADCINT2 trigger source
//
AdcRegs.INTSEL1N2.bit.INT1SEL = 5; // EOC6 triggers ADCINT1
// AdcRegs.INTSEL1N2.bit.INT2SEL = 14; // EOC14 triggers ADCINT2

//
// Setup each SOC's ADCINT trigger source
//
AdcRegs.ADCINTSOCSEL1.bit.SOC0 = 0; // ADCINT2 starts SOC0-7
AdcRegs.ADCINTSOCSEL1.bit.SOC1 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC2 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC3 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC4 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC5 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC6 = 0;
AdcRegs.ADCINTSOCSEL1.bit.SOC7 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC8 = 0; // ADCINT1 starts SOC8-15
AdcRegs.ADCINTSOCSEL2.bit.SOC9 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC10 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC11 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC12 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC13 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC14 = 0;
AdcRegs.ADCINTSOCSEL2.bit.SOC15 = 0;

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

EDIS;

}

void
main(void)
{
int conv[6];

//
// *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;
EALLOW;


//
// 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
InitAdcAio(); //provided by C2000ware
AdcOffsetSelfCal(); //provided C2000ware
AdcChanSelect_run(); //only run one time

AdcConversion_run(conv);
phase1_current=((float)(conv[0]-conv[1])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN0,AN1
phase3_current=((float)(conv[2]-conv[3])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN2,AN3 EO: was phase2 wrongly
phase2_current=((float)(conv[4]-conv[5])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN4,AN5 EO: was phase3 wrongly

AdcConversion_run(conv);
phase1_current=((float)(conv[0]-conv[1])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN0,AN1
phase3_current=((float)(conv[2]-conv[3])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN2,AN3 EO: was phase2 wrongly
phase2_current=((float)(conv[4]-conv[5])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN4,AN5 EO: was phase3 wrongly

AdcConversion_run(conv);
phase1_current=((float)(conv[0]-conv[1])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN0,AN1
phase3_current=((float)(conv[2]-conv[3])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN2,AN3 EO: was phase2 wrongly
phase2_current=((float)(conv[4]-conv[5])/4096.0f)*new_param.target_nominal_phase_gain; // Results for AN4,AN5 EO: was phase3 wrongly

}

  • Hello,

    Can you give me some more information about what your concern is with this code? What kind of failure are you seeing?

    Whitney

  • Three Phase PWM

    First read Quadrature Decoder. Then ADC read three phase currents and then adjust (after computations) three phase PWMs to follow sines. and back begin again to read Quadrature Decoder

    Some times works Ok. Others the sines jump sharply of phase at middle of the test of the Motor

    We do not which device has the error or bad configured

    Also, perhaps that ADC code have some redundancy that can be taken out
  • Are you seeing unexpected ADC results? Is that why you posted your ADC code?

    As far as redundancies go, there are a few unnecessary things in AdcConversion_run()--you shouldn't have to reconfigure INT1CONT, INTPULSEPOS, or INT1SEL unless you changed their values after configuring them in AdcChanSelect_run(). You also clear the ADCINT1 flag twice, and as far as I can tell, the resetting of the RR pointer isn't necessary the way you're using the ADC. None of these are major issues though.

    Whitney
  • With the same subject, can you validade the following init functions?



    void PWM_init_run_motor(void)
    {
    EALLOW;
    SysCtrlRegs.PCLKCR0.bit.TBCLKSYNC = 0;
    EDIS;

    //EPwm1Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;
    //EPwm2Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;
    //EPwm3Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;


    EPwm4Regs.TBPRD = 4500; // Set timer period
    EPwm4Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm4Regs.TBCTR = 0x0000; // Clear counter

    //
    // Setup TBCLK
    //
    EPwm4Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm4Regs.TBCTL.bit.PHSEN = TB_DISABLE; // Disable phase loading

    EPwm4Regs.TBCTL.bit.PRDLD = TB_SHADOW;


    EPwm4Regs.TBCTL.bit.SYNCOSEL = TB_CTR_ZERO;

    EPwm4Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm4Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    EPwm4Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO
    EPwm4Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm4Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm4Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //
    // Setup compare
    //
    EPwm4Regs.CMPA.half.CMPA = 0;

    //
    // Set actions
    //

    EPwm4Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm4Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm4Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
    EPwm4Regs.AQCTLB.bit.CAU = AQ_SET;


    //
    // Active Complementary HIGH PWMs - Setup Deadband
    //
    EPwm4Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm4Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm4Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm4Regs.DBRED = 60;
    EPwm4Regs.DBFED = 60;





    EPwm5Regs.TBPRD = 4500; // Set timer period
    EPwm5Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm5Regs.TBCTR = 0x0000; // Clear counter

    //
    // Setup TBCLK
    //
    EPwm5Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm5Regs.TBCTL.bit.PHSEN = TB_ENABLE;

    EPwm5Regs.TBCTL.bit.PRDLD = TB_SHADOW;



    EPwm5Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;

    EPwm5Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm5Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    EPwm5Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO
    EPwm5Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm5Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm5Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //
    // Setup compare
    //
    EPwm5Regs.CMPA.half.CMPA = 0;

    //
    // Set actions
    //
    EPwm5Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm5Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm5Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
    EPwm5Regs.AQCTLB.bit.CAU = AQ_SET;




    //
    // Active HIGH PWMs - Setup Deadband
    //
    EPwm5Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm5Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm5Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm5Regs.DBRED = 60;
    EPwm5Regs.DBFED = 60;

    EPwm6Regs.TBPRD = 4500; // Set timer period
    EPwm6Regs.TBPHS.half.TBPHS = 0x0000; // Phase is 0
    EPwm6Regs.TBCTR = 0x0000; // Clear counter

    //
    // Setup TBCLK
    //
    EPwm6Regs.TBCTL.bit.CTRMODE = TB_COUNT_UP; // Count up
    EPwm6Regs.TBCTL.bit.PHSEN = TB_ENABLE;

    EPwm6Regs.TBCTL.bit.PRDLD = TB_SHADOW;



    EPwm6Regs.TBCTL.bit.SYNCOSEL = TB_SYNC_IN;

    EPwm6Regs.TBCTL.bit.HSPCLKDIV = TB_DIV1; // Clock ratio to SYSCLKOUT
    EPwm6Regs.TBCTL.bit.CLKDIV = TB_DIV1;

    EPwm6Regs.CMPCTL.bit.SHDWAMODE = CC_SHADOW; // Load registers every ZERO
    EPwm6Regs.CMPCTL.bit.SHDWBMODE = CC_SHADOW;
    EPwm6Regs.CMPCTL.bit.LOADAMODE = CC_CTR_ZERO;
    EPwm6Regs.CMPCTL.bit.LOADBMODE = CC_CTR_ZERO;

    //
    // Setup compare
    //
    EPwm6Regs.CMPA.half.CMPA = 0;

    //
    // Set actions
    //

    EPwm6Regs.AQCTLA.bit.ZRO = AQ_SET;
    EPwm6Regs.AQCTLA.bit.CAU = AQ_CLEAR;
    EPwm6Regs.AQCTLB.bit.ZRO = AQ_CLEAR;
    EPwm6Regs.AQCTLB.bit.CAU = AQ_SET;


    //
    // Active HIGH PWMs - Setup Deadband
    //
    EPwm6Regs.DBCTL.bit.OUT_MODE = DB_FULL_ENABLE;
    EPwm6Regs.DBCTL.bit.POLSEL = DB_ACTV_HIC;
    EPwm6Regs.DBCTL.bit.IN_MODE = DBA_ALL;
    EPwm6Regs.DBRED = 60;
    EPwm6Regs.DBFED = 60;

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


    }

    The Quadrature encoder uses 3 pins, one is the index and the other two are the two quadrature inputs


    void Decoder(void)
    {


    EQep1Regs.QDECCTL.bit.QSRC=00; // QEP quadrature count mode

    EQep1Regs.QEPCTL.bit.FREE_SOFT=2;



    EQep1Regs.QEPCTL.bit.PCRM=00;
    EQep1Regs.QEPCTL.bit.UTE=0; // Unit Timeout Disable
    EQep1Regs.QEPCTL.bit.QCLM=0; // Latch on unit time out
    EQep1Regs.QEPCTL.bit.IEL=0b10;
    EQep1Regs.QPOSMAX=0xffffffff;
    EQep1Regs.QPOSCNT=0;
    EQep1Regs.QEPCTL.bit.QPEN=1; // QEP enable


    }
  • Hello,

    I encourage you to write some tests to make sure these modules are working as you expect them to. My simply reviewing your code without context isn't really enough to make sure there are no mistakes. If you can run some tests and try to identify the specific problems you're seeing or ask some specific questions about the code, I'd be happy to help answer them.

    Whitney
  • Already done tests offline with success. But online can appear problems that I can no see with the tests. And It is giving the problems already reported above.
  • That's good to know. Are you seeing unexpected ADC results? Do you think that's what's causing the jump in phase? How often do you see this issue?

    Whitney
  • The problem is that the jump can be in any place in the chain. We do not know where it starts. Once started it propagates through the chain. This solution is being ported from a old working solution with Motorola board
  • Sorry, it is happening regularly. Say in 30 sine cycles, one phase change
  • Do you have any oscilloscope captures of the issue that you could share?

    Whitney
  • Left Picture - Goog Picture

    Right Picture - Picture with two sharp phase shifts

    Blue Wave - Torque Waveform (right scale)

    Yellow line - Motor test speed (left scale)

    White, red, green waves - 3 phase currents

    4 pole pair motor - Each picture represents a full mechanical revolution of the motor

    A question:

    Is the quadrature encoder well initialized? (please see the code in a last post)

    Do you think that the index of the encoder reset is being done?

    Encoder Channel A - 5000 positions, Channel B 5000 positions - Total 20000 positions per turn  

    The cut of the wave only happens randomly, one time in 10 tests. And the break point of the wave is different each time

  • Can you help me how to initialize the quadrature encoder to range from -19999-0-19999 with index at 0 (after first turn)?
  • Thank you for your patience. Have you made any progress on this issue?

    Whitney
  • Yes, the decoder code was changed to range from 0 to MAX, instead of -MAX 0 MAX. But it did not solved the problem

    It was made a program to detect which device has first the wave break (from Decoder ADC and PWM)

    It was found that it was the ADC. It was measured with an oscilloscope and appears spikes in the ADCs inputs

    We do not know if them from inside of the TMS, bad ground, or outside. We are porting code from an old implementation that it has not that problem. Next time we will try to put 1uF at the inputs of the ADC (signal source 50ohms and low frequency sinusoidal inputs, 7Hz) The old implementation has "ferrite" coils separating the digital and analog power supplies. I suppose that this board has not

  • Thanks for the update. Glad to hear you were able to narrow it down to the ADC signals. Please let me know if you trace the issue back to the F2806x and need help.

    Whitney
  • Since I haven't heard back from you, I'm going to assume that the issue was elsewhere in your system and mark this thread as resolved. Please feel free to comment and reopen the thread if that is not the case.

    Whitney
  • The 1uF plastic capacitor solved the problem. We introduced also with the 1uF a 10uF tantalum capacitor in parallel.

  • Sorry, but this issue happened again. I think the spikes are of very high frequency and those components 1uF plastic and 10uF tantulum do not have response at those frequencies.

    We are thinking to introduce a ferrite (EXC3BB102H) in series (before input ADC) with a series 1KOhm resistor (I think must SMD to have response above 100MHz) and SMD capacitors 100nF+100pF in parallel with inputs. I think that the 1KOhm will increase the sample time of the ADC  

    We can see the spikes superimposing in half-rectified sine wave (ADC inputs). We do not know if the problem is from inside the TI or outside, yet

    Perhaps later, I will need to ask TI where we can interrupt one track in the board to introduce a component like the ferrite EXC3BB102H.

    I am a freelancer and I dependable of people on the field. I go to the field very irregularly. That is why my response to this thread is so spaced in time. I ask for patience  

    Please, give some support on this.

  • I seen sprui11.pdf and the board is all protected with coils in the power supplies.
  • Regarding this issue. There is any implementation of a FIR/IIR implementation of a low pass filter (second or third order in continuous domain) for CLA? With preference with 300-350Hz Bandwidth.

    Thanks

    Luis Gonçalves
  • Luis,

    For the most recent question, there is not a 100% native CLA implementation, but inside the FPU libraries we have the FIR/IIR functions:

    C:\ti\c2000\C2000Ware_1_00_04_00\libraries\dsp\FPU\c28\

    http://processors.wiki.ti.com/index.php/C2000_FFT:_VCU,_FPU_or_FixedPoint  mentions using the CLA for the phase and magnitude portions of an FFT to offload some MIPs from the main CPU.

    For the previous statement on noise still being present after the caps on the ADC pins: 

    I'm suspecting that the noise is happening when the ADC samples close to a FET(or FETs) switching to control the motor?  This would suggest a more generic noise issue with the PCB, either power plane or (more likely) the ground plane being impacted as the FET(s) switch.  One solution would be to push the ADC sampling outside this time duration, another would be to try and better isolate the high power domain from the analog plane.  Let me know if you think this is the right direction.

    Best,

    Matthew