RSDDetect.c 15 KB

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