123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403 |
- /************************************************************************
- Project: Welling Motor Control Paltform
- Filename: flxwkn.c
- Partner Filename: flxwkn.h
- Description: Flux weakening control for PMSM
- Complier: IAR Embedded Workbench for ARM 7.80.4
- CPU TYPE : GD32F3x0
- *************************************************************************
- Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
- All rights reserved.
- *************************************************************************
- *************************************************************************
- Revising History (ECL of this file):
- ************************************************************************/
- /************************************************************************
- Beginning of File, do not put anything above here except notes
- Compiler Directives:
- ************************************************************************/
- #ifndef _FLXWKN_C_
- #define _FLXWKN_C_
- #endif
- /************************************************************************
- Include File
- ************************************************************************/
- #include "flxwkn.h"
- #include "mathtool.h"
- #define abs(A) (((A) < 0) ? - (A) : (A))
- /************************************************************************
- Private Variables:
- ************************************************************************/
- UWORD flx_pvt_uwVdcMinTmpPu = 0; // Q14, Temporary minimum value of Vdc in one cycle(50Hz)
- UWORD flx_pvt_uwVdcMinPu = 0; // Q14, Minimum value of Vdc in one cycle(50Hz)
- UWORD flx_pvt_uwVdcMaxTmpPu = 0; // Q14, Temporary maximum value of Vdc in one cycle(50Hz)
- UWORD flx_pvt_uwVdcMaxPu = 0; // Q14, Maxmium value of Vdc in one cycle(50Hz)
- UWORD flx_pvt_uwVdcAvgPu = 0; // Q14, Average value of Vdc in one cycle(50Hz)
- LPF_OUT flx_pvt_stVdcAvgLpf; // Q14, Average value of Vdc after LPF
- UWORD flx_pvt_uwVdcPeriodCt = 0; // Count Vdc period
- UWORD flx_pvt_swErrZ1Pu = 0; // Q14
- SWORD flx_pvt_swUqErrZ1 = 0; // Q14
- /************************************************************************
- Constant Table:
- ************************************************************************/
- /************************************************************************
- Exported Functions:
- ************************************************************************/
- /************************************************************************
- Function:
- Description:
- Call by:
- Input Variables:
- Output/Return Variables:
- Subroutine Call:
- Reference:
- ************************************************************************/
- void flx_voInit(void)
- {
- flx_pvt_uwVdcMinTmpPu = 0xFFFF; // Q14, Temporary minimum value of Vdc in one cycle(50Hz)
- flx_pvt_uwVdcMinPu = 0; // Q14, Minimum value of Vdc in one cycle(50Hz)
- flx_pvt_uwVdcMaxTmpPu = 0; // Q14, Temporary maximum value of Vdc in one cycle(50Hz)
- flx_pvt_uwVdcMaxPu = 0; // Q14, Maximum value of Vdc in one cycle(50Hz)
- flx_pvt_uwVdcAvgPu = 0; // Q14, Average value of Vdc in one cycle(50Hz)
- flx_pvt_stVdcAvgLpf.slY.sl = 0; // Q30, Average value of Vdc after LPF
- flx_pvt_uwVdcPeriodCt = 0; // Q0,Count Vdc period
- flx_pvt_swErrZ1Pu = 0; // Q14
- flx_stCtrlOut.slIdSumPu = 0; // Q31
- flx_stCtrlOut.swIqLimPu = 0; // Q14, Iq limit value used for speed loop out
- flx_stCtrlOut.swIdRefPu = 0; // Q14, Id reference value used for current loop regulation
- flx_stCtrlOut.slIdMinEstPu = 0; // Q30, Id min Estimate
- flx_pvt_swUqErrZ1 = 0; // Q14
- }
- /************************************************************************
- Function:
- Description:
- Call by:
- Input Variables:
- Output/Return Variables:
- Subroutine Call:
- Reference:
- ************************************************************************/
- void flx_voCoef(FW_CTRL_COEFIN *in, FW_CTRL_COEF *out)
- {
- ULONG ulLpfTm; // unit: us
- SLONG slKp, slKi, slCurErr;
- UWORD uwCrossFreq;
- if (in->uwPWMDutyMax < 2)
- {
- in->uwPWMDutyMax = 2;
- }
- else if (in->uwPWMDutyMax > 1000)
- {
- in->uwPWMDutyMax = 1000;
- }
- else
- {}
- if (in->uwIBaseAp > 32767)
- {
- in->uwIBaseAp = 32767;
- }
- else if (in->uwIBaseAp < 1)
- {
- in->uwIBaseAp = 1;
- }
- else
- {}
- if (in->uwFwCurLimAp > ((SWORD)32767))
- {
- in->uwFwCurLimAp = (SWORD)32767;
- }
- else
- {}
- if (in->swIdMaxAp > ((SWORD)in->uwIBaseAp))
- {
- in->swIdMaxAp = (SWORD)in->uwIBaseAp;
- }
- else if (in->swIdMaxAp < (-(SWORD)in->uwIBaseAp))
- {
- in->swIdMaxAp = (-(SWORD)in->uwIBaseAp);
- }
- else
- {}
- if (in->swIdMinAp > ((SWORD)in->uwFwCurLimAp))
- {
- in->swIdMinAp = (SWORD)in->uwFwCurLimAp;
- }
- else if (in->swIdMinAp < (-(SWORD)in->uwFwCurLimAp))
- {
- in->swIdMinAp = (-(SWORD)in->uwFwCurLimAp);
- }
- else
- {}
- if (in->swIdPIOutMinAp <= abs(in->swIdMinAp))
- {
- in->swIdPIOutMinAp = abs(in->swIdMinAp) + 1;
- }
- else if (in->swIdPIOutMinAp > ((SWORD)in->uwIBaseAp))
- {
- in->swIdPIOutMinAp = (SWORD)in->uwIBaseAp;
- }
- else
- {}
- if (in->uwVdcMinCalcTmMs > 2000)
- {
- in->uwVdcMinCalcTmMs = 2000;
- }
- else
- {}
- if (in->uwVdcLpfFreqHz < 1)
- {
- in->uwVdcLpfFreqHz = 1;
- }
- else
- {}
- if (in->uwFreqTbcHz > 32767)
- {
- in->uwFreqTbcHz = 32767;
- }
- else if (in->uwFreqTbcHz < 1)
- {
- in->uwFreqTbcHz = 1;
- }
- else
- {}
- if (in->uwCharCurDampRatio > 16)
- {
- in->uwCharCurDampRatio = 16;
- }
- else
- {}
- if (in->uwCharCurCrossFreqHz > 32)
- {
- in->uwCharCurCrossFreqHz = 32;
- }
- else
- {}
- if (in->uwUbVt < 2)
- {
- in->uwUbVt = 2;
- }
- else
- {}
- if (in->uwUbVt < 1)
- {
- in->uwUbVt = 1;
- }
- else if (in->uwUbVt > 4096)
- {
- in->uwUbVt = 4096;
- }
- else
- {}
- if (in->uwFBaseHz < 1)
- {
- in->uwFBaseHz = 1;
- }
- else
- {}
- out->uwVdcRatioPu =
- ((ULONG)in->uwPWMDutyMax * 5000 / 1000 * in->uwPWMDutyMax / 1000); // Q14,6640 = Q14((2/pi)*(2/pi)) 5461 3640 =Q14((sqrt(2)/3)*(sqrt(2)/3))
- out->slIdMaxPu = (((SLONG)in->swIdMaxAp << 14) / in->uwIBaseAp) << 16; // Q30=Q14+Q16
- out->slIdMinPu = (((SLONG)in->swIdMinAp << 14) / in->uwIBaseAp) << 16; // Q30=Q14+Q16
- // out->slIdMinLimPu = out->slIdMinPu / 100 * in->uwIdMinLimRatio; // Q30
- // out->slIdPIOutMinPu = -((((SLONG)in->swIdPIOutMinAp << 14) / in->uwIBaseAp) << 16); // Q30=Q14+Q16
- out->slIdPIOutMinPu = out->slIdMinPu;
- out->uwFwCurLimPu = (UWORD)(((SLONG)in->uwFwCurLimAp << 14) / in->uwIBaseAp); // Q14
- out->swIqLimMaxPu =
- mth_slSqrt(((SLONG)out->uwFwCurLimPu * out->uwFwCurLimPu) - (((SLONG)out->slIdMaxPu >> 16) * ((SLONG)out->slIdMaxPu >> 16))); // Q14=sqrt(Q28)
- out->uwIdRegKpPu = in->uwIdRegKpPu; // Q16
- out->uwIdRegKitPu = in->uwIdRegKiPu; // Q16
- // slCurErr = mth_slSqrt(((SLONG)out->uwFwCurLimPu * out->uwFwCurLimPu) - (out->slIdMinPu >> 16) * (out->slIdMinPu >> 16)) << 16; // Q30
- // out->uwIqRegKpPu = slCurErr / ((-out->slIdPIOutMinPu + out->slIdMinPu) >> 14); // Q14=Q30-Q16
- // if (out->uwIqRegKpPu >= 32767)
- // {
- // out->uwIqRegKpPu = 32767;
- // }
- out->uwVdcMinCalcTm = (UWORD)((ULONG)in->uwVdcMinCalcTmMs * in->uwFreqTbcHz / 1000); // Q0
- ulLpfTm = 1000000 / in->uwVdcLpfFreqHz;
- mth_voLPFilterCoef(ulLpfTm, in->uwFreqTbcHz, &out->uwVdcAvgLpfCoef);
- // out->uwRsPu = (UWORD)(((ULONG)in->uwRsOhm << 15) / ((ULONG)in->uwUbVt * 100000 / in->uwIBaseAp)); // Q15, Phase resistance
- // uwCrossFreq = (UWORD)(((ULONG)in->uwCharCurCrossFreqHz << 15) / in->uwFBaseHz); // Q15
- // slKp = (ULONG)(in->uwCharCurDampRatio << 12) * uwCrossFreq * 2; // Q12+Q15=Q27
- // out->uwKpPu = slKp >> 11; // Q27-Q11=Q16
- // slKi = (ULONG)uwCrossFreq * uwCrossFreq; // Q15+Q15=Q30
- // out->slKitPu = ((SLONG)(slKi >> 6) * (2 * 102944 * in->uwFBaseHz / in->uwFreqTbcHz >> 7) >> 7); // Q30-Q6+(Q15-Q7)-Q7=Q25,pi(Q15)=102944
- }
- /************************************************************************
- Function:
- Description:
- Call by:
- Input Variables:
- Output/Return Variables:
- Subroutine Call:
- Reference:
- ************************************************************************/
- // Q14
- void flx_voCtrl(FW_CTRL_IN *in, FW_CTRL_COEF *coef, FW_CTRL_OUT *out)
- { // Q14
- SWORD swErrDltPu; // Q14
- SLONG slIdpPu; // Q31
- SLONG slIdiPu; // Q31
- SLONG slIdSumPu; // Q31
- SWORD swUqErr, swUqDeltaErr;
- SLONG slIdMinPPu, slIdMinIPu, slErrPu;
- SWORD swErrPu;
- SWORD swVdc2Pu; // Q14
- SWORD swUalpha2Pu; // Q14
- SWORD swUbeta2Pu;
- /* Get minimum value of Vdc in one cycle(50Hz) */
- flx_pvt_uwVdcPeriodCt++;
- if (flx_pvt_uwVdcPeriodCt <= 1)
- {
- flx_pvt_uwVdcAvgPu = in->uwVdcPu;
- flx_pvt_stVdcAvgLpf.slY.sl = in->uwVdcPu << 16;
- out->slIdMinEstPu = coef->slIdMinPu; // Q30, Id min Estimate
- }
- else if (flx_pvt_uwVdcPeriodCt < (coef->uwVdcMinCalcTm + 1))
- {
- if (flx_pvt_uwVdcMinTmpPu > in->uwVdcPu)
- {
- flx_pvt_uwVdcMinTmpPu = in->uwVdcPu; // Q14
- }
- if (flx_pvt_uwVdcMaxTmpPu < in->uwVdcPu)
- {
- flx_pvt_uwVdcMaxTmpPu = in->uwVdcPu; // Q14
- }
- }
- else
- {
- flx_pvt_uwVdcPeriodCt = 1;
- flx_pvt_uwVdcMinPu = flx_pvt_uwVdcMinTmpPu; // Q14
- flx_pvt_uwVdcMinTmpPu = in->uwVdcPu; // Q14
- flx_pvt_uwVdcMaxPu = flx_pvt_uwVdcMaxTmpPu; // Q14
- flx_pvt_uwVdcMaxTmpPu = in->uwVdcPu; // Q14
- flx_pvt_uwVdcAvgPu = (flx_pvt_uwVdcMinPu + flx_pvt_uwVdcMaxPu) >> 1;
- }
- /* Vdc LPF */
- flx_pvt_stVdcAvgLpf.uwKx = coef->uwVdcAvgLpfCoef; // Q15
- mth_voLPFilter(flx_pvt_uwVdcAvgPu, &flx_pvt_stVdcAvgLpf);
- /* Output voltage PI contorl */
- swVdc2Pu =
- (SWORD)(((SLONG)flx_pvt_stVdcAvgLpf.slY.sw.hi * (SLONG)flx_pvt_stVdcAvgLpf.slY.sw.hi >> 14) * (SLONG)coef->uwVdcRatioPu >> 14); // Q14=Q14+Q14-Q14+Q14-Q14
- swUalpha2Pu = (SWORD)((SLONG)in->swUalphaPu * (SLONG)in->swUalphaPu >> 14); // Q14
- swUbeta2Pu = (SWORD)((SLONG)in->swUbetaPu * (SLONG)in->swUbetaPu >> 14); // Q14
- slErrPu = (SLONG)swVdc2Pu - (SLONG)swUalpha2Pu - (SLONG)swUbeta2Pu; // Q14
- if (slErrPu > 32767)
- {
- slErrPu = 32767;
- }
- else if (slErrPu < -32768)
- {
- slErrPu = -32768;
- }
- else
- {}
- swErrPu = slErrPu;
- swErrDltPu = (SWORD)((SLONG)swErrPu - (SLONG)flx_pvt_swErrZ1Pu); // Q14
- flx_pvt_swErrZ1Pu = swErrPu; // Q14
- slIdpPu = (SLONG)swErrDltPu * (SLONG)coef->uwIdRegKpPu; // Q30=Q14+Q16
- slIdiPu = (SLONG)swErrPu * (SLONG)coef->uwIdRegKitPu; // Q30=Q14+Q16
- slIdSumPu = out->slIdSumPu + slIdpPu + slIdiPu; // Q30
- /* Limit Id PI output */
- if (slIdSumPu > coef->slIdMaxPu)
- {
- slIdSumPu = coef->slIdMaxPu; // Q30
- }
- else if (slIdSumPu < coef->slIdPIOutMinPu)
- {
- slIdSumPu = coef->slIdPIOutMinPu; // Q30
- }
- else
- {}
- out->slIdSumPu = slIdSumPu; // Q30
- /* Id limit*/
- if (out->slIdSumPu < out->slIdMinEstPu)
- {
- out->swIdRefPu = out->slIdMinEstPu >> 16; // Q30, Id min Estimate
- }
- else
- {
- out->swIdRefPu = out->slIdSumPu >> 16; // Q14=Q30-Q16
- }
- /* Id PI output less than minimum value */
- if (out->slIdSumPu < out->slIdMinEstPu)
- {
- out->swIqLimPu = mth_slSqrt(((SLONG)coef->uwFwCurLimPu * coef->uwFwCurLimPu) - ((SLONG)out->swIdRefPu * out->swIdRefPu)); // Q14=sqrt(Q28)
- // out->swIqLimPu = (SWORD)mth_slSqrt(((SLONG)coef->uwFwCurLimPu * coef->uwFwCurLimPu) - (out->swIdRefPu * out->swIdRefPu)) +
- // ((((out->slIdSumPu - out->slIdMinEstPu) >> 16) * coef->uwIqRegKpPu) >> 14); // Q14
- // swUqErr = -in->swUqRefPu + (in->swIqRefPu * coef->uwRsPu >> 15); // Q14
- // swUqDeltaErr = swUqErr - flx_pvt_swUqErrZ1;
- // flx_pvt_swUqErrZ1 = swUqErr; // Q14
- // slIdMinPPu = swUqDeltaErr * coef->uwKpPu; // Q14+16=30
- // slIdMinIPu = swUqErr * coef->slKitPu >> 9; // Q14+25-9=30
- // out->slIdMinEstPu = out->slIdMinEstPu + slIdMinPPu + slIdMinIPu; // Q30
- //
- // if (out->slIdMinEstPu < coef->slIdMinPu)
- // {
- // out->slIdMinEstPu = coef->slIdMinPu;
- // }
- // else if (out->slIdMinEstPu > coef->slIdMinLimPu)
- // {
- // out->slIdMinEstPu = coef->slIdMinLimPu;
- // }
- // else
- // {}
- }
- else if (out->slIdSumPu >= coef->slIdMaxPu)
- {
- out->swIqLimPu = coef->swIqLimMaxPu;
- }
- else
- {
- out->swIqLimPu = mth_slSqrt(((SLONG)coef->uwFwCurLimPu * coef->uwFwCurLimPu) - ((SLONG)out->swIdRefPu * out->swIdRefPu)); // Q14=sqrt(Q28)
- }
- /* Iq limit */
- if (out->swIqLimPu < 0)
- {
- out->swIqLimPu = 0; // Q14
- }
- }
- /************************************************************************
- Local Functions: N/A
- ************************************************************************/
- /************************************************************************
- Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
- All rights reserved.
- ************************************************************************/
- #ifdef _FLXWKN_C_
- #undef _FLXWKN_C_
- #endif
- /************************************************************************
- End of this File (EOF)!
- Do not put anything after this part!
- ************************************************************************/
|