Files
DLD154V4B/docs/env-resync-trigger-line-analysis.md
T
wangfq 6c82bf61b8 fix(V4B): V4.36.43 — 修正 V4.36.42 引入的离开变慢 (G3 计时器递减位置错误)
用户反馈: 烧 V4.36.42 后离开 3、4 秒才释放。

定位(46µH/113kHz 日志): 4 次离开全是 Car_OFF(band_timeout), 延迟 3.5~4.7s; RLN 正常
(有车态 = Origin−41, 说明 G1 生效、100ms 自激已消失) ⇒ 问题出在"正常释放路径被挡住"。

根因: G3 的 g_rel_hold_tick-- 误放 if(!loop1_VD_FLAG) 无车分支(原 :1308) ⇒ 有车期间永不递减
⇒ 首次 Car_In 后常驻 30 ⇒ g_rel_hold_tick==0 永假 ⇒ 正常释放被永久挡住, 只能等 2.5s 环带兜底
+ 平滑值抬升 ⇒ 3.5~4.7s。

修复: 倒计时移到 } else { 有车分支顶部 (TaskLoop.c:1531 后、#if USE_FLATNESS_EXIT 之前,
每 tick 必过且在释放判定之前); 误放旧行改注释留痕。REL_MIN_HOLD_TICKS 仍 30(300ms)。

单测: 8/8 全绿(场景 7 语义不变); 新增"镜像能力边界"警告 —— 镜像只验证算法语义, 验证不了固件内
执行路径/放置位置, 此类问题必须靠日志 Car_OFF 原因字段(band_timeout/FLAT/普通)暴露。
文档: devlog V2.80(+条目) / spec 头 V2.62 / manual 表 V2.19 / cmcng.h 4.36.42→4.36.43 REV 43
/ 分析稿 §13 返工记录。
待现场: 离开延迟回到 ~300ms 内; 缓慢接近/停边界仍不跳。
2026-09-11 17:06:05 +08:00

219 lines
18 KiB
Markdown
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.
# 黄灯常亮(环境重校准)后触发高度变低 — 根因分析
> 适用版本:**V4.36.31 及以后**(进入判定已切到 `vac_ref()`;判据 = DBG 行是否含 `VEM=` 字段)
> 现象:黄灯常亮故障补偿结束后,金属板进入触发的"高度"明显变低(要压得更近才触发);**断电上电后恢复正常**。
> 结论(一句话):**环境重校准 `env_resync_apply()` 原子替换了 `loop1_Origin`,但没有同步真空 EMA `g_vacuum_ema`;而进入判定用的是 `vac_ref() = min(Origin, EMA)`,于是补偿后进入线被留在旧真空上、整体低了 Δ(≥4×dlt)⇒ 必须多压出 Δ 的感应量才触发。断电上电时 EMA 由判稳重建 = Origin,故立刻恢复。**
---
## 1. 判定链(代码位置,全部可复核)
| 环节 | 位置 | 内容 |
|---|---|---|
| **进入线** | `TaskLoop.c:1432` | `if (loop1_CAPVD < (vac_ref() - loop1_dlt_ORG) && ...)`**用 vac_ref,不是 Origin** |
| 参考函数 | `TaskLoop.c:287-299` | `vac_ref() = (Origin EMA > VAC_REF_DELTA_DLT×dlt) ? EMA : Origin`(阈值 =1×dlt,取**低者** |
| 进入阈值 | `TaskLoop.c:1278` | `dlt = Origin × SensTable[SENS] >> 16`SENS3=25 ⇒ 0.038%SENS0=337 ⇒ 0.514% |
| **补偿替换** | `TaskLoop.c:945-958` | `env_resync_apply()``loop1_Origin = new_origin;` + 清 freeze/ORG/entry + snap slow**没有 EMA** |
| EMA 写点(全仓仅 3 处) | `564` / `1246` / `1309-1321` | INIT 清零 / 判稳完成 `EMA = Origin` / 无车对称窗内跟踪(α=128 τ≈1.28s,每步 ±3×dlt25% 自愈) |
| 黄灯常亮 | `TaskLoop.c:437-442` | 模式4 = `g_env_warn \|\| g_env_resync`(环境异常预判 / 重校准学习) |
| 补偿参数 | `TaskLoop.c:81,82,1082-1084` | 预判 2s → 补偿 7s → 学习窗 2s/窗 + 连续 2 窗判稳(0.1%) → 替换 → 恢复确认 2s 灭灯 |
**关键事实**`g_vacuum_ema` 的三个写点里**没有**环境重校准路径 ⇒ 补偿把 `Origin` 一次性抬到新真空电平后,EMA 仍停在补偿前的旧真空值。
---
## 2. 数值推演(Δ 必然 ≥ 4×dlt)
1. 触发补偿的前提是 `dev = CAPVD Origin > +4×dlt` **连续 7s**`ENV_RESYNC_WAIT=700`)。
2. 期间处于"负 variation 高位"分支 ⇒ **Origin 与 EMA 都被冻结**`1327-1425`),EMA 保持旧真空值。
3. 学习得到的 B = 当前 CAPVD 的 2s 窗均值(`1397-1416`)⇒ `Origin_new ≈ Origin_old + Δ`,其中 **Δ ≥ 4×dlt**
4. 替换后:`Origin EMA = Δ ≥ 4×dlt > 1×dlt``vac_ref()` 返回 **EMA(旧真空)**
5.**进入线 = 旧真空 dlt**,而物理正确应为 **新真空 − dlt = 旧真空 + Δ dlt****进入线整整低了 Δ(≥4×dlt)**
- SENS3dlt=48@130k):Δ ≥ 192 counts ⇒ 0.15% Δf/f 起的额外感应量才触发;
- devlog J1 实测位移 130~1513 counts ⇒ 观测即"触发高度下降一半甚至更多"。
---
## 3. 为什么断电上电就正常
`g_vacuum_ema` 在 INIT 清 0`564`),判稳完成时 `g_vacuum_ema = loop1_Origin``1246`)⇒ 两者重合 ⇒ `vac_ref() = Origin` ⇒ 进入线回到 `Origin dlt`
---
## 4. 为什么"黄灯灭"不等于灵敏度回来了
黄灯灭的条件只有**非高位、空闲连续 2s**(`ENV_RECOVER_WAIT=200``1290-1300`),**不检查 EMA 是否已追上新 Origin**。
补偿后 dev≈0 才落入 ±4×dlt 对称窗 ⇒ EMA 这时才开始以 τ≈1.28s 向上爬:
- 黄灯灭(替换后 2s)时 EMA 仅追回 1e^(2/1.28) ≈ **79%**
- Δ=130 时仍差 ~27 counts(≈0.56×dlt
---
## 5. 为什么"反复试板"会自持(越试越钝)
EMA 更新窗 = 无车 + `dev ∈ ±4×dlt``1302-1326`)。把板拿到感应边缘(未触发、dev −20~−40)时 **EMA 被向下拖**V4.36.33 devlog 实测 2~3s 拉低 20~40 counts);进入线 = `min(Origin, EMA) dlt`**每次试板都把线再拖低一截** ⇒ 主观上"补偿结束了但灵敏度回不来",直到彻底离开真空若干秒才慢慢回正。
> 这与 V4.36.33 已记录的老现象("金属板间隔几秒再压,触发高度下降一半甚至更多")是**同一机理**;本次新增的点是:**环境重校准会把 Δ 一次性甩到 4×dlt 以上**,比边缘悬停(0.4~0.8×dlt)严重一个量级,且黄灯灭的时刻刚好是 EMA 还差一截的时刻。
---
## 6. 第二个机制:真空 EMA 的整数步进死区(2026-09-11 单测实测)
第 5 节解释了"补偿后一次性被压低 Δ",但**为什么反复试板后仍感觉回不来**、而断电上电就彻底好?单测 `tests/test_vac_ref_reanchor.c` 实测出第二个机制:
```
现状公式 (V4.36.35): g_vacuum_ema += _ema_d / VACUUM_EMA_ALFA; /* 有符号整数除法 */
当 |_ema_d| < 128 时, 步进恒为 0 ⇒ 死区 ±127 counts
```
- 实测:让 EMA 从真空下方 200 counts 追赶,**40s 后停在真空下方 127 counts**= 2.59×dlt@SENS3)⇒ 因为 127 > 1×dlt`vac_ref()` 持续选中这个偏低的 EMA ⇒ **进入线常驻偏低 127 counts ≈ 0.10% Δf/f**
- 该偏差**不会自愈**:EMA 只会在 |d| ≥ 128 的样本上移动,而板离开后 d 稳定在 127 附近 ⇒ 需要长时间 CAPVD 噪声偶然越过阈值才缓慢爬升。
- 而**断电上电**时 `EMA = Origin`(判稳建立,精确相等,偏差 0),且此后 |d| < 128 ⇒ EMA 被"粘"在原地不动 ⇒ **永久保持正常灵敏度** ⇒ 这就是"断电上电就好了"的另一半原因。
- ⇒ 三层叠加:① 补偿一步拉开 Δ(≥4×dlt)② 边缘悬停把 EMA 拖低(≤4×dlt)③ **整数死区把 EMA 钉在真空下方 ~127 counts**。三者都让 `vac_ref()` 选到偏低的参考。
---
## 7. 现场验证(建议顺序)
**第 0 步先确认版本**DBG 行含 `VEM=`/`RLN=` ⇒ V4.36.31+,本分析适用;若老版本无 VEM,则走"Origin 被学高"的旧机理,需另判。
1. **抓日志**TTL):补偿会打印
- `EVT|env_learn_start Origin:.. CAPVD:.. dev:..`
- `EVT|env_resync Origin:..->.. CAPVD:..`
- 之后每 2s 的 `DBG|... Origin=.. VEM=.. RLN=..`
**判据**`Origin VEM > 1×dlt` 的持续时间 ≈ "触发高度异常"的持续时间;`RLN``Origindlt` 的差 ≈ 触发高度损失。
2. **单变量对照**(同一块板、同一高度序列):
(a) 补偿后立刻测 → (b) 黄灯灭后静置 10s(板远离)再测 → (c) 断电上电后测
预期 (b) 明显好于 (a)、(b)≈(c)。若 (b) 仍远差于 (c) ⇒ 另有固化路径(学习窗污染 Origin),需再取日志。
3. **固件对照实验(有权限时,最直接)**:临时在 `env_resync_apply()` 内加一行 `g_vacuum_ema = new_origin;` 复测 ⇒ 触发高度应与断电上电一致 ⇒ 根因钉死。
---
## 8. 修复候选(待拍板,暂不改源码)
| 方案 | 内容 | 风险/代价 |
|---|---|---|
| **A(最小对症)** | `env_resync_apply()``g_vacuum_ema = new_origin;`(与判稳完成建初值同语义:Origin 原子换 ⇒ 真空参考同步换) | 低。1 行;补偿后判定参考与 Origin 同时就位,黄灯灭即恢复正常灵敏度 |
| **B(通用护栏,建议叠加 A** | "Origin 大步跳变(\|Δ\| > k×dlt)即同步重锚 EMA":一次收口 `1188`(重连判稳对齐 Origin)、`1344`(冻结超时更新 Origin)等**同源**路径 | 低。把"Origin 动、EMA 不动"这类隐患统一堵住 |
| **C(稳健性,可选)** | 黄灯灭条件追加"\|Origin EMA\| ≤ 1×dlt" ⇒ 让"灯灭 = 判定参考已就位" | 低。可能让黄灯多亮 1~3s(现场需接受) |
| **D(建议叠加)** | EMA 更新改**余数累加器**(消 `d/128` 的 ±127 counts 整数死区) | 低。单测实测同条件偏差 **127→0 counts**;τ/噪声不变 |
| ✗ 不建议 | 进入线改回 `Origin dlt` | 会退回 V4.36.31 之前"Origin 学高 ⇒ 假 Car_In"devlog 20260904 已实锤) |
---
## 9. 待确认(现场)
- 测试固件的**版本号**(V4.36.31+ 才适用本文)
- 黄灯是**常亮**(=环境重校准,模式4)还是其他花样:一长一短=电感量出窗(模式5)/一长两短=156~171k(模式6)/快闪=断开·短路级(模式1)
- 线圈与 Q 档(33µH/23µH/35µH 现场差异大;V4.36.33 devlog 记 23µH 仍可复现)
- 触发补偿的动作("金属板拿走/搁置")与位移量 Δ 的量级
---
## 10. 补丁草案与验证(**已应用,未提交**)
| 产物 | 路径 | 规模 |
|---|---|---|
| 补丁 A+BOrigin/EMA 同步不变式) | `docs/patches/v4.36.41-A-B-origin-ema-sync.diff` | TaskLoop.h +1 TaskLoop.c +20 3 |
| 补丁 D(EMA 余数累加,消死区) | `docs/patches/v4.36.41-D-ema-frac-no-deadband.diff` | TaskLoop.c +13 2 |
| 新增单测 | `tests/test_vac_ref_reanchor.c` | 5 场景,`gcc -O0 -Wall -Wextra` 0 warning |
**A+B 核心**:新增 `origin_set_atomic()`,把"一步换 Origin"的 3 处(`env_resync_apply` / 重连判稳完成 `:1188` / 冻结超时更新 `:1344`)改为经由它 ⇒ 步长 > 1×dlt 时同步重锚 `g_vacuum_ema`(与 `VAC_REF_DELTA_DLT` 同口径 ⇒ 维持 `|OriginEMA| ≤ 1×dlt` 不变式)。上电首窗那处(`:701`)不需要改:EMA 在判稳完成建立、此前进入判定被 `g_loop_stable` 门控挡住。
**单测实测结论**
| 场景 | 现状行为 | 打补丁后 |
|---|---|---|
| 补偿(Δ=130 counts)后进入线 | 130457(低 130 = 2.65×dlt = **0.100% Δf/f** | 130587(低 **0** |
| 护栏:小步 20(≤1×dlt) / 大步 150 | — | 小步不动 EMA ✓ / 大步重锚 ✓ |
| V4.36.33 门控(OriginEMA = 30 / 130 | 用 Origin ✓ 用 EMA ✓ | 语义不变 ✓ |
| 上电(EMA=0 → 判稳=Origin | 进入线 = Origindlt ✓ | 不变 ✓ |
| EMA 追赶 40s(现状公式,起点 −200) | **停在真空下方 127 counts2.59×dlt** | 修复 D:偏差 **0** |
**已完成的验证**:① 两个补丁对干净树 `git apply --check` 通过,且 **A+B → D 顺序 apply** 通过;② `origin_set_atomic()` 独立 `gcc -fsyntax-only` 通过(确认在文件作用域,不在 `vac_ref()` 内);③ 大括号平衡 202/201 → **205/204**(成对增加);④ **8 个单测全绿**(原 7 个未受影响);⑤ 生成补丁过程中已修正两处结构缺陷(helper 误置于 `vac_ref()` 内、D 的 `if (_ema_d != 0)` 缺大括号)。
**应用/回退**`git apply docs/patches/v4.36.41-A-B-*.diff`(可再叠 `-D-*.diff`;两者 hunk 不重叠,已顺序 apply 验证);回退 `git apply -R``git checkout -- <file>`。**2026-09-11 更新:A+B 与 D 已按采纳决定应用到工作树(仍未提交)** —— `TaskLoop.h` +1 / `TaskLoop.c` +33 5(合计 +34 5);CRLF 保持(1825 行全 CR)、大括号 205/204 平衡、8 个单测全绿。回退:`git checkout -- utilities/`
**待拍板**:① 采用 A+B?② 叠加 D?③ 提交前要我同步 `version`/spec 表 + devlog 条目(V4.36.41)?
---
## 11. 现场日志实证(2026-09-11 `154log260911a.txt`):低Q 自激振荡的完整链条
**现象**:金属板缓慢接近并停在触发边界时,`Car_In`/`Car_OFF` 以 ~100ms 周期连续反复(16:34:50.17916:34:53.168 约 3s 内 ~30 次)。线圈 22µH / f=163kHz`EVT|coil_fault below_l_min_20_24u`)⇒ `g_q_lo=1` 低Q 路径。
**关键实测值**`Origin=129254`、进表 dlt=49SensTable 25)、释表 dlt=23SensTable_1 12)、`EMA≈129220``CAPVD/慢滤波≈129204`(深度 50 counts
**三步链条(全部可复核)**
1. **无车**`loop1_dlt_ORG`=49 ⇒ `vac_ref()` 门控阈值 = 1×49 = 49`OriginEMA`=34 **≯** 49 ⇒ **参考 = Origin** ⇒ 进入线 = 12925449 = **129205**。CAPVD=129204(差 1 count+ 5 样本确认 ⇒ `Car_In`
2. **进车瞬间**`loop1_dlt_ORG` 被切成释表值 23`TaskLoop.c:1577`)⇒ 同一个 gap(34) 现在 **> 1×23** ⇒ **`vac_ref()` 改用 EMA** ⇒ 释放线 = EMA 1.8×23 = 12922041 = **129179**= 日志 `RLN` 字段精确吻合 ✓)
3. **释放**`g_rel_smooth`(129204) > 129179 ⇒ 命中 ⇒ 5 样本确认 ⇒ `Car_OFF` ✓ ⇒ 回到步骤 1 ⇒ **自激**
**⇒ 滞回带反向重叠**:进入需"深于 **49**",释放只需"浅于 **75**"= 34 + 41)⇒ 深度落在 **(49, 75)** 的静止凹脉冲**同时满足两条判定** ⇒ 必然振荡。周期 = 进入确认 5 + 释放确认 5 = 10 样本 = **100ms**(与日志完全一致)。
**与 V4.36.41A+B/D)的关系**
- `vac_ref()` 切到 EMA 的**根因**是「门控阈值用了会随状态切换的 `loop1_dlt_ORG`」+「低Q ×1.8 释放带浅于 ×1.0 进入线」——V4.36.31/33 引入 vac_ref 时就埋下,**与 A+B/D 无关**。
-**DEMA 精确化)是"改变表象"的那一环**:旧版 EMA 有 ±127 死区,此深度下会被粘在 CAPVD 上方 ⇒ gap 为负 ⇒ 参考恒为 Origin ⇒ 释放线 = Origin41 = 129213 ⇒ 够不着 ⇒ 表现为**锁死**(不释放)而非抖动。⇒ D 把"锁死"变成了"抖",两者都不对。
- 另注:本文 §1–§10 的主结论(补偿后触发高度变低)**不受影响** —— 那段日志里 `OriginVEM ≤ 34 < 1×dlt``vac_ref()` 全程取 Origin ✓(先前仿真的"EMA 追赶扫开关"在实机上被"释放后 1s 冻结"抑制,量级被高估)。
**修复方向(待评审,先出方案不动代码)**
| 方案 | 内容 | 说明 |
|---|---|---|
| **G1 根因** | `vac_ref()` 门控阈值改用**固定进入表 dlt**(状态无关) | 参考线不再"进门瞬间跳 34 counts";进/出判定共用同一参考 |
| **G2 滞回一致** | 低Q 释放线强制**浅于**进入线:`rel_line ≥ vac_ref k×dlt_进`k<1,如 0.5)或夹紧 `rel_line ≥ entry_line + margin` | 消除 (49,75) 重叠带,恢复正向滞回 |
| **G3 通用抗抖** | 最小保持时间(进入后/释放后各 N ms 禁止反向) | 对所有 Q 档生效,掐断 100ms 级自激 |
| G4 现场 | 22µH/163kHz 落在电感量告警带(20–24µH);确认量产线圈选型 | 非量产线圈也要做 G1–G3(30µH 也可能落进重叠带) |
## 12. 修复 G1+G2+G32026-09-11 采纳并已应用到工作树)
> 决定:**D 保留 + 上 G1+G2+G3**E 单向方案留在 `docs/patches/v4.36.42-E-ema-oneway.diff` 备查,未采用)。
> ⚠ 关键前提(devlog 救命):`REL_BAND_LO_MULT=180`=41@SENS3)是 **V4.36.28 现场验证过的值** —— 23µH 板"快释放停住"回摆只到 `Origin36`,靠 41 才释放;**任何"缩小释放带"的改法都会把那个锁死改回来** ⇒ G2 只做兜底夹紧,绝不动 180。
| 方案 | 改动 | 位置 |
|---|---|---|
| **G1 根因** | 新增 `vac_gate_dlt()`= `Origin×SensTable[SENS]>>16`**状态无关**)并让 `vac_ref()` 用它做门控 ⇒ 进/出车用同一参考,不再在进门瞬间阶跃;与 `band_timeout` 的既有写法统一 | `TaskLoop.c:297` / `:307` |
| **G2 滞回兜底** | 低Q 释放带夹紧:`if (_band > vac_gate_dlt()) _band = vac_gate_dlt()-1;` ⇒ 未来参数变化若造成"反向滞回"自动兜住;今天 41<49 **不生效**(行为零变化) | `TaskLoop.c:341` |
| **G3 通用抗抖** | `REL_MIN_HOLD_TICKS=30`300ms):`Car_In` 后最小保持期内禁释放(`rel_release_hit()` 调用点加门),`Car_OFF` 清零;覆盖两种 `USE_SLOW_RELEASE` 配置。**不延迟检出**(只挡释放) | `TaskLoop.h:68` + `TaskLoop.c:1504/1600/1602/1628` |
**单测实证**`tests/test_vac_ref_reanchor.c` 场景 7,现场参数逐位复现 Origin=129254 / dlt 49·23 / EMA≈129220 / CAPVD 深 50):
| 版本 | 静止悬停 3s 内 Car_In / OFF |
|---|---|
| 现状 V4.36.41 | **300 / 300**(100ms 周期自激,与现场日志一致) |
| 同上,**35µH/128kHz** 参数(Origin=129141 / EMA 129109 / 深 53,日志 `154log260911b` | **300 / 300** → 修后 **1 / 0** ✓ |
| G1 | 1 / 0 ✓ |
| G1+G2 | 1 / 0 ✓ |
| G1+G2+G3 | 1 / 0 ✓ |
回归保护:撤板仍释放(1/1)✓;**V4.36.28 回摆释放(深度 36 < 带回 41)仍成立** ✓;全套 8 个单测全绿 ✓。
**双线圈差分验证(2026-09-11 两份现场日志)**22µH/163kHz(深 50、gap 34)与 35µH/128kHz(深 53、gap 32**同构自激** ⇒ 机理与线圈无关,只取决于
`f>100kHz`(两者都判 QLO=1,而设计窗上限 120~125kHz 对应 L≳37~40µH ⇒ **量产线圈同样落在低Q 档**)② 板停在深度 (49, 41+gap) 的重叠带。
⇒ 这不是测试线圈特例;停走排队车辆恰好停在环线边缘时同样会踩到(对流量计数即重复计数)。
**G3 权衡(现场可选调)**:300ms 最小保持会让**真实车辆离开时的释放**最多晚 300ms(对存在型/流量计数无影响;若做速度估计或需要更快的释放沿,可把 `REL_MIN_HOLD_TICKS` 降到 10=100ms)。
## 13. 返工记录:V4.36.42 的 G3 放置错误(V4.36.43 修正)
现象:烧 V4.36.42 后**离开 3、4 秒才释放**;日志 4 次 `Car_OFF` **全是 `band_timeout`**(环带兜底),延迟 3.5~4.7s`RLN` 正常(有车态 = `Origin41`)⇒ G1 目标达成(100ms 自激消失),但正常释放从未命中。
根因:`g_rel_hold_tick--` 被放进 **`if (!loop1_VD_FLAG)`(无车)分支**(原 `:1308`)⇒ 有车期间永不递减 ⇒ 首次 `Car_In` 后常驻 30 ⇒ `g_rel_hold_tick == 0` 永假 ⇒ 正常释放被永久挡住。
修正:移到 **`} else {`(有车)分支顶部**`:1531` 后、`#if USE_FLATNESS_EXIT` 之前,每 tick 必过且在释放判定之前)。
**教训(已同步进单测注释与 skill)**
1. 镜像单测只验证**算法语义**,**验证不了固件内执行路径/位置**(计数器在哪个分支递减、是否每 tick 必过)⇒ 这类错误必须靠**日志的原因字段**(`Car_OFF(band_timeout)` / `Car_OFF_FLAT` / 普通)暴露。
2. 凡是"进入后 N 秒/N tick 生效"的守卫,实现后**先查递减调用点是否在每 tick 必经路径上**,再上板。
## 附:相关历史(devlog
| 版本 | 内容 |
|---|---|
| V4.36.29/30 | Origin 过冲 + 释放带压缩 → 低Q 卡死 75s;引入环带超时兜底 |
| V4.36.31 | 引入真空 EMA `vac_ref()=min(Origin,EMA)`,修"Origin 学高 ⇒ 释放线偏高/假触发" |
| V4.36.33 | vac_ref 加 1×dlt 门控,修"**边缘悬停拉低 EMA ⇒ 触发高度漂移**"(本文同机理,量级更大) |
| V4.36.34/35 | EMA 内存污染与 cast 爆炸源修复(`(uint32_t)(_ema_d/128)` |
| V4.36.36/38 | 就绪巩固期 Q 分级;电感量告警模式 6 |
---
*分析日期:2026-09-11 证据:`TaskLoop.c` / `TaskLoop.h` / `tests/test_env_resync.c` / `docs/devlog.md` 逐行核对*