|
|
@@ -101,6 +101,7 @@ static void PMSM_FOC_Reset_PID(void) {
|
|
|
PI_Controller_Reset(_gFOC_Ctrl.pi_ctl_iq, 0);
|
|
|
PI_Controller_Reset(_gFOC_Ctrl.pi_ctl_spd, 0);
|
|
|
PI_Controller_Reset(_gFOC_Ctrl.pi_ctl_fw, 0);
|
|
|
+ PI_Controller_Reset(_gFOC_Ctrl.pi_ctl_trq, 0);
|
|
|
}
|
|
|
|
|
|
|
|
|
@@ -109,13 +110,15 @@ void PMSM_FOC_CoreInit(void) {
|
|
|
_gFOC_Ctrl.pi_ctl_iq = &PI_Ctrl_IQ;
|
|
|
_gFOC_Ctrl.pi_ctl_spd = &PI_Ctrl_Spd;
|
|
|
_gFOC_Ctrl.pi_ctl_fw = &PI_Ctrl_fw;
|
|
|
+ _gFOC_Ctrl.pi_ctl_trq = &PI_Ctrl_trq;
|
|
|
+
|
|
|
memset(&_gFOC_Ctrl.in, 0, sizeof(_gFOC_Ctrl.in));
|
|
|
memset(&_gFOC_Ctrl.out, 0, sizeof(_gFOC_Ctrl.out));
|
|
|
_gFOC_Ctrl.params.s_maxiDC = (MAX_iDQ);
|
|
|
_gFOC_Ctrl.params.s_maxiDC = (MAX_iDC);
|
|
|
_gFOC_Ctrl.params.s_maxRPM = (MAX_SPEED);
|
|
|
_gFOC_Ctrl.params.n_modulation = SVM_Modulation;
|
|
|
- _gFOC_Ctrl.params.n_PhaseFilterCeof = (0.2f);
|
|
|
+ _gFOC_Ctrl.params.n_PhaseFilterCeof = (0.1f);
|
|
|
_gFOC_Ctrl.params.maxvDQ.d = MAX_vDC;
|
|
|
_gFOC_Ctrl.params.minvDQ.d = -MAX_vDC;
|
|
|
_gFOC_Ctrl.params.maxvDQ.q = MAX_vDC;
|
|
|
@@ -123,7 +126,7 @@ void PMSM_FOC_CoreInit(void) {
|
|
|
_gFOC_Ctrl.params.s_maxIdq = MAX_iDQ;
|
|
|
_gFOC_Ctrl.params.s_minIdq = -MAX_iDQ;
|
|
|
_gFOC_Ctrl.params.n_poles = MOTOR_POLES;
|
|
|
- _gFOC_Ctrl.out.n_RunMode = OPEN_MODE;
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_OPEN;
|
|
|
_gFOC_Ctrl.out.f_vdqRation = 0;
|
|
|
_gFOC_Ctrl.in.s_manualAngle = 0x3D00;
|
|
|
_gFOC_Ctrl.in.s_vDC = (MAX_vDC);
|
|
|
@@ -136,9 +139,9 @@ void PMSM_FOC_CoreInit(void) {
|
|
|
PMSM_FOC_Reset_PID();
|
|
|
}
|
|
|
|
|
|
-
|
|
|
+//#define PHASE_LFP
|
|
|
static __INLINE void PMSM_FOC_Update_Hardware(void) {
|
|
|
- if (_gFOC_Ctrl.in.s_manualAngle != 0x3D00) {
|
|
|
+ if ((_gFOC_Ctrl.in.s_manualAngle != 0x3D00) && !_gFOC_Ctrl.in.b_MTPA_calibrate) {
|
|
|
_gFOC_Ctrl.in.s_motAngle = _gFOC_Ctrl.in.s_manualAngle;
|
|
|
_gFOC_Ctrl.in.s_hallAngle = hall_sensor_get_theta();
|
|
|
}else {
|
|
|
@@ -158,14 +161,7 @@ static __INLINE void PMSM_FOC_Update_Hardware(void) {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
-static __INLINE void PMSM_FOC_Update_PI_Ctrls(void) {
|
|
|
- /* update speed pi ctrl */
|
|
|
- if (_gFOC_Ctrl.params.s_maxIdq != _gFOC_Ctrl.pi_ctl_spd->max) {
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->max = _gFOC_Ctrl.params.s_maxIdq;
|
|
|
- }
|
|
|
- if (_gFOC_Ctrl.params.s_minIdq != _gFOC_Ctrl.pi_ctl_spd->min) {
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->min = _gFOC_Ctrl.params.s_minIdq;
|
|
|
- }
|
|
|
+static __INLINE void PMSM_FOC_Update_PI_Idq(void) {
|
|
|
/* update id pi ctrl */
|
|
|
if (_gFOC_Ctrl.params.maxvDQ.d != _gFOC_Ctrl.pi_ctl_id->max) {
|
|
|
_gFOC_Ctrl.pi_ctl_id->max = _gFOC_Ctrl.params.maxvDQ.d;
|
|
|
@@ -193,9 +189,9 @@ void PMSM_FOC_Schedule(void) {
|
|
|
|
|
|
PMSM_FOC_Update_Hardware();
|
|
|
|
|
|
- if (_gFOC_Ctrl.out.n_RunMode != OPEN_MODE) {
|
|
|
+ if (_gFOC_Ctrl.out.n_RunMode != CTRL_MODE_OPEN) {
|
|
|
|
|
|
- PMSM_FOC_Update_PI_Ctrls();
|
|
|
+ PMSM_FOC_Update_PI_Idq();
|
|
|
|
|
|
Clark(iabc[0], iabc[1], iabc[2], &vAB);
|
|
|
|
|
|
@@ -225,11 +221,12 @@ void PMSM_FOC_Schedule(void) {
|
|
|
pwm_update_sample(_gFOC_Ctrl.out.n_Sample1, _gFOC_Ctrl.out.n_Sample2, _gFOC_Ctrl.out.n_CPhases);
|
|
|
|
|
|
if (_gFOC_Ctrl.ctrl_count % 5 == 0) {
|
|
|
+ //plot_1data16(FtoS16x1000(PMSM_FOC_Get_iDC()));
|
|
|
//plot_2data16(FtoS16x1000(_gFOC_Ctrl.out.s_RealIdq.d), FtoS16x1000(_gFOC_Ctrl.out.s_RealIdq.q));
|
|
|
- plot_1data16(_gFOC_Ctrl.in.s_motRPM);
|
|
|
+ //plot_1data16(_gFOC_Ctrl.in.s_motRPM);
|
|
|
//plot_2data16(FtoS16(_gFOC_Ctrl.in.s_hallAngle), FtoS16(_gFOC_Ctrl.in.s_motAngle));
|
|
|
//plot_3data16(FtoS16x1000(iabc[0]), FtoS16x1000(_gFOC_Ctrl.in.s_targetVdq.d), FtoS16x1000(_gFOC_Ctrl.out.s_RealIdq.d));
|
|
|
- //plot_3data16(FtoS16x1000(iabc[0]), FtoS16x1000(iabc[1]), FtoS16(_gFOC_Ctrl.in.s_hallAngle)*10);
|
|
|
+ plot_3data16(FtoS16x1000(iabc[0]), FtoS16x1000(iabc[1]), FtoS16(_gFOC_Ctrl.in.s_hallAngle)*10);
|
|
|
//plot_1data16(FtoS16(_gFOC_Ctrl.in.s_hallAngle));
|
|
|
}
|
|
|
}
|
|
|
@@ -246,32 +243,65 @@ void PMSM_FOC_LogDebug(void) {
|
|
|
/*called in media task */
|
|
|
u8 PMSM_FOC_CtrlMode(void) {
|
|
|
if (!_gFOC_Ctrl.in.b_motEnable) {
|
|
|
- _gFOC_Ctrl.out.n_RunMode = OPEN_MODE;
|
|
|
- }else if (!_gFOC_Ctrl.in.b_motEnable || _gFOC_Ctrl.in.n_ctlMode == OPEN_MODE) {
|
|
|
- _gFOC_Ctrl.out.n_RunMode = OPEN_MODE;
|
|
|
- }else if (_gFOC_Ctrl.in.n_ctlMode == SPD_MODE || _gFOC_Ctrl.in.b_cruiseEna){
|
|
|
- _gFOC_Ctrl.out.n_RunMode = SPD_MODE;
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_OPEN;
|
|
|
+ }else if (_gFOC_Ctrl.in.n_ctlMode == CTRL_MODE_OPEN) {
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_OPEN;
|
|
|
+ }else if (_gFOC_Ctrl.in.n_ctlMode == CTRL_MODE_SPD || _gFOC_Ctrl.in.b_cruiseEna){
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_SPD;
|
|
|
+ }else if (_gFOC_Ctrl.in.n_ctlMode == CTRL_MODE_CURRENT) {
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_CURRENT;
|
|
|
}else {
|
|
|
- _gFOC_Ctrl.out.n_RunMode = TRQ_MODE;
|
|
|
+ _gFOC_Ctrl.out.n_RunMode = CTRL_MODE_TRQ;
|
|
|
}
|
|
|
return _gFOC_Ctrl.out.n_RunMode;
|
|
|
}
|
|
|
|
|
|
/* MPTA, 弱磁, 功率限制 */
|
|
|
static __INLINE void PMSM_FOC_idq_Assign(void) {
|
|
|
- _gFOC_Ctrl.in.s_targetIdq.d = 0;
|
|
|
- _gFOC_Ctrl.in.s_targetIdq.q = _gFOC_Ctrl.in.s_targetTrq;
|
|
|
+ if (_gFOC_Ctrl.in.b_MTPA_calibrate) {
|
|
|
+ float s, c;
|
|
|
+ normal_sincosf(degree_2_pi(_gFOC_Ctrl.in.s_manualAngle + 90.0f), &s, &c);
|
|
|
+ _gFOC_Ctrl.in.s_targetIdq.d = _gFOC_Ctrl.in.s_targetCurrent * c;
|
|
|
+ _gFOC_Ctrl.in.s_targetIdq.q = _gFOC_Ctrl.in.s_targetCurrent * s;
|
|
|
+ }else {
|
|
|
+ _gFOC_Ctrl.in.s_targetIdq.d = 0;
|
|
|
+ _gFOC_Ctrl.in.s_targetIdq.q = _gFOC_Ctrl.in.s_targetCurrent;
|
|
|
+ }
|
|
|
FOC_Set_iDqRamp(&_gFOC_Ctrl.idq_ctl[0], _gFOC_Ctrl.in.s_targetIdq.d);
|
|
|
FOC_Set_iDqRamp(&_gFOC_Ctrl.idq_ctl[1], _gFOC_Ctrl.in.s_targetIdq.q);
|
|
|
}
|
|
|
|
|
|
+static __INLINE void PMSM_FOC_Update_PI_Spd(void) {
|
|
|
+ /* update speed pi ctrl */
|
|
|
+ if (_gFOC_Ctrl.params.s_maxIdq != _gFOC_Ctrl.pi_ctl_spd->max) {
|
|
|
+ _gFOC_Ctrl.pi_ctl_spd->max = _gFOC_Ctrl.params.s_maxIdq;
|
|
|
+ }
|
|
|
+ if (_gFOC_Ctrl.params.s_minIdq != _gFOC_Ctrl.pi_ctl_spd->min) {
|
|
|
+ _gFOC_Ctrl.pi_ctl_spd->min = _gFOC_Ctrl.params.s_minIdq;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+static __INLINE void PMSM_FOC_Update_PI_Trq(void) {
|
|
|
+ /* update speed pi ctrl */
|
|
|
+ float trqIs = _gFOC_Ctrl.in.s_targetTrque;
|
|
|
+ if (trqIs != _gFOC_Ctrl.pi_ctl_trq->max) {
|
|
|
+ _gFOC_Ctrl.pi_ctl_trq->max = trqIs;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
/*called in media task */
|
|
|
void PMSM_FOC_idqCalc(void) {
|
|
|
- if (_gFOC_Ctrl.out.n_RunMode == TRQ_MODE) {
|
|
|
- _gFOC_Ctrl.in.s_targetTrq = (eCtrl_get_RefTorque());
|
|
|
+ if (_gFOC_Ctrl.out.n_RunMode == CTRL_MODE_CURRENT) {
|
|
|
+ _gFOC_Ctrl.in.s_targetCurrent = eCtrl_get_RefCurrent();
|
|
|
+ }else if (_gFOC_Ctrl.out.n_RunMode == CTRL_MODE_TRQ) {
|
|
|
+ PMSM_FOC_Update_PI_Trq();
|
|
|
+ float errRef = _gFOC_Ctrl.params.s_maxRPM - _gFOC_Ctrl.in.s_motRPM;
|
|
|
+ _gFOC_Ctrl.in.s_targetCurrent = PI_Controller_run(_gFOC_Ctrl.pi_ctl_trq, errRef);
|
|
|
}else {
|
|
|
- float errRef = min(eCtrl_get_RefSpd(), _gFOC_Ctrl.params.s_maxRPM) - _gFOC_Ctrl.in.s_motRPM;
|
|
|
- _gFOC_Ctrl.in.s_targetTrq = PI_Controller_run(_gFOC_Ctrl.pi_ctl_spd, errRef);
|
|
|
+ float errRef = min(eCtrl_get_RefSpeed(), _gFOC_Ctrl.params.s_maxRPM) - _gFOC_Ctrl.in.s_motRPM;
|
|
|
+ PMSM_FOC_Update_PI_Spd();
|
|
|
+ _gFOC_Ctrl.in.s_targetCurrent = PI_Controller_run(_gFOC_Ctrl.pi_ctl_spd, errRef);
|
|
|
|
|
|
}
|
|
|
PMSM_FOC_idq_Assign();
|
|
|
@@ -325,12 +355,12 @@ void PMSM_FOC_SetOpenVdq(float vd, float vq) {
|
|
|
|
|
|
bool PMSM_FOC_EnableCruise(bool enable) {
|
|
|
if (enable != _gFOC_Ctrl.in.b_cruiseEna) {
|
|
|
- s32q4_t motSpd = PMSM_FOC_GetSpeed();
|
|
|
+ float motSpd = PMSM_FOC_GetSpeed();
|
|
|
if (motSpd < MIN_CRUISE_RPM) { //
|
|
|
PMSM_FOC_SetErrCode(FOC_NowAllowed_With_Speed);
|
|
|
return false;
|
|
|
}
|
|
|
- eCtrl_set_TargetSpeed(motSpd);
|
|
|
+ eCtrl_set_TgtSpeed(motSpd);
|
|
|
_gFOC_Ctrl.in.b_cruiseEna = enable;
|
|
|
}
|
|
|
|
|
|
@@ -338,36 +368,50 @@ bool PMSM_FOC_EnableCruise(bool enable) {
|
|
|
}
|
|
|
|
|
|
bool PMSM_FOC_Is_CruiseEnabled(void) {
|
|
|
- return (_gFOC_Ctrl.in.b_cruiseEna && (_gFOC_Ctrl.out.n_RunMode == SPD_MODE));
|
|
|
+ return (_gFOC_Ctrl.in.b_cruiseEna && (_gFOC_Ctrl.out.n_RunMode == CTRL_MODE_SPD));
|
|
|
}
|
|
|
|
|
|
bool PMSM_FOC_Set_Speed(float rpm) {
|
|
|
if (_gFOC_Ctrl.in.b_cruiseEna) {
|
|
|
return false;
|
|
|
}
|
|
|
- eCtrl_set_TargetSpeed(rpm);
|
|
|
+ eCtrl_set_TgtSpeed(rpm);
|
|
|
+ return true;
|
|
|
+}
|
|
|
+
|
|
|
+bool PMSM_FOC_Set_Current(float is) {
|
|
|
+ eCtrl_set_TgtCurrent(is);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
-bool PMSM_FOC_Set_Trque(float Trq) {
|
|
|
- eCtrl_set_TrqCurrent(Trq);
|
|
|
+bool PMSM_FOC_Set_Trque(float trq) {
|
|
|
+ _gFOC_Ctrl.in.s_targetTrque = trq;
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
bool PMSM_FOC_Set_CruiseSpeed(float rpm) {
|
|
|
if (PMSM_FOC_Is_CruiseEnabled()) {
|
|
|
- eCtrl_set_TargetSpeed(rpm);
|
|
|
+ eCtrl_set_TgtSpeed(rpm);
|
|
|
return true;
|
|
|
}
|
|
|
PMSM_FOC_SetErrCode(FOC_NotCruiseMode);
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+void PMSM_FOC_MTPA_Calibrate(bool enable) {
|
|
|
+ _gFOC_Ctrl.in.b_MTPA_calibrate = enable;
|
|
|
+}
|
|
|
+
|
|
|
void PMSM_FOC_Set_Angle(float angle) {
|
|
|
_gFOC_Ctrl.in.s_manualAngle = (angle);
|
|
|
}
|
|
|
|
|
|
-s32q4_t PMSM_FOC_GetSpeed(void) {
|
|
|
+void PMSM_FOC_Get_TgtIDQ(DQ_t * dq) {
|
|
|
+ dq->d = _gFOC_Ctrl.in.s_targetIdq.d;
|
|
|
+ dq->q = _gFOC_Ctrl.in.s_targetIdq.q;
|
|
|
+}
|
|
|
+
|
|
|
+float PMSM_FOC_GetSpeed(void) {
|
|
|
return _gFOC_Ctrl.in.s_motRPM;
|
|
|
}
|
|
|
|
|
|
@@ -377,24 +421,15 @@ void PMSM_FOC_LockMotor(bool lock) {
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetSpdPid(float kp, float ki, float max, float min) {
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->kp = S32Q14(kp);
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->ki = S32Q14(ki);
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->max = S32Q14(max);
|
|
|
- _gFOC_Ctrl.pi_ctl_spd->min = S32Q14(min);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetIDPid(float kp, float ki, float max, float min) {
|
|
|
- _gFOC_Ctrl.pi_ctl_id->kp = S32Q14(kp);
|
|
|
- _gFOC_Ctrl.pi_ctl_id->ki = S32Q14(ki);
|
|
|
- _gFOC_Ctrl.pi_ctl_id->max = S32Q14(max);
|
|
|
- _gFOC_Ctrl.pi_ctl_id->min = S32Q14(min);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetIQPid(float kp, float ki, float max, float min) {
|
|
|
- _gFOC_Ctrl.pi_ctl_iq->kp = S32Q14(kp);
|
|
|
- _gFOC_Ctrl.pi_ctl_iq->ki = S32Q14(ki);
|
|
|
- _gFOC_Ctrl.pi_ctl_iq->max = S32Q14(max);
|
|
|
- _gFOC_Ctrl.pi_ctl_iq->min = S32Q14(min);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetTrqPid(float kp, float ki, float max, float min) {
|
|
|
@@ -402,10 +437,7 @@ void PMSM_FOC_SetTrqPid(float kp, float ki, float max, float min) {
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetFW_I(float kp, float ki, float max, float min) {
|
|
|
- _gFOC_Ctrl.pi_ctl_fw->kp = S32Q14(kp);
|
|
|
- _gFOC_Ctrl.pi_ctl_fw->ki = S32Q14(ki);
|
|
|
- _gFOC_Ctrl.pi_ctl_fw->max = S32Q14(max);
|
|
|
- _gFOC_Ctrl.pi_ctl_fw->min = S32Q14(min);
|
|
|
+
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_SetErrCode(u8 error) {
|
|
|
@@ -419,18 +451,18 @@ u8 PMSM_FOC_GetErrCode(void) {
|
|
|
}
|
|
|
|
|
|
//获取母线电流
|
|
|
-s16q5_t PMSM_FOC_Get_iDC(void) {
|
|
|
- s32 vd = _gFOC_Ctrl.out.s_OutVdq.d;
|
|
|
- s32 vq = _gFOC_Ctrl.out.s_OutVdq.q;
|
|
|
- s32 id = _gFOC_Ctrl.out.s_RealIdq.d;
|
|
|
- s32 iq = _gFOC_Ctrl.out.s_RealIdq.q;
|
|
|
+float PMSM_FOC_Get_iDC(void) {
|
|
|
+ float vd = _gFOC_Ctrl.out.s_OutVdq.d;
|
|
|
+ float vq = _gFOC_Ctrl.out.s_OutVdq.q;
|
|
|
+ float id = _gFOC_Ctrl.out.s_RealIdq.d;
|
|
|
+ float iq = _gFOC_Ctrl.out.s_RealIdq.q;
|
|
|
/*
|
|
|
根据公式(等幅值变换,功率不等):
|
|
|
iDC x vDC = 2/3(iq x vq + id x vd);
|
|
|
*/
|
|
|
- s32 m_pow = (vd * id + vq * iq); //s32q10
|
|
|
- s16 iDC = m_pow / _gFOC_Ctrl.in.s_vDC; //s16q5
|
|
|
- return S16Q5toF(iDC) * 0.667f;
|
|
|
+ float m_pow = (vd * id + vq * iq); //s32q10
|
|
|
+ float iDC = m_pow / _gFOC_Ctrl.in.s_vDC; //s16q5
|
|
|
+ return (iDC) * 0.667f;
|
|
|
}
|
|
|
|
|
|
void PMSM_FOC_Brake(bool brake) {
|