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.

TMS320F28335: Sensored HVPM

Part Number: TMS320F28335
Other Parts Discussed in Thread: CONTROLSUITE

Hello TI Community,

I m trying to control a PMSM using FOC technic. 

I started with an example project " sensorless 28335" and did some modifications.

I used PI controller for both current and speed loop, qep module ( encoder 4096 lines), speed macro...

 lsw=0 , the rotor moves a bit then is locked : the field is oriented on the d axis.

 qep1.calibratedAngle is equal to  0.

 lsw= 1 : when i'm using park.angle = rg1.out  the rotor spins but a there s a big difference between rg1.out and qep1.thetaElectric.

for park.angle=qep1.Thetaelectric, in this case the rotor stays locked doesn't spin.

my program is the following ,

--------------------------------------------------------------------------------------------------

 if(lsw==0)rc1.TargetValue = 0;
   else rc1.TargetValue = spdrf1;//1
    RC_MACRO(rc1)

// ------------------------------------------------------------------------------
//  Connect inputs of the RAMP GEN module and call the ramp generator macro
// ------------------------------------------------------------------------------
     rg1.Freq = rc1.SetpointValue;
     RG_MACRO(rg1)

// calibration Angle
if (lsw==0) {EQep1Regs.QPOSCNT=0; EQep1Regs.QCLR.bit.IEL = 1;} // Reset position cnt.


if ((EQep1Regs.QFLG.bit.IEL==1) && Init_IFlag==0) // Check the first index occurrence
{qep1.CalibratedAngle= EQep1Regs.QPOSILAT; Init_IFlag++;} // Keep the latched position


if (lsw!=0) QEP_MACRO(qep1);


// ------------------------------------------------------------------------------
//  Measure phase currents, subtract the offset and normalize from (-0.5,+0.5) to (-1,+1).
//    Connect inputs of the CLARKE module and call the clarke transformation macro
// ------------------------------------------------------------------------------
 
    clarke1.As=((AdcMirror.ADCRESULT1)*0.00024414-offsetA)*2*0.909; // Phase A curr.
    clarke1.Bs=((AdcMirror.ADCRESULT2)*0.00024414-offsetB)*2*0.909; // Phase B curr.
                                                                      
       
    
    CLARKE_MACRO(clarke1)  

// ------------------------------------------------------------------------------
//  Connect inputs of the PARK module and call the park trans. macro
// ------------------------------------------------------------------------------
    park1.Alpha = clarke1.Alpha;
    park1.Beta = clarke1.Beta;
    if(lsw==0) park1.Angle = 0;
    else if(lsw==1) park1.Angle = qep1.ElecTheta ;//rg1.Out;//
    
    park1.Sine = _IQsinPU(park1.Angle);
    park1.Cosine = _IQcosPU(park1.Angle);
    
    PARK_MACRO(park1)

    // ------------------------------------------------------------------------------
    //    Call the QEP calculation module
    // ------------------------------------------------------------------------------
        QEP_MACRO(1,qep1);

    // ------------------------------------------------------------------------------
    //    Connect inputs of the SPEED_FR module and call the speed calculation macro
    // ------------------------------------------------------------------------------
   speed1.ElecTheta = qep1.ElecTheta;
   speed1.DirectionQep = (int32)(qep1.DirectionQep);
   SPEED_FR_MACRO(speed1)

    // ------------------------------------------------------------------------------
    //  Connect inputs of the PI for speed
    // ------------------------------------------------------------------------------
   if (SpeedLoopCount==SpeedLoopPrescaler){
   pi_spd.Ref = rc1.SetpointValue;
    pi_spd.Fbk = speed1.Speed;
    PI_MACRO(pi_spd);
    SpeedLoopCount= 1 ;
   }
   else {
       SpeedLoopCount= SpeedLoopCount+1;
   }
// ------------------------------------------------------------------------------
//  Connect inputs of the PI module and call the PI IQ controller macro
// ------------------------------------------------------------------------------  
    if(lsw==0) pi_iq.Ref = 0;
    else if(lsw==1) pi_iq.Ref = pi_spd.Out;//_IQ(0.1) ;//
    pi_iq.Fbk = park1.Qs;
    PI_MACRO(pi_iq)

// ------------------------------------------------------------------------------
//  Connect inputs of the PI module and call the PI ID controller macro
// ------------------------------------------------------------------------------   
    if(lsw==0) pi_id.Ref = _IQ(0.05);
    else pi_id.Ref = IdRef;
    pi_id.Fbk = park1.Ds;
    PI_MACRO(pi_id)

