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.

A question on lab02a


In this lab I can see that the Motor ID process spins the motor to find out the I_bias and then the V_bias.

With my setup, at this time the motor spins at 218rpm instead of 100 rpm as the SpeedRef_krpm said (see picture above).


Later on, when it changes state; the Speed_krpm follows the SpeedRef_krpm in the following picture.

How does  the motor ID process work?

The value returned by CTRL_getMaximumSpeed_pu(ctrlHandle) is .12.

What dictates the maximum speed pu ?

/* --COPYRIGHT--,BSD
 * Copyright (c) 2012, Texas Instruments Incorporated
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * *  Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * *  Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * *  Neither the name of Texas Instruments Incorporated nor the names of
 *    its contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 * --/COPYRIGHT--*/
//! \file   solutions/instaspin_foc/src/proj_lab02a.c
//! \brief Using InstaSPIN�-FOC for the first time, Motor ID, full control system from ROM 
//!
//! (C) Copyright 2011, Texas Instruments, Inc.

//! \defgroup PROJ_LAB02a PROJ_LAB02a
//@{

//! \defgroup PROJ_LAB02a_OVERVIEW Project Overview
//!
//! Using InstaSPIN�-FOC for the first time, Motor ID, full control system from ROM 
//!

// **************************************************************************
// the includes

// system includes
#include <math.h>
#include "main.h"

#ifdef HAL_SCI
#include "sw/drivers/hal_sci/src/32b/f28x/f2806x/hal_sci.h"
#endif

#ifdef FLASH
#pragma CODE_SECTION(mainISR,"ramfuncs");
#endif

// Include header files used in the main function


// **************************************************************************
// the defines

#define LED_BLINK_FREQ_Hz   5


// **************************************************************************
// the globals

uint_least16_t gCounter_updateGlobals = 0;

bool Flag_Latch_softwareUpdate = true;

CTRL_Handle ctrlHandle;

HAL_Handle halHandle;

USER_Params gUserParams;

HAL_PwmData_t gPwmData = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};

HAL_AdcData_t gAdcData;

_iq gMaxCurrentSlope = _IQ(0.0);

#ifdef FAST_ROM_V1p6
CTRL_Obj *controller_obj;
#else
CTRL_Obj ctrl;				//v1p7 format
#endif

uint16_t gLEDcnt = 0;

volatile MOTOR_Vars_t gMotorVars = MOTOR_Vars_INIT;

#ifdef FLASH
// Used for running BackGround in flash, and ISR in RAM
extern uint16_t *RamfuncsLoadStart, *RamfuncsLoadEnd, *RamfuncsRunStart;
#endif


#ifdef USING_POTENTIOMETER
bool Flag_Init_Motor = true;
_iq gPotentiometer = _IQ(0.0);
#endif

#ifdef DRV8301_SPI
// Watch window interface to the 8301 SPI
DRV_SPI_8301_Vars_t gDrvSpi8301Vars;
#endif

// **************************************************************************
// the functions

