用户反馈: 金属板缓慢接近时判据乱跳; 35µH(128kHz)/46µH(112kHz) 线圈同样现象(46µH 在设计窗内且无告警)。 根因(三段链条, 现场日志与代码逐值吻合): ① 无车态 dlt_ORG=进表 49 ⇒ vac_ref() 门控 1×49; Origin−EMA=32~34 ≯49 ⇒ 参考=Origin ⇒ 进入线=Origin−49 ② 进车瞬间 dlt_ORG 切成释表 23 ⇒ 同一 gap > 1×23 ⇒ vac_ref() 改用 EMA(低 32~34 counts) ③ 释放线 = EMA−1.8×23 ⇒ 比进入线还浅 ⇒ 深度 50~58 的静止凹脉冲"进门即满足释放" ⇒ 进入确认 5 + 释放确认 5 = 10 样本 = 100ms 周期自激(日志实测 ~30 组/3s) 实现: - G1 新增 vac_gate_dlt()(状态无关进表 dlt)供 vac_ref() 门控 (TaskLoop.c:297/307) ⇒ 进/出同一参考 - G2 低Q 释放带夹紧 _band ≤ vac_gate_dlt()-1 (TaskLoop.c:339) ⇒ 只作未来兜底; 180(=41@SENS3, V4.36.28 现场值)一字未动 - G3 REL_MIN_HOLD_TICKS=30 有车后 300ms 禁释放 (TaskLoop.h:69 + TaskLoop.c 调用点) ⇒ 只挡释放不延迟检出 单测: 新增场景 7 现场参数逐位复现 —— 22µH 悬停 300/300 → 1/0; 35µH 300/300 → 1/0; 撤板 1/1; V4.36.28 回摆仍释放; 非低Q 同深度不自激; 全套 8/8 全绿 文档: devlog V2.79(+条目) / spec 文档头 V2.61 / manual 表 V2.18 / cmcng.h 4.36.41→4.36.42 REV 42 待现场: 上板复测 + 锁死侧三线圈实验 (devlog 条目内 [ ] 占位)
109 lines
7.3 KiB
Diff
109 lines
7.3 KiB
Diff
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: 冻结后降权期预置 */
|
||
}
|