pwrlim.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. /************************************************************************
  2. Project: Welling Motor Control Paltform
  3. Filename: pwrlim.c
  4. Partner Filename: pwrlim.h
  5. Description: Motor input power limit
  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. Fjy create this file;
  15. ************************************************************************/
  16. /************************************************************************
  17. Beginning of File, do not put anything above here except notes
  18. Compiler Directives:
  19. *************************************************************************/
  20. #ifndef _PWRLIM_C_
  21. #define _PWRLIM_C_
  22. #endif
  23. /************************************************************************
  24. Include File
  25. ************************************************************************/
  26. #include "user.h"
  27. /************************************************************************
  28. Constant Table:
  29. ************************************************************************/
  30. /************************************************************************
  31. Private Variables
  32. *************************************************************************/
  33. /************************************************************************
  34. Exported Functions:
  35. ************************************************************************/
  36. /************************************************************************
  37. Function: pwr_voPwrLimInit;
  38. Description: Initialize Variables for "pwr_voPwrLim"
  39. Call by:
  40. Input Variables:
  41. Output/Return Variables:
  42. Subroutine Call:
  43. Reference:
  44. ************************************************************************/
  45. void pwr_voPwrLimInit(void)
  46. {
  47. pwr_stPwrLimOut.swIqLimPu = (SWORD)cof_uwCurMaxPu;
  48. pwr_stPwrLimOut.swPwrErrZ1 = 0;
  49. pwr_stPwrLimOut.slIqLimDetaSum = 0;
  50. pwr_stPwrLimOut.swIqLimDetaSum = 0;
  51. pwr_stPwrLimOut.swIqLimPu = 0;
  52. pwr_stPwrLimOut2.slIqLimDetaSum = 0;
  53. pwr_stPwrLimOut2.swIqLimDetaSum = 0;
  54. pwr_stPwrLimOut2.swPwrErrZ1 = 0;
  55. pwr_stPwrLimOut2.swPwrLimActualPu = (SWORD)cof_uwPwrMaxPu;
  56. pwr_stPwrLimOut2.swIqLimPu = 0;
  57. }
  58. /************************************************************************
  59. Function: pwr_voPwrLimCof;
  60. Description: Coefficient calculation for "pwr_voPwrLim"
  61. Call by:
  62. Input Variables:
  63. Output/Return Variables:
  64. Subroutine Call:
  65. Reference:
  66. ************************************************************************/
  67. void pwr_voPwrLimCof(PWRLIM_COFIN *in, PWRLIM_COF *out)
  68. {
  69. UWORD uwPwrLim;
  70. ULONG ulPbWt;
  71. if (in->uwIBaseAp > 32767)
  72. {
  73. in->uwIBaseAp = 32767;
  74. }
  75. else if (in->uwIBaseAp < 1)
  76. {
  77. in->uwIBaseAp = 1;
  78. }
  79. else
  80. {
  81. // do nothing
  82. }
  83. if (in->uwUbVt < 100)
  84. {
  85. in->uwUbVt = 100;
  86. }
  87. else {}
  88. if (in->swPwrLimW > 30000)
  89. {
  90. in->swPwrLimW = 30000;
  91. }
  92. else if (in->swPwrLimW < 100)
  93. {
  94. in->swPwrLimW = 100;
  95. }
  96. else
  97. {
  98. // do noting
  99. }
  100. if (in->uwPwrErrW < 20)
  101. {
  102. in->uwPwrErrW = 20;
  103. }
  104. else if (in->uwPwrErrW >= in->swPwrLimW)
  105. {
  106. in->uwPwrErrW = in->swPwrLimW - 10;
  107. }
  108. else
  109. {
  110. // do noting
  111. }
  112. if (in->swIqMaxAp > in->uwIBaseAp)
  113. {
  114. in->swIqMaxAp = (SWORD)in->uwIBaseAp;
  115. }
  116. else if (in->swIqMaxAp < 1)
  117. {
  118. in->swIqMaxAp = 1;
  119. }
  120. else
  121. {
  122. // do nothing
  123. }
  124. out->swIqMaxPu = (SWORD)(((SLONG)in->swIqMaxAp << 14) / (SLONG)in->uwIBaseAp); // Q14, Max phase current (peak value)
  125. ulPbWt = ((ULONG)3 * in->uwUbVt * in->uwIBaseAp / 100) >> 1; // Q0, unit: 0.1w, Power base
  126. uwPwrLim = (UWORD)(((ULONG)in->uwPwrErrW << 15) / ulPbWt); // Q15
  127. out->uwPwrLimKp = (UWORD)(((ULONG)out->swIqMaxPu << 6) / uwPwrLim); // 14+6-15=Q5
  128. if (in->swPwrLimW > ((SWORD)in->uwPwrErrW))
  129. {
  130. out->swPwrLimPu = (SWORD)((((SLONG)in->swPwrLimW - (SLONG)in->uwPwrErrW) << 15) / (SLONG)ulPbWt); // Q15
  131. }
  132. else
  133. {
  134. out->swPwrLimPu = 0;
  135. }
  136. out->swPwrLimStartTemp = (SWORD)in->swPwrLimStartTempCe;
  137. out->swPwrLimEndTemp = (SWORD)((in->swAlarmTempCe + in->swPwrLimStartTempCe) >> 1);
  138. out->swPwrLimTempCof = (out->swPwrLimPu >> 1) / (out->swPwrLimEndTemp - out->swPwrLimStartTemp);
  139. out->swIqLimTempCof =
  140. ((SLONG)out->swIqMaxPu * 83 >> 7) / (out->swPwrLimEndTemp - out->swPwrLimStartTemp); ///< 0.65=83>>7
  141. out->uwPwrLimStartBatCap = 20;
  142. out->uwPwrLimEndBatCap = 5;
  143. out->uwPwrlimBatCapCof =
  144. ((SLONG)out->swPwrLimPu * 3 >> 2) / (out->uwPwrLimStartBatCap - out->uwPwrLimEndBatCap);
  145. out->uwPwrLimPIKp = in->uwPwrLimPIKp; // Q15
  146. out->uwPwrLimPIKi = in->uwPwrLimPIKi; // Q15
  147. }
  148. /************************************************************************
  149. Function: pwr_voPwrLim;
  150. Description: Power Limit Using Kp;
  151. Call by:
  152. Input Variables:
  153. Output/Return Variables:
  154. Subroutine Call:
  155. Reference:
  156. ************************************************************************/
  157. void pwr_voPwrLim(const PWRLIM_IN *in, const PWRLIM_COF *cof, PWRLIM_OUT *out)
  158. {
  159. SWORD swEmPwLimIqPu; // Q14
  160. if (in->swMotorPwrPu > cof->swPwrLimPu)
  161. {
  162. if (in->swSpdPu >= 0)
  163. {
  164. swEmPwLimIqPu =
  165. (SWORD)(((SLONG)cof->swPwrLimPu - (SLONG)in->swMotorPwrPu) * (SLONG)cof->uwPwrLimKp >> 6) + cof->swIqMaxPu; // Q15+Q5-Q6=Q14
  166. if (swEmPwLimIqPu > cof->swIqMaxPu)
  167. {
  168. swEmPwLimIqPu = cof->swIqMaxPu;
  169. }
  170. else if (swEmPwLimIqPu < 0)
  171. {
  172. swEmPwLimIqPu = 0;
  173. }
  174. else
  175. {
  176. // do nothing
  177. }
  178. out->swIqLimPu = swEmPwLimIqPu;
  179. }
  180. else
  181. {
  182. swEmPwLimIqPu = (SWORD)((((SLONG)in->swMotorPwrPu - cof->swPwrLimPu) * (SWORD)cof->uwPwrLimKp >> 6) - cof->swIqMaxPu); // Q14
  183. if (swEmPwLimIqPu < -cof->swIqMaxPu)
  184. {
  185. swEmPwLimIqPu = -cof->swIqMaxPu;
  186. }
  187. else if (swEmPwLimIqPu > 0)
  188. {
  189. swEmPwLimIqPu = 0;
  190. }
  191. else
  192. {
  193. // do nothing
  194. }
  195. out->swIqLimPu = swEmPwLimIqPu;
  196. }
  197. }
  198. else
  199. {
  200. if (in->swSpdPu >= 0)
  201. {
  202. out->swIqLimPu = cof->swIqMaxPu;
  203. }
  204. else
  205. {
  206. out->swIqLimPu = -cof->swIqMaxPu;
  207. }
  208. }
  209. }
  210. /************************************************************************
  211. Function: pwr_voPwrLim;
  212. Description: Power Limit Using Kp and Ki;
  213. Call by:
  214. Input Variables:
  215. Output/Return Variables:
  216. Subroutine Call:
  217. Reference:
  218. ************************************************************************/
  219. void pwr_voPwrLimPI(const PWRLIM_IN *in, const PWRLIM_COF *cof, PWRLIM_OUT *out)
  220. {
  221. SWORD swError, swErrorDeta; ///< Q14
  222. SLONG slError; ///< Q15
  223. SLONG slIqLimDetaP, slIqLimDetaI, slIqLimSum; ///< Q30
  224. SWORD swPwrLimActualPu1 = cof->swPwrLimPu, swPwrLimActualPu2 = cof->swPwrLimPu; ///< Q15
  225. SWORD swIqlimPu1 = cof->swIqMaxPu, swIqlimPu2 = cof->swIqMaxPu; ///< Q14
  226. /* 根据温度限制功率,电机测试模式开放 */
  227. if (cp_stFlg.RunModelSelect == ClZLOOP)
  228. {
  229. if (in->swPCBTemp < cof->swPwrLimStartTemp)
  230. {
  231. swPwrLimActualPu1 = cof->swPwrLimPu;
  232. }
  233. else if (in->swPCBTemp < cof->swPwrLimEndTemp)
  234. {
  235. swPwrLimActualPu1 = cof->swPwrLimPu - ((in->swPCBTemp - cof->swPwrLimStartTemp) * cof->swPwrLimTempCof);
  236. }
  237. else
  238. {
  239. swPwrLimActualPu1 = cof->swPwrLimPu >> 1; ///< EndTemp时限制为1/2的功率
  240. }
  241. }
  242. /* 根据电池电量限制功率 */
  243. if (in->uwBatCap > cof->uwPwrLimStartBatCap)
  244. {
  245. swPwrLimActualPu2 = cof->swPwrLimPu;
  246. }
  247. else if (in->uwBatCap > cof->uwPwrLimEndBatCap)
  248. {
  249. swPwrLimActualPu2 = cof->swPwrLimPu - ((cof->uwPwrLimStartBatCap - in->uwBatCap) * cof->uwPwrlimBatCapCof);
  250. }
  251. else
  252. {
  253. swPwrLimActualPu2 = cof->swPwrLimPu >> 2; ///< EndTemp时限制为1/4的功率
  254. }
  255. out->swPwrLimActualPu = (swPwrLimActualPu1 < swPwrLimActualPu2) ? swPwrLimActualPu1 : swPwrLimActualPu2;
  256. /* 根据PCB温度限制电流 */
  257. if (cp_stFlg.RunModelSelect == CityBIKE || cp_stFlg.RunModelSelect == MountainBIKE)
  258. {
  259. if (in->swPCBTemp < cof->swPwrLimStartTemp)
  260. {
  261. swIqlimPu1 = cof->swIqMaxPu;
  262. }
  263. else if (in->swPCBTemp < cof->swPwrLimEndTemp)
  264. {
  265. swIqlimPu1 = cof->swIqMaxPu - ((SLONG)(in->swPCBTemp - cof->swPwrLimStartTemp) * cof->swIqLimTempCof);
  266. }
  267. else
  268. {
  269. swIqlimPu1 = (SWORD)((SLONG)cof->swIqMaxPu * 45 >> 7); ///< EndTemp时限制为额定电流=0.35*最大电流
  270. }
  271. }
  272. /* 功率限制PI调节:根据功率限制电流 */
  273. slError = out->swPwrLimActualPu - in->swMotorPwrPu;
  274. if (slError >= 32768)
  275. {
  276. slError = 32768;
  277. }
  278. else if (slError < -32768)
  279. {
  280. slError = -32768;
  281. }
  282. else
  283. {
  284. // do nothing
  285. }
  286. swError = (SWORD)slError;
  287. swErrorDeta = swError - out->swPwrErrZ1;
  288. out->swPwrErrZ1 = swError;
  289. slIqLimDetaP = (SLONG)cof->uwPwrLimPIKp * swErrorDeta; ///< Q15+Q15=Q30
  290. slIqLimDetaI = (SLONG)cof->uwPwrLimPIKi * swError; ///< Q15+Q15=Q30
  291. slIqLimSum = out->slIqLimDetaSum + slIqLimDetaP + slIqLimDetaI;
  292. if (slIqLimSum > 0)
  293. {
  294. out->slIqLimDetaSum = 0;
  295. }
  296. else if (slIqLimSum < -((SLONG)cof->swIqMaxPu << 16))
  297. {
  298. out->slIqLimDetaSum = -((SLONG)cof->swIqMaxPu << 16);
  299. }
  300. else
  301. {
  302. out->slIqLimDetaSum = slIqLimSum; ///< Q30
  303. }
  304. out->swIqLimDetaSum = (SWORD)(out->slIqLimDetaSum >> 16); ///< Q30-Q16=Q14
  305. swIqlimPu2 = cof->swIqMaxPu + out->swIqLimDetaSum;
  306. /* 电流限制值输出 */
  307. out->swIqLimPu = (swIqlimPu1 < swIqlimPu2) ? swIqlimPu1 : swIqlimPu2;
  308. }
  309. /************************************************************************
  310. Local Functions (N/A)
  311. ************************************************************************/
  312. /************************************************************************
  313. Copyright (c) 2018 Welling Motor Technology(Shanghai) Co. Ltd.
  314. All rights reserved.
  315. ************************************************************************/
  316. #ifdef _PWRLIM_C_
  317. #undef _PWRLIM_C_ /* parasoft-suppress MISRA2004-19_6 "本项目中无法更改,后续避免使用" */
  318. #endif
  319. /************************************************************************
  320. End of this File (EOF)!
  321. Do not put anything after this part!
  322. ************************************************************************/