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.

Instaspin-foc的参数辨识程序-lab02b

Other Parts Discussed in Thread: MOTORWARE

1.lab02b相对lab02a将ctrl_run()函数开源,

2.控制器有三种状态:

if(ctrlState == CTRL_State_OnLine)
{
CTRL_Obj *obj = (CTRL_Obj *)handle;

// increment the current count
CTRL_incrCounter_current(handle);

// increment the speed count
CTRL_incrCounter_speed(handle);

if(EST_getState(obj->estHandle) >= EST_State_MotorIdentified)
{
// run the online controller
CTRL_runOnLine_User(handle,pAdcData,pPwmData);
}
else
{
// run the online controller
CTRL_runOnLine(handle,pAdcData,pPwmData);
}
}
else if(ctrlState == CTRL_State_OffLine)
{
// run the offline controller
CTRL_runOffLine(handle,halHandle,pAdcData,pPwmData);
}
else if(ctrlState == CTRL_State_Idle)
{
// set all pwm outputs to zero
pPwmData->Tabc.value[0] = _IQ(0.0);
pPwmData->Tabc.value[1] = _IQ(0.0);
pPwmData->Tabc.value[2] = _IQ(0.0);
}

idle:PWM输出置0;

offline:CTRL_runOffLine()函数进行offset计算(一阶滤波),和将PWM置0;

online:如果电机辨识完成,运行CTRL_runOnLine_User(handle,pAdcData,pPwmData);//FOC实现程序,将2a的代码开源

            电机未辨识,运行CTRL_runOnLine(handle,pAdcData,pPwmData);电机进行R、L、RATED_FLUX是否是在这里进行,估算器EST代码是否开源:

就是实现电机参数辨识的算法,在CTRL_runOnLine()函数没有找到相关代码。

对比CTRL_runOnLine_User(handle,pAdcData,pPwmData)函数和CTRL_runOnLine_User(handle,pAdcData,pPwmData)函数并没有太大的区别,这是怎么实现的电机参数辨识算法?

3.FAST observer是FAST观测器 ,输出Flux、angle 、speed、torque.

估算器EST指的就是运行电机参数辨识的程序吗,

