Files
DLD154V4B/docs/patches/v4.36.41-A-B-origin-ema-sync.diff
T
wangfq 5fd58e035a fix(V4B): V4.36.41 — 环境重校准后触发高度变低根治 (基准/派生参考同步 + EMA 余数累加)
用户反馈: 黄灯常亮故障补偿后, 金属板进入触发的高度比断电上电后低很多, 补偿结束也恢复不了正常灵敏度。

根因(两处, 均可复核): V4B 进入判定用 vac_ref()=min(Origin, 真空EMA) 而非 Origin (TaskLoop.c:1432)
 ① env_resync_apply() 只原子换 loop1_Origin, 没同步 g_vacuum_ema。补偿前提是 dev>+4×dlt 连续 7s,
    学到的 B≈当前 CAPVD ⇒ Δ≥4×dlt 必然 ⇒ Origin−EMA=Δ>1×dlt ⇒ vac_ref 必然切旧 EMA ⇒ 进入线整整低 Δ
 ② g_vacuum_ema += _ema_d/128 为整数除法, |d|<128 时步进恒 0 ⇒ EMA 粘在真空下方 ≤127 counts
    (2.59×dlt > 1×dlt 门槛) ⇒ 进入线常驻偏低 ≈0.100% Δf/f 且不自愈; 断电上电 EMA=Origin(偏差 0) 故持久正常

修复:
 - 新增 origin_set_atomic() (TaskLoop.c:308): "一步换 Origin"时 |ΔOrigin| > ORIGIN_JUMP_REANCH_DLT(=1)×dlt
   则同步重锚 g_vacuum_ema; 与 VAC_REF_DELTA_DLT 同口径 ⇒ 维持 |Origin−EMA| ≤ 1×dlt 不变式; 小步不动 EMA
 - 3 处 Origin 写入点改经它: env_resync_apply(:968) / 重连判稳完成(:1207) / 冻结超时更新(:1372)
 - EMA 更新改余数累加器 g_vac_frac(:1344) 消 ±127 counts 死区; g_vac_frac 在 INIT(:583)/判稳(:1266) 清零

单测(新增 tests/test_vac_ref_reanchor.c, 5 场景; gcc -O0 -Wall -Wextra 0 warning; 全套 8/8 全绿):
 补偿后进入线 130457(低 130 counts = 2.65×dlt = 0.100% Δf/f) → 130587(低 0); EMA 追赶偏差 127→0 counts

文档: devlog V2.78(+条目) / spec 文档头 V2.60 / manual 版本表 V2.17 / cmcng.h 4.36.40→4.36.41 (REV 41)
归档: docs/env-resync-trigger-line-analysis.md + docs/patches/v4.36.41-{A-B,D}*.diff

待现场(编译烧录后回填 devlog 条目): 4 项 [ ] + 2 处日志待填 (EVT|env_resync / DBG Origin·VEM·RLN)
2026-09-11 14:08:25 +08:00

