Files
vd-analysis/docs/measurement-window-quantization.md
T
wangfq 3a679ee373 docs(measurement): §9 时序链详解 —— Xn / Value / CAPVD / Origin 六个量的更新时间(用户提出)
- 三级降采样链:捕获级(Xn,6.25kHz)→ 窗级(Value/CAPVD,92Hz)→ 基线级(Origin,0.92Hz)
- PD132T @100kHz:Xn=480tick=**160µs**(÷32 后信号的半周期 = 16 个线圈周期)/
  Value = 68×160µs = **10.880ms** / Origin = 100 窗 = **1.088s**
- PD136HA @100kHz:Xn = **320µs**(整周期 = 32 个线圈周期)/ Value = **21.760ms** / Origin = 256 窗 = **5.571s**
- τ 换算成"窗"后与型号无关:τ/T = 256/α ⇒ α79 = 3.24 窗、α64 = 4.0 窗
- Origin 是**块平均**(`ORG_SUM/100`;PD136HA `>>8`),非滑动平均 ⇒ 基线跟踪粒度 = 1 个块;
  有车期间 ORG_SUM 清零 + ORG_CNT 停止 ⇒ 冻结 + 重新累计
- 上电首个 Origin 只有**单窗样本**(92Hz 单点),需 1.09s / 5.57s 才变块平均 ⇒ 学习/静默期长度的根本依据
- 响应链三段:①窗内平均 ≤1 窗 ②IIR ≈ τ·ln(Δ/(Δ−阈值)) ③输出级 50ms tick(PD132T 进入确认 = 0)
- 精化跨型号表 PD132T「进入确认」表述(无 IN_DELAY 判定,而非"已注释");表格校验 0 异常
2026-09-11 09:35:56 +08:00

243 lines
16 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.
# 测量节拍不是常数:周期累积法的窗口量化(`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 |
---
## 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:150V3.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 时间常数 τ、进入/离开响应时间、最小可检占压、积分深度 | 表中数值标注"**标称(上限)**",实际 = 标称 × `(BASEr₀)/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 | 480PD132T/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 读 RAMPD136HA 有 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 补,用户提出)
整条链是**三级降采样**:捕获级(每 `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 += (ValueCAPVD)·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.1256/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` 是块平均**:每 100PD136HA 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/M1HPD136HA 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`