void main(void)
{
  uint_least8_t estNumber = 0;

#ifdef FAST_ROM_V1p6
  uint_least8_t ctrlNumber = 0;
#endif

  // Only used if running from FLASH
  // Note that the variable FLASH is defined by the project
  #ifdef FLASH
  // Copy time critical code and Flash setup code to RAM
  // The RamfuncsLoadStart, RamfuncsLoadEnd, and RamfuncsRunStart
  // symbols are created by the linker. Refer to the linker files.
  memCopy((uint16_t *)&RamfuncsLoadStart,(uint16_t *)&RamfuncsLoadEnd,(uint16_t *)&RamfuncsRunStart);
  #endif

  // initialize the hardware abstraction layer
  halHandle = HAL_init(&hal,sizeof(hal));

  // check for errors in user parameters
  USER_checkForErrors(&gUserParams);

  // store user parameter error in global variable
  gMotorVars.UserErrorCode = USER_getErrorCode(&gUserParams);

  // do not allow code execution if there is a user parameter error
  if(gMotorVars.UserErrorCode != USER_ErrorCode_NoError)
    {
      for(;;)
        {
          gMotorVars.Flag_enableSys = false;
        }
    }


  // initialize the user parameters
  USER_setParams(&gUserParams);


  // set the hardware abstraction layer parameters
  HAL_setParams(halHandle,&gUserParams);


  // initialize the controller
#ifdef FAST_ROM_V1p6
  ctrlHandle = CTRL_initCtrl(ctrlNumber, estNumber);  		//v1p6 format (06xF and 06xM devices)
  controller_obj = (CTRL_Obj *)ctrlHandle;
#else
  ctrlHandle = CTRL_initCtrl(estNumber,&ctrl,sizeof(ctrl));	//v1p7 format default
#endif


  {
    CTRL_Version version;

    // get the version number
    CTRL_getVersion(ctrlHandle,&version);

    gMotorVars.CtrlVersion = version;
  }


  // set the default controller parameters
  CTRL_setParams(ctrlHandle,&gUserParams);

  #ifdef HAL_SCI
  HAL_sciA_init(halHandle);
  #endif

  // setup faults
  HAL_setupFaults(halHandle);


  // initialize the interrupt vector table
  HAL_initIntVectorTable(halHandle);


  // enable the ADC interrupts
  HAL_enableAdcInts(halHandle);


  // enable global interrupts
  HAL_enableGlobalInts(halHandle);


  // enable debug interrupts
  HAL_enableDebugInt(halHandle);


  // disable the PWM
  HAL_disablePwm(halHandle);


#ifdef DRV8301_SPI
  // turn on the DRV8301 if present
  HAL_enableDrv(halHandle);
  // initialize the DRV8301 interface
  HAL_setupDrvSpi(halHandle,&gDrvSpi8301Vars);
#endif


  // enable DC bus compensation
  CTRL_setFlag_enableDcBusComp(ctrlHandle, true);

#ifdef HAL_SCI
  HAL_printf(halHandle, "\n...LAB02a : " BOLD_S UNDER_S  "Minimun setup using FOC"  NORM_S);
  HAL_printf(halHandle, "\n...");

  HAL_print_state(halHandle, "Before going to the forever loop");
#endif


  for(;;)
  {
      #ifdef HAL_SCI
	  unsigned int prt = 0;
      #endif

      #ifdef USING_POTENTIOMETER
	  if (Flag_Init_Motor) {
		  HAL_print_state(halHandle, "Delay 5000ms ...");
		  usDelay(5000L);
		  gMotorVars.Flag_enableSys = true;
          #ifdef HAL_SCI
		  HAL_print_flag(halHandle, gMotorVars.Flag_enableSys);
          #endif
	  }
      #endif

    // Waiting for enable system flag to be set
    while(!(gMotorVars.Flag_enableSys));

    // loop while the enable system flag is true
    while(gMotorVars.Flag_enableSys)
      {
        #ifdef HAL_SCI
     	char str1[20], str2[20], str0[20];
        #endif

        CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle;

        // increment counters
        gCounter_updateGlobals++;


        if(CTRL_isError(ctrlHandle))
          {
            // set the enable controller flag to false
            CTRL_setFlag_enableCtrl(ctrlHandle,false);

            // set the enable system flag to false
            gMotorVars.Flag_enableSys = false;

            // disable the PWM
            HAL_disablePwm(halHandle);
          }
        else
          {
            // update the controller state
            bool flag_ctrlStateChanged = CTRL_updateState(ctrlHandle);

            #ifdef USING_POTENTIOMETER
            if (Flag_Init_Motor) {
        	  usDelay(5000L);
        	  gMotorVars.Flag_Run_Identify = true;
              #ifdef HAL_SCI
        	  HAL_print_flag(halHandle, gMotorVars.Flag_Run_Identify);
              #endif
        	  Flag_Init_Motor = false;
            }
            #endif

            // enable or disable the control
            CTRL_setFlag_enableCtrl(ctrlHandle, true/*gMotorVars.Flag_Run_Identify*/);

            if(flag_ctrlStateChanged)
              {
                CTRL_State_e ctrlState = CTRL_getState(ctrlHandle);
                EST_State_e estState = EST_getState(obj->estHandle);

                if(ctrlState == CTRL_State_OffLine)
                  {
                    // enable the PWM
                    HAL_enablePwm(halHandle);
                    HAL_print_state(halHandle, CTRL_State_OffLine);
                  }
                else if(ctrlState == CTRL_State_OnLine)
                  {

                    HAL_print_state(halHandle, CTRL_State_OnLine);

                    if((estState < EST_State_LockRotor) || (estState > EST_State_MotorIdentified))
                      {
                        // update the ADC bias values
                        HAL_updateAdcBias(halHandle);
                      }

                    // Return the bias value for currents
                    gMotorVars.I_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Current,0);
                    gMotorVars.I_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Current,1);
                    gMotorVars.I_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Current,2);

                    // Return the bias value for voltages
                    gMotorVars.V_bias.value[0] = HAL_getBias(halHandle,HAL_SensorType_Voltage,0);
                    gMotorVars.V_bias.value[1] = HAL_getBias(halHandle,HAL_SensorType_Voltage,1);
                    gMotorVars.V_bias.value[2] = HAL_getBias(halHandle,HAL_SensorType_Voltage,2);

                    // enable the PWM
                    HAL_enablePwm(halHandle);

                    #ifdef HAL_SCI
                    _IQ24toa(str0,"%1.15f",gMotorVars.I_bias.value[0]);
                    _IQ24toa(str1,"%1.15f",gMotorVars.I_bias.value[1]);
                    _IQ24toa(str2,"%1.15f",gMotorVars.I_bias.value[2]);
                    HAL_printf(halHandle, "\n\n...\tI_bias = {%s,%s,%s}", str0, str1, str2);

                    _IQ24toa(str0,"%1.15f",gMotorVars.V_bias.value[0]);
                    _IQ24toa(str1,"%1.15f",gMotorVars.V_bias.value[1]);
                    _IQ24toa(str2,"%1.15f",gMotorVars.V_bias.value[2]);
                    HAL_printf(halHandle, "\n...\tV_bias = {%s,%s,%s}\n",  str0, str1, str2);

                    _IQ24toa(str0,"%1.15f",gMotorVars.Rs_Ohm);
                    _IQ24toa(str1,"%1.15f",gMotorVars.Lsq_H);
                    HAL_printf(halHandle, "\n...\Rs_Ohm = %s    Lsq_H = %s\n", str0, str1);
                    // HAL_printf(halHandle, "\n...\Rs_Ohm %1.15d * Lsq_H %1.15d\n",  gMotorVars.Rs_Ohm, gMotorVars.Lsq_H);
                    HAL_print_state(halHandle, CTRL_State_OnLine);
                    #endif
                  }
                else if(ctrlState == CTRL_State_Idle)
                  {
                    // disable the PWM
                    HAL_disablePwm(halHandle);
                    gMotorVars.Flag_Run_Identify = false;
                    HAL_print_state(halHandle, CTRL_State_Idle);
                  }

                if((CTRL_getFlag_enableUserMotorParams(ctrlHandle) == true) &&
                  (ctrlState > CTRL_State_Idle) &&
                  (gMotorVars.CtrlVersion.minor == 6))
                  {
                    // call this function to fix 1p6
                    USER_softwareUpdate1p6(ctrlHandle);
                  }

              }
          }


        if(EST_isMotorIdentified(obj->estHandle))
          {
            // set the current ramp
            EST_setMaxCurrentSlope_pu(obj->estHandle,gMaxCurrentSlope);
            gMotorVars.Flag_MotorIdentified = true;

            #ifdef USING_POTENTIOMETER

            // Using the potentiometer here to control the speed
            gPotentiometer = HAL_readPotentiometerData(halHandle);
            gMotorVars.SpeedRef_krpm =  _IQmpy( gPotentiometer, CTRL_getMaximumSpeed_pu(ctrlHandle) );

            #ifdef HAL_SCI
            if (prt == 501) {
            	_IQ13toa(str1,"%10.03f",_IQ13mpy(_IQtoIQ13(gMotorVars.SpeedRef_krpm), _IQ13(1000.00)));
            	_IQ13toa(str2,"%10.03f",_IQ13mpy(_IQtoIQ13(gMotorVars.Speed_krpm),    _IQ13(1000.00)));
            	_IQtoa(str0,"%10.03f",gPotentiometer);
            	HAL_printf(halHandle,"\r... %s rpm  (set at %s) pot %s   ", str2, str1, str0);
            	prt = 1;
            } else {
            	prt++;
            }
            #endif

            #endif

            // set the speed reference
            CTRL_setSpd_ref_krpm(ctrlHandle,gMotorVars.SpeedRef_krpm);

            // set the speed acceleration
            CTRL_setMaxAccel_pu(ctrlHandle,_IQmpy(MAX_ACCEL_KRPMPS_SF,gMotorVars.MaxAccel_krpmps));

            if(Flag_Latch_softwareUpdate)
            {
              Flag_Latch_softwareUpdate = false;

              USER_calcPIgains(ctrlHandle);
            }

          }
        else
          {
            Flag_Latch_softwareUpdate = true;

            // the estimator sets the maximum current slope during identification
            gMaxCurrentSlope = EST_getMaxCurrentSlope_pu(obj->estHandle);
          }


        // when appropriate, update the global variables
        if(gCounter_updateGlobals >= NUM_MAIN_TICKS_FOR_GLOBAL_VARIABLE_UPDATE)
          {
            // reset the counter
            gCounter_updateGlobals = 0;

            updateGlobalVariables_motor(ctrlHandle);
          }

        // recalculate Kp and Ki gains to fix the R/L limitation of 2000.0, and Kp limit to 0.11
        recalcKpKi(ctrlHandle);

        if(CTRL_getMotorType(ctrlHandle) == MOTOR_Type_Induction)
          {
            // set electrical frequency limit to zero while identifying an induction motor
            setFeLimitZero(ctrlHandle);

            // calculate Dir_qFmt for acim motors
            acim_Dir_qFmtCalc(ctrlHandle);
          }

        // enable/disable the forced angle
        EST_setFlag_enableForceAngle(obj->estHandle,gMotorVars.Flag_enableForceAngle);

        // enable or disable power warp
        CTRL_setFlag_enablePowerWarp(ctrlHandle,gMotorVars.Flag_enablePowerWarp);