68 lines
3.9 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
diff --git a/utilities/at32f421_freertos_demo/inc/TaskLoop.h b/utilities/at32f421_freertos_demo/inc/TaskLoop.h
index afece45..35d3d36 100644
--- a/utilities/at32f421_freertos_demo/inc/TaskLoop.h
+++ b/utilities/at32f421_freertos_demo/inc/TaskLoop.h
@@ -43,6 +43,7 @@
#define VACUUM_EMA_ALFA 128 // V4.36.31: 真空 EMA 平滑因子 (τ≈1.28s@10ms): B3 判定参考解耦
// 无车 dev 窗内跟踪实时真空; 噪声 σ_ema≈σ/16 (σ1-2 → 0.1 counts)
#define VAC_REF_DELTA_DLT 1 // V4.36.33: vac_ref 重锚阈值 (×dlt): 仅 OriginEMA > 1×dlt(真锚错)
+#define ORIGIN_JUMP_REANCH_DLT 1 // V4.36.41: Origin 单步跳变 > 1×dlt ⇒ 同步重锚真空 EMA (B1 护栏)
// 才用 EMA 锚低 — 防金属板悬感应边缘(dev20~40<4dlt)快速拉低 EMA
// → 触发线漂移(触发高度下降); 小偏差仍用 Origin
// 150(→35)不够: 23µH 现场实测板停临界回摆 Origin-36, 需释放线<Origin-37 才释放;
diff --git a/utilities/at32f421_freertos_demo/src/TaskLoop.c b/utilities/at32f421_freertos_demo/src/TaskLoop.c
index afbe2d1..2a16a6a 100644
--- a/utilities/at32f421_freertos_demo/src/TaskLoop.c
+++ b/utilities/at32f421_freertos_demo/src/TaskLoop.c
@@ -297,6 +297,23 @@ static uint32_t vac_ref(void)
return loop1_Origin;
}
+/* V4.36.41: 原子换 Origin ⇒ 同步真空参考 (B1 通用护栏)
+ * 背景: 进入判定用 vac_ref()=min(Origin,EMA); 任何"一步换 Origin"的路径若不换 EMA,
+ * 现场环境重校准后 Origin 已到新真空而 EMA 停在旧真空 ⇒ 固定偏差
+ * (实测拉开 ≥4×dlt) ⇒ 进入线被拖低同量 ⇒ 触发高度明显变低, 断电上电才恢复
+ * 策略: 步长 > ORIGIN_JUMP_REANCH_DLT×dlt 才重锚 EMA; 小步(≤1×dlt)不动,
+ * 与 VAC_REF_DELTA_DLT 同口径 ⇒ 保持 |OriginEMA| ≤ 1×dlt 不变式,
+ * 不干扰 EMA 在对称窗内的实时真空跟踪 */
+static void origin_set_atomic(uint32_t new_origin)
+{
+ int32_t _jump = (int32_t)new_origin - (int32_t)loop1_Origin;
+ if (_jump < 0) _jump = -_jump;
+ loop1_Origin = new_origin;
+ if (g_vacuum_ema == 0 || loop1_dlt_ORG == 0 ||
+ _jump > (int32_t)(loop1_dlt_ORG * ORIGIN_JUMP_REANCH_DLT))
+ g_vacuum_ema = new_origin;
+}
+
static uint8_t rel_release_hit(void)
{
uint32_t _cmp = loop1_CAPVD;
@@ -946,7 +963,7 @@ static void env_resync_apply(uint32_t new_origin)
{
PRINT("EVT|env_resync Origin:%d->%d CAPVD:%d\n",
loop1_Origin, new_origin, loop1_CAPVD);
- loop1_Origin = new_origin;
+ origin_set_atomic(new_origin); /* V4.36.41: 同步真空 EMA — 补偿后进入线不再被旧真空拖低 */
loop1_freeze_cnt = 0;
loop1_freeze_ref = 0;
loop1_ORG_CNT = 0;
@@ -1185,7 +1202,7 @@ void vd1_task(void)
if (_d < 0) _d = -_d;
if (_d <= (int32_t)_dlt) {
/* 回带内=空场确认 → Origin 对齐当前空场(消基线差) */
- loop1_Origin = loop1_CAPVD;
+ origin_set_atomic(loop1_CAPVD); /* V4.36.41: 护栏(小步≤1×dlt 不动 EMA) */
loop1_CAPVD_slow = loop1_CAPVD;
loop1_dlt_ORG = ((uint32_t)loop1_Origin *
SensTable[loop1_SensLevel]) >> 16;
@@ -1341,7 +1358,7 @@ void vd1_task(void)
}
loop1_freeze_cnt++;
if (loop1_freeze_cnt >= FREEZE_TIMEOUT) {
- loop1_Origin = loop1_CAPVD;
+ origin_set_atomic(loop1_CAPVD); /* V4.36.41: 护栏(大步下跳也同步重锚) */
loop1_freeze_cnt = 0;
loop1_freeze_ref = 0;
loop1_ORG_CNT = 0;