extern void VS_FREQ_setProfile(VS_FREQ_Handle handle, float_t LowFreq, float_t HighFreq, float_t VoltMin, float_t VoltMax) { VS_FREQ_Obj *obj = (VS_FREQ_Obj *)handle; obj->LowFreq = _IQ(LowFreq/obj->iqFullScaleFreq_Hz); obj->HighFreq = _IQ(HighFreq/obj->iqFullScaleFreq_Hz); obj->VoltMin = _IQ(VoltMin/obj->iqFullScaleVoltage_V); obj->VoltMax = _IQ(VoltMax/obj->iqFullScaleVoltage_V); obj->VfSlope = _IQdiv((obj->VoltMax - obj->VoltMin), (obj->HighFreq - obj->LowFreq)); obj->Vdq_gain.value[0] = _IQ(0.3); obj->Vdq_gain.value[1] = _IQsqrt(_IQ(obj->maxVsMag_pu*obj->maxVsMag_pu) - _IQmpy(obj->Vdq_gain.value[0], obj->Vdq_gain.value[0])); return; } // end of VS_FREQ_setProfile() function
void updateGlobalVariables_motor(CTRL_Handle handle) { CTRL_Obj *obj = (CTRL_Obj *)handle; int32_t tmp; // 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 torque estimate gMotorVars.Torque_Nm = USER_computeTorque_Nm(handle, gTorque_Flux_Iq_pu_to_Nm_sf, gTorque_Ls_Id_Iq_pu_to_Nm_sf); // when calling EST_ functions that return a float, and fpu32 is enabled, an integer is needed as a return // so that the compiler reads the returned value from the accumulator instead of fpu32 registers // get the magnetizing current tmp = EST_getIdRated(obj->estHandle); gMotorVars.MagnCurr_A = *((float_t *)&tmp); // get the rotor resistance tmp = EST_getRr_Ohm(obj->estHandle); gMotorVars.Rr_Ohm = *((float_t *)&tmp); // get the stator resistance tmp = EST_getRs_Ohm(obj->estHandle); gMotorVars.Rs_Ohm = *((float_t *)&tmp); // get the stator inductance in the direct coordinate direction tmp = EST_getLs_d_H(obj->estHandle); gMotorVars.Lsd_H = *((float_t *)&tmp); // get the stator inductance in the quadrature coordinate direction tmp = EST_getLs_q_H(obj->estHandle); gMotorVars.Lsq_H = *((float_t *)&tmp); // get the flux in V/Hz in floating point tmp = EST_getFlux_VpHz(obj->estHandle); gMotorVars.Flux_VpHz = *((float_t *)&tmp); // get the flux in Wb in fixed point gMotorVars.Flux_Wb = USER_computeFlux(handle, gFlux_pu_to_Wb_sf); // get the controller state gMotorVars.CtrlState = CTRL_getState(handle); // get the estimator state gMotorVars.EstState = EST_getState(obj->estHandle); // read Vd and Vq vectors per units gMotorVars.Vd = CTRL_getVd_out_pu(ctrlHandle); gMotorVars.Vq = CTRL_getVq_out_pu(ctrlHandle); // calculate vector Vs in per units gMotorVars.Vs = _IQsqrt(_IQmpy(gMotorVars.Vd, gMotorVars.Vd) + _IQmpy(gMotorVars.Vq, gMotorVars.Vq)); // read Id and Iq vectors in amps gMotorVars.Id_A = _IQmpy(CTRL_getId_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A)); gMotorVars.Iq_A = _IQmpy(CTRL_getIq_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A)); // calculate vector Is in amps gMotorVars.Is_A = _IQsqrt(_IQmpy(gMotorVars.Id_A, gMotorVars.Id_A) + _IQmpy(gMotorVars.Iq_A, gMotorVars.Iq_A)); // 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 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); // Initialize field weakening fwHandle = FW_init(&fw,sizeof(fw)); // Disable field weakening FW_setFlag_enableFw(fwHandle, false); // Clear field weakening counter FW_clearCounter(fwHandle); // Set the number of ISR per field weakening ticks FW_setNumIsrTicksPerFwTick(fwHandle, FW_NUM_ISR_TICKS_PER_CTRL_TICK); // Set the deltas of field weakening FW_setDeltas(fwHandle, FW_INC_DELTA, FW_DEC_DELTA); // Set initial output of field weakening to zero FW_setOutput(fwHandle, _IQ(0.0)); // Set the field weakening controller limits FW_setMinMax(fwHandle,_IQ(USER_MAX_NEGATIVE_ID_REF_CURRENT_A/USER_IQ_FULL_SCALE_CURRENT_A),_IQ(0.0)); // 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); // compute scaling factors for flux and torque calculations gFlux_pu_to_Wb_sf = USER_computeFlux_pu_to_Wb_sf(); gFlux_pu_to_VpHz_sf = USER_computeFlux_pu_to_VpHz_sf(); gTorque_Ls_Id_Iq_pu_to_Nm_sf = USER_computeTorque_Ls_Id_Iq_pu_to_Nm_sf(); gTorque_Flux_Iq_pu_to_Nm_sf = USER_computeTorque_Flux_Iq_pu_to_Nm_sf(); for(;;) { // Waiting for enable system flag to be set while(!(gMotorVars.Flag_enableSys)); Flag_Latch_softwareUpdate = true; // Enable the Library internal PI. Iq is referenced by the speed PI now CTRL_setFlag_enableSpeedCtrl(ctrlHandle, true); // loop while the enable system flag is true while(gMotorVars.Flag_enableSys) { CTRL_Obj *obj = (CTRL_Obj *)ctrlHandle; // increment counters gCounter_updateGlobals++; // enable/disable the use of motor parameters being loaded from user.h CTRL_setFlag_enableUserMotorParams(ctrlHandle,gMotorVars.Flag_enableUserParams); // enable/disable Rs recalibration during motor startup EST_setFlag_enableRsRecalc(obj->estHandle,gMotorVars.Flag_enableRsRecalc); // enable/disable automatic calculation of bias values CTRL_setFlag_enableOffset(ctrlHandle,gMotorVars.Flag_enableOffsetcalc); 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); // enable or disable the control CTRL_setFlag_enableCtrl(ctrlHandle, gMotorVars.Flag_Run_Identify); if(flag_ctrlStateChanged) { CTRL_State_e ctrlState = CTRL_getState(ctrlHandle); if(ctrlState == CTRL_State_OffLine) { // enable the PWM HAL_enablePwm(halHandle); } else if(ctrlState == CTRL_State_OnLine) { if(gMotorVars.Flag_enableOffsetcalc == true) { // update the ADC bias values HAL_updateAdcBias(halHandle); } else { // set the current bias HAL_setBias(halHandle,HAL_SensorType_Current,0,_IQ(I_A_offset)); HAL_setBias(halHandle,HAL_SensorType_Current,1,_IQ(I_B_offset)); HAL_setBias(halHandle,HAL_SensorType_Current,2,_IQ(I_C_offset)); // set the voltage bias HAL_setBias(halHandle,HAL_SensorType_Voltage,0,_IQ(V_A_offset)); HAL_setBias(halHandle,HAL_SensorType_Voltage,1,_IQ(V_B_offset)); HAL_setBias(halHandle,HAL_SensorType_Voltage,2,_IQ(V_C_offset)); } // 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); } else if(ctrlState == CTRL_State_Idle) { // disable the PWM HAL_disablePwm(halHandle); gMotorVars.Flag_Run_Identify = false; } 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)) { _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)); // 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); // set the current ramp EST_setMaxCurrentSlope_pu(obj->estHandle,gMaxCurrentSlope); gMotorVars.Flag_MotorIdentified = true; // 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); // initialize the watch window kp and ki current values with pre-calculated values gMotorVars.Kp_Idq = CTRL_getKp(ctrlHandle,CTRL_Type_PID_Id); gMotorVars.Ki_Idq = CTRL_getKi(ctrlHandle,CTRL_Type_PID_Id); } } else { Flag_Latch_softwareUpdate = true; // initialize the watch window kp and ki values with pre-calculated values gMotorVars.Kp_spd = CTRL_getKp(ctrlHandle,CTRL_Type_PID_spd); gMotorVars.Ki_spd = CTRL_getKi(ctrlHandle,CTRL_Type_PID_spd); // 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); } // update Kp and Ki gains updateKpKiGains(ctrlHandle); // set field weakening enable flag depending on user's input FW_setFlag_enableFw(fwHandle,gMotorVars.Flag_enableFieldWeakening); // 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
void updateGlobalVariables_motor(CTRL_Handle handle, ST_Handle sthandle) { CTRL_Obj *obj = (CTRL_Obj *)handle; ST_Obj *stObj = (ST_Obj *)sthandle; // 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(STVELMOVE_getVelocityReference(stObj->velMoveHandle),EST_get_pu_to_krpm_sf(obj->estHandle)); // get the torque estimate gMotorVars.Torque_Nm = USER_computeTorque_Nm(handle, gTorque_Flux_Iq_pu_to_Nm_sf, gTorque_Ls_Id_Iq_pu_to_Nm_sf); // 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 in V/Hz in floating point gMotorVars.Flux_VpHz = EST_getFlux_VpHz(obj->estHandle); // get the flux in Wb in fixed point gMotorVars.Flux_Wb = USER_computeFlux(handle, gFlux_pu_to_Wb_sf); // 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)); // get the Iq reference from the speed controller gMotorVars.IqRef_A = _IQmpy(STVELCTL_getTorqueReference(stObj->velCtlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A)); // gets the Velocity Controller status gMotorVars.SpinTAC.VelCtlStatus = STVELCTL_getStatus(stObj->velCtlHandle); // get the inertia setting gMotorVars.SpinTAC.InertiaEstimate_Aperkrpm = _IQmpy(STVELCTL_getInertia(stObj->velCtlHandle), _IQ(ST_SPEED_PU_PER_KRPM * USER_IQ_FULL_SCALE_CURRENT_A)); // get the friction setting gMotorVars.SpinTAC.FrictionEstimate_Aperkrpm = _IQmpy(STVELCTL_getFriction(stObj->velCtlHandle), _IQ(ST_SPEED_PU_PER_KRPM * USER_IQ_FULL_SCALE_CURRENT_A)); // get the Velocity Controller error gMotorVars.SpinTAC.VelCtlErrorID = STVELCTL_getErrorID(stObj->velCtlHandle); // get the Velocity Move status gMotorVars.SpinTAC.VelMoveStatus = STVELMOVE_getStatus(stObj->velMoveHandle); // get the Velocity Move profile time gMotorVars.SpinTAC.VelMoveTime_ticks = STVELMOVE_getProfileTime_tick(stObj->velMoveHandle); // get the Velocity Move error gMotorVars.SpinTAC.VelMoveErrorID = STVELMOVE_getErrorID(stObj->velMoveHandle); // read Vd and Vq vectors per units gMotorVars.Vd = CTRL_getVd_out_pu(ctrlHandle); gMotorVars.Vq = CTRL_getVq_out_pu(ctrlHandle); // calculate vector Vs in per units gMotorVars.Vs = _IQsqrt(_IQmpy(gMotorVars.Vd, gMotorVars.Vd) + _IQmpy(gMotorVars.Vq, gMotorVars.Vq)); // read Id and Iq vectors in amps gMotorVars.Id_A = _IQmpy(CTRL_getId_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A)); gMotorVars.Iq_A = _IQmpy(CTRL_getIq_in_pu(ctrlHandle), _IQ(USER_IQ_FULL_SCALE_CURRENT_A)); // calculate vector Is in amps gMotorVars.Is_A = _IQsqrt(_IQmpy(gMotorVars.Id_A, gMotorVars.Id_A) + _IQmpy(gMotorVars.Iq_A, gMotorVars.Iq_A)); return; } // end of updateGlobalVariables_motor() function