#ifdef DRV8301_SPI
        HAL_writeDrvData(halHandle,&gDrvSpi8301Vars);

        HAL_readDrvData(halHandle,&gDrvSpi8301Vars);
#endif

      } // end of while(gFlag_enableSys) loop


    // disable the PWM
    HAL_disablePwm(halHandle);

    // set the default controller parameters (Reset the control to re-identify the motor)
    CTRL_setParams(ctrlHandle,&gUserParams);
    gMotorVars.Flag_Run_Identify = false;

  } // end of for(;;) loop

} // end of main() function


interrupt void mainISR(void)
{
  HAL_PwmData_t negPwmData = {_IQ(0.0), _IQ(0.0), _IQ(0.0)};

  // toggle status LED
  if(gLEDcnt++ > (uint_least32_t)(USER_ISR_FREQ_Hz / LED_BLINK_FREQ_Hz))
  {
    HAL_toggleLed(halHandle,(GPIO_Number_e)HAL_Gpio_LED2);
    gLEDcnt = 0;
  }


  // acknowledge the ADC interrupt
  HAL_acqAdcInt(halHandle,ADC_IntNumber_1);


  // convert the ADC data
  HAL_readAdcData(halHandle,&gAdcData);


  // run the controller
  CTRL_run(ctrlHandle,halHandle,&gAdcData,&negPwmData);


  // negate PwmData generated by SVGEN module in ROM
  gPwmData.Tabc.value[0] = _IQmpy(negPwmData.Tabc.value[0], _IQ(-1.0));
  gPwmData.Tabc.value[1] = _IQmpy(negPwmData.Tabc.value[1], _IQ(-1.0));
  gPwmData.Tabc.value[2] = _IQmpy(negPwmData.Tabc.value[2], _IQ(-1.0));


  // write the PWM compare values
  HAL_writePwmData(halHandle,&gPwmData);


  // setup the controller
  CTRL_setup(ctrlHandle);


  return;
} // end of mainISR() function


