# 测量节拍不是常数:周期累积法的窗口量化(`floor(BASE/Xn)·Xn`) > **2026-09-11** · 起因:指出 `void CAP1_isr()` 里 `loop1_Value = loop1_CapSum`(累加 LPCNT 个 `Xn`)与 `loop1_LPCNT = 32768/loop1_Xn` 的**整数除法** ⇒ **测量节拍是区间,不是定值**。 > 适用:**PD132T / PD136HA / M1H**(BASE=32768 同族,代码逐行同构);**DLD154V4B / 154Pro 同理**(BASE 不同,误差更小,见 §7)。 ## 0. 结论 | # | 结论 | 说明 | |---|---|---| | 1 | **测量窗 = `floor(BASE/Xn₀) · Xn₁ / f_cap`** | `Xn₀` = 学习时算得并**冻结**的周期计数;`Xn₁` = 当前周期计数 | | 2 | **标称值 `BASE/f_cap`(10.92 / 21.85ms)是上限,不是真值** | 实际窗 = `BASE − (BASE mod Xn₀)` 个 tick ⇒ **只短不长** | | 3 | 站点偏差 = `(BASE mod Xn₀)/BASE` ⇒ 带内 **0 ~ −6.2%** | Xn₀ 越接近带低端(2050)越短;典型 100kHz 线圈(Xn₀=480)为 **−0.39%** | | 4 | 另有**频率跟踪分量**:窗时长 ∝ `1/f_now` | 阈值量级(≤0.46%)可忽略;**深占压**(线圈频偏 −5%)时窗变长 +5.3% | | 5 | ⭐ **Δf/f 口径完全不受影响** | `Value/Origin = Xn₁/Xn₀` **精确成立**(整除余数 r 在分子分母**完全约掉**)⇒ 既有灵敏度/交付结论全部保持 | | 6 | ⚠ **`loop1_LPCNT` 声明为 `INT8U`(≤255)** | 同族靠 `406 < Xn < 2050` 保证 `LPCNT ≤ 80`;**PD136HA 已把该窗口注释掉** ⇒ `Xn < 129`(线圈 >372kHz)会 8 位溢出(§5) | --- ### 0.1 符号约定(先钉死,避免把曲线画反) | 环节 | 车辆进入时的方向 | |---|---| | 线圈电感 `L` | **↓**(涡流去磁为主;铁磁体不改变结论方向) | | 谐振频率 `f` | **↑**(`f = 1/(2π√(LC))`);典型 Δf/f = **+0.02% ~ +1%**,大车/深占压可达 **+5%** | | 分频后周期 / `Xn`(`∝ 1/f`) | **↓** | | `Value` / `CAPVD`(`∝ Xn`) | **↓** ⇒ 判据 `CAPVD < Origin − dlt` 取的正是**下降侧** ✓ | | 测量窗时长(`∝ 1/f`) | **↓**(−0.02% ~ −4.8%) | 与交付报告一致的关系式:`CAPVD ≈ BASE·f₀/f` ⇒ `(Origin − CAPVD)/Origin ≈ Δf/f`(**车辆时 > 0**)✓ ⇒ **"深占压"= 频率升高、窗长缩短**;旧稿"频偏 −5% ⇒ 窗 +5.3%"方向写反,2026-09-11 已改正(窗长公式 `∝ f₀/f_now` 本身对两个方向都成立,只是场景标注错了)。 ## 1. 代码机理(PD132T / PD136HA 逐行同构) ```c /* PD132T main.c:96-105 / PD136HA main.c:163-172 —— 学习期:LPCNT 算一次后冻结 */ if (loop1_INI_LOOP) { if (loop1_LPCNT == 0) { if (loop1_CapCnt > 100) { loop1_LPCNT = 32768 / loop1_Xn; // ← 整数除法,截断 if (loop1_LPCNT == 0) loop1_LPCNT = 1; // Xn>32768 时兜底 loop1_CAPVD = 0; loop1_CapSum = 0; loop1_CapCnt = 0; } } } /* 测量期:累加 LPCNT 个 Xn */ loop1_CapSum += loop1_Xn; if (loop1_CapCnt >= loop1_LPCNT) { loop1_Value = loop1_CapSum; // = Σ(LPCNT 个 Xn) loop1_CapSum = 0; loop1_CapCnt = 0; } ``` 关键性质(两条都容易被忽略): 1. **`LPCNT` 是"一次冻结"**:只在 `LPCNT == 0` 且 `CapCnt > 100` 时计算一次,此后不再重算;只有 `INIT_VD()`(学习/复位)才 `LPCNT = 0` 重新标定。 2. **`CapCnt++` 发生在累加之前**(PD132T:83 / PD136HA:148)⇒ 判据触发时 `CapSum` 恰好含 **LPCNT** 项 ⇒ `Value = LPCNT × Xn`(Xn 恒定时)✓ ⇒ 因此:**窗长(tick)= `LPCNT × Xn₁` = `floor(BASE/Xn₀) × Xn₁`**,而**不是**恒定 `BASE`。 --- ## 2. 代数:窗为什么"只短不长",而口径为什么不受影响 记 `BASE = 32768`,`r₀ = BASE mod Xn₀`,则 ``` LPCNT = (BASE − r₀) / Xn₀ (整数除法) 窗长(tick) = LPCNT · Xn₁ = (BASE − r₀) · (Xn₁ / Xn₀) (Xn₁ = 当前值) 窗时长 = 窗长(tick) / f_cap ``` **两条分量**: | 分量 | 表达式 | 量级 | 性质 | |---|---|---|---| | ① 整除余数量化 | `(BASE − r₀)/BASE` | 带内 **0 ~ −6.2%** | **站点确定值**(不抖动;随该站点线圈频率而定) | | ② 频率跟踪 | `Xn₁/Xn₀ = f₀/f_now` | 阈值内 ≤ +0.46%;深占压 +5% 量级 | 与频偏**同向**(频率跌 ⇒ 窗变长) | **口径为什么不受影响**(最重要): ``` Origin = LPCNT · Xn₀ = BASE − r₀ (学习值) Value = LPCNT · Xn₁ (当前值) Value / Origin = Xn₁ / Xn₀ ← 精确,r₀ 完全约掉 ✓ ``` ⇒ 相对量 `Δf/f = 1 − Value/Origin` **与 r₀、与 BASE、与 f_cap 全部无关** ✓(数值验证:Xn₀ = 406/480/800/2050 四种站点,频偏 0.5% 时 `Value/Origin` 均精确等于 `Xn₁/Xn₀`)。 唯一残留误差是判据阈值的**截断**:`dlt = Origin × 表值 >> 16` ⇒ 有效阈值 = `表值/65536 ± 1/Origin`,即 **±0.003%**(1/32768)—— 可忽略。 ## 3. 数值表(按站点线圈频率) `Xn₀ = C / f_coil`(族内 `C = 32·f_cap/边沿系数 = 4.8×10⁷`,PD132T/PD136HA 通用): | 线圈频率 | Xn₀ | LPCNT | 窗长(tick) | PD132T 窗@3MHz | 偏差 | PD136HA 窗@1.5MHz | 偏差 | M1H 窗@4MHz | |---|---|---|---|---|---|---|---|---| | 240 kHz | 200 | 163 | 32 600 | 10.867 ms | −0.51% | 21.733 ms | −0.51% | 8.150 ms | | **100 kHz(标称)** | 480 | 68 | 32 640 | **10.880 ms** | **−0.39%** | **21.760 ms** | **−0.39%** | 8.160 ms | | 60 kHz | 800 | 40 | 32 000 | 10.667 ms | −2.34% | 21.333 ms | −2.34% | 8.000 ms | | 40 kHz | 1200 | 27 | 32 400 | 10.800 ms | −1.12% | 21.600 ms | −1.12% | 8.100 ms | | 23.4 kHz(带低端) | 2050 | 15 | 30 750 | 10.250 ms | **−6.16%** | 20.500 ms | −6.16% | 7.688 ms | | (带内最差) | 2049 | 15 | 30 735 | 10.245 ms | **−6.20%** | 20.490 ms | −6.20% | 7.684 ms | **读法**:`10.92 ms` / `21.85 ms` 是**标称上限**;具体站点按上表由**线圈频率**决定(偏差随 `LPCNT` 变小而变大 —— 低频线圈的窗更短、量化更粗)。 **积分深度**(每窗平均的有效线圈周期数)同样按此缩放:PD132T ≈ `16·LPCNT`、PD136HA ≈ `32·LPCNT`(100kHz 站点:1088 / 2176 个线圈周期)。 --- ## 4. 频率跟踪分量(窗随时间"伸缩") 因为 `LPCNT` 冻结、而窗累加的是**当前**周期,所以: ``` 窗时长(t) = 窗长(tick)/f_cap = (BASE − r₀)/f_cap × (f₀ / f_now) ``` | 线圈频偏 | 窗时长变化 | 现场含义 | |---|---|---| | −0.032%(PD132T 档 3 阈值) | +0.032% | 可忽略 | | −0.458%(PD132T 档 0 阈值) | +0.460% | 可忽略 | | −1% | +1.01% | 温度漂移量级 | | **−5%** | **+5.26%** | **大车/拖车深占压**:窗变长 ⇒ 恢复更慢 | ⇒ 结论:**在"检测阈值"量级上可忽略(≤0.5%),在"深占压"场景下会把响应/恢复时间再拉长百分之几**。这也解释了为什么"深占压后基线跟踪慢"的代码设计(冻结 + `LC_HOLD` 重学)是必要的。 --- ## 5. ⚠ 位宽与窗口检查(本轮新发现) | 变量 | 类型 | 上限 | 约束 | 风险 | |---|---|---|---|---| | `loop1_LPCNT` | `INT8U`(PD132T main.h:37 / PD136HA main.h:64) | **255** | `LPCNT = 32768/Xn ≤ 255` ⇒ 需 `Xn ≥ 129` | ⚠ 见下 | | `loop1_CapCnt` | `INT8U` | 255 | 需 `LPCNT ≤ 255`(同上) | 同上 | | `loop1_CapSum` / `Value` / `CAPVD` | `INT16U` | 65 535 | 标称 32 768(**余量 2×**) | 频率下漂 >100%(Xn 翻倍)才溢出 ⇒ 现实不可达 | **同族靠频率窗口保护 8 位 LPCNT**:`406 < Xn < 2050` ⇒ `LPCNT ≤ 80` ✓(PD132T main.c:85、M1H 同构)。 **PD136HA 已把该窗口注释掉**(`// if(loop1_Xn>400 && loop1_Xn<2030)`,main.c:150,V3.14 去环路 LED 时一并屏蔽)⇒ **保护消失**: - 若 `Xn < 129`(等效线圈 > 372 kHz,例如线圈断线/短路的异常振荡、或强干扰产生的窄脉冲)⇒ `LPCNT` 真值 >255 ⇒ **8 位截断**(如 327 → 71)⇒ 窗长骤降(71×Xn)而 `Origin ≈ 32768` ⇒ `Value ≪ Origin − dlt` ⇒ **判为"持续有车"** ⇒ 继电器吸合 → HOLD 300s 超时 → 整机复位。 - 对比 **PD132T**:同样的异常会走 `LOOP_OK = 0` + LED 快闪(**故障指示**,不产生有车输出)。 - ⇒ **行为差异**:同一种线圈异常,PD132T 报"故障",PD136HA 可能报"堵车"。 - **建议**(固件侧,待评估):PD136HA 恢复窗口检查,或至少加 `if (loop1_LPCNT > 80) → 判故障` 的兜底钳制。 > 同类检查也适用于 M1H(同 8 位 `LPCNT` + 无窗口检查 ⇒ 同风险)。**注意**:PD132T 的窗口检查同时承担"线圈异常 → 故障"的职责,恢复/删除前要确认异常语义有替代路径。 --- ## 6. 受影响 / 不受影响(既有数值的正确读法) | 类别 | 项目 | 处置 | |---|---|---| | ✅ **不受影响** | `Δf/f = 表值/65536` 口径、灵敏度表换算、跨型号档位对比、进入/离开判据、滞回语义 | 保持不动(§2 代数保证) | | ⚠️ **同一因子缩放** | 测量节拍、基线更新周期、IIR 时间常数 τ、进入/离开响应时间、最小可检占压、积分深度 | 表中数值标注"**标称(上限)**",实际 = 标称 × `(BASE−r₀)/BASE` × `f₀/f_now` | **修正后的表述模板**(建议全仓沿用): > 测量节拍 **≈10.88 ms**(标称上限 10.923 ms = 32768/3MHz;实际 = `floor(32768/Xn₀)·Xn₀/f_cap`,100kHz 站点 −0.39%,带内最差 −6.2%) 例:PD132T 基线更新周期 = 100 × 10.88ms = **1.088 s**(标称上限 1.092s);PD136HA = 256 × 21.76ms = **5.571 s**(标称上限 5.593s)。 --- ## 7. 跨型号意义:BASE 越大量化误差越小 站点量化误差上限 = `Xn₀/BASE`(= `1/LPCNT`): | 型号 | BASE | 100kHz 站点 Xn₀ | LPCNT | 窗量化误差上限 | |---|---|---|---|---| | M1H / PD132L / PD132T / PD136HA | 32 768 | 480(PD132T/136HA) | 68 | **≤1.46%**(带低端 ≤6.25%) | | DLD154V4B | 131 072 | 1200 | 109 | ≤0.92% | | DLD154Pro | 524 288 | 600 | 873 | ≤0.11% | ⇒ **大基数的第二个好处**(除既有"绝对分辨率高 4×"之外):**同比降低窗量化误差** —— 因为 `LPCNT` 更大,"`floor` 截断"的相对损失更小。V4B 的 1.09ms 窗实际为 ≈1.09ms(−0.9% 上限),154Pro 的 8.74ms 窗几乎无量化损失。 --- ## 8. 验证与复算方法 1. **纯计算**(现场 5 分钟):量出线圈频率 `f_coil` ⇒ `Xn₀ = C/f_coil`(`C = 4.8×10⁷`,PD132T/PD136HA 通用)⇒ `LPCNT = ⌊32768/Xn₀⌋` ⇒ 窗长 = `LPCNT·Xn₀` tick ⇒ 窗时长 = 窗长/`f_cap`。可算到 0.1% 以内。 2. **固件侧**:把 `loop1_LPCNT` / `loop1_Value` 引到可用观测(PD132T 无 UART ⇒ 需临时改 LED 或 ISP 读 RAM;PD136HA 有 SWD ⇒ 直接在线看变量最省事)。 3. **回归验证**:若实测"基线更新时间"与 `窗长×100(256)` 不符,说明 `LPCNT` 被二次重算过 —— 检查是否存在第二处 `LPCNT = 0`(PD132T `INIT_VD()`、PD136HA main.c:411;其 430 行为注释状态)。 4. **台架**:信号发生器替代 CD4060 输出已知 f_in ⇒ 交替改频率 0.1%/0.5%/2%,观察继电器翻转窗口数与理论 `dlt` 是否一致(验证 §2 的"口径精确"结论)。 --- ## 9. 时序链详解:六个量的更新时间(2026-09-11 补,用户提出) ![PD132T 端到端时序图:三段横轴 —— ① 一个窗(0~11.2ms)② 检测到输出(0~600ms)③ 基线块平均(0~12s)](img/timing-chain-pd132t.png) > 矢量版(可放大/edit):`docs/img/timing-chain-pd132t.svg`(由 `tools/plot_timing_chain.py` 生成,纯 stdlib 手写 SVG;图中曲线按 §1~§4 公式**真算**而非示意): > `python3 tools/plot_timing_chain.py && chromium --headless=new --disable-gpu --no-sandbox --default-background-color=FFFFFFFF --window-size=1680,1560 --screenshot=docs/img/timing-chain-pd132t.png file://$PWD/docs/img/timing-chain-pd132t.svg` 整条链是**三级降采样**:捕获级(每 `Xn` 一次)→ 窗级(每 `LPCNT` 次捕获一次)→ 基线级(每 100/256 窗一次)。 ``` 捕获中断(PCA/ADTIM4) 窗结账(ISR 内) 主循环(紧随其后) 块平均 │ │ │ │ 每 t_Xn 一次 每 LPCNT 次捕获 每次 Value 更新 每 100/256 窗 ├── Xn = 相邻捕获差 ────► ├── Value = Σ Xn ────────► ├── CAPVD = IIR(Value) ──► ├── Origin = ΣCAPVD/N │ (6.25 kHz) │ (92 Hz) │ (92 Hz) │ (0.92 Hz) └── 频率窗口检查(若启用) └── CAP_OK = 1 └── 判据 dlt = Origin×表>>16 ``` ### 9.1 六个量逐一(PD132T @ 100kHz 站点,`Xn₀=480`、`LPCNT=68`) | 量 | 更新触发 | 更新周期 | 物理含义 | |---|---|---|---| | **`loop1_Xn`** | **每次捕获中断**(相邻两次捕获之差) | `t_Xn = Xn/f_cap = **160 µs**`(6 250 次/s) | ÷32 后信号的**半周期** = **16 个线圈周期**(双沿捕获) | | **`loop1_Value`** | ISR 内 `CapCnt >= LPCNT` 时 | `LPCNT·t_Xn = **10.880 ms**`(92 次/s) | `LPCNT` 个 `Xn` 之和(= 窗)⇒ 同步置 `CAP_OK=1` | | **`loop1_CAPVD`** | 紧随其后调用 `VD1_TASK()`(主循环) | **10.880 ms**(与 Value 同拍) | IIR 平滑值:`CAPVD += (Value−CAPVD)·Flt_Reg>>8` | | **`loop1_Origin`** | `VD1_TASK()` 内 `ORG_CNT == 99` 且**无车** | **100 窗 = 1.088 s**(0.92 次/s) | `Origin = ORG_SUM/100`(**块平均**,非滑动) | | **测量节拍** | = `Value`/`CAPVD`/判据的共同节拍 | **10.880 ms**(标称上限 10.923) | 见 §1-§3(区间值,按站点 −0.4%~−6.2%) | | **基线更新周期** | = `Origin` 的更新间隔 | **1.088 s**(标称上限 1.092 s) | 块粒度 ⇒ 基线跟踪"阶梯式" | | IIR 时间常数 **τ** | — | α79: **35.3 ms**(= **3.24 窗**)/ α64: **43.5 ms**(= **4.0 窗**) | `τ = T·256/α` | ### 9.2 同表:PD136HA @ 100kHz(`Xn₀=480`、`LPCNT=68`,f_cap 减半) | 量 | 更新周期 | 与 PD132T 的比 | |---|---|---| | `loop1_Xn` | `480/1.5MHz = **320 µs**`(3 125 次/s) | ×2(单沿 ⇒ 整周期 = **32 个线圈周期**) | | `loop1_Value` | `68 × 320µs = **21.760 ms**`(46 次/s) | ×2 | | `loop1_CAPVD` | **21.760 ms** | ×2 | | `loop1_Origin` | `256 窗 = **5.571 s**` | ×5.1(256/100 × 2) | | τ(α64) | **87.0 ms** = **4.0 窗** | 窗数相同、绝对 ×2 | ### 9.3 四条容易搞混的关系(重点) 1. **`t_Xn = 前端分频比 /(边沿系数 · f_coil)`** —— PD132T = `16/f_coil`、PD136HA = `32/f_coil`、M1H = `32/f_coil`(双沿 ⇒ 16,单沿 ⇒ 32)。**`Xn` 是"测量结果"而不是"时间源"**:它本身随线圈频率变化(`Xn ∝ 1/f`),所以"更新周期"必须写成 `Xn/f_cap`(随站点变),而不是常数。 2. **`Value` 是"计数域降采样",不是抽点**:`Value = Σ(LPCNT 个 Xn)` 是**箱式积分**(boxcar),因此 `Xn` 的 6.25kHz 信息在 92Hz 处**被平均而不是被丢弃**(无混叠问题);这也是 `Δf/f` 口径精确的来源(§2)。 3. **τ 换算成"窗"后与型号无关**:`τ/T = 256/α` ⇒ α79 = **3.24 窗**、α64 = **4.0 窗**(与 BASE、f_cap、分频比全无关)⇒ 讨论"滤波快慢"时用"窗"最直观。 4. **`Origin` 是块平均**:每 100(PD136HA 256)个 `CAPVD` 才整体替换一次 ⇒ **基线跟踪的时间分辨率 = 1 个块**(1.09 s / 5.57 s),块内一直用"上一个块的均值"。有车期间 `ORG_SUM` 被清零且 `ORG_CNT` 停止 ⇒ **有车冻结 + 重新累计**(不是"有车也跟踪")。 ### 9.4 响应链:三段叠加 | 段 | 延迟 | 说明 | |---|---|---| | ① 窗内平均 | ≤ 1 窗(≤10.9 / 21.8 ms) | 变化要"填满"当前窗才在 `Value` 中完整体现 | | ② IIR 上升到阈值 | `≈ τ·ln(Δ/(Δ−阈值))` | 大信号快(Δ=1% vs 阈值 0.09% ⇒ ≈0.09τ ≈ 3ms);小信号慢(Δ≈阈值 ⇒ 多个 τ) | | ③ 输出级 | 50 ms 节拍(PD132T/M1H;PD136HA tick ⚠待实测) | `FLAG_IN` 在 T1 ISR 里被消费;进入确认 PD132T = **0**(立即,无 IN_DELAY 判定)、M1H = `IN_DELAY=10`≈0.6 s | ⇒ 例:PD132T 大车(Δ≈1%)⇒ ≈10.9 + 3 + ≤50 ≈ **≤65 ms**;PD136HA 同条件 ⇒ ≈21.8 + 6 + ≤50 ≈ **≤80 ms**(IIR 更慢但窗长翻倍是主因)。 ### 9.5 上电初期的一个易忽略点 `INI_LOOP` 结束时(`CapCnt>100` 后第一个满窗)执行的是: ```c loop1_CAPVD = loop1_CapSum; loop1_Origin = loop1_CAPVD; loop1_INI_LOOP = 0; ``` ⇒ **上电时 `Origin` 只有一个窗的样本**(92Hz 单点、噪声最大),要等**第一个块(100/256 窗 = 1.09 s / 5.57 s)** 完成才变成块平均 ⇒ 这就是"上电静默期/学习期"必须留足时间的根本原因(PD136HA 侧更长,5.6 s)。 --- ## 相关文档 - 双型号对比:`docs/pd132t-vs-pd136ha-comparison.md`(§3 测量与归一化) - 跨型号总表:`docs/cross-model-comparison.md`(测量节拍/基线周期行) - 滤波系数专题:`docs/filter-coefficient-79-vs-64.md`(τ 口径) - 交付对齐:`docs/pd136ha-to-dld154v4b-delivery-alignment.md`、`docs/pd132t-to-v4b-delivery-alignment.md`