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.

Emergency motor stop

Genius 5910 points

Hi,

I want to make Emergency motor stop function, to stop the motor as fast as possible and disable the controller. I don 't know If I'm running in velocity or position control.

A made this:

void Control_Emergency (INTR_Handle intr)
{
    ST_Obj *stObj = (ST_Obj *) intr->stHandle;
    STPOSMOVE_setCurveType(stObj->posMoveHandle,ST_MOVE_CUR_TRAP); // Set trapezoidal profile
    STPOSMOVE_setDecelerationLimit(stObj->posMoveHandle,_IQmpy (STPOSMOVE_getDecelerationMaximum(stObj->posMoveHandle), _IQ(ST_SPEED_PU_PER_KRPM))); // set Deceleration to maximum
    STPOSMOVE_setJerkLimit(stObj->posMoveHandle, _IQ20mpy (STPOSMOVE_getJerkMaximum(stObj->posMoveHandle), _IQ20 (ST_SPEED_PU_PER_KRPM))); // set Jerk  to maximum
    STPOSMOVE_setVelocityEnd  (stObj->posMoveHandle,_IQ (0)); // Set end speed to 0
    STPOSMOVE_setPositionStep_mrev(stObj->posMoveHandle,0,0); // set move to 0.
    STPOSMOVE_setEnable(stObj->posMoveHandle, true);
    // STPOSMOVE_setReset (stObj->posMoveHandle, true);
    STPOSMOVE_run(stObj->posMoveHandle);
}

