void ST_runVelMove(ST_Handle handle, CTRL_Handle ctrlHandle)
{

    ST_Obj *stObj = (ST_Obj *)handle;
    CTRL_Obj *ctrlObj = (CTRL_Obj *)ctrlHandle;

	// Run SpinTAC Move
	// If we are not in reset, and the SpeedRef_krpm has been modified
	if((EST_getState(ctrlObj->estHandle) == EST_State_OnLine) && (_IQmpy(gMotorVars.SpeedRef_krpm, _IQ(ST_SPEED_PU_PER_KRPM)) != STVELMOVE_getVelocityEnd(stObj->velMoveHandle))) {
		// Get the configuration for SpinTAC Move
		STVELMOVE_setCurveType(stObj->velMoveHandle, gMotorVars.SpinTAC.VelMoveCurveType);
		STVELMOVE_setVelocityEnd(stObj->velMoveHandle, _IQmpy(gMotorVars.SpeedRef_krpm, _IQ(ST_SPEED_PU_PER_KRPM)));
		STVELMOVE_setAccelerationLimit(stObj->velMoveHandle, _IQmpy(gMotorVars.MaxAccel_krpmps, _IQ(ST_SPEED_PU_PER_KRPM)));
		STVELMOVE_setJerkLimit(stObj->velMoveHandle, _IQ20mpy(gMotorVars.MaxJrk_krpmps2, _IQ20(ST_SPEED_PU_PER_KRPM)));
		// Enable SpinTAC Move
		STVELMOVE_setEnable(stObj->velMoveHandle, true);
		// If starting from zero speed, enable ForceAngle, otherwise disable ForceAngle
		if(_IQabs(STVELMOVE_getVelocityStart(stObj->velMoveHandle)) < _IQ(ST_MIN_ID_SPEED_PU)) {
			EST_setFlag_enableForceAngle(ctrlObj->estHandle, true);
			gMotorVars.Flag_enableForceAngle = true;
		}
		else {
			EST_setFlag_enableForceAngle(ctrlObj->estHandle, false);
			gMotorVars.Flag_enableForceAngle = false;
		}
	}
	STVELMOVE_run(stObj->velMoveHandle);
}
Esempio n. 2
0
void smopos_calc(SMOPOS *v)
{	
    _iq E0;
    
    E0 = _IQ(0.5);
    
// Sliding mode current observer
    v->EstIalpha = _IQmpy(v->Fsmopos,v->EstIalpha) + _IQmpy(v->Gsmopos,(v->Valpha-v->Ealpha-v->Zalpha));
    v->EstIbeta = _IQmpy(v->Fsmopos,v->EstIbeta) + _IQmpy(v->Gsmopos,(v->Vbeta-v->Ebeta-v->Zbeta));

// Current errors
    v->IalphaError = v->EstIalpha - v->Ialpha;
    v->IbetaError = v->EstIbeta - v->Ibeta;

// Sliding control calculator
    if (_IQabs(v->IalphaError) < E0)
       v->Zalpha = _IQmpy(v->Kslide,_IQdiv(v->IalphaError,E0));  
    else if (v->IalphaError >= E0) 
       v->Zalpha = v->Kslide;
    else if (v->IalphaError <= -E0) 
       v->Zalpha = -v->Kslide;

    if (_IQabs(v->IbetaError) < E0)
       v->Zbeta = _IQmpy(v->Kslide,_IQdiv(v->IbetaError,E0));  
    else if (v->IbetaError >= E0) 
       v->Zbeta = v->Kslide;
    else if (v->IbetaError <= -E0) 
       v->Zbeta = -v->Kslide;

// Sliding control filter -> back EMF calculator
    v->Ealpha = v->Ealpha + _IQmpy(v->Kslf,(v->Zalpha-v->Ealpha));
    v->Ebeta = v->Ebeta + _IQmpy(v->Kslf,(v->Zbeta-v->Ebeta));

// Rotor angle calculator -> Theta = atan(-Ealpha,Ebeta)
    v->Theta = _IQatan2PU(-v->Ealpha,v->Ebeta); 
}
Esempio n. 3
0
//----------------------------------------------------------------------------
// Main code:
//----------------------------------------------------------------------------
int main(void)
{
    unsigned int  i;

    _iq tempX, tempY, tempP, tempM, tempMmax;
//  char buffer[20];

    int *WatchdogWDCR = (void *) 0x7029;

    // Disable the watchdog:
    asm(" EALLOW ");
    *WatchdogWDCR = 0x0068;
    asm(" EDIS ");

    Step.Xsize = _IQ(STEP_X_SIZE);
    Step.Ysize = _IQ(STEP_Y_SIZE);
    Step.Yoffset = 0;
    Step.X = 0;
    Step.Y = Step.Yoffset;

    // Fill the buffers with some initial value
    for(i=0; i < DATA_LOG_SIZE; i++)
    {
        Dlog.Xwaveform[i] = _IQ(0.0);
        Dlog.Ywaveform[i] = _IQ(0.0);
        Dlog.Mag[i] = _IQ(0.0);
        Dlog.Phase[i] = _IQ(0.0);
        Dlog.Exp[i] = _IQ(0.0);
    }

    Step.GainX = _IQ(X_GAIN);
	Step.FreqX = _IQ(X_FREQ);
	Step.GainY = _IQ(Y_GAIN);
	Step.FreqY = _IQ(Y_FREQ);

    // Calculate maximum magnitude value:
    tempMmax = _IQmag(Step.GainX, Step.GainY);

    for(i=0; i < DATA_LOG_SIZE; i++)
    {
        // Calculate waveforms:
        Step.X = Step.X + _IQmpy(Step.Xsize, Step.FreqX);
        if( Step.X > _IQ(2*PI) )
            Step.X -= _IQ(2*PI);

        Step.Y = Step.Y + _IQmpy(Step.Ysize, Step.FreqY);
        if( Step.Y > _IQ(2*PI) )
            Step.Y -= _IQ(2*PI);

        Dlog.Xwaveform[i] = tempX = _IQmpy(_IQsin(Step.X), Step.GainX);
        Dlog.Ywaveform[i] = tempY = _IQmpy(_IQabs(_IQsin(Step.Y)), Step.GainY);

        // Calculate normalized magnitude:
        //
        // Mag = sqrt(X^2 + Y^2)/sqrt(GainX^2 + GainY^2);
        tempM = _IQmag(tempX, tempY);
        Dlog.Mag[i] = _IQdiv(tempM, tempMmax);

        // Calculate normalized phase:
        //
        // Phase = (long) (atan2PU(X,Y) * 360);
        tempP = _IQatan2PU(tempY,tempX);
        Dlog.Phase[i] = _IQmpyI32int(tempP, 360);

        // Use the exp function
        Dlog.Exp[i] = _IQexp(_IQmpy(_IQ(.075L),_IQ(i)));

		// Use the asin function
		Dlog.Asin[i] = _IQasin(Dlog.Xwaveform[i]);
    }
}
// MainISR
interrupt void MainISR(void)
{
    // Verifying the ISR
    IsrTicker++;

    if(RunMotor)
    {
        // =============================== LEVEL 1 ======================================
        //   Checks target independent modules, duty cycle waveforms and PWM update
        //   Keep the motors disconnected at this level
        // ==============================================================================

#if (BUILDLEVEL==LEVEL1)

        // ------------------------------------------------------------------------------
        //  Connect inputs of the RMP module and call the ramp control macro
        // ------------------------------------------------------------------------------
        rc1.TargetValue = VRef1;
        RC_MACRO(rc1)

        // ------------------------------------------------------------------------------
        //  Connect inputs of the PWM_DRV module and call the PWM signal generation macro
        // ------------------------------------------------------------------------------
        pwm1.MfuncC1 = (int16)_IQtoIQ15(_IQabs(rc1.SetpointValue)); // MfuncC1 is in Q15
        PWM_MACRO(pwm1) // Calculate the new PWM compare values
        

        if(rc1.SetpointValue < 0)
        {
            Rotation1 = 0;
        }
        else
        {
            Rotation1 = 1;
        }

        if(Motor==1)
        {
            if(Rotation1==0)
            {
                EPwm1Regs.AQCSFRC.bit.CSFB = 0;    //Forcing Disabled on EPWM1B
                EPwm1Regs.AQCSFRC.bit.CSFA = 1;    //EPWM1A forced low
            }
            else if(Rotation1 == 1)
            {
                EPwm1Regs.AQCSFRC.bit.CSFA = 0;    //Forcing Disabled on EPWM1A
                EPwm1Regs.AQCSFRC.bit.CSFB = 1;    //EPWM1B forced low
            }
            else
            {
                EPwm1Regs.AQCSFRC.bit.CSFA = 1;    //EPWM1A forced low
                EPwm1Regs.AQCSFRC.bit.CSFB = 1;    //EPWM1B forced low
            }
            EPwm1Regs.CMPA.half.CMPA=pwm1.PWM1out;
        }
        //else if (Motor==2)
        //{
            if(Rotation1==0)
            {
                EPwm2Regs.AQCSFRC.bit.CSFB = 0;    //Forcing Disabled on EPWM2B
                EPwm2Regs.AQCSFRC.bit.CSFA = 1;    //EPWM2A forced low
            }
            else if(Rotation1 == 1)
            {
                EPwm2Regs.AQCSFRC.bit.CSFA = 0;    //Forcing Disabled on EPWM2A
                EPwm2Regs.AQCSFRC.bit.CSFB = 1;    //EPWM2B forced low
            }
            else
            {
                EPwm2Regs.AQCSFRC.bit.CSFA = 1;    //EPWM2A forced low
                EPwm2Regs.AQCSFRC.bit.CSFB = 1;    //EPWM2B forced low
            }
            EPwm2Regs.CMPA.half.CMPA=pwm1.PWM1out;
        //}

        // ------------------------------------------------------------------------------
        //    Connect inputs of the PWMDAC module
        // ------------------------------------------------------------------------------
        PwmDacCh1 = (int16)_IQtoIQ15(VRef1);
        PwmDacCh2 = (int16)_IQtoIQ15(rc1.SetpointValue);

        // ------------------------------------------------------------------------------
        //    Connect inputs of the DATALOG module
        // ------------------------------------------------------------------------------
        DlogCh1 = (int16)_IQtoIQ15(VRef1);
        DlogCh2 = (int16)_IQtoIQ15(rc1.SetpointValue);
        DlogCh3 = (int16)_IQtoIQ15(VRef1);
        DlogCh4 = (int16)_IQtoIQ15(rc1.SetpointValue);

#endif // (BUILDLEVEL==LEVEL1)

        // =============================== LEVEL 2 ======================================
        //   Level 2 verifies the analog-to-digital conversion, offset compensation
        // ==============================================================================

#if (BUILDLEVEL==LEVEL2)

// ------------------------------------------------------------------------------
//  Connect inputs of the RMP module and call the ramp control macro
// ------------------------------------------------------------------------------
        rc1.TargetValue = VRef1;
        RC_MACRO(rc1)

// ------------------------------------------------------------------------------
//  Measure phase currents, subtract the offset and normalize from (-0.5,+0.5) to (-1,+1).
// ------------------------------------------------------------------------------
        if(Motor==1)
        {
            IFdbk1b=_IQ15toIQ((AdcResult.ADCRESULT1<<3)-_IQ15(0.5))<<1;
            IFdbk1a=_IQ15toIQ((AdcResult.ADCRESULT0<<3)-_IQ15(0.5))<<1;
            IFdbk1 = (IFdbk1a - IFdbk1b) >> 1;
        }
        else if(Motor==2)
void ST_runVelPlan(ST_Handle handle, CTRL_Handle ctrlHandle)
{

    _iq speedFeedback;
    ST_Obj *stObj = (ST_Obj *)handle;
    CTRL_Obj *ctrlObj = (CTRL_Obj *)ctrlHandle;

    // Get the mechanical speed in pu
    speedFeedback = EST_getFm_pu(ctrlObj->estHandle);

	// SpinTAC Velocity Plan
	if(gVelPlanRunFlag == ST_PLAN_STOP && gMotorVars.SpinTAC.VelPlanRun == ST_PLAN_START) {
		if(gMotorVars.SpeedRef_krpm != 0) {
			gMotorVars.SpeedRef_krpm = 0;
		}
		if(_IQabs(speedFeedback) < _IQ(ST_MIN_ID_SPEED_PU)) {
			if(STVELPLAN_getErrorID(stObj->velPlanHandle) != false) {
				STVELPLAN_setEnable(stObj->velPlanHandle, false);
				STVELPLAN_setReset(stObj->velPlanHandle, true);
				gMotorVars.SpinTAC.VelPlanRun = gVelPlanRunFlag;
			}
			else {
				STVELPLAN_setEnable(stObj->velPlanHandle, true);
				STVELPLAN_setReset(stObj->velPlanHandle, false);
				gVelPlanRunFlag = gMotorVars.SpinTAC.VelPlanRun;
			}
		}
	}
	if(gMotorVars.SpinTAC.VelPlanRun == ST_PLAN_STOP) {
		STVELPLAN_setReset(stObj->velPlanHandle, true);
		gVelPlanRunFlag = gMotorVars.SpinTAC.VelPlanRun;
	}
	if(gVelPlanRunFlag == ST_PLAN_START && gMotorVars.SpinTAC.VelPlanRun == ST_PLAN_PAUSE) {
		STVELPLAN_setEnable(stObj->velPlanHandle, false);
		gVelPlanRunFlag = gMotorVars.SpinTAC.VelPlanRun;
	}
	if(gVelPlanRunFlag == ST_PLAN_PAUSE && gMotorVars.SpinTAC.VelPlanRun == ST_PLAN_START) {
		STVELPLAN_setEnable(stObj->velPlanHandle, true);
		gVelPlanRunFlag = gMotorVars.SpinTAC.VelPlanRun;
	}

	// Run SpinTAC Velocity Plan
	STVELPLAN_run(stObj->velPlanHandle);

	// Update the global variable for the SpinTAC Plan State
	gState = (PlanState_e)STVELPLAN_getCurrentState(stObj->velPlanHandle);

	if(STVELPLAN_getStatus(stObj->velPlanHandle) != ST_PLAN_IDLE) {
		// Send the profile configuration to SpinTAC Velocity Profile Generator
		gMotorVars.SpeedRef_krpm = _IQmpy(STVELPLAN_getVelocitySetpoint(stObj->velPlanHandle), _IQ(ST_SPEED_KRPM_PER_PU));
		gMotorVars.MaxAccel_krpmps = _IQmpy(STVELPLAN_getAccelerationLimit(stObj->velPlanHandle), _IQ(ST_SPEED_KRPM_PER_PU));
		gMotorVars.MaxJrk_krpmps2 = _IQ20mpy(STVELPLAN_getJerkLimit(stObj->velPlanHandle), _IQ20(ST_SPEED_KRPM_PER_PU));
	}
	else
	{
		if(gVelPlanRunFlag == ST_PLAN_START && gMotorVars.SpinTAC.VelPlanRun == ST_PLAN_START) {
			gMotorVars.SpinTAC.VelPlanRun = ST_PLAN_STOP;
			gVelPlanRunFlag = gMotorVars.SpinTAC.VelPlanRun;
			gMotorVars.SpeedRef_krpm = gMotorVars.StopSpeedRef_krpm;
		}
	}
}
void ST_runVelId(ST_Handle handle, CTRL_Handle ctrlHandle)
{

    _iq speedFeedback, iqReference;
    ST_Obj *stObj = (ST_Obj *)handle;
    CTRL_Obj *ctrlObj = (CTRL_Obj *)ctrlHandle;

    // Get the mechanical speed in pu
    speedFeedback = EST_getFm_pu(ctrlObj->estHandle);

	if(gMotorVars.SpinTAC.VelIdRun == true) {
		// if beginning the SpinTAC Identify process
		// set the speed reference to zero
		gMotorVars.SpeedRef_krpm = 0;
		// wait until the actual speed is zero
		if((_IQabs(speedFeedback) < _IQ(ST_MIN_ID_SPEED_PU)) && (STVELID_getEnable(stObj->velIdHandle) == false)) {
			CTRL_setFlag_enableSpeedCtrl(ctrlHandle, false);
			gMotorVars.Flag_enableForceAngle = true;
			EST_setFlag_enableForceAngle(ctrlObj->estHandle, gMotorVars.Flag_enableForceAngle);
			// set the GoalSpeed
			STVELID_setGoalSpeed(stObj->velIdHandle, _IQmpy(gMotorVars.SpinTAC.VelIdGoalSpeed_krpm, _IQ(ST_SPEED_PU_PER_KRPM)));
			// set the Torque Ramp Time
			STVELID_setTorqueRampTime_sec(stObj->velIdHandle, gMotorVars.SpinTAC.VelIdTorqueRampTime_sec);
			// Enable SpinTAC Inertia Identify
			STVELID_setEnable(stObj->velIdHandle, true);
			// Set a positive speed reference to FAST to provide direction information
			gMotorVars.SpeedRef_krpm = _IQ(0.001);
			CTRL_setSpd_ref_krpm(ctrlHandle, gMotorVars.SpeedRef_krpm);
		}
	}

	// Run SpinTAC Inertia Identify
	STVELID_setVelocityFeedback(stObj->velIdHandle, speedFeedback);
	STVELID_run(stObj->velIdHandle);

	if((STVELID_getStatus(stObj->velIdHandle) == ST_VEL_ID_IDLE) && (_IQabs(speedFeedback) < _IQ(ST_MIN_ID_SPEED_PU))) {
		// If inertia identification is successful, update the inertia setting of SpinTAC Velocity Controller
		// EXAMPLE: STVELCTL_setInertia(stObj->velCtlHandle, STVELID_getInertiaEstimate(stObj->velIdHandle));
		gMotorVars.SpinTAC.VelIdRun = false;
		// return the speed reference to zero
		gMotorVars.SpeedRef_krpm = gMotorVars.StopSpeedRef_krpm;
		CTRL_setFlag_enableSpeedCtrl(ctrlHandle, true);
		CTRL_setSpd_ref_krpm(ctrlHandle, gMotorVars.SpeedRef_krpm);
	}
	else if((STVELID_getErrorID(stObj->velIdHandle) != false) && (STVELID_getErrorID(stObj->velIdHandle) != ST_ID_INCOMPLETE_ERROR)) {
	// if not done & in error, wait until speed is less than 1RPM to exit
		if(_IQabs(speedFeedback) < _IQ(ST_MIN_ID_SPEED_PU)) {
			gMotorVars.SpinTAC.VelIdRun = false;
			// return the speed reference to zero
			gMotorVars.SpeedRef_krpm = gMotorVars.StopSpeedRef_krpm;
			CTRL_setFlag_enableSpeedCtrl(ctrlHandle, true);
			CTRL_setSpd_ref_krpm(ctrlHandle, gMotorVars.SpeedRef_krpm);
		}
	}

	// select SpinTAC Identify
	iqReference = STVELID_getTorqueReference(stObj->velIdHandle);

	// Set the Iq reference that came out of SpinTAC Velocity Control
	CTRL_setIq_ref_pu(ctrlHandle, iqReference);
}