FocControlFunction.c 15 KB

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