/* * usr_gpio.c * * Created on: 2022年4月11日 * Author: amos */ #include "usr_motor.h" #define BOUNCE_THRESHOLD 2 // 800ms长按阈值 #define LONG_PRESS_THRESHOLD 80 // 800ms长按阈值 #define CONTINUOUS_INTERVAL 40 // 300ms内算连续按键 #define USER_STOP_TIMER 200 // 长按2s不放,停止混匀 #define FIND_OPTIC_SPEED 50 // 找光开速度 #define FIND_OPTIC_BACK_SPEED 43 // 过光开回退速度 #define FIND_OPTIC_BACK_GAP 2 // 过光开回退速度 #define MAX_RUNCNT 4 // 找光开速度 typedef enum swing_state { SWING_IDLE, SWING_START, SWING_LOOP, SWING_END, LOOP_START, LOOP_END, EMERGENCY_END, FIND_GAPNUM, FIND_HOMEGAP, SWING_ERR, } swing_state_def; typedef enum { KEY_IDLE, // 空闲状态 KEY_SHORT, // 短按 KEY_CONTINUE, // 连续按 KEY_LONG, // 空闲状态,长按抬起,复位设备 KEY_END //混匀状态,长按不释放,停止混匀 } KeyState; volatile struct { KeyState state; uint32_t press_tick; // 按下时刻(10ms单位) uint32_t release_tick; // 当前释放时刻 uint32_t last_release_tick; // 新增:上一次释放时刻 uint32_t click_count; // 连续按键计数 uint32_t last_level; uint32_t key_valid_flag; // 连续按键标志 } key_ctrl; swing_state_def sw_st, last_st; unsigned int keyState = 0; unsigned int MotorOptState = 0; extern uint32_t conter100ms; uint32_t conter10ms; int32_t runLoopTime = 600; int32_t runLoopSpeed = 80; uint32_t curtimeinner; uint32_t timeinner = 6000; uint32_t swingtime = 100; uint32_t swingtimeRight = 40; uint32_t swingtimePause = 100; int32_t backOptFlag = 0; int32_t startLoopConter = 0; int32_t swingspeed = 60; int32_t stateFistin; int32_t REVORFWD; //extern uint8_t error_set(uint8_t error); uint32_t timerBuf[16]; uint32_t timerconter; uint32_t intoGap; uint32_t OutGap; uint32_t lastGap; uint32_t judgeGap; uint32_t curGap; uint32_t checkPWM; MOTOR_DIR findhomedir; uint32_t intoGapFlag; uint32_t resetFromSwingFlag; uint32_t swingLoopHigtTime = 0; uint32_t swingHigStopflage = 0; uint32_t swingStoptime = 0; uint32_t startFindHometime = 0; uint32_t findHome = 0; extern void DelayMS(uint32_t ms); //冒泡法排序,排序结果有小到大 void Bubble_Sort(unsigned int *Array,unsigned int n) { unsigned char i, j; unsigned int temp; for(i=0;i Array[j]) { temp = Array[i]; Array[i] = Array[j]; Array[j] = temp; } } } } uint32_t Read_Motor(void) { return (HAL_GPIO_ReadPin(MINI7_V2_REF_SW2_GPIO_Port,MINI7_V2_REF_SW2_Pin)) ? 1 : 0; // 检查PF5引脚值 } uint32_t Read_key(void) { return (HAL_GPIO_ReadPin(MINI7_V2_KEY_GPIO_Port,MINI7_V2_KEY_Pin)) ? 1 : 0; // 检查PF5引脚值 } uint32_t TIMER_GetCounter(void) { return htim3.Instance->CNT; } /** * @brief SetMotorPwm * * @param value between 0-100 * * @return None * * @details */ void SetMotorPwm(int dir, int32_t value) { /* Start PWM counter */ unsigned int DutyCycle; if (value > 100) { value = 100; } else if (value < 0) { value = 0; DutyCycle = 0; } DutyCycle = value*10; if (dir) { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, DutyCycle); } else { __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, DutyCycle); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_3, 0); } } /** * @brief GPIO PA/PB/PG/PH IRQ * * @param None * * @return None * * @details The PA/PB/PG/PH default IRQ, declared in startup_M031Series.s. */ void KYE_IRQHandler(void) { volatile uint32_t temp; conter10ms = sysinf.conter10ms; /* To check if PB.2 interrupt occurred */ { uint8_t curr_level = Read_key(); if (curr_level != key_ctrl.last_level) { key_ctrl.last_level = curr_level; if (curr_level == 0) { // 下降沿(按下) key_ctrl.press_tick = conter10ms; if (key_ctrl.state == KEY_SHORT) { key_ctrl.last_release_tick = key_ctrl.release_tick; // 更新上次释放时间 } else { key_ctrl.last_release_tick = 0; } } else { // 上升沿(释放) key_ctrl.release_tick = conter10ms; uint32_t press_duration = 0; if(key_ctrl.press_tick){ press_duration = key_ctrl.release_tick - key_ctrl.press_tick; } key_ctrl.press_tick = 0; // 长按判定 if (press_duration <= BOUNCE_THRESHOLD) { key_ctrl.state = KEY_IDLE; key_ctrl.last_release_tick = 0; } else if (press_duration >= LONG_PRESS_THRESHOLD) { key_ctrl.state = KEY_LONG; key_ctrl.last_release_tick = 0; // 更新上次释放时间 key_ctrl.key_valid_flag = 1; } // 短按判定 else { key_ctrl.click_count = 1; key_ctrl.state = KEY_SHORT; if ((key_ctrl.release_tick - key_ctrl.last_release_tick) <= CONTINUOUS_INTERVAL) { key_ctrl.key_valid_flag = 1; key_ctrl.click_count++; key_ctrl.state = KEY_CONTINUE; } } } } } } void check_keyShortValid(void) { volatile uint32_t temp; /* To check if PB.2 interrupt occurred */ if (key_ctrl.state == KEY_SHORT) { if ((conter10ms - key_ctrl.release_tick) > CONTINUOUS_INTERVAL * 2) { key_ctrl.key_valid_flag = 1; } } if (sw_st != SWING_IDLE && key_ctrl.press_tick) { if ((conter10ms - key_ctrl.press_tick) > USER_STOP_TIMER) { key_ctrl.state = KEY_END; key_ctrl.key_valid_flag = 1; key_ctrl.press_tick = 0; } } } /** * @brief GPIO PC/PD/PE/PF IRQ * * @param None * * @return None * * @details The PC/PD/PE/PF default IRQ, declared in startup_M031Series.s. */ void OPTO_IRQHandler(void) { // // volatile unsigned int temp; /* To check if PB.2 interrupt occurred */ { conter10ms = sysinf.conter10ms; switch(sw_st){ case FIND_GAPNUM:{ if (Read_Motor()){ intoGap = TIMER_GetCounter(); }else{ OutGap = TIMER_GetCounter(); if((conter10ms - startFindHometime) > MOTOR_LOOP_TIM){ if(MAX_RUNCNT > timerconter){ if(OutGap > intoGap){ timerBuf[timerconter++] = OutGap - intoGap; }else{ timerBuf[timerconter++] = OutGap + 0x10000 - intoGap; } if(MAX_RUNCNT == timerconter){ Bubble_Sort(timerBuf,MAX_RUNCNT); judgeGap = 0; if(timerBuf[0]*1.25 intoGap){ curGap = OutGap - intoGap; }else{ curGap = OutGap + 0x10000 - intoGap; } timerBuf[timerconter++] = curGap ; if(curGap > judgeGap){ sw_st = FIND_HOMEGAP; SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); stateFistin = 1; checkPWM = checkPWM*0.8; /*降速便于复位*/ findhomedir = (MOTOR_DIR)!findhomedir; } if(timerconter==sizeof(timerBuf)){ SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); timerconter = 0; } } } } } break; case FIND_HOMEGAP:{ /*找远点阶段,光开亮停止*/ if (Read_Motor()){ SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); intoGapFlag = 1; intoGap = TIMER_GetCounter(); } } break; case SWING_LOOP:{ /*找远点阶段,光开亮停止*/ if(startLoopConter > 0){ startLoopConter --; }else{ if (Read_Motor()){ SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); intoGapFlag = 1; intoGap = TIMER_GetCounter(); } } }break; default:{ SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); // sw_st = FIND_GAPNUM; // stateFistin = 1; }break; } } } /** * @brief Motor_Init * * @param init key and optic input * * @return None * * @details */ void Motor_Init() { key_ctrl.last_level = 1; timeinner = sysinf.timeinner; swingspeed = sysinf.swingspeed; swingtime =sysinf.swingtime; swingtimeRight =sysinf.swingtimeRight; swingtimePause =sysinf.swingtimePause; runLoopTime = sysinf.runLoopTime; runLoopSpeed =sysinf.runLoopSpeed; } /** * @brief Motor_mix * * @param init key and optic input * * @return 0正常,1没离开光开,2,没回到光开 * * @details 设置夹爪转动参数。 */ uint32_t Motor_mix(uint32_t time, uint32_t speed, uint32_t swing, uint32_t timeRight, uint32_t timePause) { timeinner = time; swingtime = swing; swingspeed = speed; swingtimeRight = timeRight; swingtimePause = timePause; // timeinner = time - time % (swing + timeRight); // curtimeinner = timeinner; if (speed == 0) { return 0; } curtimeinner = conter10ms; sw_st = SWING_LOOP; startLoopConter = 2; stateFistin = 1; backOptFlag = 1; findhomedir = MOTOR_REV; return 0; } /** * @brief Motor_deal_key * * @param 按键处理,短按,左右摇;连续点击,转圈摇;长按,复位; * * @return 0正常,1没离开光开,2,没回到光开 * * @details 夹爪根据。 */ uint32_t Motor_deal_key(swing_state_def st, KeyState key) { if (st == SWING_IDLE) { switch (key) { case KEY_SHORT: curtimeinner = conter10ms; sw_st = SWING_LOOP; startLoopConter = 2; stateFistin = 1; backOptFlag = 1; findhomedir = MOTOR_REV; break; // case KEY_CONTINUE: // curtimeinner = conter10ms; // sw_st = LOOP_START; // stateFistin = 1; // break; case KEY_LONG: curtimeinner = conter10ms; sw_st = FIND_GAPNUM; stateFistin = 1; break; default: break; } } if (key == KEY_LONG || key == KEY_END ) { sw_st = FIND_GAPNUM; stateFistin = 1; resetFromSwingFlag = 0; } return 0; } void Motor_reset(void) { curtimeinner = conter10ms; sw_st = FIND_GAPNUM; stateFistin = 1; resetFromSwingFlag = 0; } /** * @brief Motor_mix_work * * @param init key and optic input * * @return 0正常,1没离开光开,2,没回到光开 * * @details 夹爪根据。 */ uint32_t Motor_mix_work(void) { static uint32_t last10ms; static uint32_t firstINGap; static uint32_t powerOnFlag = 1; check_keyShortValid(); if(powerOnFlag){ powerOnFlag = 0; // Motor_Check(0); resetFromSwingFlag = 0; sw_st = FIND_GAPNUM; stateFistin = 1; } conter10ms = sysinf.conter10ms; if (key_ctrl.key_valid_flag) { key_ctrl.key_valid_flag = 0; Motor_deal_key(sw_st, key_ctrl.state); key_ctrl.state = KEY_IDLE; } if(sw_st == SWING_ERR){ /*电机故障,不执行操作*/ return 0; } switch (sw_st) { case SWING_IDLE: { SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); } break; case FIND_GAPNUM: { if (stateFistin) { timerconter = 0; intoGap = 0; OutGap = 0; lastGap = 0; judgeGap = 0; HAL_TIM_Base_Stop(&htim4); HAL_TIM_Base_Start(&htim4); last10ms = conter10ms; stateFistin = 0; startFindHometime = conter10ms; findhomedir = MOTOR_REV; checkPWM = swingspeed; SetMotorPwm(findhomedir, checkPWM); } else { if (((conter10ms - last10ms) > MOTOR_LOOP_TIM*4 )&&(timerconter < MAX_RUNCNT)) { /*电机不动,返回报错*/ SetMotorPwm(MOTOR_REV, 0); sw_st = SWING_ERR; error_set(ERROR_MOTOR_FIALED); return 1; } } } break; case FIND_HOMEGAP: { if (stateFistin) { last10ms = conter10ms; stateFistin = 0; intoGapFlag = 0; firstINGap = 0; SetMotorPwm(findhomedir, checkPWM); } else { if (!intoGapFlag && (conter10ms - last10ms) > MOTOR_LOOP_TIM) { /*电机来回不动,返回报错*/ stateFistin = 1; checkPWM = checkPWM/0.85; /*降速便于复位*/ } if(intoGapFlag){ if(!firstINGap){ /*进入缝隙,置位,延时判读*/ firstINGap = 1; last10ms = conter10ms; }else{ if((conter10ms - last10ms) > MOTOR_MOVEFORM_OPTIC_TIM){ if(Read_Motor()){ sw_st = SWING_IDLE; stateFistin = 1; findHome = 1; } else{ sw_st = FIND_HOMEGAP; stateFistin = 1; findhomedir = (MOTOR_DIR)!findhomedir; checkPWM = checkPWM*0.9; /*降速便于复位*/ } } } } } } break; case LOOP_START: { if (stateFistin) { SetMotorPwm(MOTOR_REV, runLoopSpeed); last10ms = conter10ms; stateFistin = 0; } else { if ((conter10ms - last10ms) == (runLoopTime)) { SetMotorPwm(MOTOR_REV, 0); SetMotorPwm(MOTOR_FWD, 0); } if ((conter10ms - last10ms) >= (runLoopTime + swingtimePause)) { sw_st = LOOP_END; stateFistin = 1; REVORFWD = 0; } } } break; case LOOP_END: { sw_st = FIND_GAPNUM; stateFistin = 1; REVORFWD = 1; } break; case SWING_LOOP: { if (stateFistin ) { /**/ if(backOptFlag){ if(swingtime< (conter10ms - swingStoptime)){ checkPWM = swingspeed; backOptFlag = 0; SetMotorPwm(findhomedir, checkPWM); stateFistin = 0; last10ms = conter10ms; swingHigStopflage = 0; } }else{ SetMotorPwm(findhomedir, checkPWM); stateFistin = 0; last10ms = conter10ms; swingHigStopflage = 0; } intoGapFlag = 0; firstINGap = 0; } else{ if (!intoGapFlag && (conter10ms - last10ms) > MOTOR_LOOP_TIM) { /*速度过底,电机回不来*/ backOptFlag = 1; swingStoptime = conter10ms; findhomedir = MOTOR_REV; stateFistin = 1; } if(intoGapFlag){ if(!firstINGap){ /*进入缝隙,置位,延时判读*/ firstINGap = 1; last10ms = conter10ms; }else{ if((conter10ms - last10ms) > MOTOR_MOVEFORM_OPTIC_TIM){ stateFistin = 1; if(Read_Motor()){ backOptFlag = 1; swingStoptime = conter10ms; findhomedir = MOTOR_REV; } else{ findhomedir = (MOTOR_DIR)!findhomedir; checkPWM = checkPWM*0.9; /*降速便于复位*/ } } } } if ((conter10ms - curtimeinner) > (timeinner)){ resetFromSwingFlag = 0; __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); __HAL_TIM_SET_COMPARE(&htim3, TIM_CHANNEL_2, 0); timerconter = 0; memset(timerBuf,0,sizeof(timerBuf)); stateFistin = 1; sw_st = FIND_GAPNUM; } } } break; default: sw_st = SWING_ERR; break; } return 0; } /** * @brief Motor_mix * * @param init key and optic input * * @return 空闲返回1 其他返回0 * * @details 设置夹爪转动参数。 */ uint32_t Motor_idle() { return(sw_st == SWING_IDLE); } uint32_t print_home_time() { if(findHome){ findHome = 0; Van_Device_Printf(VAN_LOG_NOTICE,"gap:%d ",timerconter); if(timerconter > sizeof(timerBuf)){ timerconter = sizeof(timerBuf); } for(unsigned int i=0;i