feat: 冻结超时增加稳定性检查 — CAPVD波动超±2%则重置计数

问题: 上次提交仅计数冻结持续时长,若CAPVD在冻结期间大幅波动
(如车辆缓慢驶入过程中CAPVD持续爬升),30s后也会被误认为"环境变化"。

方案:
- 新增 loop1_freeze_ref: 记录进入冻结时的CAPVD值
- 每tick检查 |CAPVD - freeze_ref| > freeze_ref * 2%
- 波动超限 → 重置计数并以当前值重新开始计时
- 只有CAPVD连续30s稳定在±2%窗口内 → 才更新Origin

这确保了"连续稳定的新值"而非"连续偏高但波动的值"才会触发基线更新。
This commit is contained in:
wangfq
2026-06-29 10:30:01 +08:00
parent 22ffdede70
commit fec67d6f20
2 changed files with 23 additions and 5 deletions

View File

@@ -39,6 +39,7 @@
#define MAX_SLOPE_RATE 5 // 斜率限幅: 单次最大变化 5% (物理限制, 拒绝 EMI 尖峰) #define MAX_SLOPE_RATE 5 // 斜率限幅: 单次最大变化 5% (物理限制, 拒绝 EMI 尖峰)
#define ENTRY_CONFIRM 3 // 进入确认: 连续 N 次低于阈值才判定有车 #define ENTRY_CONFIRM 3 // 进入确认: 连续 N 次低于阈值才判定有车
#define FREEZE_TIMEOUT 3000 // 基线冻结超时: ~30s @ 10ms/tick, 持续偏高后强制更新基线 #define FREEZE_TIMEOUT 3000 // 基线冻结超时: ~30s @ 10ms/tick, 持续偏高后强制更新基线
#define FREEZE_STABILITY_RATE 2 // 冻结稳定性窗口: 参考值的 ±2% (CAPVD 需在此范围内才累计超时)
/*=========================================================================== /*===========================================================================
* 离开检测模式 * 离开检测模式
@@ -105,6 +106,7 @@ extern uint8_t loop1_cnt_release; // 离开防抖计数
extern uint32_t loop1_CAPVD_fast; // 快速 IIR 值 (α=0.5, τ≈28ms, 用于检测) extern uint32_t loop1_CAPVD_fast; // 快速 IIR 值 (α=0.5, τ≈28ms, 用于检测)
extern uint8_t loop1_entry_cnt; // 进入确认计数 extern uint8_t loop1_entry_cnt; // 进入确认计数
extern uint16_t loop1_freeze_cnt; // 基线冻结持续计数(超时后强制更新 Origin extern uint16_t loop1_freeze_cnt; // 基线冻结持续计数(超时后强制更新 Origin
extern uint32_t loop1_freeze_ref; // 冻结参考值CAPVD 偏离此值超限则重置计数)
#if USE_FLATNESS_EXIT #if USE_FLATNESS_EXIT
extern uint8_t g_exit_state; // 离开检测: 0=追踪斜率, 1=等待平坦 extern uint8_t g_exit_state; // 离开检测: 0=追踪斜率, 1=等待平坦
extern uint16_t g_max_slope; // 第一上升坡面最大 |f'| extern uint16_t g_max_slope; // 第一上升坡面最大 |f'|

View File

@@ -40,6 +40,7 @@ uint8_t Flt_Reg;
uint32_t loop1_CAPVD_fast; uint32_t loop1_CAPVD_fast;
uint8_t loop1_entry_cnt; uint8_t loop1_entry_cnt;
uint16_t loop1_freeze_cnt; uint16_t loop1_freeze_cnt;
uint32_t loop1_freeze_ref;
/*=========================================================================== /*===========================================================================
* 全局状态变量 — 标志位 * 全局状态变量 — 标志位
@@ -344,6 +345,7 @@ void INIT_VD(void)
loop1_CAPVD_fast = 0; loop1_CAPVD_fast = 0;
loop1_entry_cnt = 0; loop1_entry_cnt = 0;
loop1_freeze_cnt = 0; loop1_freeze_cnt = 0;
loop1_freeze_ref = 0;
#if USE_FLATNESS_EXIT #if USE_FLATNESS_EXIT
g_exit_state = 0; g_exit_state = 0;
g_max_slope = 0; g_max_slope = 0;
@@ -707,13 +709,26 @@ void vd1_task(void)
&loop1_Origin, loop1_CAPVD, 100); &loop1_Origin, loop1_CAPVD, 100);
} else { } else {
/* CAPVD 异常偏高 → 冻结跟踪 */ /* CAPVD 异常偏高 → 冻结跟踪 */
if (loop1_freeze_cnt == 0) {
loop1_freeze_ref = loop1_CAPVD; // 记录冻结起始值
} else {
/* 稳定性检查: CAPVD 偏离参考值超过 FREEZE_STABILITY_RATE% 则重置 */
int32_t drift = (int32_t)loop1_CAPVD - (int32_t)loop1_freeze_ref;
if (drift < 0) drift = -drift;
if (drift > (int32_t)(loop1_freeze_ref * FREEZE_STABILITY_RATE / 100)) {
/* 波动过大 → 不是稳定值,重置计数并以当前值重新计时 */
loop1_freeze_cnt = 0;
loop1_freeze_ref = loop1_CAPVD;
}
}
loop1_freeze_cnt++; loop1_freeze_cnt++;
if (loop1_freeze_cnt >= FREEZE_TIMEOUT) { if (loop1_freeze_cnt >= FREEZE_TIMEOUT) {
/* 超时: CAPVD 持续偏高稳定 → 可能是环境变化,强制更新基线 */ /* 超时: CAPVD 持续偏高稳定 → 环境变化,接受新基线 */
loop1_Origin = loop1_CAPVD; loop1_Origin = loop1_CAPVD;
loop1_freeze_cnt = 0; loop1_freeze_cnt = 0;
loop1_ORG_CNT = 0; loop1_freeze_ref = 0;
loop1_ORG_SUM = 0; loop1_ORG_CNT = 0;
loop1_ORG_SUM = 0;
PRINT("Baseline timeout update, new Origin:%d\\n", loop1_Origin); PRINT("Baseline timeout update, new Origin:%d\\n", loop1_Origin);
} else { } else {
/* 未超时: 保持冻结,重置累计(防止突然解冻时旧数据污染) */ /* 未超时: 保持冻结,重置累计(防止突然解冻时旧数据污染) */
@@ -736,7 +751,8 @@ void vd1_task(void)
loop1_VD_FLAG = 1; loop1_VD_FLAG = 1;
loop1_FLAG_IN = 1; loop1_FLAG_IN = 1;
loop1_entry_cnt = 0; loop1_entry_cnt = 0;
loop1_freeze_cnt = 0; // 入场时重置冻结计数 loop1_freeze_cnt = 0; // 入场时重置冻结状态
loop1_freeze_ref = 0;
/* 有限存在计时(非安全复位模式下) */ /* 有限存在计时(非安全复位模式下) */
if (!SET_SAFE) { if (!SET_SAFE) {