diff --git a/utilities/at32f421_freertos_demo/inc/TaskLoop.h b/utilities/at32f421_freertos_demo/inc/TaskLoop.h index 35d3d36..f37c3ef 100644 --- a/utilities/at32f421_freertos_demo/inc/TaskLoop.h +++ b/utilities/at32f421_freertos_demo/inc/TaskLoop.h @@ -66,6 +66,7 @@ #define ENTRY_CONFIRM_MID 4 // 中Q(80~100k) #define ENTRY_CONFIRM_LO 5 // 低Q(f>100k): 抖动大, 多样本防假进入 #define REL_ORIGIN_FREEZE_TICKS 100 // V4.36.26/32: 释放后 Origin 全冻结 1000ms — 残余缓离窗口不入均值窗 +#define REL_MIN_HOLD_TICKS 30 // V4.36.42(G3): 有车后最小保持 300ms 禁释放 (掐断进/出 100ms 级自激; 不延迟检出) #define ORIGIN_LOWLEARN_TICKS 200 // V4.36.32: 冻结后降权低速补偿期 2000ms: 残余低值样本权重降 ×1/MULT // 仿 PD132T 慢采样等效(10ms 快采样让 5s 窗装得快, 残余易拉低 Origin; 慢学更稳) #define ORIGIN_LOWLEARN_MULT 5 // V4.36.32: 降权期均值窗放大 500→2500 样本(25s 窗), 学习速率 1/5 diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c index 4d589a9..c987683 100644 --- a/utilities/at32f421_freertos_demo/src/TaskLoop.c +++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c @@ -47,6 +47,7 @@ uint8_t g_q_lo = 0; // V4.36.19: 低Q 档标志 (空场 f>100 uint16_t g_origin_freeze_tick = 0; // V4.36.26/32: 释放后 Origin 全冻结计数 (1s) uint16_t g_origin_lowlearn_tick = 0; // V4.36.32: 冻结后降权低速补偿计数 (2s, 残余低值降权学入) uint16_t g_rel_band_cnt = 0; // V4.36.30: 低Q 环带超时兜底计数 (离开触发深度持续 2.5s → 强制释放) +uint16_t g_rel_hold_tick = 0; // V4.36.42(G3): 有车后最小保持计数 (禁释放, 掐断进/出自激) uint32_t g_vacuum_ema = 0; // V4.36.31: 真空 EMA 基线 (B3: 释放/触发参考与锚错 Origin 解耦) static int32_t g_vac_frac = 0; // V4.37(D): EMA 余数累加器 (消 ±127 counts 整数死区) uint16_t g_ready_hold_tick = 0; // V4.36.36: 判稳后就绪巩固期计数 (5ms tick, poll_green_led 递减; 按 Q 档置 5s/7s/10s) @@ -288,12 +289,22 @@ uint32_t get_flt_value_rel(uint32_t new_value, uint32_t last_value) /* V4.36.31: B3 判定参考 — min(Origin, 真空 EMA) * Origin 可能被 env 学习锚到高位(板搁置态/过冲, J1: 130636 vs 真空 130506) → 释放线偏高 * → 撤板真空也够不着; 取 min 使参考锚向实时真空(低者=保守方向), 双侧自动正确 */ +/* V4.36.42(G1): 真空门控阈值 — 必须"状态无关" + * 现场 20260911 日志: loop1_dlt_ORG 在进车瞬间被切成释放表值(49→23) ⇒ 同一 EMA 偏差(34) + * 原本不触发切换、进车后却触发 ⇒ vac_ref() 从 Origin 阶跃到 EMA ⇒ 释放线瞬间浅 34 counts + * ⇒ 深度 50~58 counts 的静止凹脉冲"进门即满足释放" ⇒ 100ms 周期自激(约 30 次/3s) + * 修法: 门控一律用进表 dlt(与 :band_timeout 的写法统一) ⇒ 进/出车用同一参考 */ +static uint32_t vac_gate_dlt(void) +{ + return ((uint32_t)loop1_Origin * SensTable[loop1_SensLevel]) >> 16; +} + static uint32_t vac_ref(void) { if (g_vacuum_ema == 0) return loop1_Origin; /* V4.36.33: 仅明显锚错(Origin 高于 EMA > 1×dlt)才重锚 EMA — 边缘金属悬停拉低 EMA 的小偏差忽略 */ if ((int32_t)loop1_Origin - (int32_t)g_vacuum_ema > - (int32_t)(loop1_dlt_ORG * VAC_REF_DELTA_DLT)) + (int32_t)(vac_gate_dlt() * VAC_REF_DELTA_DLT)) return g_vacuum_ema; return loop1_Origin; } @@ -321,8 +332,14 @@ static uint8_t rel_release_hit(void) uint32_t _line = loop1_Origin - loop1_dlt_ORG; if (g_q_lo) { + /* V4.36.42(G1/G2): 释放线与进入线必须同参考, 且带回不得越过进入阈值(否则反向滞回) + * G1 已保证同参考; 此处只做"未来参数变化"兜底夹紧 —— 绝不动现场验证过的 180 + * (=41@SENS3: V4.36.28 修静态带回缺口, 23uH 回摆 Origin-36 靠它才释放) */ + uint32_t _band = (loop1_dlt_ORG * REL_BAND_LO_MULT) / 100; + uint32_t _ent = vac_gate_dlt(); _cmp = g_rel_smooth; - _line = vac_ref() - ((loop1_dlt_ORG * REL_BAND_LO_MULT) / 100); /* V4.36.31: 锚真空参考 */ + if (_band > _ent) _band = _ent - 1; + _line = vac_ref() - _band; } return (_line < _cmp) ? 1 : 0; } @@ -579,6 +596,7 @@ void INIT_VD(void) g_q_lo = 0; /* V4.36.19: 低Q 档标志清零 */ g_origin_freeze_tick = 0; /* V4.36.26: 释放冻结计数清零 */ g_rel_band_cnt = 0; /* V4.36.30: 环带兜底计数清零 */ + g_rel_hold_tick = 0; /* V4.36.42(G3): 最小保持清零 */ g_vacuum_ema = 0; /* V4.36.31: 真空 EMA 清零 (判稳后重建) */ g_vac_frac = 0; /* V4.37(D): 余数累加器同步清零 */ g_ready_hold_tick = 0; /* V4.36.36: 就绪巩固期清零 (重建判稳时会再置) */ @@ -1287,6 +1305,7 @@ void vd1_task(void) g_origin_freeze_tick--; else if (g_origin_lowlearn_tick > 0) /* V4.36.32: 冻结结束 → 降权期开始递减 */ g_origin_lowlearn_tick--; + if (g_rel_hold_tick > 0) g_rel_hold_tick--; /* V4.36.42(G3): 有车最小保持倒计时 */ /*--- 基线跟踪(仿 TLD-110:有车时冻结) * V4.20 修复: 双向对称保护 — 负偏差(负variation)也冻结基线 @@ -1482,6 +1501,7 @@ void vd1_task(void) #endif g_rel_smooth = loop1_CAPVD; /* V4.36.19: 低Q 释放平滑 snap 到进入点 */ g_rel_band_cnt = 0; /* V4.36.30: 环带兜底计数进入时清零 */ + g_rel_hold_tick = REL_MIN_HOLD_TICKS; /* V4.36.42(G3): 进入后 300ms 禁释放 */ if (!SET_SAFE) { loop1_LC_HOLD = 1; @@ -1577,9 +1597,9 @@ void vd1_task(void) loop1_dlt_ORG = ((uint32_t)loop1_Origin * SensTable_1[loop1_SensLevel]) >> 16; // 方案B(V4.06): 调浅释放表已并入 SensTable_1 #if USE_SLOW_RELEASE - if ((loop1_Origin - loop1_dlt_ORG) < loop1_CAPVD_slow) { // 方案A: 用慢滤波值对齐 PD132T 释放手感 + if (((loop1_Origin - loop1_dlt_ORG) < loop1_CAPVD_slow) && (g_rel_hold_tick == 0)) { // 方案A + V4.36.42(G3) 最小保持 #else - if (rel_release_hit()) { // V4.36.19: 低Q 平滑值+带回加宽; 高/中Q 退回原快值逻辑 + if ((g_rel_hold_tick == 0) && rel_release_hit()) { // V4.36.42(G3) 最小保持 + V4.36.19 低Q 平滑/带回加宽 #endif if (loop1_cnt_release == 0) { /* 过渡事件: 第一次命中离开线 (定位"为什么开始释放") */ @@ -1605,6 +1625,7 @@ void vd1_task(void) loop1_ORG_SUM = 0; Hold_CNT = 0; loop1_cnt_release = 0; + g_rel_hold_tick = 0; /* V4.36.42(G3): 释放即清保持 */ g_origin_freeze_tick = REL_ORIGIN_FREEZE_TICKS; /* V4.36.26: 释放后 Origin 均值窗冻结 */ g_origin_lowlearn_tick = ORIGIN_LOWLEARN_TICKS; /* V4.36.32: 冻结后降权期预置 */ }