void updateGlobalVariables_motor(CTRL_Handle handle)
{
  CTRL_Obj *obj = (CTRL_Obj *)handle;

  // get the speed estimate
  gMotorVars.Speed_krpm = EST_getSpeed_krpm(obj->estHandle);

  // get the real time speed reference coming out of the speed trajectory generator
  gMotorVars.SpeedTraj_krpm = _IQmpy(CTRL_getSpd_int_ref_pu(handle),EST_get_pu_to_krpm_sf(obj->estHandle));

  // get the magnetizing current
  gMotorVars.MagnCurr_A = EST_getIdRated(obj->estHandle);

  // get the rotor resistance
  gMotorVars.Rr_Ohm = EST_getRr_Ohm(obj->estHandle);

  // get the stator resistance
  gMotorVars.Rs_Ohm = EST_getRs_Ohm(obj->estHandle);

  // get the stator inductance in the direct coordinate direction
  gMotorVars.Lsd_H = EST_getLs_d_H(obj->estHandle);

  // get the stator inductance in the quadrature coordinate direction
  gMotorVars.Lsq_H = EST_getLs_q_H(obj->estHandle);

  // get the flux
  gMotorVars.Flux_VpHz = EST_getFlux_VpHz(obj->estHandle);

  // get the controller state
  gMotorVars.CtrlState = CTRL_getState(handle);

  // get the estimator state
  gMotorVars.EstState = EST_getState(obj->estHandle);

  // Get the DC buss voltage
  gMotorVars.VdcBus_kV = _IQmpy(gAdcData.dcBus,_IQ(USER_IQ_FULL_SCALE_VOLTAGE_V/1000.0));

  return;
} // end of updateGlobalVariables_motor() function


