FocControlFunction.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. #include <Myproject.h>
  2. /**
  3. * @function Abs_F32
  4. * @brief 取绝对值
  5. * @param[in] Xn0: [输入/出]
  6. * @return None
  7. * @date 2025-11-08
  8. */
  9. uint32_t Abs_F32(int32_t Xn0)
  10. {
  11. if (Xn0 < 0)
  12. { return (-Xn0); }
  13. else
  14. { return (Xn0); }
  15. }
  16. void FOC_Init(void)
  17. {
  18. DRV_CMR = 0x0ABF;
  19. // 使能FOC
  20. ClrBit(DRV_CR, DRVEN);
  21. ClrBit(DRV_CR, FOCEN);
  22. SetBit(DRV_CR, FOCEN);
  23. SetBit(FOC_CR0, MERRS1 | MERRS0);
  24. FOC_EOMEKLPF = 0xff; //速度滤波系数,值越小滤波深度越深
  25. FOC_KFG = 0; //FG计算系数 = 6M(TIM4分频结果)/640(FBase)
  26. // 配置FOC寄存器
  27. FOC_CR1 = 0;
  28. FOC_CR2 = 0;
  29. FOC_IDREF = 0;
  30. FOC_IQREF = 0;
  31. FOC__THETA = 0;
  32. FOC_RTHEACC = 0;
  33. FOC__RTHESTEP = 0;
  34. FOC_RTHECNT = 0;
  35. FOC_THECOR = 0x02; // 误差角度补偿
  36. // 电流环参数配置
  37. FOC_DKP = DQKP;
  38. FOC_DKI = DQKI;
  39. FOC_QKP = DQKP;
  40. FOC_QKI = DQKI;
  41. FOC_ID_LPFK = 250;
  42. FOC_IQ_LPFK = 250;
  43. FOC_DMAX = DOUTMAX;
  44. FOC_DMIN = DOUTMIN;
  45. FOC_QMAX = QOUTMAX;
  46. FOC_QMIN = QOUTMIN;
  47. SetBit(FOC_CR0, ESCMS);
  48. // 估算器配置
  49. #if (EstimateAlgorithm == SMO)
  50. {
  51. ClrBit(FOC_CR2, ESEL);
  52. ClrBit(FOC_CR3, MFP_EN);
  53. }
  54. #elif (EstimateAlgorithm == AO)
  55. {
  56. SetBit(FOC_CR3, MFP_EN);
  57. ClrBit(FOC_CR2, ESEL);
  58. }
  59. #elif (EstimateAlgorithm == PLL)
  60. {
  61. ClrBit(FOC_CR3, MFP_EN);
  62. SetBit(FOC_CR2, ESEL);
  63. FOC_KSLIDE = OBSE_PLLKP_GAIN1;
  64. FOC_EKLPFMIN = OBSE_PLLKI_GAIN1;
  65. }
  66. #endif
  67. FOC_EK1 = OBS_K1T;
  68. FOC_EK2 = OBS_K2T;
  69. FOC_EK3 = OBS_K3T;
  70. FOC_EK4 = OBS_K4T;
  71. FOC_KSLIDE = OBS_KSLIDE;
  72. FOC_EKLPFMIN = OBS_EA_KS;
  73. FOC_FBASE = OBS_FBASE;
  74. FOC_OMEKLPF = SPEED_KLPF;
  75. FOC_TGLI = PWM_TGLI_LOAD;
  76. SetBit(FOC_CR1, SVPWMEN);
  77. // 转向配置
  78. #if (IRMODE)
  79. SetBit(DRV_CR, DDIR);
  80. #else
  81. ClrBit(DRV_CR, DDIR);
  82. #endif
  83. // 过调制
  84. #if (OverModulation)
  85. SetBit(FOC_CR1, OVMDL);
  86. #endif
  87. // 单电阻采样;需要最小采样窗,FOC_TRGDLY为0,七段式SVPWM方式
  88. #if (Shunt_Resistor_Mode == Single_Resistor)
  89. {
  90. SetReg(FOC_CR1, CSM0 | CSM1, 0x00);
  91. FOC_TSMIN = PWM_TS_LOAD; // 最小采样窗口
  92. FOC_TRGDLY = 0x3B; // 采样时刻在中点,一般考虑开关噪声影响,会设置延迟;3B
  93. SetReg(FOC_CR2, CSOC0 | CSOC1, 0x00);
  94. FOC_CSO = currOffset.IwBusOffset;
  95. }
  96. // 双电阻采样,可设置死区补偿值,在下降沿结束前开始采样Ia,配置81
  97. #elif (Shunt_Resistor_Mode == Double_Resistor)
  98. {
  99. SetReg(FOC_CR1, CSM0 | CSM1, CSM0);
  100. FOC_TSMIN = PWM_DT_LOAD; // 死区补偿值
  101. FOC_TRGDLY = 0x05; // ADC采样的时刻,采样时刻在计数器零点附近,83为下降沿结束前3个clock采样Ia,与单电阻不同
  102. // 01为上升沿开始后第一个clock开始采样。根据实际情况调整。
  103. FOC_TBLO = PWM_DLOWL_TIME; //下桥臂最小脉冲,保证采样
  104. SetReg(FOC_CR2, CSOC0 | CSOC1, CSOC0);
  105. FOC_CSO = currOffset.IuOffset;
  106. SetReg(FOC_CR2, CSOC0 | CSOC1, CSOC1);
  107. FOC_CSO = currOffset.IvOffset;
  108. // 采样配置
  109. #if (DouRes_Sample_Mode == DouRes_1_Cycle)
  110. ClrBit(FOC_CR2, DSS);
  111. #elif (DouRes_Sample_Mode == DouRes_2_Cycle)
  112. SetBit(FOC_CR2, DSS);
  113. #endif
  114. }
  115. // 三电阻采样
  116. #elif (Shunt_Resistor_Mode == Three_Resistor)
  117. {
  118. SetReg(FOC_CR1, CSM0 | CSM1, CSM0 | CSM1);
  119. FOC_TSMIN = PWM_DT_LOAD; // 死区补偿值
  120. FOC_TRGDLY = 0x08; // ADC采样的时刻,采样时刻在计数器零点附近,83为下降沿结束前3个clock采样Ia,与单电阻不同。
  121. // 01为上升沿开始后第一个clock开始采样。根据实际情况调整。
  122. FOC_TBLO = PWM_OVERMODULE_TIME; // 过调制电流采样处理的TB脉宽
  123. // 采样配置
  124. #if (DouRes_Sample_Mode == DouRes_1_Cycle)
  125. ClrBit(FOC_CR2, DSS);
  126. #elif (DouRes_Sample_Mode == DouRes_2_Cycle)
  127. SetBit(FOC_CR2, DSS);
  128. #endif
  129. SetReg(FOC_CR2, CSOC0 | CSOC1, CSOC0);
  130. FOC_CSO = currOffset.IuOffset;
  131. SetReg(FOC_CR2, CSOC0 | CSOC1, CSOC1);
  132. FOC_CSO = currOffset.IvOffset;
  133. SetReg(FOC_CR2, CSOC0 | CSOC1, 0x00);
  134. FOC_CSO = currOffset.IwBusOffset;
  135. }
  136. #endif
  137. // SVPWM 配置
  138. #if (SVPMW_Mode == SVPWM_7_Segment)
  139. ClrBit(FOC_CR2, F5SEG);
  140. #elif (SVPMW_Mode == SVPWM_5_Segment)
  141. SetBit(FOC_CR2, F5SEG);
  142. #endif
  143. SetBit(DRV_CR, DRVEN);
  144. SetBit(DRV_CR, OCS);
  145. }
  146. /**
  147. @function Motor_Align
  148. @brief 预定位
  149. @date 2025-11-08
  150. */
  151. void Motor_Align(void)
  152. {
  153. if (McStaSet.SetFlag.AlignSetFlag == 0)
  154. {
  155. McStaSet.SetFlag.AlignSetFlag = 1;
  156. // FOC初始化
  157. FOC_Init();
  158. // 配置预定位的电流、KP、KI
  159. FOC_IDREF = 0;
  160. FOC_IQREF = 0;
  161. FOC_DKP = DQKP_Alignment;
  162. FOC_DKI = DQKI_Alignment;
  163. FOC_QKP = DQKP_Alignment;
  164. FOC_QKI = DQKI_Alignment;
  165. FOC_EKP = OBSW_KP_GAIN;
  166. FOC_EKI = OBSW_KI_GAIN;
  167. // 配置预定位角度
  168. #if (EstimateAlgorithm == SMO)
  169. FOC__ETHETA = FOC__THETA - 4836;
  170. #elif (EstimateAlgorithm == PLL)
  171. FOC__ETHETA = FOC__THETA;
  172. #endif
  173. DRV_CMR |= 0x03F;
  174. MOE = 1;
  175. }
  176. if (mcFocCtrl.State_Count > (AlignmentHoldTime1 + AlignmentHoldTime2))
  177. {
  178. mcFocCtrl.CurrentAlignStatus = 0;
  179. FOC__THETA = Align_Angle1;
  180. FOC_IQREF = ID_Align_CURRENT_End * (Align_Time - mcFocCtrl.State_Count) / AlignmentRampTime;
  181. }
  182. else if (mcFocCtrl.State_Count > AlignmentHoldTime2)
  183. {
  184. mcFocCtrl.CurrentAlignStatus = 1;
  185. FOC__THETA = Align_Angle1;
  186. FOC_IQREF = ID_Align_CURRENT_End;
  187. }
  188. else if (mcFocCtrl.State_Count > 0)
  189. {
  190. mcFocCtrl.CurrentAlignStatus = 2;
  191. FOC__THETA = Align_Angle2;
  192. FOC_IQREF = ID_Align_CURRENT_End;
  193. }
  194. else
  195. { mcState = mcStart; }
  196. }
  197. /**
  198. @function Motor_Open
  199. @brief 启动
  200. @date 2025-11-08
  201. */
  202. void Motor_Open(void)
  203. {
  204. static uint8 OpenRampCycles;
  205. // FOC_Init();
  206. // 启动角度
  207. // FOC__THETA = _Q15((float)0.0 / 180.0);
  208. #if ((EstimateAlgorithm == SMO)||(EstimateAlgorithm == AO))
  209. FOC__ETHETA = FOC__THETA - 4836; //SMO估算角度延迟
  210. #elif (EstimateAlgorithm == PLL)
  211. FOC__ETHETA = FOC__THETA;
  212. #endif
  213. FOC__EOME = 0;
  214. // 配置参数
  215. FOC_IDREF = 0;
  216. FOC_DKP = DQKPStart;
  217. FOC_DKI = DQKIStart;
  218. FOC_QKP = DQKPStart;
  219. FOC_QKI = DQKIStart;
  220. FOC_EKP = OBSW_KP_GAIN;
  221. FOC_EKI = OBSW_KI_GAIN;
  222. /// 启动方式选择
  223. #if (Open_Start_Mode == Omega_Start)
  224. {
  225. FOC_EFREQACC = MOTOR_OMEGA_RAMP_ACC;
  226. FOC_EFREQMIN = MOTOR_OMEGA_ACC_MIN;
  227. FOC_EFREQHOLD = MOTOR_OMEGA_ACC_END;
  228. SetReg(FOC_CR1, EFAE | RFAE | ANGM, EFAE | ANGM);
  229. #if (IFFDebugg)
  230. {
  231. // 估算器禁止输出
  232. ClrBit(FOC_CR1, EFAE); // 禁止估算器强制输出
  233. ClrBit(FOC_CR1, RFAE); // 使能强拉
  234. ClrBit(FOC_CR1, ANGM); // 禁止估算器输出
  235. }
  236. #endif
  237. // 切入启动
  238. mcFocCtrl.State_Count = 1200;
  239. mcState = mcRun;
  240. }
  241. #elif (Open_Start_Mode == Open_Start)
  242. {
  243. FOC_RTHEACC = MOTOR_OPEN_ACC;
  244. FOC__RTHESTEP = MOTOR_OPEN_ACC_MIN;
  245. FOC_RTHECNT = MOTOR_OPEN_ACC_CNT;
  246. SetReg(FOC_CR1, EFAE | RFAE | ANGM, RFAE);
  247. // 切入启动
  248. if (OpenRampCycles < (MOTOR_OPEN_ACC_CYCLE - 1))
  249. {
  250. if (!ReadBit(FOC_CR1, RFAE))
  251. {
  252. SetBit(FOC_CR1, RFAE);
  253. OpenRampCycles++;
  254. }
  255. }
  256. else
  257. {
  258. mcFocCtrl.State_Count = 2;
  259. mcState = mcRun;
  260. }
  261. FOC_EKP = OBSW_KP_GAIN_RUN4;
  262. FOC_EKI = OBSW_KI_GAIN_RUN4;
  263. }
  264. #elif (Open_Start_Mode == Open_Omega_Start)
  265. {
  266. FOC_RTHEACC = MOTOR_OPEN_ACC;
  267. FOC__RTHESTEP = MOTOR_OPEN_ACC_MIN;
  268. FOC_RTHECNT = MOTOR_OPEN_ACC_CNT;
  269. FOC_EFREQACC = Motor_OMEGA_RAMP_ACC;
  270. FOC_EFREQMIN = MOTOR_OMEGA_ACC_MIN;
  271. FOC_EFREQHOLD = MOTOR_OMEGA_ACC_END;
  272. SetReg(FOC_CR1, EFAE | RFAE | ANGM, EFAE | RFAE | ANGM);
  273. // 切入启动
  274. mcFocCtrl.State_Count = 2600;
  275. mcState = mcRun;
  276. }
  277. #endif
  278. // Q轴启动电流
  279. FOC_IQREF = IQ_Start_CURRENT ;
  280. }
  281. /**
  282. * @function StarRampDealwith
  283. * @brief 估算器增益调整
  284. * @date 2025-11-08
  285. */
  286. void StarRampDealwith(void)
  287. {
  288. if ((mcState == mcRun) || (mcState == mcStart))
  289. {
  290. if (mcFocCtrl.State_Count == 1200)
  291. {
  292. FOC_EKP = OBSW_KP_GAIN_RUN; // 估算器里的PI的KP
  293. FOC_EKI = OBSW_KI_GAIN_RUN; // 估算器里的PI的KI
  294. #if (EstimateAlgorithm == PLL)
  295. {
  296. FOC_KSLIDE = OBSE_PLLKP_GAIN2;
  297. FOC_EKLPFMIN = OBSE_PLLKI_GAIN2;
  298. }
  299. #endif
  300. }
  301. else if (mcFocCtrl.State_Count == 1000)
  302. {
  303. FOC_EKP = OBSW_KP_GAIN_RUN1; // 估算器里的PI的KP
  304. FOC_EKI = OBSW_KI_GAIN_RUN1; // 估算器里的PI的KI
  305. #if (EstimateAlgorithm == PLL)
  306. {
  307. FOC_KSLIDE = OBSE_PLLKP_GAIN3;
  308. FOC_EKLPFMIN = OBSE_PLLKI_GAIN3;
  309. }
  310. #endif
  311. }
  312. else if (mcFocCtrl.State_Count == 600)
  313. {
  314. FOC_EKP = OBSW_KP_GAIN_RUN2; // 估算器里的PI的KP
  315. FOC_EKI = OBSW_KI_GAIN_RUN2; // 估算器里的PI的KI
  316. #if (EstimateAlgorithm == PLL)
  317. {
  318. FOC_KSLIDE = OBSE_PLLKP_GAIN4;
  319. FOC_EKLPFMIN = OBSE_PLLKI_GAIN4;
  320. }
  321. #endif
  322. }
  323. else if (mcFocCtrl.State_Count == 400)
  324. {
  325. FOC_EKP = OBSW_KP_GAIN_RUN3; // 估算器里的PI的KP
  326. FOC_EKI = OBSW_KI_GAIN_RUN3; // 估算器里的PI的KI
  327. #if (EstimateAlgorithm == PLL)
  328. {
  329. FOC_KSLIDE = OBSE_PLLKP_GAIN5;
  330. FOC_EKLPFMIN = OBSE_PLLKI_GAIN5;
  331. }
  332. #endif
  333. }
  334. else if (mcFocCtrl.State_Count == 300)
  335. {
  336. FOC_EKP = OBSW_KP_GAIN_RUN4; // 估算器里的PI的KP
  337. FOC_EKI = OBSW_KI_GAIN_RUN4; // 估算器里的PI的KI
  338. #if (EstimateAlgorithm == PLL)
  339. {
  340. FOC_KSLIDE = OBSE_PLLKP_GAIN5;
  341. FOC_EKLPFMIN = OBSE_PLLKI_GAIN5;
  342. }
  343. #endif
  344. }
  345. }
  346. }
  347. #if (FiledWeakenCompEnable)
  348. FieldWeakeningTypeDef xdata mcFieldWeaken;
  349. void FiledWeakenControl(int16 Ud, int16 Uq, uint16 Dcbusk, int16 Is)
  350. {
  351. //获取Us和Udc
  352. SCAT1_COS = Ud;
  353. SCAT1_SIN = Uq;
  354. SMDU_RunBlock(1, 5);
  355. mcFieldWeaken.FieldWeakenActualUS_Q15 = SCAT1_RES1;
  356. mcFieldWeaken.FieldWeakenActualDcbus_Q15 = Dcbusk;
  357. // 计算弱磁角度
  358. mcFieldWeaken.FieldWeakenIsTheta = HW_One_Calc(mcFieldWeaken.FieldWeakenActualDcbus_Q15 - mcFieldWeaken.FieldWeakenActualUS_Q15);
  359. //获取D轴电流和Q轴电流参考值。
  360. SCAT1_COS = Is;
  361. SCAT1_THE = mcFieldWeaken.FieldWeakenIsTheta;
  362. SCAT1_SIN = 0;
  363. SMDU_RunBlock(1, 4);
  364. mcFieldWeaken.mcIdref = SCAT1_RES2 ;//sin的结果
  365. mcFieldWeaken.mcIqref = SCAT1_RES1;//cos的结果
  366. }
  367. #endif