RSDDetect.c 15 KB

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