RSDDetect.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. /**************************** (C) COPYRIGHT 2018 Fortiortech shenzhen *****************************
  2. File Name : RSDDetect.c
  3. Author : Bruce,Fortiortech RD
  4. Version : V1.0
  5. Date : 2018-07-01
  6. Description : This file contains init speed detection used for Motor Control.
  7. ***************************************************************************************************
  8. All Rights Reserved
  9. **************************************************************************************************/
  10. /* Includes -------------------------------------------------------------------------------------*/
  11. #include <MyProject.h>
  12. #if (TAILWIND_MODE == RSDMethod)
  13. MotorRSDTypeDef mcRsd;
  14. static void Time2_RSD_Init(void);
  15. static void CMP_RSD_Init(void);
  16. static void RSDFOCCloseLoopStart(void);
  17. /**
  18. @brief RSD 启动处理函数
  19. @date 2022-07-13
  20. */
  21. MotStateType RSDStartProcess(void)
  22. {
  23. MotStateType returnStatus;
  24. returnStatus = mcTailWind;
  25. if (mcRsd.SpeedUpdate == 1)
  26. {
  27. if (mcRsd.Speed < S_Value(-50)) // 逆风
  28. {
  29. mcFocCtrl.State_Count = 1000;
  30. mcFocCtrl.Start_Mode = HEADWIND_START; // 逆风启动
  31. ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
  32. ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
  33. returnStatus = mcStart;
  34. }
  35. else if (mcRsd.Speed > S_Value(1000)) //正转
  36. {
  37. mcRsd.SpeedUpdate = 0;
  38. }
  39. else if (mcRsd.Speed > MOTOR_LOOP_RPM) //正转
  40. {
  41. if (mcRsd.HighSpdStart == 2) //启动完成,切状态机
  42. {
  43. mcFocCtrl.Start_Mode = TAILWIND_START;
  44. returnStatus = mcStart;
  45. }
  46. if (mcRsd.HighSpdStart == 0)
  47. {
  48. mcRsd.HighSpdStart = 1; // 设置启动
  49. }
  50. }
  51. else//其他,如静止
  52. {
  53. mcFocCtrl.Start_Mode = STATIC_START;
  54. ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
  55. ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
  56. #if (PosCheckEnable == Enable)
  57. returnStatus = mcPosiCheck;
  58. McStaSet.SetFlag.PosiCheckSetFlag = 0;
  59. mcFocCtrl.mcPosCheckAngle = 0xffff; // 角度赋初值
  60. #elif (ALIGN_MOME != ALIGN_DSIABLE)
  61. mcFocCtrl.mcPosCheckAngle = Align_Angle;
  62. returnStatus = mcAlign;
  63. mcFocCtrl.State_Count = Align_Time;
  64. #else
  65. returnStatus = mcStart;
  66. #endif
  67. }
  68. }
  69. return returnStatus;
  70. }
  71. /**
  72. @brief RSD初始化函数,电机状态切入 顺逆风检测状态时 运行一次
  73. @date 2022-07-13
  74. */
  75. void RSDDetectInit(void)
  76. {
  77. MOE = 0;
  78. mcRsd.SpeedUpdate = 0;
  79. mcRsd.Times = 0;
  80. mcRsd.Period = 0;
  81. mcRsd.Count = 0;
  82. mcRsd.CountPre = 0;
  83. mcRsd.State = STATIC;
  84. mcRsd.Speed = 0;
  85. mcRsd.HighSpdStart = 0;
  86. mcRsd.RSDStep = 0;
  87. mcRsd.RSDSpeedBase = RSDSpeedCalBase;
  88. mcRsd.SetFR = FR_MODE;
  89. ClrBit(DRV_CR, FOCEN); // 关闭FOC
  90. CMP_RSD_Init();
  91. Time2_RSD_Init(); // RSD用的是Time2
  92. }
  93. /**
  94. @brief RSD 比较器初始化
  95. @date 2022-07-13
  96. */
  97. static void CMP_RSD_Init(void)
  98. {
  99. /* -------------------------------------------------------------------------------------------------
  100. CMP Input Pin Mode
  101. P1.4--CMP0_IN+, P1.6--CMP1_IN+, P2.1--CMP2_IN+
  102. P1.5--CMP0_IN-, P1.7--CMP1_IN-, P2.2--CMP2_IN-
  103. P1.3--CMP1P2
  104. -------------------------------------------------------------------------------------------------*/
  105. SetBit(P1_AN, P14 | P15 | HBMOD);
  106. ClrBit(P1_OE, P13);
  107. /* -------------------------------------------------------------------------------------------------
  108. CMP0_MOD:
  109. 00: 无内置虚拟中心点电阻的BEMF模式
  110. 01: 内置虚拟中心点电阻的BEMF模式
  111. 10: 3差分比较器模式
  112. 11: 2比较器模式RSD
  113. -------------------------------------------------------------------------------------------------*/
  114. SetReg(CMP_CR2, CMP0MOD0 | CMP0MOD1, CMP0MOD0 | CMP0MOD1);
  115. /* -------------------------------------------------------------------------------------------------
  116. 比较器输出选择配置,与CMP0_MOD配合使用
  117. CMP0_SEL[1:0]=00,比较器0工作在2比较器轮询模式,正端在CMP0P、CMP1P2之间自动轮流选择,负端固定接CMP0M,
  118. 其输出结果分别送至CMP0_OUT、CMP1_OUT
  119. CMP0_SEL[1:0]=01,比较器0选择CMP0对应的端口组合,即正端接CMP0P,负端接CMP0M,输出接CMP0_OUT
  120. CMP0_SEL[1:0]=10,比较器0选择CMP1对应的端口组合,即正端接CMP1P2,负端接CMP0M,输出接CMP1_OUT
  121. -----------------------------------------------------------------------------*/
  122. SetReg(CMP_CR2, CMP0SEL0 | CMP0SEL1, 0x00);
  123. /* -------------------------------------------------------------------------------------------------
  124. 比较器迟滞电压选择
  125. 000: 无迟滞 001: ±2.5mV 010: -5mV 011: +5mV
  126. 100: +-5mV 101: -10mV 110: +10mV 111: +-10mV
  127. -------------------------------------------------------------------------------------------------*/
  128. //SetReg(CMP_CR1, CMP0HYS0 | CMP0HYS1 | CMP0HYS2, CMP0HYS0 | CMP0HYS1 | CMP0HYS2 );
  129. /* -------------------------------------------------------------------------------------------------
  130. CMP0的轮询时间设置
  131. -------------------------------------------------------------------------------------------------*/
  132. SetReg(CMP_CR1, CMP0CSEL0 | CMP0CSEL1, 0x00);
  133. EA = 0;
  134. /* ------------------------------------------------------
  135. 使能比较器CMP0,CMP1,CMP2和ADC在pwm on/off采样功能
  136. 00:在on和off均采样,没有延迟采样开启
  137. 01:只在off采样,根据CMP_SAMR延迟采样开启
  138. 10:只在on采样,根据CMP_SAMR延迟采样开启
  139. 11:在on和off均采样,根据CMP_SAMR延迟采样开启
  140. ---------------------------------------------------------**/
  141. // SetReg(CMP_CR3, SAMSEL0 | SAMSEL1, SAMSEL1);
  142. /* 采样延迟设置 */
  143. CMP_SAMR = 0x10;
  144. SetBit(CMP_CR2, CMP0EN); //使能比较器
  145. }
  146. /**
  147. @brief Rsd Timer2功能初始化
  148. @date 2022-07-13
  149. */
  150. static void Time2_RSD_Init(void)
  151. {
  152. /* -------------------------------------------------------------------------------------------------
  153. 先停止计数,配置完寄存器后,最后启动计数
  154. -------------------------------------------------------------------------------------------------*/
  155. ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
  156. /* -------------------------------------------------------------------------------------------------
  157. 时钟分频设置(T2PSC)
  158. 000:cpuclk(24MHz) 001:cpuclk/2^1(12MHz) 010:cpuclk/2^2(6MHz) 011:cpuclk/2^3(3MHz)
  159. 100:cpuclk/2^4(1.5MHz) 101:cpuclk/2^5(750KHz) 110:cpuclk/2^6(375KHz) 111:cpuclk/2^7(187.5KHz)
  160. -------------------------------------------------------------------------------------------------*/
  161. SetReg(TIM2_CR0, T2PSC0 | T2PSC1 | T2PSC2, T2PSC0 | T2PSC1 | T2PSC2);
  162. /* -------------------------------------------------------------------------------------------------
  163. /模式选择
  164. T2MODE1,T2MODE0
  165. 00--输入Timer模式;01--输出模式
  166. 10--输入Count模式;11--QEP或者RSD模式
  167. -------------------------------------------------------------------------------------------------*/
  168. SetReg(TIM2_CR0, T2MOD0 | T2MOD1, T2MOD0 | T2MOD1);
  169. ClrBit(TIM2_CR1, T2FE); // 滤波使能
  170. /* -------------------------------------------------------------------------------------------------
  171. 清除中断标志位
  172. 禁止PWM周期检测中断使能
  173. 使能计数器上溢中断使能
  174. -----------------------------------------------------------------------------------------------------*/
  175. ClrBit(TIM2_CR1, T2IR | T2IF | T2IP); // 清除中断标志位
  176. ClrBit(TIM2_CR0, T2CES | T2IRE); // 清零脉冲计数器不使能
  177. SetBit(TIM2_CR1, T2IPE | T2IFE); // 输入有效边沿变化中断使能和基本计数器上溢使能
  178. /* -------------------------------------------------------------------------------------------------
  179. 定时器2中断优先级配置及芯片中断总使能
  180. PTIM231-PTIM230,中断优先级控制值从0-3依次表示优先级从最低到最高,共4级优化级控制
  181. EA,芯片中断总使能
  182. -------------------------------------------------------------------------------------------------*/
  183. SetBit(IP1, PTIM21 ); // 输入有效边沿变化中断使能和基本计数器上溢使能
  184. SetBit(IP1, PTIM20 ); // 输入有效边沿变化中断使能和基本计数器上溢使能
  185. EA = 1;
  186. /* -------------------------------------------------------------------------------------------------
  187. 配置周期值、比较值、计数值
  188. -------------------------------------------------------------------------------------------------*/
  189. TIM2__CNTR = 0;
  190. /*-----------启动计数------------------------------------------------*/
  191. SetBit(TIM2_CR1, T2CEN); //启动计数
  192. }
  193. /**
  194. @brief RSD检测函数,使用Timer2 RSD功能,QEP接口相同,运行于Timer2 IP中断
  195. @date 2022-07-13
  196. */
  197. void RsdProcess(void)
  198. {
  199. uint16 temp_ARR = 0;
  200. int16 temp_speedCal = 0;
  201. mcRsd.CountPre = mcRsd.Count;
  202. mcRsd.Count = TIM2__CNTR;
  203. mcRsd.Status = CMP_SR & 0x03;
  204. if (mcRsd.CountPre < 0) // 上一个状态为正转
  205. {
  206. if (mcRsd.Count < mcRsd.CountPre) // 当前为继续正转
  207. {
  208. if (mcRsd.Count < -8)
  209. {
  210. /* 连续单方向转动,则取出周期时。 一个反电势周期是4个RSD跳变状态 */
  211. mcRsd.Period = (mcRsd.StepTime[0] >> 2) + (mcRsd.StepTime[1] >> 2) + (mcRsd.StepTime[2] >> 2) + (mcRsd.StepTime[3] >> 2);
  212. if (mcRsd.SetFR == CW)
  213. {
  214. mcRsd.State = FORWARD;
  215. }
  216. else
  217. {
  218. mcRsd.State = REVERSE;
  219. }
  220. }
  221. if (mcRsd.ArrCnt > 3)
  222. {
  223. mcRsd.ArrCnt = 0;
  224. }
  225. temp_ARR = TIM2__ARR;
  226. mcRsd.StepTime[mcRsd.ArrCnt++] = temp_ARR; // 取出每个单独RSD电平状态对应的周期计数值
  227. }
  228. else //正转过程中发生反转
  229. {
  230. TIM2__CNTR = 0;
  231. mcRsd.Count = 0;
  232. mcRsd.Period = 65535;
  233. mcRsd.State = DETECTING; // 检测中
  234. }
  235. }
  236. else if (mcRsd.CountPre > 0) // 上一个状态为反转
  237. {
  238. if (mcRsd.Count > mcRsd.CountPre) // 当前为继续反转
  239. {
  240. if (mcRsd.Count > 8)
  241. {
  242. /* 连续单方向转动,则取出周期时。 一个周期反电势是4个RSD跳变状态 */
  243. mcRsd.Period = (mcRsd.StepTime[0] >> 2) + (mcRsd.StepTime[1] >> 2) + (mcRsd.StepTime[2] >> 2) + (mcRsd.StepTime[3] >> 2);
  244. if (mcRsd.SetFR == CW)
  245. {
  246. mcRsd.State = REVERSE;
  247. }
  248. else
  249. {
  250. mcRsd.State = FORWARD;
  251. }
  252. }
  253. if (mcRsd.ArrCnt > 3)
  254. {
  255. mcRsd.ArrCnt = 0;
  256. }
  257. temp_ARR = TIM2__ARR;
  258. mcRsd.StepTime[mcRsd.ArrCnt++] = temp_ARR; // 取出每个单独RSD电平状态对应的周期计数值
  259. }
  260. else // 反转过程中发生正转
  261. {
  262. TIM2__CNTR = 0;
  263. mcRsd.Count = 0;
  264. mcRsd.Period = 65535;
  265. mcRsd.State = DETECTING; // 检测中
  266. }
  267. }
  268. else
  269. {
  270. mcRsd.State = DETECTING; // 检测中
  271. }
  272. mcRsd.Times++; // 多次中断次数
  273. if (mcRsd.SpeedUpdate == 0)
  274. {
  275. if (mcRsd.State == FORWARD || mcRsd.State == REVERSE )//处理速度
  276. {
  277. if (mcRsd.Period < RSDSpeedCalMaxSpeed)
  278. { mcRsd.Period = RSDSpeedCalMaxSpeed ; }// 防止mcRsd.Period 太小导致计算出错
  279. temp_speedCal = DivQ_L_MDU((mcRsd.RSDSpeedBase >> 16), mcRsd.RSDSpeedBase, mcRsd.Period);
  280. if (mcRsd.State == REVERSE)
  281. {
  282. mcRsd.Speed = -temp_speedCal;
  283. }
  284. else
  285. {
  286. mcRsd.Speed = temp_speedCal;
  287. }
  288. mcRsd.SpeedUpdate = 1;
  289. }
  290. }
  291. if (mcRsd.HighSpdStart == 1) // 高速顺风启动
  292. {
  293. if (mcRsd.Status == 0x03) // 03状态 对应90启动
  294. {
  295. ClrBit(CMP_CR2, CMP0EN); // 关闭比较器
  296. ClrBit(TIM2_CR1, T2CEN); // 0,停止计数;1,使能计数
  297. RSDFOCCloseLoopStart();
  298. mcRsd.HighSpdStart = 2; // 启动完成
  299. }
  300. }
  301. }
  302. /**
  303. @brief RSD顺风启动函数
  304. @date 2022-07-13
  305. */
  306. static void RSDFOCCloseLoopStart(void)
  307. {
  308. /* FOC初始化 */
  309. FOC_Init();
  310. /* 启动电流、KP、KI */
  311. FOC_IDREF = ID_RUN_CURRENT; // D轴启动电流
  312. FOC_IQREF = 0; // Q轴启动电流
  313. mcFocCtrl.IqRef = IQ_RUN_CURRENT; // Q轴启动电流
  314. FOC_QKP = _Q12(0.5);
  315. FOC_QKI = _Q15(0.005);
  316. FOC_DKP = _Q12(0.5);
  317. FOC_DKI = _Q15(0.005);
  318. FOC_EKP = OBSW_KP_GAIN_RUN4;
  319. FOC_EKI = OBSW_KI_GAIN_RUN4;
  320. FOC_EFREQACC = 100;
  321. FOC_EFREQMIN = 0;
  322. FOC_EFREQHOLD = MOTOR_OMEGA_RAMP_END;
  323. SetBit(FOC_CR1, ANGM); // 估算模式
  324. ClrBit(FOC_CR1, RFAE); // 禁止强拉
  325. ClrBit(FOC_CR1, EFAE); // 估算器强制输出
  326. // FOC__EOME = mcRsd.Speed;
  327. // FOC_EKLPFMIN = OBS_EA_KS_TAILWIND;
  328. if (mcRsd.Status == 3)
  329. {
  330. FOC__ETHETA = _Q15(90 / 180.0);
  331. FOC__THETA = _Q15(90 / 180.0);
  332. }
  333. #if (EstimateAlgorithm == SMO || EstimateAlgorithm == AO)
  334. FOC_EKP = OBSW_KP_GAIN_RUN4;
  335. FOC_EKI = OBSW_KI_GAIN_RUN4;
  336. #elif (EstimateAlgorithm == PLL)
  337. FOC_EKP = OBSW_KP_GAIN_RUN4;
  338. FOC_EKI = OBSW_KI_GAIN_RUN4;
  339. mcFocCtrl.mcIqref = IQ_RUN_CURRENT;
  340. #endif // end EstimateAlgorithm
  341. FOC_OMEKLPF = SPEED_KLPF;
  342. mcFocCtrl.State_Count = 50;
  343. mcFocCtrl.CtrlMode = 0;
  344. /* 使能输出 */
  345. DRV_CMR |= 0x3F; // U、V、W相输出
  346. MOE = 1;
  347. }
  348. #endif