This works for velocity control but not position control. I tried to get in the STPOSMOVE halt state (en=false en res=true) but that didn't stop the motor.  What is wrong?

 

  • Ernst,

    One thing I noticed if that on the lines:

    STPOSMOVE_setDecelerationLimit(stObj->posMoveHandle,_IQmpy (STPOSMOVE_getDecelerationMaximum(stObj->posMoveHandle), _IQ(ST_SPEED_PU_PER_KRPM))); // set Deceleration to maximum
    STPOSMOVE_setJerkLimit(stObj->posMoveHandle, _IQ20mpy (STPOSMOVE_getJerkMaximum(stObj->posMoveHandle), _IQ20 (ST_SPEED_PU_PER_KRPM))); // set Jerk to maximum

    The units coming from Move are in the same scaled units that it is expecting as inputs so you don't need the multiply by the scale factor.  You also should set the acceleration limit as well.  So your code would look like this:

    STPOSMOVE_setAccelerationLimit(stObj->posMoveHandle,STPOSMOVE_getAccelerationMaximum(stObj->posMoveHandle)); // set Acceleration to maximum
    STPOSMOVE_setDecelerationLimit(stObj->posMoveHandle,STPOSMOVE_getDecelerationMaximum(stObj->posMoveHandle)); // set Deceleration to maximum
    STPOSMOVE_setJerkLimit(stObj->posMoveHandle, STPOSMOVE_getJerkMaximum(stObj->posMoveHandle)); // set Jerk  to maximum

    When running in position mode, you cannot interrupt the profile.  In order to get it to halt you should set enable to false.  That is a big difference between position mode and velocity mode.



  • Adam,

    For Velocity control this works great, almost a direct stop.

    But for position control :

    When SpinTAC.PosMoveDone == 0(the complete move) and  setting enable to true/false and/or set reset to true/false. Doesn't do anything till SpinTAC.PosMoveDone == 1 again. In that stage PosMoveStatus == ST_MOVE_HALT and not ST_MOVE_BUSY.   So  it looks like, when the controller makes a position move the controller doesn't respond to any command till it finished.

    Edit: is there a flag that indicate that the motor is at a standstill?

     

  • Ernst,

    In position mode, when the status is ST_MOVE_HALT it is doing a transition to stop (defined as zero velocity).  But when doing that transition it is using the configured limits.  So if you want it to do a stop very quickly you still need to set the limits to the maximum values.

  • Adam,

    I don't understand what you mean by maximum values. I assume jerk, Accelerate and Decelerate. I have those set to  max. Because  I have other results.

     I did some tests. And every time I tried to stop it, the motion finished the transition. And even when you don't try to abort the move the state the move is in is ST_MOVE_HALT in stead of ST_MOVE_BUSY.  It was in ST_MOVE_HALT the whole move without trying to aborting.

    In Velocity control when the motor Accelerate/Decelerate  the state is ST_MOVE_BUSY and when it is up to speed ,it is ST_MOVE_IDLE.

     

  • Ernst,

    Are you working with lab 13c or 13d?

    If so I think there might be a logic bug in that lab where the halt state is being forced incorrectly.  There is a piece of logic in the function ST_runPosPlan.  I've replicated it below:

    if(gMotorVars.SpinTAC.PosPlanRun == ST_PLAN_STOP) {
    	STPOSPLAN_setReset(stObj->posPlanHandle, true);
    	STPOSMOVE_setEnable(stObj->posMoveHandle, false);
    	gPosPlanRunFlag = gMotorVars.SpinTAC.PosPlanRun;
    }

    I think this is forcing Move into a HALT state incorrectly.  Try replacing that code with the following:

    if(gMotorVars.SpinTAC.PosPlanRun == ST_PLAN_STOP && gPosPlanRunFlag != ST_PLAN_STOP) {
    	STPOSPLAN_setReset(stObj->posPlanHandle, true);
    	STPOSMOVE_setEnable(stObj->posMoveHandle, false);
    	gPosPlanRunFlag = gMotorVars.SpinTAC.PosPlanRun;
    }

    The best way to force Move into halt is to set the enable to false.  You just need to make sure that the limits are also updated otherwise it will do a slow transition to the halt condition of zero speed.

    What the profile generator does, is that when the enable signal is set to false during a move, it will automatically change the profile type to be velocity, and will set the goal velocity to be zero.  It will then execute that profile where it is trying to drive the velocity to zero.  

  • Adam,

    Thanks for your help.  The problem was, I didn't set Reset to false in my program init. 

    So my program works now. This is the end result:

    / Emergency motor stop. Controller is switched off.
    void Contrl_Emergency (INTR_Handle intr)
    {
        ST_Obj *stObj = (ST_Obj *) intr->stHandle;
        STPOSMOVE_setCurveType(stObj->posMoveHandle,ST_MOVE_CUR_TRAP); // Set trapezoidal profile
        STPOSMOVE_setDecelerationLimit(stObj->posMoveHandle,STPOSMOVE_getDecelerationMaximum(stObj->posMoveHandle)); // set Deceleration to maximum
        STPOSMOVE_setJerkLimit(stObj->posMoveHandle, STPOSMOVE_getJerkMaximum(stObj->posMoveHandle)); // set Jerk to maximum
        STPOSMOVE_setVelocityEnd  (stObj->posMoveHandle,_IQ (0)); // Set end speed to 0
        STPOSMOVE_setPositionStep_mrev(stObj->posMoveHandle,0,0); // set move to 0.
        STPOSCTL_setPositionReference_mrev (stObj->posCtlHandle,STPOSCONV_getPosition_mrev(stObj->posConvHandle));
        // Flag_enableFOC = true is velocity control mode
        if (intr->Flag_enableFOC == true){
            STPOSMOVE_setEnable(stObj->posMoveHandle, true);
            STPOSMOVE_setReset(stObj->posMoveHandle, false);

        } else {
            STPOSMOVE_setEnable(stObj->posMoveHandle, false);
            STPOSMOVE_setReset(stObj->posMoveHandle, true);
        }
        STPOSMOVE_run(stObj->posMoveHandle);
        // Wait till motor is at standstill
        while (intr->SpinTAC.PosMoveStatus != ST_MOVE_IDLE);
        Contrl_SetEnableFlag (intr,false); // Disable Controller
    }

  • Ernst,

    I'm glad to hear that you were able to get it working.