// ------------------------------------------------------------------------------
//    Connect inputs of the INV_PARK module and call the inverse park trans. macro
// ------------------------------------------------------------------------------
    ipark1.Ds = pi_id.Out;
    ipark1.Qs = pi_iq.Out ;
    ipark1.Sine   = park1.Sine;
    ipark1.Cosine = park1.Cosine;
    IPARK_MACRO(ipark1)

// ------------------------------------------------------------------------------
//  Connect inputs of the SVGEN_DQ module and call the space-vector gen. macro
// ------------------------------------------------------------------------------
      svgen1.Ualpha = ipark1.Alpha;
     svgen1.Ubeta = ipark1.Beta;
      SVGENDQ_MACRO(svgen1)        

// ------------------------------------------------------------------------------
//  Connect inputs of the PWM_DRV module and call the PWM signal generation macro
// ------------------------------------------------------------------------------
    pwm1.MfuncC1 = svgen1.Ta;  
    pwm1.MfuncC2 = svgen1.Tb;   
    pwm1.MfuncC3 = svgen1.Tc;
    PWM_MACRO(1,2,3,pwm1)                            // Calculate the new PWM compare values    

// ------------------------------------------------------------------------------
//    Connect inputs of the PWMDAC module
// ------------------------------------------------------------------------------    
    pwmdac1.MfuncC1 = clarke1.As;
    pwmdac1.MfuncC2 = clarke1.Bs;
    PWMDAC_MACRO(6,pwmdac1)                              // PWMDAC 6A, 6B
    
    pwmdac1.MfuncC1 = qep1.ElecTheta;
    pwmdac1.MfuncC2 = svgen1.Tb-svgen1.Tc;
    PWMDAC_MACRO(7,pwmdac1)                              // PWMDAC 7A, 7B  
    
// ------------------------------------------------------------------------------
//    Connect inputs of the DATALOG module
// ------------------------------------------------------------------------------
    DlogCh1 = _IQtoQ15(clarke1.As );
    DlogCh2 = _IQtoQ15(clarke1.Bs);
    DlogCh3 = _IQtoQ15(qep1.ElecTheta);
    DlogCh4 = _IQtoQ15(rg1.Out);

Could you please help me ?
Regards, 

  • You might refer to HVPM_Sensored or HVPM_Sensored_Servo example projects since you are using sensor-FOC based encoder position sensor, both projects could be found in controlSUITE also.
    Please ensure the physical connection of encoder is correct and do a calibration for the encoder. You should change the qep1.CalibratedAngle based on the encoder of your motor that may be some difference between the output of the RG module and QEP module if the calibration value is not correct.
  • Hello Yanming Luo,
    thank you for answering i ll check the connection.
    for angle calibration : the qep1.CalibratedAngle takes the value of EQep1Regs.POSCNT when it detectes the index signal for the first time. when you say change the calibrated angle based on my encoder you mean the encoders number of lines ?
    regards,
  • Not only the encoder number of lines, and you need to set qep1.CalibratedAngle which is from the installation offset, and will be achieved by using align the rotor of a motor. You might find the procedure in the example project.
  • Hi Yanming Luo,

    I resolved the problem : my encoder generates six signals A,B,I and their complementaries. I was using only the A,B,I as Inputs for the QEP module, the parasites signals (caused by inverter) did a lot of distorsion in ThetaElectrical. I added an AM26LS32ACN and now it works good.

    Thank you,          

  • Great! Thanks for your update. Let me know if you have any further questions.
  • I encountred another problem with position loop.

    my main goal is to synchronize the index signal (from encoder) to external signal (from GBF).

    I used " capture " to read the frequency from the external signal : which is the réference speed. 

    Then i applied a vector control with current and speed loop : and i checked with oscilloscope the Iq Current reference and the feedback (for speed too), using the PWM6A PWM6B pins on board. the PI correctors are working good.

     using the configuration of delta mode for Ecaps*Regs, I used the Timer from Capture  TSCTR devided by cap.EventPeriod as an image of position reference ( external signal ) and the position feedback(from index) .Then i used proportional corrector for this loop.

    at steady state, The current and speed feedbacks are identical to references up to two digit after the decimal point (using expressions window in CCS). 

    The problem is synchronizing both signals is complicated : the index signal oscillate s around the rising edge of the external signal.

    do you think this is due to the small error between the referencies and the feedbacks of speed and current, when we pass from the p.u to real scale this error becomes considerable . 

    for example at speed of 3000rpm : case of speed error = 0.005 pu , this means real speed error is 15rpm.