FocControlFunction.c 11 KB

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