这两个是不同的,是吗?谢谢~



  • EST就是运行电机参数辨识。

  • 文档中写到:

    when the motor is being identified CTRL_runOnLine is executed from ROM. After the motor is identified, CTRL_runOnLine_User is run from user RAM. CTRL_runOnLine_User is an inlined function that is located in ctrl.h. It contains the entire FOC implementation with calls to the FAST observer for rotor flux angle values.

     电机未辨识,运行CTRL_runOnLine(handle,pAdcData,pPwmData);电机进行参数辨识的估算器算法在这里执行完成。

    电机识别完成,运行CTRL_runOnLine_User(handle,pAdcData,pPwmData);//调用FAST观测器的电角度实现完整的FOC控制

    这两个函数实现不同的功能,对比CTRL_runOnLine_User(handle,pAdcData,pPwmData)函数和CTRL_runOnLine_User(handle,pAdcData,pPwmData)函数并没有太大的区别,请详细分析下电机参数辨识在CTRL_runOnLine函数是如何实现的?估算器部分程序不开源具体是在哪里调用的,谢谢

    附上CTRL_runOnLine(handle,pAdcData,pPwmData)函数:

    //! \brief Runs the online controller
    //! \param[in] handle The controller (CTRL) handle
    //! \param[in] pAdcData The pointer to the ADC data
    //! \param[out] pPwmData The pointer to the PWM data
    inline void CTRL_runOnLine(CTRL_Handle handle,
    const HAL_AdcData_t *pAdcData,HAL_PwmData_t *pPwmData)
    {
    CTRL_Obj *obj = (CTRL_Obj *)handle;

    _iq angle_pu;

    MATH_vec2 phasor;


    // run Clarke transform on current
    CLARKE_run(obj->clarkeHandle_I,&pAdcData->I,CTRL_getIab_in_addr(handle));

    // run Clarke transform on voltage
    CLARKE_run(obj->clarkeHandle_V,&pAdcData->V,CTRL_getVab_in_addr(handle));


    // run the estimator
    EST_run(obj->estHandle,CTRL_getIab_in_addr(handle),CTRL_getVab_in_addr(handle),
    pAdcData->dcBus,TRAJ_getIntValue(obj->trajHandle_spd));


    // generate the motor electrical angle
    angle_pu = EST_getAngle_pu(obj->estHandle);


    // compute the sin/cos phasor
    CTRL_computePhasor(angle_pu,&phasor);


    // set the phasor in the Park transform
    PARK_setPhasor(obj->parkHandle,&phasor);


    // run the Park transform
    PARK_run(obj->parkHandle,CTRL_getIab_in_addr(handle),CTRL_getIdq_in_addr(handle));


    // when appropriate, run the PID speed controller
    if(EST_doSpeedCtrl(obj->estHandle))
    {
    if(CTRL_doSpeedCtrl(handle))
    {
    _iq refValue = TRAJ_getIntValue(obj->trajHandle_spd);
    _iq fbackValue = EST_getFm_pu(obj->estHandle);
    _iq outMax = TRAJ_getIntValue(obj->trajHandle_spdMax);
    _iq outMin = -outMax;

    // reset the speed count
    CTRL_resetCounter_speed(handle);

    PID_setMinMax(obj->pidHandle_spd,outMin,outMax);

    PID_run_spd(obj->pidHandle_spd,refValue,fbackValue,CTRL_getSpd_out_addr(handle));
    }
    }
    else
    {
    // zero the speed command
    CTRL_setSpd_out_pu(handle,_IQ(0.0));

    // reset the integrator
    PID_setUi(obj->pidHandle_spd,_IQ(0.0));
    }


    // when appropriate, run the PID Id and Iq controllers
    if(CTRL_doCurrentCtrl(handle) && EST_doCurrentCtrl(obj->estHandle))
    {
    _iq Kp_Id = CTRL_getKp(handle,CTRL_Type_PID_Id);
    _iq Kp_Iq = CTRL_getKp(handle,CTRL_Type_PID_Iq);
    _iq refValue;
    _iq fbackValue;
    _iq outMin,outMax;

    _iq maxVsMag = CTRL_getMaxVsMag_pu(handle);

    // reset the current count
    CTRL_resetCounter_current(handle);

    // ***********************************
    // configure and run the Id controller

    // compute the Kp gain
    // Scale Kp instead of output to prevent saturation issues
    if(CTRL_getFlag_enableDcBusComp(handle))
    {
    Kp_Id = _IQmpy(Kp_Id,EST_getOneOverDcBus_pu(obj->estHandle));
    }

    PID_setKp(obj->pidHandle_Id,Kp_Id);

    // compute the reference value
    refValue = TRAJ_getIntValue(obj->trajHandle_Id) + CTRL_getId_ref_pu(handle);

    // update the Id reference value
    EST_updateId_ref_pu(obj->estHandle,&refValue);

    // get the feedback value
    fbackValue = CTRL_getId_in_pu(handle);

    // set minimum and maximum for Id controller output
    outMax = maxVsMag;
    outMin = -outMax;

    // set the minimum and maximum values
    PID_setMinMax(obj->pidHandle_Id,outMin,outMax);

    // run the Id PID controller
    PID_run(obj->pidHandle_Id,refValue,fbackValue,CTRL_getVd_out_addr(handle));

    // set the Id reference value in the estimator
    EST_setId_ref_pu(obj->estHandle,refValue);

    // ***********************************
    // configure and run the Iq controller

    // compute the Kp gain
    // Scale Kp instead of output to prevent saturation issues
    if(CTRL_getFlag_enableDcBusComp(handle))
    {
    Kp_Iq = _IQmpy(Kp_Iq,EST_getOneOverDcBus_pu(obj->estHandle));
    }

    PID_setKp(obj->pidHandle_Iq,Kp_Iq);

    // get the reference value
    if(CTRL_getFlag_enableSpeedCtrl(handle))
    {
    if(!CTRL_useZeroIq_ref(handle))
    {
    refValue = CTRL_getSpd_out_pu(handle);
    }
    else
    {
    refValue = _IQ(0.0);
    }
    }
    else
    {
    // get the Iq reference value
    refValue = CTRL_getIq_ref_pu(handle);
    }

    // get the feedback value
    fbackValue = CTRL_getIq_in_pu(handle);

    // generate the Iq PID output limits without square root
    outMax = maxVsMag - _IQabs(CTRL_getVd_out_pu(handle));
    outMin = -outMax;

    // set the minimum and maximum values
    PID_setMinMax(obj->pidHandle_Iq,outMin,outMax);

    // run the Iq PID controller
    PID_run(obj->pidHandle_Iq,refValue,fbackValue,CTRL_getVq_out_addr(handle));

    // set the Iq reference value in the estimator
    EST_setIq_ref_pu(obj->estHandle,refValue);
    }


    // set the phasor in the inverse Park transform
    IPARK_setPhasor(obj->iparkHandle,&phasor);


    // run the inverse Park module
    IPARK_run(obj->iparkHandle,CTRL_getVdq_out_addr(handle),CTRL_getVab_out_addr(handle));


    // run the space Vector Generator (SVGEN) module
    SVGEN_run(obj->svgenHandle,CTRL_getVab_out_addr(handle),&(pPwmData->Tabc));

    return;
    } // end of CTRL_runOnLine() function

    附上CTRL_runOnLine_User(handle,pAdcData,pPwmData)函数:
    //! \brief Runs the online user controller
    //! \details An implementation of the field oriented control. The online user controller
    //! is executed in user's memory i.e. RAM/FLASH and can be changed in any way
    //! suited to the user.
    //! \param[in] handle The controller (CTRL) handle
    //! \param[in] pAdcData The pointer to the ADC data
    //! \param[out] pPwmData The pointer to the PWM data
    inline void CTRL_runOnLine_User(CTRL_Handle handle,
    const HAL_AdcData_t *pAdcData,HAL_PwmData_t *pPwmData)
    {
    CTRL_Obj *obj = (CTRL_Obj *)handle;

    _iq angle_pu;

    MATH_vec2 phasor;


    // run Clarke transform on current
    CLARKE_run(obj->clarkeHandle_I,&pAdcData->I,CTRL_getIab_in_addr(handle));


    // run Clarke transform on voltage
    CLARKE_run(obj->clarkeHandle_V,&pAdcData->V,CTRL_getVab_in_addr(handle));


    // run the estimator
    EST_run(obj->estHandle,CTRL_getIab_in_addr(handle),CTRL_getVab_in_addr(handle),
    pAdcData->dcBus,TRAJ_getIntValue(obj->trajHandle_spd));


    // generate the motor electrical angle
    angle_pu = EST_getAngle_pu(obj->estHandle);


    // compute the sin/cos phasor
    CTRL_computePhasor(angle_pu,&phasor);


    // set the phasor in the Park transform
    PARK_setPhasor(obj->parkHandle,&phasor);


    // run the Park transform
    PARK_run(obj->parkHandle,CTRL_getIab_in_addr(handle),CTRL_getIdq_in_addr(handle));


    // when appropriate, run the PID speed controller
    if(CTRL_doSpeedCtrl(handle))
    {
    _iq refValue = TRAJ_getIntValue(obj->trajHandle_spd);
    _iq fbackValue = EST_getFm_pu(obj->estHandle);
    _iq outMax = TRAJ_getIntValue(obj->trajHandle_spdMax);
    _iq outMin = -outMax;

    // reset the speed count
    CTRL_resetCounter_speed(handle);

    PID_setMinMax(obj->pidHandle_spd,outMin,outMax);

    PID_run_spd(obj->pidHandle_spd,refValue,fbackValue,CTRL_getSpd_out_addr(handle));
    }


    // when appropriate, run the PID Id and Iq controllers
    if(CTRL_doCurrentCtrl(handle))
    {
    _iq Kp_Id = CTRL_getKp(handle,CTRL_Type_PID_Id);
    _iq Kp_Iq = CTRL_getKp(handle,CTRL_Type_PID_Iq);
    _iq refValue;
    _iq fbackValue;
    _iq outMin,outMax;

    // read max voltage vector to set proper limits to current controllers
    _iq maxVsMag = CTRL_getMaxVsMag_pu(handle);


    // reset the current count
    CTRL_resetCounter_current(handle);

    // ***********************************
    // configure and run the Id controller

    // compute the Kp gain
    // Scale Kp instead of output to prevent saturation issues
    if(CTRL_getFlag_enableDcBusComp(handle))
    {
    Kp_Id = _IQmpy(Kp_Id,EST_getOneOverDcBus_pu(obj->estHandle));
    }

    PID_setKp(obj->pidHandle_Id,Kp_Id);

    // compute the reference value
    refValue = TRAJ_getIntValue(obj->trajHandle_Id) + CTRL_getId_ref_pu(handle);

    // update the Id reference value
    EST_updateId_ref_pu(obj->estHandle,&refValue);

    // get the feedback value
    fbackValue = CTRL_getId_in_pu(handle);

    // set minimum and maximum for Id controller output
    outMax = maxVsMag;
    outMin = -outMax;

    // set the minimum and maximum values
    PID_setMinMax(obj->pidHandle_Id,outMin,outMax);

    // run the Id PID controller
    PID_run(obj->pidHandle_Id,refValue,fbackValue,CTRL_getVd_out_addr(handle));

    // ***********************************
    // configure and run the Iq controller

    // compute the Kp gain
    // Scale Kp instead of output to prevent saturation issues
    if(CTRL_getFlag_enableDcBusComp(handle))
    {
    Kp_Iq = _IQmpy(Kp_Iq,EST_getOneOverDcBus_pu(obj->estHandle));
    }

    PID_setKp(obj->pidHandle_Iq,Kp_Iq);

    // get the reference value
    if(CTRL_getFlag_enableSpeedCtrl(handle))
    {
    refValue = CTRL_getSpd_out_pu(handle);
    }
    else
    {
    // get the Iq reference value
    refValue = CTRL_getIq_ref_pu(handle);
    }

    // get the feedback value
    fbackValue = CTRL_getIq_in_pu(handle);

    // set minimum and maximum for Id controller output
    outMax = _IQsqrt(_IQmpy(maxVsMag,maxVsMag) - _IQmpy(CTRL_getVd_out_pu(handle),CTRL_getVd_out_pu(handle)));
    outMin = -outMax;

    // set the minimum and maximum values
    PID_setMinMax(obj->pidHandle_Iq,outMin,outMax);

    // run the Iq PID controller
    PID_run(obj->pidHandle_Iq,refValue,fbackValue,CTRL_getVq_out_addr(handle));
    }

    {
    _iq angleComp_pu;


    // compensate angle delay
    angleComp_pu = CTRL_angleDelayComp(handle, angle_pu);


    // compute the sin/cos phasor
    CTRL_computePhasor(angleComp_pu,&phasor);
    }


    // set the phasor in the inverse Park transform
    IPARK_setPhasor(obj->iparkHandle,&phasor);


    // run the inverse Park module
    IPARK_run(obj->iparkHandle,CTRL_getVdq_out_addr(handle),CTRL_getVab_out_addr(handle));


    // run the space Vector Generator (SVGEN) module
    SVGEN_run(obj->svgenHandle,CTRL_getVab_out_addr(handle),&(pPwmData->Tabc));

    return;
    } // end of CTRL_runOnLine_User() function


  • CTRL_runOnLine函数是如何实现参数辨识的?谢谢~

  • 参数辨识部分的程序是固化在ROM里的 在程序中调用即可,具体的原理老外没有公开,只是提供了接口参数。另外你可以看一下motorware中相关的文档:

    InstaSPIN-FOC™ and InstaSPIN-MOTION™ User's Guide

  •  非常感谢的回答~

    我有看过User's Guide的chapter 6 他具体的参数辨识策略,我也都能明白。只是这两个函数完全实现不同的功能,但对比这两个函数没有发现太大的区别。

     电机未辨识,运行CTRL_runOnLine(handle,pAdcData,pPwmData);电机进行参数辨识的估算器算法在这里执行完成。

    电机识别完成,运行CTRL_runOnLine_User(handle,pAdcData,pPwmData);//调用FAST观测器的电角度实现完整的FOC控制

    有如下几处差别:

    1.TI有没有关于ROM中的算法和用户存储区代码的相关说明,和具体调用策略。谢谢~