From 8955887f9860b7167b629f32a6d19e828691bc35 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=BC=96=E7=A8=8B=E6=B5=A9?= <540616471@qq.com> Date: Mon, 2 Mar 2026 17:43:52 +0800 Subject: [PATCH] =?UTF-8?q?v1.2=E4=BF=AE=E5=A4=8D=E4=BA=86EEPROM=E7=9A=84?= =?UTF-8?q?=E8=AF=BB=E5=86=99=E4=BB=A5=E5=8F=8A=E6=8E=89=E7=94=B5=E4=BF=9D?= =?UTF-8?q?=E6=8C=81=E5=8F=82=E6=95=B0=E7=9A=84=E5=8A=9F=E8=83=BD=EF=BC=8C?= =?UTF-8?q?=E7=8E=B0=E5=9C=A8=E4=B8=A2=E6=AD=A5=E7=9A=84=E8=AF=AF=E5=B7=AE?= =?UTF-8?q?=E4=BC=9A=E4=BF=9D=E5=AD=98=E5=9C=A8Canopen=E5=AD=97=E5=85=B8?= =?UTF-8?q?=E7=9A=840x60F4=E4=BD=8D=E7=BD=AE=EF=BC=8C=E7=BD=91=E5=85=B3?= =?UTF-8?q?=E9=82=A3=E8=BE=B9=E5=8F=AF=E4=BB=A5=E9=80=9A=E8=BF=87SDO?= =?UTF-8?q?=E8=AF=BB=E5=8F=96=E5=88=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Application/app_main.c | 1 - Application/app_motor.c | 44 +- Application/app_param_store.c | 62 +- .../three-axis_stepper.build_log.htm | 13 +- .../three-axis_stepper/three-axis_stepper.htm | 3060 +++++++++-------- Middleware/CANopenNode/402/CiA402_defs.h | 100 +- Middleware/CANopenNode/CO_driver_STM32/OD.c | 8 + Middleware/CANopenNode/CO_driver_STM32/OD.h | 9 +- Middleware/CANopenNode/NodeSlave.xdd | 10 +- 9 files changed, 1710 insertions(+), 1597 deletions(-) diff --git a/Application/app_main.c b/Application/app_main.c index 10abe7d..4b0a354 100644 --- a/Application/app_main.c +++ b/Application/app_main.c @@ -77,7 +77,6 @@ void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) break; case ENCODER1_Z_Pin: encoder_1.z++; - break; default: break; } diff --git a/Application/app_motor.c b/Application/app_motor.c index 9c1ee95..d9e3c4e 100644 --- a/Application/app_motor.c +++ b/Application/app_motor.c @@ -31,6 +31,7 @@ typedef struct uint16_t prev_raw_cnt; uint8_t prev_raw_valid; uint8_t motion_active; + uint32_t prev_cmd_steps; /* 停止后延时上报 */ uint8_t wait_stop_settle; @@ -44,6 +45,7 @@ typedef struct 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) @@ -117,6 +119,28 @@ static void Update_PP_FollowingError_StatusBit(float stop_error_mm) 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) { @@ -176,6 +200,7 @@ void App_Motor_Init(void) void App_Motor_Process(void) { Sync_FollowingErrorThreshold_From_OD(); + Update_FollowingErrorActual_To_OD(s_step_loss.abs_error_mm); /* 先跑CiA402状态机,再执行业务运动逻辑 */ Process_StateMachine(); @@ -198,17 +223,19 @@ 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) + 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) @@ -224,9 +251,18 @@ void App_Motor_StepLossCheck(void) } /* int16差分可自然处理16位计数器回绕(溢出/下溢) */ - int16_t 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; + 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; diff --git a/Application/app_param_store.c b/Application/app_param_store.c index efb4612..d0adbe8 100644 --- a/Application/app_param_store.c +++ b/Application/app_param_store.c @@ -15,6 +15,7 @@ #define APP_PARAM_VERSION 0x0001u #define APP_PARAM_EEPROM_ADDR 0x0000u #define APP_PARAM_AUTOSAVE_DEBOUNCE_MS 500u +#define APP_PARAM_THRESHOLD_DEFAULT_MM 0.1f /* Log level: 0=off, 1=error, 2=info */ #define APP_PARAM_STORE_LOG_LEVEL 2 @@ -176,9 +177,13 @@ static bool App_ParamStore_ReadCurrentFromOD(App_RunParams_t *params) OD_entry_t *entry_acc = OD_find(OD, CIA402_INDEX_PROFILE_ACC); OD_entry_t *entry_dec = OD_find(OD, CIA402_INDEX_PROFILE_DEC); OD_entry_t *entry_ferr = OD_find(OD, CIA402_INDEX_FOLLOWING_ERROR_WINDOW); + ODR_t odr_acc = ODR_DEV_INCOMPAT; + ODR_t odr_dec = ODR_DEV_INCOMPAT; + ODR_t odr_ferr = ODR_DEV_INCOMPAT; uint32_t acc_raw = 0u; uint32_t dec_raw = 0u; float32_t ferr_raw = 0.0f; + float ferr_mm = APP_PARAM_THRESHOLD_DEFAULT_MM; if ((params == 0) || (entry_acc == 0) || (entry_dec == 0) || (entry_ferr == 0)) { @@ -188,30 +193,55 @@ static bool App_ParamStore_ReadCurrentFromOD(App_RunParams_t *params) if (CO != 0) { CO_LOCK_OD(CO->CANmodule); - (void)OD_get_u32(entry_acc, 0, &acc_raw, true); - (void)OD_get_u32(entry_dec, 0, &dec_raw, true); - (void)OD_get_f32(entry_ferr, 0, &ferr_raw, true); + odr_acc = OD_get_u32(entry_acc, 0, &acc_raw, true); + odr_dec = OD_get_u32(entry_dec, 0, &dec_raw, true); + odr_ferr = OD_get_f32(entry_ferr, 0, &ferr_raw, true); CO_UNLOCK_OD(CO->CANmodule); } else { - (void)OD_get_u32(entry_acc, 0, &acc_raw, true); - (void)OD_get_u32(entry_dec, 0, &dec_raw, true); - (void)OD_get_f32(entry_ferr, 0, &ferr_raw, true); + odr_acc = OD_get_u32(entry_acc, 0, &acc_raw, true); + odr_dec = OD_get_u32(entry_dec, 0, &dec_raw, true); + odr_ferr = OD_get_f32(entry_ferr, 0, &ferr_raw, true); } - if ((acc_raw == 0u) || (acc_raw > 65535u) || (dec_raw == 0u) || (dec_raw > 65535u)) + if ((odr_acc != ODR_OK) || (odr_dec != ODR_OK) || (odr_ferr != ODR_OK)) { + APP_PS_LOGE("[EEPROM] read OD failed, odr_acc=%d odr_dec=%d odr_ferr=%d", + (int)odr_acc, (int)odr_dec, (int)odr_ferr); return false; } - if (((float)ferr_raw <= 0.0f) || ((float)ferr_raw > SOFT_LIMIT_MAX_MM)) + + if (acc_raw == 0u) { - return false; + acc_raw = 1u; + } + if (dec_raw == 0u) + { + dec_raw = 1u; + } + if (acc_raw > 65535u) + { + acc_raw = 65535u; + } + if (dec_raw > 65535u) + { + dec_raw = 65535u; + } + + ferr_mm = (float)ferr_raw; + if (!(ferr_mm == ferr_mm) || (ferr_mm <= 0.0f)) + { + ferr_mm = APP_PARAM_THRESHOLD_DEFAULT_MM; + } + if (ferr_mm > SOFT_LIMIT_MAX_MM) + { + ferr_mm = SOFT_LIMIT_MAX_MM; } params->acc_mm_s2 = (uint16_t)acc_raw; params->dec_mm_s2 = (uint16_t)dec_raw; - params->step_loss_threshold_mm = (float)ferr_raw; + params->step_loss_threshold_mm = ferr_mm; return true; } @@ -239,6 +269,8 @@ static uint8_t App_ParamStore_ParamsEqual(const App_RunParams_t *a, const App_Ru void App_ParamStore_Init(void) { + App_RunParams_t current; + /* EEPROM驱动初始化:参数由Int_EEPROM24xx内部宏配置。 */ if (Int_EEPROM24xx_Init() != INT_EEPROM_OK) { @@ -246,7 +278,15 @@ void App_ParamStore_Init(void) APP_PS_LOGE("[EEPROM] init failed"); } - g_last_seen_valid = 0u; + if (App_ParamStore_ReadCurrentFromOD(¤t)) + { + g_last_seen_params = current; + g_last_seen_valid = 1u; + } + else + { + g_last_seen_valid = 0u; + } g_autosave_dirty = 0u; g_autosave_due_ms = 0u; } diff --git a/MDK-ARM/three-axis_stepper/three-axis_stepper.build_log.htm b/MDK-ARM/three-axis_stepper/three-axis_stepper.build_log.htm index b69d948..c4f2579 100644 --- a/MDK-ARM/three-axis_stepper/three-axis_stepper.build_log.htm +++ b/MDK-ARM/three-axis_stepper/three-axis_stepper.build_log.htm @@ -27,9 +27,16 @@ Project File Date: 03/02/2026