#include "app_motor.h" /* 当前位置相关:用于CiA402位置反馈 */ float current_absolute_pos_mm = 0.0f; float last_move_start_pos_mm = 0.0f; /* 电机内部状态机 */ Motor_State_t internal_state = STATE_SWITCH_ON_DISABLED; Homing_State_t homing_state = HOMING_IDLE; /* 兼容旧调试变量:值由StepLossMonitor同步更新 */ float error = 0.0f; float distance = 0.0f; float encoder_distance = 0.0f; uint32_t steps = 0; #define STEPLOSS_SETTLE_MS 200U #define STEPLOSS_THRESHOLD_MM_DEFAULT 0.1f /* 丢步检测运行态:集中管理,避免状态分散在多个全局变量 */ typedef struct { /* 实时观测量 */ float abs_error_mm; float cmd_distance_mm; float enc_distance_mm; uint32_t cmd_steps; /* 编码器16位计数扩展 */ int32_t accum_pulses; uint16_t prev_raw_cnt; uint8_t prev_raw_valid; uint8_t motion_active; uint32_t prev_cmd_steps; /* 停止后延时上报 */ uint8_t wait_stop_settle; uint32_t stop_tick_ms; uint8_t report_ready; float report_error_mm; float threshold_mm; Stepper_state_t prev_state; } StepLossMonitor_t; static StepLossMonitor_t s_step_loss = { .threshold_mm = STEPLOSS_THRESHOLD_MM_DEFAULT, .prev_state = STOP, .prev_cmd_steps = 0U, }; static float Normalize_FollowingErrorThreshold(float threshold_mm, float fallback_mm) { if (!(threshold_mm == threshold_mm)) { return fallback_mm; } if (threshold_mm <= 0.0f) { return fallback_mm; } if (threshold_mm > SOFT_LIMIT_MAX_MM) { return SOFT_LIMIT_MAX_MM; } return threshold_mm; } static void Sync_FollowingErrorThreshold_From_OD(void) { OD_entry_t *entry_ferr = OD_find(OD, CIA402_INDEX_FOLLOWING_ERROR_WINDOW); if (entry_ferr == NULL) { return; } float32_t threshold_mm = 0.0f; if (OD_get_f32(entry_ferr, 0, &threshold_mm, true) == ODR_OK) { s_step_loss.threshold_mm = Normalize_FollowingErrorThreshold((float)threshold_mm, s_step_loss.threshold_mm); } } static void Update_PP_FollowingError_StatusBit(float stop_error_mm) { OD_entry_t *entry_mode = OD_find(OD, CIA402_INDEX_OP_MODE); OD_entry_t *entry_sw = OD_find(OD, CIA402_INDEX_STATUSWORD); if (entry_mode == NULL || entry_sw == NULL) { return; } int8_t mode = 0; OD_get_i8(entry_mode, 0, &mode, true); if (mode != 1) { return; } CO_LOCK_OD(CO->CANmodule); uint16_t sw = 0; OD_get_u16(entry_sw, 0, &sw, true); if (stop_error_mm > s_step_loss.threshold_mm) { sw |= CIA402_STATUS_OMS_13; } else { sw &= (uint16_t)(~CIA402_STATUS_OMS_13); } OD_set_u16(entry_sw, 0, sw, true); CO_UNLOCK_OD(CO->CANmodule); } static void Update_FollowingErrorActual_To_OD(float abs_error_mm) { OD_entry_t *entry_ferr_actual = OD_find(OD, CIA402_INDEX_FOLLOWING_ERROR_ACTUAL); float32_t ferr_mm = (float32_t)abs_error_mm; if (entry_ferr_actual == NULL) { return; } if (CO != NULL) { CO_LOCK_OD(CO->CANmodule); (void)OD_set_f32(entry_ferr_actual, 0, ferr_mm, true); CO_UNLOCK_OD(CO->CANmodule); } else { (void)OD_set_f32(entry_ferr_actual, 0, ferr_mm, true); } } /* 核心运动分发:先做安全判断,再按模式进入回零/位置模式处理 */ static void Process_Motion_Logic(void) { /* 未使能运行时,强制停机并维持状态反馈 */ if ((internal_state != STATE_OPERATION_ENABLED) && (stepper_1.run_flag == 0u)) { if (stepper_1.state != STOP) { Int_TMC2209_stop(); stepper_1.state = STOP; } homing_state = HOMING_IDLE; Update_Motion_State_To_OD(); return; } Update_Motion_State_To_OD(); OD_entry_t *entry_mode = OD_find(OD, CIA402_INDEX_OP_MODE); OD_entry_t *entry_mode_disp = OD_find(OD, CIA402_INDEX_OP_MODE_DISPLAY); if (entry_mode != NULL) { int8_t mode = 0; OD_get_i8(entry_mode, 0, &mode, true); if (entry_mode_disp != NULL) { OD_set_i8(entry_mode_disp, 0, mode, true); } switch (mode) { case 6: Handle_Homing_Mode(); break; case 1: Handle_Position_Mode(); break; default: break; } } } void App_Motor_Init(void) { /* 统一初始化运行态与位置基准 */ current_absolute_pos_mm = 0.0f; last_move_start_pos_mm = 0.0f; homing_state = HOMING_IDLE; internal_state = STATE_SWITCH_ON_DISABLED; Int_Encoder_Init(); debug_printf("App Motor Initialized."); } void App_Motor_Process(void) { Sync_FollowingErrorThreshold_From_OD(); Update_FollowingErrorActual_To_OD(s_step_loss.abs_error_mm); /* 先跑CiA402状态机,再执行业务运动逻辑 */ Process_StateMachine(); Process_Motion_Logic(); float stop_error_mm = 0.0f; if (App_Motor_TryGetStopError(&stop_error_mm)) { Update_PP_FollowingError_StatusBit(stop_error_mm); /* 回零流程不输出StepLoss误差日志,避免与“回零成功/失败”语义混淆 */ if (homing_state == HOMING_IDLE) { debug_printf("[StepLoss] stop+200ms error = %.6f mm", stop_error_mm); } } } void App_Motor_StepLossCheck(void) { /* 周期读取硬件计数与已发步数(TIM12中断调用) */ uint16_t raw_cnt = (uint16_t)__HAL_TIM_GET_COUNTER(&htim1); uint8_t rebase_now = 0U; s_step_loss.cmd_steps = stepper_1.step_count; /* 新动作开始时重置累计基准,避免跨动作串扰 */ if (stepper_1.state != STOP) { if ((!s_step_loss.motion_active) || (s_step_loss.cmd_steps < s_step_loss.prev_cmd_steps)) { s_step_loss.motion_active = 1U; s_step_loss.accum_pulses = 0; s_step_loss.prev_raw_cnt = raw_cnt; s_step_loss.prev_raw_valid = 1U; rebase_now = 1U; } } else if (s_step_loss.motion_active) { s_step_loss.motion_active = 0U; } /* 首次采样仅建立基准,不计算位移增量 */ if (!s_step_loss.prev_raw_valid) { s_step_loss.prev_raw_cnt = raw_cnt; s_step_loss.prev_raw_valid = 1U; } /* int16差分可自然处理16位计数器回绕(溢出/下溢) */ int16_t delta = 0; if (rebase_now) { /* New move baseline: skip one diff sample to avoid counter-reset jump. */ } else { delta = (int16_t)(raw_cnt - s_step_loss.prev_raw_cnt); s_step_loss.accum_pulses += (int32_t)delta; s_step_loss.prev_raw_cnt = raw_cnt; } s_step_loss.prev_cmd_steps = s_step_loss.cmd_steps; /* 输出扩展后的总脉冲给上层使用 */ encoder_1.pulses = s_step_loss.accum_pulses; encoder_1.overflow = (uint16_t)(abs(encoder_1.pulses) / 65536); /* 统一换算为mm并计算绝对误差 */ s_step_loss.cmd_distance_mm = (float)s_step_loss.cmd_steps / STEPS_PER_MM; s_step_loss.enc_distance_mm = (float)abs(encoder_1.pulses) * STICK_LEAD / (float)ENCODER_PULSES_PER_CIRCLE; s_step_loss.abs_error_mm = s_step_loss.enc_distance_mm - s_step_loss.cmd_distance_mm; if (s_step_loss.abs_error_mm < 0.0f) { s_step_loss.abs_error_mm = -s_step_loss.abs_error_mm; } /* 同步旧调试变量,便于观察窗口/旧日志继续使用 */ steps = s_step_loss.cmd_steps; distance = s_step_loss.cmd_distance_mm; encoder_distance = s_step_loss.enc_distance_mm; error = s_step_loss.abs_error_mm; /* 运动中不出最终结论,仅标记“停稳后需要上报一次” */ if (stepper_1.state != STOP) { s_step_loss.wait_stop_settle = 1U; s_step_loss.report_ready = 0U; s_step_loss.prev_state = stepper_1.state; return; } /* 从运动态切换到STOP时,开始计时稳定窗口 */ if (s_step_loss.prev_state != STOP) { s_step_loss.prev_state = STOP; s_step_loss.stop_tick_ms = HAL_GetTick(); return; } /* STOP持续到阈值后,锁存一次最终误差 */ if (s_step_loss.wait_stop_settle && ((uint32_t)(HAL_GetTick() - s_step_loss.stop_tick_ms) >= STEPLOSS_SETTLE_MS)) { s_step_loss.report_error_mm = s_step_loss.abs_error_mm; s_step_loss.report_ready = 1U; s_step_loss.wait_stop_settle = 0U; } } /* 一次性读取“停止后最终误差”;读取成功后自动清ready标志 */ bool App_Motor_TryGetStopError(float *err_mm) { if (!s_step_loss.report_ready) { return false; } if (err_mm != NULL) { *err_mm = s_step_loss.report_error_mm; } s_step_loss.report_ready = 0U; return true; }