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.

FOC with DRV8301 kit - Level6A

Expert 1800 points

Hi,

I could successfully try level 6A Isw=1 while with Isw = 2 the motor starts smoothly till 30RPM and then stops (attached the code below).  I could capture the caliberated angle with small correction factor also.  But did not help in sorting the issue. 

I did a small change in the code is using the qep1.ElecTheta instead of smo1.Theta for park1.Angle (anticipating problem with SMO).  If it works with QEP then I could start fine tuning the SMO.

Pl let me know what could be the problem.

thx

// =============================== LEVEL 6 ======================================
//      Level 6 verifies the speed regulator performed by PID_GRANDO_CONTROLLER module.
//      The system speed loop is closed by using the measured speed as a feedback.
// ==============================================================================  
//  lsw=0: lock the rotor of the motor
//  lsw=1: close the current loop
//    lsw=2: close the speed/sensorless current loop


#if (BUILDLEVEL==LEVEL6)

// ------------------------------------------------------------------------------
//  Connect inputs of the RMP module and call the ramp control macro
// ------------------------------------------------------------------------------

    if(lsw==0) rc1.TargetValue = 0;
    else rc1.TargetValue = SpeedRef;
    RC_MACRO(rc1)

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

// ------------------------------------------------------------------------------
//  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
// ------------------------------------------------------------------------------
    #ifdef F2806x_DEVICE_H
//    clarke1.As=-(((AdcResult.ADCRESULT0)*0.00024414-cal_offset_A)*2); // Phase A curr.
//    clarke1.Bs=-(((AdcResult.ADCRESULT1)*0.00024414-cal_offset_B)*2); // Phase B curr.
    clarke1.As=(((AdcResult.ADCRESULT0)*0.00024414-cal_offset_A)*2); // Phase A curr.
    clarke1.Bs=(((AdcResult.ADCRESULT1)*0.00024414-cal_offset_B)*2); // Phase B curr.
    #endif                                                            // ((ADCmeas(q12)/2^12)-0.5)*2            

    #ifdef DSP2803x_DEVICE_H
//    clarke1.As=-(_IQ15toIQ((AdcResult.ADCRESULT1<<3)-cal_offset_A)<<1);
//    clarke1.Bs=-(_IQ15toIQ((AdcResult.ADCRESULT2<<3)-cal_offset_B)<<1);
    clarke1.As=(_IQ15toIQ((AdcResult.ADCRESULT1<<3)-cal_offset_A)<<1);
    clarke1.Bs=(_IQ15toIQ((AdcResult.ADCRESULT2<<3)-cal_offset_B)<<1);
    #endif
        
    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 = rg1.Out;
//    else park1.Angle = smo1.Theta;  Master
        else park1.Angle = qep1.ElecTheta;
    
    park1.Sine = _IQsinPU(park1.Angle);
    park1.Cosine = _IQcosPU(park1.Angle);
    
    PARK_MACRO(park1)

// ------------------------------------------------------------------------------
//    Connect inputs of the PID_GRANDO_CONTROLLER module and call the PID speed controller macro
// ------------------------------------------------------------------------------  
  if (SpeedLoopCount==SpeedLoopPrescaler)
     {
      pid1_spd.term.Ref = rc1.SetpointValue;
      pid1_spd.term.Fbk = speed1.Speed;
      PID_GR_MACRO(pid1_spd)
      SpeedLoopCount=1;
     }
  else SpeedLoopCount++;   

  if(lsw==0 || lsw==1)
  {
      pid1_spd.data.ui=0;
      pid1_spd.data.i1=0;
  }

// ------------------------------------------------------------------------------
//    Connect inputs of the PID_GRANDO_CONTROLLER module and call the PID IQ controller macro
// ------------------------------------------------------------------------------  
    if(lsw==0) pid1_iq.term.Ref = 0;
    else if(lsw==1) pid1_iq.term.Ref = IqRef;
    else pid1_iq.term.Ref = pid1_spd.term.Out; //pid1_spd.term.Out; (pid1_spd.term.Out->Level 6A, IqRef->Level 6B)
    pid1_iq.term.Fbk = park1.Qs;
    PID_GR_MACRO(pid1_iq)

// ------------------------------------------------------------------------------
//    Connect inputs of the PID_GRANDO_CONTROLLER module and call the PID ID controller macro
// ------------------------------------------------------------------------------  
    if(lsw==0) pid1_id.term.Ref = _IQ(0.05);
    else pid1_id.term.Ref = 0;
    pid1_id.term.Fbk = park1.Ds;
    PID_GR_MACRO(pid1_id)

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

// ------------------------------------------------------------------------------
//    Call the QEP calculation module
// ------------------------------------------------------------------------------
        if (lsw==0) {EQep1Regs.QPOSCNT=0; EQep1Regs.QCLR.bit.IEL = 1; Init_IFlag=0;} // Reset position cnt.

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

        QEP_MACRO(qep1);

//    QEP_MACRO(qep1);  // Master

