acr.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378
  1. /************************************************************************
  2. Project: Welling Motor Control Paltform
  3. Filename: acr.c
  4. Partner Filename: acr.h
  5. Description: Automatic current regulator
  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. WLBDM_M4_SR_20180831-new FSM1.1, by mz, create this file;
  15. ************************************************************************/
  16. /************************************************************************
  17. Beginning of File, do not put anything above here except notes
  18. Compiler Directives:
  19. *************************************************************************/
  20. #ifndef _ACR_C_
  21. #define _ACR_C_
  22. #endif
  23. /************************************************************************
  24. Included File:
  25. *************************************************************************/
  26. #include "acr.h"
  27. /************************************************************************
  28. Constant Table:
  29. *************************************************************************/
  30. /************************************************************************
  31. Exported Functions:
  32. *************************************************************************/
  33. /***************************************************************
  34. Function: acr_voCurPICoef;
  35. Description: Coefficient calculation for "acr_voCurPI"
  36. Call by: functions in main loop;
  37. Input Variables: ACR_CURPI_COFIN
  38. Output/Return Variables: ACR_CURPI_COF
  39. Subroutine Call: N/A;
  40. Reference: N/A
  41. ****************************************************************/
  42. void acr_voCurPICoef(ACR_CURPI_COFIN *in, ACR_CURPI_COF *out)
  43. {
  44. // in->uwLPu(Q10); out->uwKpPu(Q12)
  45. // in->uwRsPu(Q15); out->uwKitPu(Q15)
  46. // in->uwTCurCtrPu(Q15); out->uwRaPu(Q15)
  47. // in->uwWicPu(Q10)
  48. // in->uwRaCoefPu(Q0)
  49. UWORD uwTiPu;
  50. ULONG ulWebRadps;
  51. UWORD uwRbOm;
  52. UWORD uwLbHm;
  53. UWORD uwLPu;
  54. UWORD uwRsPu;
  55. UWORD uwTCurCtrPu;
  56. UWORD uwWicPu;
  57. if (in->uwFbHz < 1)
  58. {
  59. in->uwFbHz = 1;
  60. }
  61. if (in->uwFTbcHz < 1)
  62. {
  63. in->uwFTbcHz = 1;
  64. }
  65. if (in->uwIbAp < 1)
  66. {
  67. in->uwIbAp = 1;
  68. }
  69. if (in->uwRaCoef > 10)
  70. {
  71. in->uwRaCoef = 10;
  72. }
  73. else if (in->uwRaCoef <= 0)
  74. {
  75. in->uwRaCoef = 0;
  76. }
  77. if (in->uwMtRsOh < 1)
  78. {
  79. in->uwMtRsOh = 1;
  80. }
  81. if (in->uwUbVt < 1)
  82. {
  83. in->uwUbVt = 1;
  84. }
  85. if (in->uwLHm < 1)
  86. {
  87. in->uwLHm = 1;
  88. }
  89. ulWebRadps = (ULONG)2 * 31416 * in->uwFbHz / 1000; /* unit: 0.1rad/s, Electrical radian frequency base */
  90. uwRbOm = (ULONG)in->uwUbVt * 100000 / in->uwIbAp; /* unit: 0.1mOhm, Resistance base */
  91. uwLbHm = (ULONG)uwRbOm * 100000 / ulWebRadps; /* unit: 0.01uH, Inductance base */
  92. uwLPu = ((ULONG)in->uwLHm << 10) / uwLbHm; /* Q10, D/Q axis inductance */
  93. uwRsPu = ((ULONG)in->uwMtRsOh << 15) / uwRbOm; /* Q15, Phase resistance */
  94. uwTCurCtrPu = (ULONG)2 * 102944 * in->uwFbHz / in->uwFTbcHz; /* Q15, Current control period Pu, pi(Q15)=102944 */
  95. uwWicPu = ((ULONG)in->uwWicHz << 10) /
  96. in->uwFbHz; // BW_HZ2PU // Q10, Current loop frequency bandwidth //BW_HZ2PU // Q10, Current loop frequency bandwidth
  97. // Ti = L / R
  98. // Kp = Wic * L
  99. // Kit = (Kra+1) * Kp * T_cnt_ctrl / Ti
  100. out->uwRaPu = in->uwRaCoef * uwRsPu; // Q0 + Q15 = Q15
  101. out->uwKpPu = (ULONG)uwWicPu * uwLPu >> 8; // Q10 + Q10 - Q8 = Q12
  102. uwTiPu = ((ULONG)uwLPu << 11) /
  103. uwRsPu; // Q10 + Q11 - Q15 = Q6
  104. out->uwKitPu = ((ULONG)(in->uwRaCoef + 1) * out->uwKpPu * uwTCurCtrPu >> 6) / uwTiPu; //Q12 + Q15 - Q6 - Q6 = Q15
  105. //out->uwKitPu = (out->uwKpPu * uwTCurCtrPu >> 6)/ uwTiPu; // Q12 + Q15 - Q6 - Q6 = Q15
  106. }
  107. /***************************************************************
  108. Function: acr_voCurPI;
  109. Description: current PI regulator;
  110. Call by: functions in TBC;
  111. Input Variables: ACR_CURPI_IN,ACR_CURPI_COF
  112. Output/Return Variables: ACR_CURPI_OUT
  113. Subroutine Call: N/A;
  114. Reference: N/A
  115. ****************************************************************/
  116. void acr_voCurPI(ACR_CURPI_IN *in, ACR_CURPI_COF *coef, ACR_CURPI_OUT *out)
  117. {
  118. // in->swCurRefPu(Q14); cof->uwKpPu(Q12); out->slURefPu(Q26)
  119. // in->swCurFdbPu(Q14); cof->uwKitPu(Q15); out->swURefPu(Q14)
  120. // in->swULimPu(Q12); out->swErrZ1Pu(Q14)
  121. SLONG slErrPu;
  122. SLONG slDeltaErrPu; // Q14
  123. // SLONG slUiPreLimPu;
  124. SLONG slUpPu, slUiPu; // Q29
  125. SLONG slUmaxPu, slUminPu; // Q29
  126. SQWORD sqURefPu;
  127. SQWORD sqUpPu;
  128. slUmaxPu = (SLONG)in->swUmaxPu << 15; // Q14+Q15=Q29
  129. slUminPu = (SLONG)in->swUminPu << 15; // Q14+Q15=Q29
  130. /*U(k) = U(k-1) + Kp * (Err(k) - Err(k-1)) + Kit * Err(k)*/
  131. slErrPu = in->swCurRefPu - in->swCurFdbPu; // Q14
  132. if (slErrPu > 32767)
  133. {
  134. slErrPu = 32767;
  135. }
  136. else if (slErrPu < -32768)
  137. {
  138. slErrPu = -32768;
  139. }
  140. else
  141. {
  142. /* Nothing */
  143. }
  144. slDeltaErrPu = slErrPu - out->swErrZ1Pu; // Q14
  145. if (slDeltaErrPu > 32767)
  146. {
  147. slDeltaErrPu = 32767;
  148. }
  149. else if (slDeltaErrPu < -32768)
  150. {
  151. slDeltaErrPu = -32768;
  152. }
  153. else
  154. {
  155. /* Nothing */
  156. }
  157. slUpPu = slDeltaErrPu * coef->uwKpPu; // Q14+Q12=Q26
  158. sqUpPu = (SQWORD)slUpPu << 3;
  159. slUiPu = slErrPu * coef->uwKitPu; // Q14+Q15=Q29
  160. sqURefPu = sqUpPu + (SQWORD)slUiPu + (SQWORD)out->slURefPu; // Q29
  161. if (sqURefPu >= slUmaxPu)
  162. {
  163. out->slURefPu = slUmaxPu;
  164. out->slURefRemPu = 1;
  165. }
  166. else if (sqURefPu <= slUminPu)
  167. {
  168. out->slURefPu = slUminPu;
  169. out->slURefRemPu = 1;
  170. }
  171. else
  172. {
  173. out->slURefPu = sqURefPu;
  174. }
  175. out->swURefPu = out->slURefPu >> 15; // Q29-Q15=Q14
  176. out->swErrZ1Pu = (SWORD)slErrPu;
  177. }
  178. /***************************************************************
  179. Function: acr_voCurPIInit;
  180. Description: Current PI initialization
  181. Call by: functions in main loop;
  182. Input Variables: N/A
  183. Output/Return Variables: N/A
  184. Subroutine Call: N/A;
  185. Reference: N/A
  186. ****************************************************************/
  187. void acr_voCurPIInit(void)
  188. {
  189. acr_stCurIdPIOut.slURefPu = 0;
  190. acr_stCurIdPIOut.swURefPu = 0;
  191. acr_stCurIdPIOut.swErrZ1Pu = 0;
  192. acr_stCurIdPIOut.slURefRemPu = 0;
  193. acr_stCurIqPIOut.slURefPu = 0;
  194. acr_stCurIqPIOut.swURefPu = 0;
  195. acr_stCurIqPIOut.swErrZ1Pu = 0;
  196. acr_stCurIqPIOut.slURefRemPu = 0;
  197. }
  198. /***************************************************************
  199. Function: acr_voUdqDcp;
  200. Description: Feedforward decoupled, Calculate Output Voltage
  201. Call by: functions in TBC;
  202. Input Variables: ACR_UDQDCP_IN
  203. Output/Return Variables: ACR_UDQDCP_OUT
  204. Subroutine Call: N/A;
  205. Reference: N/A
  206. ****************************************************************/
  207. void acr_voUdqDcp(ACR_UDQDCP_IN *in, ACR_UDQDCP_COF *coef, ACR_UDQDCP_OUT *out)
  208. {
  209. // in->swIdRefPu(Q14); cof->uwLdPu(Q10); out->swUdPu(Q14)
  210. // in->swIqRefPu(Q14); cof->uwLqPu(Q10); out->swUqPu(Q14)
  211. // in->swWsPu(Q15); cof->uwFluxFPu(Q12);
  212. SLONG slUdDcp; //(Q12)
  213. SLONG slUqDcp; //(Q12)
  214. // UFFd = - ws * Lq * Iq_ref , max 6;min -6,related with Lq
  215. slUdDcp = -((SLONG)in->swWsPu * coef->uwLqPu) >> 15; // Q15+Q10-Q15=Q10
  216. slUdDcp = ((SLONG)slUdDcp * in->swIqRefPu) >> 10; // Q10+Q14-Q10=Q14;
  217. if (slUdDcp > 32767)
  218. {
  219. out->swUdPu = 32767;
  220. }
  221. else if (slUdDcp < -32767)
  222. {
  223. out->swUdPu = -32767;
  224. }
  225. else
  226. {
  227. out->swUdPu = slUdDcp;
  228. }
  229. // UFFq = ws * Ld * Id_ref + ws * FluxF,max 2 ;min -2,related with Ld
  230. slUqDcp = (((SLONG)coef->uwLdPu * in->swIdRefPu) >> 12) + coef->uwFluxFPu; // Q10+Q14-Q12=Q12
  231. slUqDcp = ((SLONG)in->swWsPu * slUqDcp) >> 13; // Q15+Q12-Q13=Q14
  232. if (slUqDcp > 32767)
  233. {
  234. out->swUqPu = 32767;
  235. }
  236. else if (slUqDcp < -32767)
  237. {
  238. out->swUqPu = -32767;
  239. }
  240. else
  241. {
  242. out->swUqPu = slUqDcp;
  243. }
  244. if (out->swUqPu > in->swUdqLimPu) // Q14
  245. {
  246. out->swUqPu = in->swUdqLimPu;
  247. }
  248. else if (out->swUqPu < (-in->swUdqLimPu))
  249. {
  250. out->swUqPu = -in->swUdqLimPu;
  251. }
  252. else
  253. {}
  254. if (out->swUdPu > in->swUdqLimPu)
  255. {
  256. out->swUdPu = in->swUdqLimPu;
  257. }
  258. else if (out->swUdPu < (-in->swUdqLimPu))
  259. {
  260. out->swUdPu = -in->swUdqLimPu;
  261. }
  262. else
  263. {}
  264. }
  265. /***************************************************************
  266. Function: acr_voUdqDcpCoef;
  267. Description: Coefficient calculation for "acr_voUdqDcp"
  268. Call by: functions in main loop;
  269. Input Variables: ACR_UDQDCP_COFIN
  270. Output/Return Variables: ACR_UDQDCP_COF
  271. Subroutine Call: N/A;
  272. Reference: N/A
  273. ****************************************************************/
  274. void acr_voUdqDcpCoef(ACR_UDQDCP_COFIN *in, ACR_UDQDCP_COF *out)
  275. {
  276. ULONG ulWebRadps;
  277. UWORD uwFluxbWb;
  278. UWORD uwRbOm;
  279. UWORD uwLbHm;
  280. if (in->uwFbHz < 1)
  281. {
  282. in->uwFbHz = 1;
  283. }
  284. if (in->uwMtFlxWb < 1)
  285. {
  286. in->uwMtFlxWb = 1;
  287. }
  288. if (in->uwIbAp < 1)
  289. {
  290. in->uwIbAp = 1;
  291. }
  292. if (in->uwLdHm < 1)
  293. {
  294. in->uwLdHm = 1;
  295. }
  296. if (in->uwLqHm < 1)
  297. {
  298. in->uwLqHm = 1;
  299. }
  300. if (in->uwUbVt < 1)
  301. {
  302. in->uwUbVt = 1;
  303. }
  304. ulWebRadps = (ULONG)2 * 31416 * in->uwFbHz / 1000; /* unit: 0.1rad/s, Electrical radian frequency base */
  305. uwFluxbWb = (ULONG)in->uwUbVt * 1000000 / ulWebRadps; /* unit: 0.001mWb, Flux linkage base */
  306. out->uwFluxFPu = ((ULONG)in->uwMtFlxWb << 12) / uwFluxbWb; /* unit: 0.001mWb, Q12, Flux linkage */
  307. uwRbOm = (ULONG)in->uwUbVt * 100000 / in->uwIbAp; /* unit: 0.1mOhm, Resistance base */
  308. uwLbHm = (ULONG)uwRbOm * 100000 / ulWebRadps; /* unit: 0.01uH, Inductance base */
  309. out->uwLdPu = ((ULONG)in->uwLdHm << 10) / uwLbHm; /* Q10, D axis inductance */
  310. out->uwLqPu = ((ULONG)in->uwLqHm << 10) / uwLbHm; /* Q10, Q axis inductance */
  311. }
  312. /***************************************************************
  313. Function: acr_voUdqDcpInit;
  314. Description: Feedforward decoupled initialization
  315. Call by: functions in main loop;
  316. Input Variables: N/A
  317. Output/Return Variables: N/A
  318. Subroutine Call: N/A;
  319. Reference: N/A
  320. ****************************************************************/
  321. void acr_voUdqDcpInit(void)
  322. {
  323. acr_stUdqDcpOut.swUdPu = 0;
  324. acr_stUdqDcpOut.swUqPu = 0;
  325. }
  326. /*************************************************************************
  327. Local Functions (N/A)
  328. *************************************************************************/
  329. /************************************************************************
  330. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co., Ltd.
  331. All rights reserved.
  332. *************************************************************************/
  333. #ifdef _ACR_C_
  334. #undef _ACR_C_
  335. #endif
  336. /*************************************************************************
  337. End of this File (EOF)!
  338. Do not put anything after this part!
  339. *************************************************************************/