From 3ddde992732785edf3d88f770e4a241aa9ef84ee Mon Sep 17 00:00:00 2001 From: wangfq Date: Mon, 29 Jun 2026 17:56:38 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E5=BF=AB=E9=80=9F=20IIR=20=E6=96=9C?= =?UTF-8?q?=E7=8E=87=E9=99=90=E5=B9=85=E5=8F=82=E8=80=83=E6=94=B9=E4=B8=BA?= =?UTF-8?q?=20CAPVD=5Ffast=EF=BC=8C=E8=A7=A3=E5=86=B3=20ALFA=5FCAP1=3D18?= =?UTF-8?q?=20=E5=93=8D=E5=BA=94=E6=85=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 根因: 斜率限幅 max_step = CAPVD × 5%,但 CAPVD 受 ALFA_CAP1=18 拖累(τ=135ms),在车辆骤入时移动不足,导致 clamped_value 被过度砍削。 快速 IIR 吃到的 fast_input 已经是"被慢速 CAPVD 限制过的值"。 修复: 快速路径独立做斜率限幅,参考 CAPVD_fast (τ=28ms)。 两路各用各的参考基准,快慢解耦: 慢速: clamped = clamp(Value, CAPVD ± 5%) → IIR_slow → CAPVD 快速: fast_input = clamp(Value, CAPVD_fast ± 5%) → IIR_fast ALFA_CAP1 只影响基线跟踪,不再拖累进入检测速度。 --- .../at32f421_freertos_demo/src/TaskLoop.c | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c index aea83cb..2fc62a8 100644 --- a/utilities/at32f421_freertos_demo/src/TaskLoop.c +++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c @@ -653,27 +653,38 @@ void vd1_task(void) * - 用途: 进入/离开检测判定 *================================================================*/ - /* 1a. 慢速 IIR — 斜率限幅 */ + /* 1a. 慢速 IIR — 斜率限幅(参考 CAPVD)*/ { - uint32_t fast_input; // 快速 IIR 的输入:限幅后的原始值,不经慢速 IIR 滞后 + uint32_t fast_input; if (loop1_CAPVD == 0) { loop1_CAPVD = loop1_Value; fast_input = loop1_Value; } else { - /* 斜率限幅: 物理车辆不可能让频率瞬间跳变 > MAX_SLOPE_RATE% */ + /*--- 慢速路径:斜率限幅参考 CAPVD (τ=135ms),保护基线跟踪 ---*/ int32_t raw_delta = (int32_t)loop1_Value - (int32_t)loop1_CAPVD; int32_t max_step = (int32_t)(loop1_CAPVD * MAX_SLOPE_RATE / 100); - if (max_step < 100) max_step = 100; // 最小限幅,防止 origin 很小时锁死 + if (max_step < 100) max_step = 100; if (raw_delta > max_step) raw_delta = max_step; if (raw_delta < -max_step) raw_delta = -max_step; uint32_t clamped_value = (uint32_t)((int32_t)loop1_CAPVD + raw_delta); loop1_CAPVD = get_flt_value(clamped_value, loop1_CAPVD); - fast_input = clamped_value; + + /*--- 快速路径:斜率限幅参考 CAPVD_fast (τ=28ms),限幅窗口随快速值扩展 + * 解决 ALFA_CAP1=18 时 CAPVD 移动太慢限制限幅天花板的问题 ---*/ + if (loop1_CAPVD_fast == 0) { + fast_input = clamped_value; + } else { + int32_t f_delta = (int32_t)loop1_Value - (int32_t)loop1_CAPVD_fast; + int32_t f_max = (int32_t)(loop1_CAPVD_fast * MAX_SLOPE_RATE / 100); + if (f_max < 100) f_max = 100; + if (f_delta > f_max) f_delta = f_max; + if (f_delta < -f_max) f_delta = -f_max; + fast_input = (uint32_t)((int32_t)loop1_CAPVD_fast + f_delta); + } } - /* 1b. 快速 IIR — α=0.5: (old + new) / 2 - * 输入直接用限幅后的原始值,不经过慢速 IIR,保持 τ≈28ms 的响应速度 */ + /* 1b. 快速 IIR — α=0.5: (old + new) / 2 */ if (loop1_CAPVD_fast == 0) { loop1_CAPVD_fast = fast_input; } else {