// ------------------------------------------------------------------------------
//    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 VOLT_CALC module and call the phase voltage macro
// ------------------------------------------------------------------------------
    #ifdef F2806x_DEVICE_H
    volt1.DcBusVolt = ((AdcResult.ADCRESULT2)*0.00024414); // DC Bus voltage meas.
    #endif                                                         // (ADCmeas(q12)/2^12)    
    
    #ifdef DSP2803x_DEVICE_H
    volt1.DcBusVolt = _IQ15toIQ((AdcResult.ADCRESULT3<<3));         // DC Bus voltage meas.
    BackEMF_ABus = _IQ15toIQ((AdcResult.ADCRESULT4<<3));        //    Phase A BackVoltage
    BackEMF_BBus = _IQ15toIQ((AdcResult.ADCRESULT5<<3));        //    Phase B BackVoltage
    BackEMF_CBus = _IQ15toIQ((AdcResult.ADCRESULT6<<3));        //    Phase C BackVoltage

    #endif

    volt1.MfuncV1 = svgen_dq1.Ta;
    volt1.MfuncV2 = svgen_dq1.Tb;
    volt1.MfuncV3 = svgen_dq1.Tc;        
    VOLT_MACRO(volt1)

// ------------------------------------------------------------------------------
//    Connect inputs of the SMO_POS module and call the sliding-mode observer macro
// ------------------------------------------------------------------------------
    smo1.Ialpha = clarke1.Alpha;
      smo1.Ibeta  = clarke1.Beta;
    smo1.Valpha = volt1.Valpha;
    smo1.Vbeta  = volt1.Vbeta;
    SMO_MACRO(smo1)

// ------------------------------------------------------------------------------
//    Connect inputs of the SPEED_EST module and call the estimated speed macro
// ------------------------------------------------------------------------------
    speed3.EstimatedTheta = smo1.Theta;
    SE_MACRO(speed3)  

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

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

    EPwm1Regs.CMPA.half.CMPA=pwm1.PWM1out;    // PWM 1A - PhaseA
    EPwm2Regs.CMPA.half.CMPA=pwm1.PWM2out;    // PWM 2A - PhaseB
    EPwm3Regs.CMPA.half.CMPA=pwm1.PWM3out;    // PWM 3A - PhaseC  


// ------------------------------------------------------------------------------
//    Connect inputs of the PWMDAC module
// ------------------------------------------------------------------------------    
//    PwmDacCh1 = _IQtoQ15(smo1.Theta);
//    PwmDacCh2 = _IQtoQ15(rg1.Out);

    PwmDacCh1 = _IQtoQ15(svgen_dq1.Ta);
    PwmDacCh2 = _IQtoQ15(qep1.ElecTheta);
    PwmDacCh3 = _IQtoQ15(clarke1.As);
    PwmDacCh4 = _IQtoQ15(clarke1.Bs);

// ------------------------------------------------------------------------------
//    Connect inputs of the DATALOG module
// ------------------------------------------------------------------------------
//    DlogCh1 = _IQtoQ15(smo1.Theta); Master
    DlogCh2 = _IQtoQ15(rg1.Out); //Master

//    DlogCh1 = _IQtoQ15(svgen_dq1.Ta);
    DlogCh1 = _IQtoQ15(qep1.ElecTheta);
    DlogCh3 = _IQtoQ15(clarke1.As);
    DlogCh4 = _IQtoQ15(clarke1.Bs);

  • have you gone through the SMO tuning process?

    using QEP and trying to match the SMO output to the mechanical sensor is a good strategy.

    you are having start-up problems with the QEP?

  • Hi Chris,

    Thanks for your suggestion.  There is no startup problem the motor starts smoothly with 0.001 speedref and I keep increasing the value.  As Speedref keeps increasing the motor increases the speed but stops.  There is no vibrations or any sound too.  In level 6 Isw=1 motor reached an RPM of 250 when it stalled.  Not sure what could be the problem.

    SMO would be tried once I taste success with QEP with the closed loop since its easy to sort the issues one after the other.  

    Thx 

  • Hi Chris,

    Regarding program of the header below:

    / * ================================================ ==============================
    System Name: HVACI_Sensored

    File Name: HVACI_Sensored.C

    Description: Primary file system for the Implementation of Real Sensored
               Field Orientation Control for Induction Motors

    Originator: Digital control systems Group - Texas Instruments
    ================================================== ===================================
      History:
    -------------------------------------------------- -----------------------------------
      10/09/2010 Version 1.1: Supports F2803x
    ================================================== =============================== * /

    How do I change the control of the acceleration?

    For example,

    When vario SpeedRef of "0.5" to "0.0", the engine spends long time for decelerate. Ideally it was almost instant.

    How to proceed for change this?

    Thank you!

  • Well, usually there is a Trajectory Module that feeds all of the intermediate speed commands between current speed and target speed, based on an acceleration.  But you're right, I don't see this module being used in this - or any - of the projects.  Hmmm.

    Let me forward to the content owner to see if they have any comments

  • There is a macro called 'RC_MACRO'. Its function is to control the ramp rate of speed reference. Look for a variable named 'RampDelyMax' within the structure defined for this macro's use, and reduce the value as per your need.

    rgds,

    ramesh