obs.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383
  1. /************************************************************************
  2. Project: Welling Motor Control Paltform
  3. Filename: obs.c
  4. Partner Filename: obs.h
  5. Description: The position and speed observer for PMSM
  6. Complier: IAR Embedded Workbench for ARM 7.80, IAR Systems.
  7. CPU TYPE : GD32F3x0
  8. *************************************************************************
  9. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
  10. All rights reserved.
  11. *************************************************************************
  12. *************************************************************************
  13. Revising History (ECL of this file):
  14. ************************************************************************/
  15. /************************************************************************
  16. Beginning of File, do not put anything above here except notes
  17. Compiler Directives:
  18. *************************************************************************/
  19. #ifndef _OBS_C_
  20. #define _OBS_C_
  21. #endif
  22. /************************************************************************
  23. Included File:
  24. *************************************************************************/
  25. #include "syspar.h"
  26. #include "user.h"
  27. /************************************************************************
  28. Private Variables
  29. *************************************************************************/
  30. SWORD obs_pvt_swEMFAlphaCompPu = 0; // Q14, Output stationary alfa-axis EMF value
  31. SWORD obs_pvt_swEMFBetaCompPu = 0; // Q14, Output stationary beta-axis EMF value
  32. SLONG obs_pvt_slDeltaErrPu = 0; // Q15, Last delta value for PLL PI control
  33. /************************************************************************
  34. Constant Table (N/A)
  35. *************************************************************************/
  36. /************************************************************************
  37. Exported Functions:
  38. *************************************************************************/
  39. /***************************************************************
  40. Function: obs_voObsInit;
  41. Description: observer output initialization
  42. Call by:
  43. Input Variables: N/A
  44. Output/Return Variables: N/A
  45. Subroutine Call: N/A;
  46. Reference: N/A
  47. ****************************************************************/
  48. void obs_voObsInit(void)
  49. {
  50. obs_stObsOutPu.slFluxAlphaPu = 0; // Q26
  51. obs_stObsOutPu.slFluxBetaPu = 0; // Q26
  52. obs_stObsOutPu.swElecFreqPu = 0; // Q15
  53. obs_stObsOutPu.slElecFreqPu = 0; // Q29
  54. obs_stObsOutPu.uwElecThetaPu = 0; // Q15
  55. obs_stObsOutPu.slElecThetaPu = 0; // Q29
  56. obs_stObsOutPu.swActiveFluxPu = 0; // Q10
  57. obs_stObsOutPu.swFluxAlphaPu = 0; // Q10
  58. obs_stObsOutPu.swFluxBetaPu = 0; // Q10
  59. obs_stFluxAlphaPIOut.slURefPu = 0; // Q28
  60. obs_stFluxAlphaPIOut.swURefPu = 0; // Q14
  61. obs_stFluxAlphaPIOut.swErrZ1Pu = 0; // Q10
  62. obs_stFluxBetaPIOut.slURefPu = 0; // Q28
  63. obs_stFluxBetaPIOut.swURefPu = 0; // Q14
  64. obs_stFluxBetaPIOut.swErrZ1Pu = 0; // Q10
  65. obs_pvt_swEMFAlphaCompPu = 0;
  66. obs_pvt_swEMFBetaCompPu = 0;
  67. obs_pvt_slDeltaErrPu = 0;
  68. }
  69. /***************************************************************
  70. Function: obs_voObsCoef;
  71. Description: Coefficient calculation for "asr_voSpdPI"
  72. Call by: functions in main loop;
  73. Input Variables: ASR_SPDPI_COFIN
  74. Output/Return Variables: ASR_SPDPI_COF
  75. Subroutine Call: N/A;
  76. Reference: N/A
  77. ****************************************************************/
  78. void obs_voObsCoef(OBS_COF_IN *in, OBS_COF *out)
  79. {
  80. UWORD uwWebRadps;
  81. UWORD uwMvcPu;
  82. ULONG ulDamper;
  83. UWORD uwDamper;
  84. ULONG ulKp;
  85. ULONG ulKi;
  86. UWORD uwDampingRatio;
  87. UWORD uwCrossFreq;
  88. if (in->uwRbOm < 10)
  89. {
  90. in->uwRbOm = 10;
  91. }
  92. if (in->uwLbHm < 10)
  93. {
  94. in->uwLbHm = 10;
  95. }
  96. if (in->uwFluxbWb < 10)
  97. {
  98. in->uwFluxbWb = 10;
  99. }
  100. if (in->uwFbHz < 10)
  101. {
  102. in->uwFbHz = 10;
  103. }
  104. else if (in->uwFbHz > 10000)
  105. {
  106. in->uwFbHz = 10000;
  107. }
  108. if (in->uwFreqTbcHz < 10)
  109. {
  110. in->uwFreqTbcHz = 10;
  111. }
  112. if (in->uwSpdPllMcoef > 100)
  113. {
  114. in->uwSpdPllMcoef = 100;
  115. }
  116. if ((in->uwFluxWb >> 5) > in->uwFluxbWb)
  117. {
  118. in->uwFluxWb = (in->uwFluxbWb << 5);
  119. }
  120. if (in->uwRsOm > in->uwRbOm)
  121. {
  122. in->uwRsOm = in->uwRbOm;
  123. }
  124. if ((in->uwLqHm >> 5) > in->uwLbHm)
  125. {
  126. in->uwLqHm = (in->uwLbHm << 5);
  127. }
  128. if ((in->uwLdHm >> 5) > in->uwLbHm)
  129. {
  130. in->uwLdHm = (in->uwLbHm << 5);
  131. }
  132. if (in->uwFbHz > ((ULONG)in->uwFreqTbcHz * 0x2AAA >> 15))
  133. {
  134. in->uwFbHz = (ULONG)in->uwFreqTbcHz * 0x2AAA >> 15;
  135. }
  136. uwWebRadps = (ULONG)2 * 31416 * in->uwFbHz / 10000; // unit: rad/s, Electrical radian frequency base
  137. if (in->uwFluxDampingRatio < 1)
  138. {
  139. in->uwFluxDampingRatio = 1;
  140. }
  141. else if (in->uwFluxDampingRatio > 100)
  142. {
  143. in->uwFluxDampingRatio = 100;
  144. }
  145. if (in->uwFluxCrossFreqHz < 1)
  146. {
  147. in->uwFluxCrossFreqHz = 1;
  148. }
  149. else if (in->uwFluxCrossFreqHz > 100)
  150. {
  151. in->uwFluxCrossFreqHz = 100;
  152. }
  153. out->uwFluxPPu = ((ULONG)in->uwFluxWb << 10) / in->uwFluxbWb; // Q10
  154. out->uwRsPu = ((ULONG)in->uwRsOm << 15) / in->uwRbOm; // Q15
  155. out->uwLqPu = ((ULONG)in->uwLqHm << 10) / in->uwLbHm; // Q10
  156. out->uwLdPu = ((ULONG)in->uwLdHm << 10) / in->uwLbHm; // Q10
  157. out->uwCurTsPu = ((ULONG)205887 * in->uwFbHz) / in->uwFreqTbcHz; // Q15, Q15(2pi)-->205887
  158. out->uwCurTs = ((ULONG)in->uwFbHz << 10) / in->uwFreqTbcHz; // Q10, TBC time
  159. /************************Speed PLL Coefficient*****************************/
  160. uwMvcPu = ((ULONG)in->uwSpdPllWvcHz << 10) / in->uwFbHz; // Q10
  161. /* PLL Kp=M*w/sqrt(1+M^2) */
  162. ulDamper = (1 + in->uwSpdPllMcoef * in->uwSpdPllMcoef) << 8; // Q8
  163. uwDamper = mth_slSqrt(ulDamper); // Q4
  164. out->uwSpdPllKpPu = ((ULONG)in->uwSpdPllMcoef * uwMvcPu / uwDamper) << 8; // Q10-Q4+Q8=Q14
  165. /* PLL Ki=w^2*T_cnt_ctrl/sqrt(1+M^2) */
  166. out->uwSpdPllKiPu = ((((ULONG)uwMvcPu * out->uwCurTsPu) / uwDamper) * uwMvcPu) >> 17; // Q10+Q15-Q4+Q10-Q17=Q14
  167. /**************************Flux PI Coefficient*****************************/
  168. /* Flux PI regulator Kp=2*k*w */
  169. uwDampingRatio = ((ULONG)in->uwFluxDampingRatio << 12) / 10; // Q12
  170. uwCrossFreq = ((ULONG)2 * 31416 * in->uwFluxCrossFreqHz / 10000) << 8; // Q8
  171. ulKp = (ULONG)uwDampingRatio * uwCrossFreq * 2; // Q12+Q8=Q20
  172. out->uwFluxKpPu = ulKp / uwWebRadps >> 2; // Q20-Q2=Q18
  173. /* Flux PI regulator Ki=w^2 */
  174. ulKi = (ULONG)uwCrossFreq * uwCrossFreq; // Q8+Q8=Q16
  175. out->uwFluxKitPu = (ulKi / uwWebRadps * out->uwCurTsPu / uwWebRadps) >> 3; // Q16+Q15-Q3=Q28
  176. }
  177. /***************************************************************
  178. Function: obs_voObsCalc
  179. Description: speed and position caculate
  180. Call by: tbc_it
  181. Input Variables:
  182. Output/Return Variables:
  183. Subroutine Call:
  184. Reference: N/A
  185. ****************************************************************/
  186. void obs_voObsCalc(OBS_IN *in, OBS_COF *coef, OBS_OUT *out)
  187. {
  188. SWORD swEMFAlphaPu, swEMFBetaPu;
  189. SWORD swRtFluxAlphaPu, swRtFluxBetaPu;
  190. SINCOS sincosTmp; //, sincosTmp1;
  191. SLONG slDeltaTmpPu, slDeltaErrTmpPu;
  192. SLONG slKpTmpPu, slKitTmpPu;
  193. SLONG slSpdRefPu;
  194. SLONG slPreRtPosPu, slActRtPosPu;
  195. UWORD uwPreRtPosPu;
  196. SWORD swFluxDPu, swFluxQPu;
  197. SWORD swMaxVsPu;
  198. /*****************************Current Model*****************************/
  199. /* Predict the rotor Angle according to last rotor angle and speed */
  200. slPreRtPosPu = out->slElecThetaPu + ((out->slElecFreqPu >> 10) * coef->uwCurTs); // Q29-Q10+Q10=Q29
  201. if (slPreRtPosPu >= 0x20000000) // Q29
  202. {
  203. slPreRtPosPu -= 0x20000000;
  204. }
  205. else if (slPreRtPosPu < 0)
  206. {
  207. slPreRtPosPu += 0x20000000;
  208. }
  209. uwPreRtPosPu = (UWORD)(slPreRtPosPu >> 14); // Q29-Q14=Q15
  210. mth_voSinCos(uwPreRtPosPu, &sincosTmp);
  211. /* Current Park (I_alpha I_beta -> Id Iq) */
  212. obs_stParkInPu.swAlphaPu = in->swIalphaPu; // Q14
  213. obs_stParkInPu.swBetaPu = in->swIbetaPu; // Q14
  214. obs_stParkInPu.uwThetaPu = uwPreRtPosPu; // Q15
  215. crd_voPark(&obs_stParkInPu, &obs_stFluxParkPu);
  216. /* Flux_D = Ld*id+Flux_PM; Flux_Q = Lq*iq */
  217. swFluxDPu = coef->uwFluxPPu + (((SLONG)obs_stFluxParkPu.swDPu * coef->uwLdPu) >> 14); // Q14+Q10-Q14=Q10
  218. swFluxQPu = ((SLONG)obs_stFluxParkPu.swQPu * coef->uwLqPu) >> 14; // Q14+Q10-Q14=Q10
  219. /* Flux IPark (Fluxd Fluxq -> Fluxalpha Fluxbeta) */
  220. obs_stIParkInPu.swDPu = swFluxDPu; // Q10
  221. obs_stIParkInPu.swQPu = swFluxQPu; // Q10
  222. obs_stIParkInPu.uwThetaPu = uwPreRtPosPu; // Q15
  223. crd_voIPark(&obs_stIParkInPu, &obs_stFluxIParkPu);
  224. /*****************************Voltage Model*****************************/
  225. swEMFAlphaPu = in->swUalphaPu - (in->swIalphaPu * coef->uwRsPu >> 15); // Q14+Q15-Q15=Q14
  226. swEMFBetaPu = in->swUbetaPu - (in->swIbetaPu * coef->uwRsPu >> 15); // Q14+Q15-Q15=Q14
  227. obs_pvt_swEMFAlphaCompPu = swEMFAlphaPu + obs_stFluxAlphaPIOut.swURefPu; // Q14
  228. obs_pvt_swEMFBetaCompPu = swEMFBetaPu + obs_stFluxBetaPIOut.swURefPu; // Q14
  229. out->slFluxAlphaPu = out->slFluxAlphaPu + ((SLONG)obs_pvt_swEMFAlphaCompPu * coef->uwCurTsPu >> 3); // Q14+Q15-Q3=Q26
  230. out->slFluxBetaPu = out->slFluxBetaPu + ((SLONG)obs_pvt_swEMFBetaCompPu * coef->uwCurTsPu >> 3); // Q14+Q15-Q3=Q26
  231. out->swFluxAlphaPu = out->slFluxAlphaPu >> 16; // Q26-Q16=Q10
  232. out->swFluxBetaPu = out->slFluxBetaPu >> 16; // Q26-Q16=Q10
  233. swMaxVsPu = ((SLONG)in->uwVdcPu * 0x5555) >> 15; // Q14+Q15-Q15=Q14
  234. /* Flux alpha PI regulator */
  235. obs_stFluxAlphaPIIn.swRefPu = obs_stFluxIParkPu.swAlphaPu; // Q10
  236. obs_stFluxAlphaPIIn.swFdbPu = out->swFluxAlphaPu; // Q10
  237. obs_stFluxAlphaPIIn.swUmaxPu = swMaxVsPu; // Q14
  238. obs_stFluxAlphaPIIn.swUminPu = -swMaxVsPu; // Q14
  239. obs_stFluxAlphaPICoef.uwFluxKpPu = coef->uwFluxKpPu; // Q18
  240. obs_stFluxAlphaPICoef.uwFluxKitPu = coef->uwFluxKitPu; // Q28
  241. obs_voFluxPI(&obs_stFluxAlphaPIIn, &obs_stFluxAlphaPICoef, &obs_stFluxAlphaPIOut);
  242. /* Flux beta PI regulator */
  243. obs_stFluxBetaPIIn.swRefPu = obs_stFluxIParkPu.swBetaPu; // Q10
  244. obs_stFluxBetaPIIn.swFdbPu = out->swFluxBetaPu; // Q10
  245. obs_stFluxBetaPIIn.swUmaxPu = swMaxVsPu; // Q14
  246. obs_stFluxBetaPIIn.swUminPu = -swMaxVsPu; // Q14
  247. obs_stFluxBetaPICoef.uwFluxKpPu = coef->uwFluxKpPu; // Q18
  248. obs_stFluxBetaPICoef.uwFluxKitPu = coef->uwFluxKitPu; // Q28
  249. obs_voFluxPI(&obs_stFluxBetaPIIn, &obs_stFluxBetaPICoef, &obs_stFluxBetaPIOut);
  250. /* Stator Flux -> Rotor Flux */
  251. swRtFluxAlphaPu = out->swFluxAlphaPu - (((SLONG)in->swIalphaPu * coef->uwLqPu) >> 14); // Q14+Q10-Q14=Q10
  252. swRtFluxBetaPu = out->swFluxBetaPu - (((SLONG)in->swIbetaPu * coef->uwLqPu) >> 14); // Q14+Q10-Q14=Q10
  253. /* PLL to trace the latest speed */
  254. slDeltaTmpPu = (((SLONG)swRtFluxBetaPu * sincosTmp.swCosPu) - ((SLONG)swRtFluxAlphaPu * sincosTmp.swSinPu)) >> 10; // Q10+Q15-Q10=Q15
  255. slDeltaErrTmpPu = slDeltaTmpPu - obs_pvt_slDeltaErrPu; // Q15
  256. obs_pvt_slDeltaErrPu = slDeltaTmpPu; // Q15
  257. slKpTmpPu = slDeltaErrTmpPu * coef->uwSpdPllKpPu; // Q15+Q14=Q29
  258. slKitTmpPu = slDeltaTmpPu * coef->uwSpdPllKiPu; // Q15+Q14=Q29
  259. slSpdRefPu = slKpTmpPu + slKitTmpPu + out->slElecFreqPu; // Q29
  260. /* Limit the speed value to avoid overflow */
  261. if (slSpdRefPu >= 0x20000000)
  262. {
  263. slSpdRefPu = 0x20000000 - 1; // Q29
  264. }
  265. else if (slSpdRefPu <= -0x20000000)
  266. {
  267. slSpdRefPu = -0x20000000; // Q29
  268. }
  269. out->slElecFreqPu = slSpdRefPu; // Q29
  270. out->swElecFreqPu = out->slElecFreqPu >> 14; // Q29-Q14=Q15
  271. /* Electrical speed to Electrical position */
  272. // slActRtPosPu = out->slElecThetaPu + ((((slSpdRefPu + out->slElecFreqPu) >> 1) >> 10) * coef->uwCurTs); //Q29+Q10-Q10=Q29
  273. slActRtPosPu = out->slElecThetaPu + (((SLONG)out->swElecFreqPu * coef->uwCurTs) << 4);
  274. if (slActRtPosPu >= 0x20000000)
  275. {
  276. slActRtPosPu -= 0x20000000; // Q15+Q14=Q29
  277. }
  278. else if (slActRtPosPu < 0)
  279. {
  280. slActRtPosPu += 0x20000000; // Q15+Q14=Q29
  281. }
  282. out->slElecThetaPu = slActRtPosPu; // Q29
  283. out->uwElecThetaPu = out->slElecThetaPu >> 14; // Q29-Q14=Q15
  284. // mth_voSinCos(out->uwElecThetaPu, &sincosTmp1);
  285. // slActiveFluxPu = (SLONG)swRtFluxAlphaPu * sincosTmp1.swCosPu + (SLONG)swRtFluxBetaPu * sincosTmp1.swSinPu; //Q10+Q15=Q25
  286. // out->swActiveFluxPu = slActiveFluxPu >> 15; //Q25-Q15=Q10
  287. // //Q29-Q14=Q15
  288. }
  289. /***************************************************************
  290. Function: obs_voFluxPI;
  291. Description: Flux PI regulator;
  292. Call by: functions in TBC;
  293. Input Variables: ACR_CURPI_IN,ACR_CURPI_COF
  294. Output/Return Variables: ACR_CURPI_OUT
  295. Subroutine Call: N/A;
  296. Reference: N/A
  297. ****************************************************************/
  298. void obs_voFluxPI(OBS_FLUXPI_IN *in, OBS_FLUXPI_COF *coef, OBS_FLUXPI_OUT *out)
  299. {
  300. SWORD tmp_swErrPu, tmp_swDeltaErrPu;
  301. SLONG tmp_slUpPu, tmp_slUiPu, tmp_slURefPu;
  302. SLONG tmp_slUmaxPu, tmp_slUminPu;
  303. /* U(k) = U(k-1) + Kp * (Err(k) - Err(k-1)) + Kit * Err(k) */
  304. tmp_swErrPu = in->swRefPu - in->swFdbPu; // Q10
  305. tmp_swDeltaErrPu = tmp_swErrPu - out->swErrZ1Pu; // Q10
  306. tmp_slUpPu = (SLONG)tmp_swDeltaErrPu * coef->uwFluxKpPu; // Q10+Q18=Q28
  307. tmp_slUiPu = ((SLONG)tmp_swErrPu * coef->uwFluxKitPu) >> 10; // Q10+Q28-Q10=Q28
  308. tmp_slURefPu = out->slURefPu + tmp_slUpPu + tmp_slUiPu; // Q28
  309. tmp_slUmaxPu = (SLONG)in->swUmaxPu << 14; // Q14+Q14=Q28
  310. tmp_slUminPu = (SLONG)in->swUminPu << 14; // Q14+Q14=Q28
  311. if (tmp_slURefPu > tmp_slUmaxPu)
  312. {
  313. tmp_slURefPu = tmp_slUmaxPu;
  314. }
  315. else if (tmp_slURefPu < tmp_slUminPu)
  316. {
  317. tmp_slURefPu = tmp_slUminPu;
  318. }
  319. else
  320. {}
  321. out->swURefPu = tmp_slURefPu >> 14; // Q28-Q14=Q14
  322. out->slURefPu = tmp_slURefPu; // Q28
  323. out->swErrZ1Pu = tmp_swErrPu; // Q10
  324. }
  325. /************************************************************************
  326. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
  327. All rights reserved.
  328. *************************************************************************/
  329. #ifdef _OBS_C_
  330. #undef _OBS_C_
  331. #endif
  332. /*************************************************************************
  333. End of this File (EOF):
  334. !!!!!!Do not put anything after this part!!!!!!!!!!!
  335. *************************************************************************/