用户反馈: 黄灯常亮故障补偿后, 金属板进入触发的高度比断电上电后低很多, 补偿结束也恢复不了正常灵敏度。
根因(两处, 均可复核): 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)
68 lines
3.9 KiB
Diff
68 lines
3.9 KiB
Diff
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): 仅 Origin−EMA > 1×dlt(真锚错)
|
||
+#define ORIGIN_JUMP_REANCH_DLT 1 // V4.36.41: Origin 单步跳变 > 1×dlt ⇒ 同步重锚真空 EMA (B1 护栏)
|
||
// 才用 EMA 锚低 — 防金属板悬感应边缘(dev−20~−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 同口径 ⇒ 保持 |Origin−EMA| ≤ 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;
|