void recalcKpKi(CTRL_Handle handle)
{
  CTRL_Obj *obj = (CTRL_Obj *)handle;
  EST_State_e EstState = EST_getState(obj->estHandle);

  if((EST_isMotorIdentified(obj->estHandle) == false) && (EstState == EST_State_Rs))
    {
      float_t Lhf = CTRL_getLhf(handle);
      float_t Rhf = CTRL_getRhf(handle);
      float_t RhfoverLhf = Rhf/Lhf;
      _iq Kp = _IQ(0.25*Lhf*USER_IQ_FULL_SCALE_CURRENT_A/(USER_CTRL_PERIOD_sec*USER_IQ_FULL_SCALE_VOLTAGE_V));
      _iq Ki = _IQ(RhfoverLhf*USER_CTRL_PERIOD_sec);

      // set Rhf/Lhf
      CTRL_setRoverL(handle,RhfoverLhf);

      // set the controller proportional gains
      CTRL_setKp(handle,CTRL_Type_PID_Id,Kp);
      CTRL_setKp(handle,CTRL_Type_PID_Iq,Kp);

      // set the Id controller gains
      CTRL_setKi(handle,CTRL_Type_PID_Id,Ki);
      PID_setKi(obj->pidHandle_Id,Ki);

      // set the Iq controller gains
      CTRL_setKi(handle,CTRL_Type_PID_Iq,Ki);
      PID_setKi(obj->pidHandle_Iq,Ki);
    }

  return;
} // end of recalcKpKi() function


void setFeLimitZero(CTRL_Handle handle)
{
  CTRL_Obj *obj = (CTRL_Obj *)handle;
  EST_State_e EstState = EST_getState(obj->estHandle);

  _iq fe_neg_max_pu;
  _iq fe_pos_min_pu;

  if((EST_isMotorIdentified(obj->estHandle) == false) && (CTRL_getMotorType(handle) == MOTOR_Type_Induction))
    {
	  fe_neg_max_pu = _IQ30(0.0);

	  fe_pos_min_pu = _IQ30(0.0);
    }
  else
    {
	  fe_neg_max_pu = _IQ30(-USER_ZEROSPEEDLIMIT);

	  fe_pos_min_pu = _IQ30(USER_ZEROSPEEDLIMIT);
    }

  EST_setFe_neg_max_pu(obj->estHandle, fe_neg_max_pu);

  EST_setFe_pos_min_pu(obj->estHandle, fe_pos_min_pu);

  return;
} // end of setFeLimitZero() function


void acim_Dir_qFmtCalc(CTRL_Handle handle)
{
  CTRL_Obj *obj = (CTRL_Obj *)handle;
  EST_State_e EstState = EST_getState(obj->estHandle);

  if(EstState == EST_State_IdRated)
    {
      EST_setDir_qFmt(obj->estHandle, EST_computeDirection_qFmt(obj->estHandle, 0.7));
    }

  return;
} // end of acim_Dir_qFmtCalc() function


