FocControlFunction.c 12 KB

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