usr_motor.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678
  1. /*
  2. * usr_gpio.c
  3. *
  4. * Created on: 2022年4月11日
  5. * Author: amos
  6. */
  7. #include "usr_motor.h"
  8. #define BOUNCE_THRESHOLD 2 // 800ms长按阈值
  9. #define LONG_PRESS_THRESHOLD 80 // 800ms长按阈值
  10. #define CONTINUOUS_INTERVAL 40 // 300ms内算连续按键
  11. #define USER_STOP_TIMER 200 // 长按2s不放,停止混匀
  12. #define FIND_OPTIC_SPEED 50 // 找光开速度
  13. #define FIND_OPTIC_BACK_SPEED 43 // 过光开回退速度
  14. #define FIND_OPTIC_BACK_GAP 2 // 过光开回退速度
  15. #define MAX_RUNCNT 4 // 找光开速度
  16. typedef enum swing_state {
  17. SWING_IDLE,
  18. SWING_START,
  19. SWING_LOOP,
  20. SWING_END,
  21. LOOP_START,
  22. LOOP_END,
  23. EMERGENCY_END,
  24. FIND_GAPNUM,
  25. FIND_HOMEGAP,
  26. SWING_ERR,
  27. } swing_state_def;
  28. typedef enum {
  29. KEY_IDLE, // 空闲状态
  30. KEY_SHORT, // 短按
  31. KEY_CONTINUE, // 连续按
  32. KEY_LONG, // 空闲状态,长按抬起,复位设备
  33. KEY_END //混匀状态,长按不释放,停止混匀
  34. } KeyState;
  35. volatile
  36. struct {
  37. KeyState state;
  38. uint32_t press_tick; // 按下时刻(10ms单位)
  39. uint32_t release_tick; // 当前释放时刻
  40. uint32_t last_release_tick; // 新增:上一次释放时刻
  41. uint32_t click_count; // 连续按键计数
  42. uint32_t last_level;
  43. uint32_t key_valid_flag; // 连续按键标志
  44. } key_ctrl;
  45. swing_state_def sw_st, last_st;
  46. unsigned int keyState = 0;
  47. unsigned int MotorOptState = 0;
  48. extern uint32_t conter100ms;
  49. uint32_t conter10ms;
  50. int32_t runLoopTime = 600;
  51. int32_t runLoopSpeed = 80;
  52. uint32_t curtimeinner;
  53. uint32_t timeinner = 6000;
  54. uint32_t swingtime = 100;
  55. uint32_t swingtimeRight = 40;
  56. uint32_t swingtimePause = 100;
  57. int32_t backOptFlag = 0;
  58. int32_t startLoopConter = 0;
  59. int32_t swingspeed = 60;
  60. int32_t stateFistin;
  61. int32_t REVORFWD;
  62. //extern uint8_t error_set(uint8_t error);
  63. uint32_t timerBuf[16];
  64. uint32_t timerconter;
  65. uint32_t intoGap;
  66. uint32_t OutGap;
  67. uint32_t lastGap;
  68. uint32_t judgeGap;
  69. uint32_t curGap;
  70. uint32_t checkPWM;
  71. MOTOR_DIR findhomedir;
  72. uint32_t intoGapFlag;
  73. uint32_t resetFromSwingFlag;
  74. uint32_t swingLoopHigtTime = 0;
  75. uint32_t swingHigStopflage = 0;
  76. uint32_t swingStoptime = 0;
  77. uint32_t startFindHometime = 0;
  78. uint32_t findHome = 0;
  79. extern void DelayMS(uint32_t ms);
  80. //冒泡法排序,排序结果有小到大
  81. void Bubble_Sort(unsigned int *Array,unsigned int n)
  82. {
  83. unsigned char i, j;
  84. unsigned int temp;
  85. for(i=0;i<n-1;i++)
  86. {
  87. for(j=i+1;j<n;j++)
  88. {
  89. if(Array[i] > Array[j])
  90. {
  91. temp = Array[i];
  92. Array[i] = Array[j];
  93. Array[j] = temp;
  94. }
  95. }
  96. }
  97. }
  98. uint32_t Read_Motor(void) {
  99. return (HAL_GPIO_ReadPin(MINI7_V2_REF_SW2_GPIO_Port,MINI7_V2_REF_SW2_Pin)) ? 1 : 0; // 检查PF5引脚值
  100. }
  101. uint32_t Read_key(void) {
  102. return (HAL_GPIO_ReadPin(MINI7_V2_KEY_GPIO_Port,MINI7_V2_KEY_Pin)) ? 1 : 0; // 检查PF5引脚值
  103. }
  104. uint32_t TIMER_GetCounter(void) {
  105. return htim3.Instance->CNT;
  106. }
  107. /**
  108. * @brief SetMotorPwm
  109. *
  110. * @param value between 0-100
  111. *
  112. * @return None
  113. *
  114. * @details
  115. */
  116. void SetMotorPwm(int dir, int32_t value) {
  117. /* Start PWM counter */
  118. unsigned int DutyCycle;
  119. if (value > 100) {
  120. value = 100;
  121. } else if (value < 0) {
  122. value = 0;
  123. DutyCycle = 0;
  124. }
  125. DutyCycle = value*10;
  126. if (dir) {
  127. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
  128. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, DutyCycle);
  129. } else {
  130. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, DutyCycle);
  131. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0);
  132. }
  133. }
  134. /**
  135. * @brief GPIO PA/PB/PG/PH IRQ
  136. *
  137. * @param None
  138. *
  139. * @return None
  140. *
  141. * @details The PA/PB/PG/PH default IRQ, declared in startup_M031Series.s.
  142. */
  143. void KYE_IRQHandler(void) {
  144. volatile uint32_t temp;
  145. conter10ms = sysinf.conter10ms;
  146. /* To check if PB.2 interrupt occurred */
  147. {
  148. uint8_t curr_level = Read_key();
  149. if (curr_level != key_ctrl.last_level) {
  150. key_ctrl.last_level = curr_level;
  151. if (curr_level == 0) { // 下降沿(按下)
  152. key_ctrl.press_tick = conter10ms;
  153. if (key_ctrl.state == KEY_SHORT) {
  154. key_ctrl.last_release_tick =
  155. key_ctrl.release_tick; // 更新上次释放时间
  156. } else {
  157. key_ctrl.last_release_tick = 0;
  158. }
  159. } else { // 上升沿(释放)
  160. key_ctrl.release_tick = conter10ms;
  161. uint32_t press_duration = 0;
  162. if(key_ctrl.press_tick){
  163. press_duration = key_ctrl.release_tick - key_ctrl.press_tick;
  164. }
  165. key_ctrl.press_tick = 0;
  166. // 长按判定
  167. if (press_duration <= BOUNCE_THRESHOLD) {
  168. key_ctrl.state = KEY_IDLE;
  169. key_ctrl.last_release_tick = 0;
  170. } else if (press_duration >= LONG_PRESS_THRESHOLD) {
  171. key_ctrl.state = KEY_LONG;
  172. key_ctrl.last_release_tick = 0; // 更新上次释放时间
  173. key_ctrl.key_valid_flag = 1;
  174. }
  175. // 短按判定
  176. else {
  177. key_ctrl.click_count = 1;
  178. key_ctrl.state = KEY_SHORT;
  179. if ((key_ctrl.release_tick - key_ctrl.last_release_tick) <=
  180. CONTINUOUS_INTERVAL) {
  181. key_ctrl.key_valid_flag = 1;
  182. key_ctrl.click_count++;
  183. key_ctrl.state = KEY_CONTINUE;
  184. }
  185. }
  186. }
  187. }
  188. }
  189. }
  190. void check_keyShortValid(void) {
  191. volatile uint32_t temp;
  192. /* To check if PB.2 interrupt occurred */
  193. if (key_ctrl.state == KEY_SHORT) {
  194. if ((conter10ms - key_ctrl.release_tick) > CONTINUOUS_INTERVAL * 2) {
  195. key_ctrl.key_valid_flag = 1;
  196. }
  197. }
  198. if (sw_st != SWING_IDLE && key_ctrl.press_tick) {
  199. if ((conter10ms - key_ctrl.press_tick) > USER_STOP_TIMER) {
  200. key_ctrl.state = KEY_END;
  201. key_ctrl.key_valid_flag = 1;
  202. key_ctrl.press_tick = 0;
  203. }
  204. }
  205. }
  206. /**
  207. * @brief GPIO PC/PD/PE/PF IRQ
  208. *
  209. * @param None
  210. *
  211. * @return None
  212. *
  213. * @details The PC/PD/PE/PF default IRQ, declared in startup_M031Series.s.
  214. */
  215. void OPTO_IRQHandler(void) {
  216. //
  217. // volatile unsigned int temp;
  218. /* To check if PB.2 interrupt occurred */
  219. {
  220. conter10ms = sysinf.conter10ms;
  221. switch(sw_st){
  222. case FIND_GAPNUM:{
  223. if (Read_Motor()){
  224. intoGap = TIMER_GetCounter();
  225. }else{
  226. OutGap = TIMER_GetCounter();
  227. if((conter10ms - startFindHometime) > MOTOR_LOOP_TIM){
  228. if(MAX_RUNCNT > timerconter){
  229. if(OutGap > intoGap){
  230. timerBuf[timerconter++] = OutGap - intoGap;
  231. }else{
  232. timerBuf[timerconter++] = OutGap + 0x10000 - intoGap;
  233. }
  234. if(MAX_RUNCNT == timerconter){
  235. Bubble_Sort(timerBuf,MAX_RUNCNT);
  236. judgeGap = 0;
  237. if(timerBuf[0]*1.25<timerBuf[1]){
  238. judgeGap = timerBuf[0]+timerBuf[0];
  239. }else{
  240. judgeGap = timerBuf[1]+timerBuf[0];
  241. }
  242. // for(unsigned int i =0;i<(MAX_RUNCNT/2);i++){
  243. // judgeGap += timerBuf[i];
  244. // }
  245. judgeGap =judgeGap*0.625;
  246. timerBuf[timerconter++] = judgeGap ;
  247. /*判决门限为最低两个值均值的1.5倍*/
  248. }
  249. }else{
  250. if(OutGap > intoGap){
  251. curGap = OutGap - intoGap;
  252. }else{
  253. curGap = OutGap + 0x10000 - intoGap;
  254. }
  255. timerBuf[timerconter++] = curGap ;
  256. if(curGap > judgeGap){
  257. sw_st = FIND_HOMEGAP;
  258. SetMotorPwm(MOTOR_REV, 0);
  259. SetMotorPwm(MOTOR_FWD, 0);
  260. stateFistin = 1;
  261. checkPWM = checkPWM*0.8; /*降速便于复位*/
  262. findhomedir = !findhomedir;
  263. }
  264. if(timerconter==sizeof(timerBuf)){
  265. SetMotorPwm(MOTOR_REV, 0);
  266. SetMotorPwm(MOTOR_FWD, 0);
  267. timerconter = 0;
  268. }
  269. }
  270. }
  271. }
  272. }
  273. break;
  274. case FIND_HOMEGAP:{
  275. /*找远点阶段,光开亮停止*/
  276. if (Read_Motor()){
  277. SetMotorPwm(MOTOR_REV, 0);
  278. SetMotorPwm(MOTOR_FWD, 0);
  279. intoGapFlag = 1;
  280. intoGap = TIMER_GetCounter();
  281. }
  282. }
  283. break;
  284. case SWING_LOOP:{
  285. /*找远点阶段,光开亮停止*/
  286. if(startLoopConter > 0){
  287. startLoopConter --;
  288. }else{
  289. if (Read_Motor()){
  290. SetMotorPwm(MOTOR_REV, 0);
  291. SetMotorPwm(MOTOR_FWD, 0);
  292. intoGapFlag = 1;
  293. intoGap = TIMER_GetCounter();
  294. }
  295. }
  296. }break;
  297. default:{
  298. SetMotorPwm(MOTOR_REV, 0);
  299. SetMotorPwm(MOTOR_FWD, 0);
  300. // sw_st = FIND_GAPNUM;
  301. // stateFistin = 1;
  302. }break;
  303. }
  304. }
  305. }
  306. /**
  307. * @brief Motor_Init
  308. *
  309. * @param init key and optic input
  310. *
  311. * @return None
  312. *
  313. * @details
  314. */
  315. void Motor_Init()
  316. { /* Configure PB.2 as Input mode and enable interrupt by
  317. rising edge trigger */
  318. // sw_st = SWING_END;
  319. key_ctrl.last_level = 1;
  320. /*
  321. timeinner = g_cfg.timeinner;
  322. swingspeed = g_cfg.swingspeed;
  323. swingtime =g_cfg.swingtime;
  324. swingtimeRight =g_cfg.swingtimeRight;
  325. swingtimePause =g_cfg.swingtimePause;
  326. runLoopTime = g_cfg.runLoopTime;
  327. runLoopSpeed =g_cfg.runLoopSpeed;
  328. */
  329. }
  330. /**
  331. * @brief Motor_mix
  332. *
  333. * @param init key and optic input
  334. *
  335. * @return 0正常,1没离开光开,2,没回到光开
  336. *
  337. * @details 设置夹爪转动参数。
  338. */
  339. uint32_t Motor_mix(uint32_t time, uint32_t speed, uint32_t swing,
  340. uint32_t timeRight, uint32_t timePause) {
  341. timeinner = time;
  342. swingtime = swing;
  343. swingspeed = speed;
  344. swingtimeRight = timeRight;
  345. swingtimePause = timePause;
  346. // timeinner = time - time % (swing + timeRight);
  347. // curtimeinner = timeinner;
  348. if (speed == 0) {
  349. swingspeed = MOTOR_CHECK_SPEED;
  350. }
  351. curtimeinner = sysinf.conter10ms;
  352. sw_st = SWING_LOOP;
  353. stateFistin = 1;
  354. return 0;
  355. }
  356. /**
  357. * @brief Motor_deal_key
  358. *
  359. * @param 按键处理,短按,左右摇;连续点击,转圈摇;长按,复位;
  360. *
  361. * @return 0正常,1没离开光开,2,没回到光开
  362. *
  363. * @details 夹爪根据。
  364. */
  365. uint32_t Motor_deal_key(swing_state_def st, KeyState key) {
  366. if (st == SWING_IDLE) {
  367. switch (key) {
  368. case KEY_SHORT:
  369. curtimeinner = conter10ms;
  370. sw_st = SWING_LOOP;
  371. startLoopConter = 2;
  372. stateFistin = 1;
  373. backOptFlag = 1;
  374. findhomedir = MOTOR_REV;
  375. break;
  376. // case KEY_CONTINUE:
  377. // curtimeinner = conter10ms;
  378. // sw_st = LOOP_START;
  379. // stateFistin = 1;
  380. // break;
  381. case KEY_LONG:
  382. curtimeinner = conter10ms;
  383. sw_st = FIND_GAPNUM;
  384. stateFistin = 1;
  385. break;
  386. default:
  387. break;
  388. }
  389. }
  390. if (key == KEY_LONG || key == KEY_END ) {
  391. sw_st = FIND_GAPNUM;
  392. stateFistin = 1;
  393. resetFromSwingFlag = 0;
  394. }
  395. return 0;
  396. }
  397. /**
  398. * @brief Motor_mix_work
  399. *
  400. * @param init key and optic input
  401. *
  402. * @return 0正常,1没离开光开,2,没回到光开
  403. *
  404. * @details 夹爪根据。
  405. */
  406. uint32_t Motor_mix_work(void) {
  407. static uint32_t last10ms;
  408. static uint32_t firstINGap;
  409. static uint32_t powerOnFlag = 1;
  410. check_keyShortValid();
  411. if(powerOnFlag){
  412. powerOnFlag = 0;
  413. // Motor_Check(0);
  414. resetFromSwingFlag = 0;
  415. sw_st = FIND_GAPNUM;
  416. stateFistin = 1;
  417. }
  418. conter10ms = sysinf.conter10ms;
  419. if (key_ctrl.key_valid_flag) {
  420. key_ctrl.key_valid_flag = 0;
  421. Motor_deal_key(sw_st, key_ctrl.state);
  422. key_ctrl.state = KEY_IDLE;
  423. }
  424. if(sw_st == SWING_ERR){
  425. /*电机故障,不执行操作*/
  426. return 0;
  427. }
  428. switch (sw_st) {
  429. case SWING_IDLE: {
  430. SetMotorPwm(MOTOR_REV, 0);
  431. SetMotorPwm(MOTOR_FWD, 0);
  432. } break;
  433. case FIND_GAPNUM: {
  434. if (stateFistin) {
  435. timerconter = 0;
  436. intoGap = 0;
  437. OutGap = 0;
  438. lastGap = 0;
  439. judgeGap = 0;
  440. HAL_TIM_Base_Stop(&htim4);
  441. HAL_TIM_Base_Start(&htim4);
  442. last10ms = conter10ms;
  443. stateFistin = 0;
  444. startFindHometime = conter10ms;
  445. findhomedir = MOTOR_REV;
  446. checkPWM = swingspeed;
  447. SetMotorPwm(findhomedir, checkPWM);
  448. } else {
  449. if (((conter10ms - last10ms) > MOTOR_LOOP_TIM*4 )&&(timerconter < MAX_RUNCNT)) {
  450. /*电机不动,返回报错*/
  451. SetMotorPwm(MOTOR_REV, 0);
  452. sw_st = SWING_ERR;
  453. // error_set(ERROR_MOTOR_FIALED);
  454. return 1;
  455. }
  456. }
  457. } break;
  458. case FIND_HOMEGAP: {
  459. if (stateFistin) {
  460. last10ms = conter10ms;
  461. stateFistin = 0;
  462. intoGapFlag = 0;
  463. firstINGap = 0;
  464. SetMotorPwm(findhomedir, checkPWM);
  465. } else {
  466. if (!intoGapFlag && (conter10ms - last10ms) > MOTOR_LOOP_TIM) {
  467. /*电机来回不动,返回报错*/
  468. stateFistin = 1;
  469. checkPWM = checkPWM/0.85; /*降速便于复位*/
  470. }
  471. if(intoGapFlag){
  472. if(!firstINGap){
  473. /*进入缝隙,置位,延时判读*/
  474. firstINGap = 1;
  475. last10ms = conter10ms;
  476. }else{
  477. if((conter10ms - last10ms) > MOTOR_MOVEFORM_OPTIC_TIM){
  478. if(Read_Motor()){
  479. sw_st = SWING_IDLE;
  480. stateFistin = 1;
  481. findHome = 1;
  482. }
  483. else{
  484. sw_st = FIND_HOMEGAP;
  485. stateFistin = 1;
  486. findhomedir = !findhomedir;
  487. checkPWM = checkPWM*0.9; /*降速便于复位*/
  488. }
  489. }
  490. }
  491. }
  492. }
  493. } break;
  494. case LOOP_START: {
  495. if (stateFistin) {
  496. SetMotorPwm(MOTOR_REV, runLoopSpeed);
  497. last10ms = conter10ms;
  498. stateFistin = 0;
  499. } else {
  500. if ((conter10ms - last10ms) == (runLoopTime)) {
  501. SetMotorPwm(MOTOR_REV, 0);
  502. SetMotorPwm(MOTOR_FWD, 0);
  503. }
  504. if ((conter10ms - last10ms) >= (runLoopTime + swingtimePause)) {
  505. sw_st = LOOP_END;
  506. stateFistin = 1;
  507. REVORFWD = 0;
  508. }
  509. }
  510. } break;
  511. case LOOP_END: {
  512. sw_st = FIND_GAPNUM;
  513. stateFistin = 1;
  514. REVORFWD = 1;
  515. } break;
  516. case SWING_LOOP: {
  517. if (stateFistin ) {
  518. /**/
  519. if(backOptFlag){
  520. if(swingtime< (conter10ms - swingStoptime)){
  521. checkPWM = swingspeed;
  522. backOptFlag = 0;
  523. SetMotorPwm(findhomedir, checkPWM);
  524. stateFistin = 0;
  525. last10ms = conter10ms;
  526. swingHigStopflage = 0;
  527. }
  528. }else{
  529. SetMotorPwm(findhomedir, checkPWM);
  530. stateFistin = 0;
  531. last10ms = conter10ms;
  532. swingHigStopflage = 0;
  533. }
  534. intoGapFlag = 0;
  535. firstINGap = 0;
  536. } else{
  537. if (!intoGapFlag && (conter10ms - last10ms) > MOTOR_LOOP_TIM) {
  538. /*速度过底,电机回不来*/
  539. backOptFlag = 1;
  540. swingStoptime = conter10ms;
  541. findhomedir = MOTOR_REV;
  542. stateFistin = 1;
  543. }
  544. if(intoGapFlag){
  545. if(!firstINGap){
  546. /*进入缝隙,置位,延时判读*/
  547. firstINGap = 1;
  548. last10ms = conter10ms;
  549. }else{
  550. if((conter10ms - last10ms) > MOTOR_MOVEFORM_OPTIC_TIM){
  551. stateFistin = 1;
  552. if(Read_Motor()){
  553. backOptFlag = 1;
  554. swingStoptime = conter10ms;
  555. findhomedir = MOTOR_REV;
  556. }
  557. else{
  558. findhomedir = !findhomedir;
  559. checkPWM = checkPWM*0.9; /*降速便于复位*/
  560. }
  561. }
  562. }
  563. }
  564. if ((conter10ms - curtimeinner) > (timeinner)){
  565. resetFromSwingFlag = 0;
  566. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
  567. __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0);
  568. timerconter = 0;
  569. memset(timerBuf,0,sizeof(timerBuf));
  570. stateFistin = 1;
  571. sw_st = FIND_GAPNUM;
  572. }
  573. }
  574. } break;
  575. default:
  576. sw_st = SWING_ERR;
  577. break;
  578. }
  579. return 0;
  580. }
  581. /**
  582. * @brief Motor_mix
  583. *
  584. * @param init key and optic input
  585. *
  586. * @return 空闲返回1 其他返回0
  587. *
  588. * @details 设置夹爪转动参数。
  589. */
  590. uint32_t Motor_idle() {
  591. return(sw_st == SWING_IDLE);
  592. }
  593. uint32_t print_home_time() {
  594. if(findHome){
  595. findHome = 0;
  596. Van_Device_Printf(VAN_LOG_NOTICE,"gap:%d ",timerconter);
  597. if(timerconter > sizeof(timerBuf)){
  598. timerconter = sizeof(timerBuf);
  599. }
  600. for(unsigned int i=0;i<timerconter;i++){
  601. Van_Device_Printf(VAN_LOG_NOTICE," %d ",timerBuf[i]);
  602. }
  603. Van_Device_Printf(VAN_LOG_NOTICE,"\n");
  604. }
  605. return 0;
  606. }