//@} //defgroup
// end of file



  • Tinhtan Nguyen said:
    In this lab I can see that the Motor ID process spins the motor to find out the I_bias and then the V_bias.

    No, the bias is found initially before any of the ID process begins.  The motor doesn't spin until RampUp phase.

    The speed target for RampUp is set by #define USER_MOTOR_FLUX_EST_FREQ_Hz and PU is set by any value / #define USER_IQ_FULL_SCALE_FREQ_Hz

    Please read SPRUHJ1 - it is very detailed on the ID process.

     

  • As I understand USER_IQ_FULL_SCALE_FREQ_Hz is the cap of expecting maximum speed we want to get from the motor.

    For example, in the user.h with a value of 800 for an 8-pole motor we would not have the motor running over 6000rpm. ( 6000/60 * 8 = 800)

    The USER_MOTOR_FLUX_EST_FREQ_Hz which I thought is only used for the Motor ID process and  it is the minimum freq to spin the motor (?)

    I still could not figure out how the estimator determines the maximum speed allowed (after the Motor ID process done.) Which factors contribute into that ?

    The reason I asked because I could not figure out how to increase  the max rpm of the motor. I know the motor could run faster than the returned value of CTRL_getMaximumSpeed_pu(). So does this function, CTRL_getMaximumSpeed_pu, returns a smaller value when we increase USER_IQ_FULL_SCALE_FREQ_Hz ?

  • Basically, I would like to know 

    1. when was CTRL_setMaximumSpeed_pu(CTRL_Handle handle,const _iq maxSpeed_pu) being called? Is it from inside the EST state machine?

    2. and how was the maxSpeed_pu calculated?

    Thanks.

  • Tinhtan Nguyen said:

    As I understand USER_IQ_FULL_SCALE_FREQ_Hz is the cap of expecting maximum speed we want to get from the motor.

    For example, in the user.h with a value of 800 for an 8-pole motor we would not have the motor running over 6000rpm. ( 6000/60 * 8 = 800)

    USER_IQ_FULL_SCALE_FREQ_Hz is used as the quotient in determining the per unit frequency scale. It is also used as a static variable to scale other variables. It should be slightly greater than any expected frequency so that expected frequency / USER_IQ_FULL_SCALE_FREQ_Hz < 1.0, but the IQmath number type allows up to 1.99 values.

    Tinhtan Nguyen said:
    The USER_MOTOR_FLUX_EST_FREQ_Hz which I thought is only used for the Motor ID process and  it is the minimum freq to spin the motor (?)

    Yes, this is just used during motor ID to set the speed target for the RampUp state of estimation.

    Tinhtan Nguyen said:
    I still could not figure out how the estimator determines the maximum speed allowed (after the Motor ID process done.) Which factors contribute into that ?

    There isn't a maximum allowed in the InstaSPIN-FOC projects. You can send a too large command to the system.  From a fixed point (IQmath) variable scaling I mentioned above that you can command / request just less than 2x the USER_IQ_FULL_SCALE_FREQ_Hz

    Per the project / lab write-ups you set a speed command by this function. We have made the value a global variable that you can instrument from the Expressions or from the Universal GUI.

    // set the speed reference
    CTRL_setSpd_ref_krpm(ctrlHandle,gMotorVars.SpeedRef_krpm);

     

  • I should also note that the output of the speed PI controller is an IqRef command. If being used, this output is limited by / saturated to

    USER_MOTOR_MAX_CURRENT          

  • Thanks Chris.

    I think I have found the answer. Somewhere in the FAST lib, it does something like this:

                _iq Is_Max_squared_pu = _IQ((USER_MOTOR_MAX_CURRENT*USER_MOTOR_MAX_CURRENT)/  \
                                       (USER_IQ_FULL_SCALE_CURRENT_A*USER_IQ_FULL_SCALE_CURRENT_A));
                 _iq Id_squared_pu = _IQmpy(CTRL_getId_ref_pu(ctrlHandle),CTRL_getId_ref_pu(ctrlHandle));

                 _iq Iq_Max_pu;

                 // Take into consideration that Iq^2+Id^2 = Is^2
                 Iq_Max_pu = _IQsqrt(Is_Max_squared_pu-Id_squared_pu);

                 //Set new max trajectory
                 CTRL_setSpdMax(ctrlHandle, Iq_Max_pu);

    That segment of code is in lab09.