237 lines
6.3 KiB
C
237 lines
6.3 KiB
C
#include "app_key.h"
|
||
#include <stddef.h>
|
||
|
||
/* 按键行为说明:
|
||
* K1 单击 -> 回零(朝光电开关方向,低速)
|
||
* K2 长按/松开 -> JOG+ 启动 / 减速停止
|
||
* K3 长按/松开 -> JOG- 启动 / 减速停止
|
||
* K4 单击 -> 速度档位循环
|
||
* K5 单击 -> 立即停止
|
||
*/
|
||
#define SPEED_LEVEL_COUNT (3u)
|
||
#define JOG_SPEED_LOW_MM_S (5.0f)
|
||
#define JOG_SPEED_MID_MM_S (25.0f)
|
||
#define JOG_SPEED_HIGH_MM_S (60.0f)
|
||
#define HOME_SPEED_MM_S (5.0f)
|
||
#define HOME_TRAVEL_MM (500.0f)
|
||
|
||
static const float s_speed_levels[SPEED_LEVEL_COUNT] = {
|
||
JOG_SPEED_LOW_MM_S,
|
||
JOG_SPEED_MID_MM_S,
|
||
JOG_SPEED_HIGH_MM_S,
|
||
};
|
||
|
||
static uint8_t s_speed_idx = 0u;
|
||
static uint8_t s_jog_key = KEY_NONE;
|
||
static uint8_t s_home_active = 0u;
|
||
|
||
/* 光电零位开关:低电平有效。 */
|
||
static uint8_t key_home_switch_active(void)
|
||
{
|
||
return (HAL_GPIO_ReadPin(X_ZERO_GPIO_Port, X_ZERO_Pin) == GPIO_PIN_RESET) ? 1u : 0u;
|
||
}
|
||
|
||
/* 根据方向和已走步数估算当前位置(mm)。 */
|
||
static float key_estimate_pos_mm(const Stepper_t *stepper)
|
||
{
|
||
float moved_mm = (float)stepper->step_count / STEPS_PER_MM;
|
||
if (stepper->dir == GPIO_PIN_RESET)
|
||
{
|
||
return last_move_start_pos_mm + moved_mm;
|
||
}
|
||
return last_move_start_pos_mm - moved_mm;
|
||
}
|
||
|
||
static void local_motion_start(Stepper_t *stepper, GPIO_PinState dir, float speed_mm_s, float travel_mm)
|
||
{
|
||
if (stepper == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (speed_mm_s < 0.1f)
|
||
{
|
||
speed_mm_s = 0.1f;
|
||
}
|
||
|
||
if (stepper->state != STOP)
|
||
{
|
||
Int_TMC2209_stop();
|
||
stepper->state = STOP;
|
||
}
|
||
|
||
stepper->dir = dir;
|
||
stepper->distance = travel_mm;
|
||
stepper->speed = (uint16_t)speed_mm_s;
|
||
stepper->acc = 50;
|
||
stepper->dec = 50;
|
||
stepper->start_speed = 1.0f;
|
||
stepper->run_flag = 1u;
|
||
last_move_start_pos_mm = current_absolute_pos_mm;
|
||
|
||
Int_TMC2209_start(stepper, &encoder_1);
|
||
}
|
||
|
||
/* 将当前运动切换为减速停止。 */
|
||
static void local_motion_stop_decel(Stepper_t *stepper)
|
||
{
|
||
if (stepper == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
if (stepper->state == STOP)
|
||
{
|
||
stepper->run_flag = 0u;
|
||
return;
|
||
}
|
||
|
||
stepper->total_step = stepper->step_count + stepper->acc_step;
|
||
if (stepper->state == ACCELERATE || stepper->state == CONSTANT)
|
||
{
|
||
stepper->state = DECELERATE;
|
||
}
|
||
stepper->run_flag = 0u;
|
||
}
|
||
|
||
/* 立即停止通道:用于 STOP 按键和 HOME 完成后的收尾。 */
|
||
static void local_motion_estop(Stepper_t *stepper)
|
||
{
|
||
if (stepper == NULL)
|
||
{
|
||
return;
|
||
}
|
||
|
||
Int_TMC2209_stop();
|
||
stepper->state = STOP;
|
||
stepper->run_flag = 0u;
|
||
s_jog_key = KEY_NONE;
|
||
s_home_active = 0u;
|
||
}
|
||
|
||
/* 运行时守卫:运动中执行限位判断与 HOME 触发判断。 */
|
||
static void key_guard_check(Stepper_t *stepper)
|
||
{
|
||
float est_pos_mm = 0.0f;
|
||
uint8_t xzero_active = 0u;
|
||
|
||
if (stepper == NULL || stepper->state == STOP)
|
||
{
|
||
return;
|
||
}
|
||
|
||
est_pos_mm = key_estimate_pos_mm(stepper);
|
||
current_absolute_pos_mm = est_pos_mm;
|
||
xzero_active = key_home_switch_active();
|
||
if (xzero_active == 1u)
|
||
{
|
||
/* 引脚有效即锁存命中,避免短脉冲漏检。 */
|
||
stepper->x_zero = 1u;
|
||
}
|
||
|
||
if (s_home_active)
|
||
{
|
||
if (stepper->x_zero == 1u)
|
||
{
|
||
local_motion_estop(stepper);
|
||
stepper->x_zero = 0u;
|
||
debug_printf("[KEY] HOME done");
|
||
}
|
||
return;
|
||
}
|
||
|
||
if ((s_jog_key == KEY_2) && (est_pos_mm >= SOFT_LIMIT_MAX_MM))
|
||
{
|
||
local_motion_stop_decel(stepper);
|
||
current_absolute_pos_mm = SOFT_LIMIT_MAX_MM;
|
||
debug_printf("[KEY] JOG+ reach soft limit %.1f mm", SOFT_LIMIT_MAX_MM);
|
||
}
|
||
else if ((s_jog_key == KEY_3) &&
|
||
(stepper->x_zero == 1u))
|
||
{
|
||
local_motion_stop_decel(stepper);
|
||
stepper->x_zero = 0u;
|
||
debug_printf("[KEY] JOG- reach home boundary");
|
||
}
|
||
}
|
||
|
||
void App_key_run(Stepper_t *stepper)
|
||
{
|
||
Int_Key_Task();
|
||
key_guard_check(stepper);
|
||
|
||
KeyAction_t action;
|
||
while (Int_Key_PopAction(&action))
|
||
{
|
||
switch (action.key)
|
||
{
|
||
case KEY_1:
|
||
if (action.evt == KEY_EVT_CLICK)
|
||
{
|
||
s_jog_key = KEY_NONE;
|
||
s_home_active = 1u;
|
||
stepper->x_zero = 0u;
|
||
local_motion_start(stepper, GPIO_PIN_SET, HOME_SPEED_MM_S, HOME_TRAVEL_MM);
|
||
debug_printf("[KEY] HOME start @ %.1f mm/s", HOME_SPEED_MM_S);
|
||
}
|
||
break;
|
||
|
||
case KEY_2:
|
||
if (action.evt == KEY_EVT_LONG_START)
|
||
{
|
||
s_home_active = 0u;
|
||
s_jog_key = KEY_2;
|
||
local_motion_start(stepper, GPIO_PIN_RESET, s_speed_levels[s_speed_idx], HOME_TRAVEL_MM);
|
||
debug_printf("[KEY] JOG+ start @ %.1f mm/s", s_speed_levels[s_speed_idx]);
|
||
}
|
||
else if (action.evt == KEY_EVT_RELEASE && s_jog_key == KEY_2)
|
||
{
|
||
local_motion_stop_decel(stepper);
|
||
s_jog_key = KEY_NONE;
|
||
debug_printf("[KEY] JOG+ release -> decel stop");
|
||
}
|
||
break;
|
||
|
||
case KEY_3:
|
||
if (action.evt == KEY_EVT_LONG_START)
|
||
{
|
||
s_home_active = 0u;
|
||
s_jog_key = KEY_3;
|
||
stepper->x_zero = 0u;
|
||
local_motion_start(stepper, GPIO_PIN_SET, s_speed_levels[s_speed_idx], HOME_TRAVEL_MM);
|
||
debug_printf("[KEY] JOG- start @ %.1f mm/s", s_speed_levels[s_speed_idx]);
|
||
}
|
||
else if (action.evt == KEY_EVT_RELEASE && s_jog_key == KEY_3)
|
||
{
|
||
local_motion_stop_decel(stepper);
|
||
s_jog_key = KEY_NONE;
|
||
debug_printf("[KEY] JOG- release -> decel stop");
|
||
}
|
||
break;
|
||
|
||
case KEY_4:
|
||
if (action.evt == KEY_EVT_CLICK)
|
||
{
|
||
s_speed_idx++;
|
||
if (s_speed_idx >= SPEED_LEVEL_COUNT)
|
||
{
|
||
s_speed_idx = 0u;
|
||
}
|
||
debug_printf("[KEY] SPEED -> %.1f mm/s", s_speed_levels[s_speed_idx]);
|
||
}
|
||
break;
|
||
|
||
case KEY_5:
|
||
if (action.evt == KEY_EVT_CLICK)
|
||
{
|
||
local_motion_estop(stepper);
|
||
debug_printf("[KEY] STOP");
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
}
|