Files
vd_960/vd960Loop/docs/variation-analysis.md
T
wangfq db52f92348 docs: 新增 variation 上报量分析报告
分析 uart_report_packet_loop_acs 中 variation=|Origin-CAPVD| 的更新机制:
- 三操作数节奏: CAPVD~10ms / Origin 5s阶跃 / 上报窗150/600ms采样
- Origin 基线状态机: 稳定期(win100~1s)/正常(win500~5s)/冻结/冻结超时(~10s)/有车冻结
- 波形特征: 无车漂移锯齿波、车辆驻留干净跟随、大干扰防污染冻结
- 风险: 采样混叠、2B截断回绕、锯齿谷误判空闲、稳定期切换拐点
2026-07-14 11:47:19 +08:00

148 lines
6.5 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.
# variation 上报量分析报告
> 分析对象:`uart_report_packet_loop_acs()` 中上报的 **变化量 variation**
> 涉及文件:`src/main.c`(组包)、`src/TaskLoop.c`(基线/IIR 更新)、`inc/TaskLoop.h`(参数宏)
> 结论层次:物理层 → 信号层 → 数据层 → 上报调度层
---
## 0. 一句话结论
`variation = |loop_Origin loop_CAPVD|`,是 **"慢阶跃基线"** 与 **"快速跟踪当前值"** 两个不同时间尺度量的瞬时差。
它在 **每次组包时实时计算**,本身无独立状态;真正决定其波形形态的是三个错位的时钟:
- `loop_CAPVD`**≈10ms** 采样
- `loop_Origin`**5s 阶跃** 更新
- 上报的 **150ms / 600ms** 采样窗
三者不同步 → 无车时 variation 天然呈 **锯齿波**
---
## 1. 定义位置
`src/main.c``uart_report_packet_loop_acs()` 组包段:
```c
// 变化量 (2B, LE)
uint32_t variation = (unit->loop_Origin > unit->loop_CAPVD)
? (unit->loop_Origin - unit->loop_CAPVD)
: (unit->loop_CAPVD - unit->loop_Origin);
g_pkg_uart_report.pkg[i++] = (uint8_t)(variation & 0xFF);
g_pkg_uart_report.pkg[i++] = (uint8_t)((variation >> 8) & 0xFF);
```
-`|Origin CAPVD|`,无符号,无方向信息
- 仅上报低 **2 字节**(≤ 65535),高位被截断
---
## 2. 三个操作数的更新节奏
| 量 | 物理含义 | 更新触发 | 真实周期 | 特性 |
|---|---|---|---|---|
| `loop_CAPVD` | IIR 后当前线圈值 | 每次 `loop_CAP_OK``vd1_task_per_channel()` | **≈10ms**(固定测量窗 `LPCNT×Xn≈131072` timer counts | 快,τ≈32ms,斜率限幅 5% |
| `loop_Origin` | 基线 | `update_moving_average()` 窗口满才写 | **阶跃式**(见 §3) | 慢,平台期恒定不动 |
| `variation` | 上报的变化量 | 每次组包现算 | 被 **上报窗采样**:事件 150ms / 空闲 600ms | 瞬时差,2 字节 |
> 关键点:`variation` 没有独立状态,它只是组包那一刻两值之差。
> 它的"更新周期"实际是 **上报采样周期**150/600ms);它的"波形形态"由 Origin 的阶跃周期决定。
上报间隔宏(`inc/TaskLoop.h`50ms tick):
```c
#define REPORT_IDLE_TICKS 12 // 空闲稳定: 12×50ms = 600ms
#define REPORT_EVENT_TICKS 3 // 事件/变化: 3×50ms = 150ms
```
上报调度还叠加了 **上电 3s 抑制**`misc_counter < 60` 跳过,等基线稳定)。
---
## 3. loop_Origin 基线更新的状态机(核心)
`update_moving_average()`**累加到窗口满才写一次**,中途 Origin 岿然不动:
```c
*p_sum += new_value; (*p_cnt)++;
if (*p_cnt >= window) { // 只有这里改写 Origin
*p_origin = *p_sum / window;
*p_cnt = 0; *p_sum = 0;
}
```
| 状态 | 判据 | window | 阶跃周期 @10ms | 对 variation 的影响 |
|---|---|---|---|---|
| **稳定期** | `!loop_stable``stable_cnt < 128` | 100 | **~1s** | 上电快速收敛,`CAPVD = Value` 直通 |
| **正常跟踪** | 无车 & `dev < dlt_ORG×4` | **500** | **~5s** | Origin 每 5s 阶跃一次,锯齿主因 |
| **冻结** | 无车 & `dev ≥ dlt_ORG×4` | — | `ORG_CNT/SUM` 清零,**不更新** | Origin 锁死,variation 保持大值 |
| **冻结超时** | 冻结持续 & 漂移 <±2% 达 1000 次 | — | **~10s 一次性抓取** | Origin 直接 = CAPVDvariation **突然归零** |
| **有车** | `loop_VD_FLAG == 1` | — | 不进基线分支 | Origin 全程冻结,variation 忠实跟随 CAPVD |
相关参数宏(`inc/TaskLoop.h`):
```c
#define STABLE_SAMPLES 128 // 稳定期样本数
#define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500×10ms = 5s)
#define FREEZE_TIMEOUT 1000 // 冻结超时 ~10s @10ms
#define FREEZE_STABILITY_RATE 2 // 稳定性窗口 ±2%
#define MAX_SLOPE_RATE 5 // 斜率限幅 5%
#define ENTRY_CONFIRM 3 // 进入确认次数
```
---
## 4. variation 波形特征
### 场景 1 — 无车缓慢漂移(温漂 / 湿漂),最典型
```
CAPVD ─╱╱╱╱╱ 持续缓慢漂移(每10ms微动)
Origin ───┐ ┌───┐ ┌── 每5s阶跃追一次
└────────┘ └────────┘
variation: | | | | ← 锯齿波!
峰=5s漂移量, 谷≈0(基线刚追上)
```
- 5s 窗口内 Origin 恒定,CAPVD 漂 → variation 线性爬升
- 窗口边界 Origin 阶跃到近 5s 均值 → variation **突然跌回 ~0**
- **锯齿幅度 ≈ 漂移速率 × 5s**;变频器干扰下漂移快,齿更高
### 场景 2 — 车辆进入 / 驻留(设计正确 ✅)
- 车进入瞬间 `ORG_CNT/SUM` 清零 + `VD_FLAG=1`Origin **完全冻结**
- variation 快速跟随 CAPVD 拉大 → 真实反映车辆信号强度,干净无锯齿
### 场景 3 — 大干扰但非车(半截车 / 邻道串扰 / 金属堆放)
- `dev ≥ dlt_ORG×4` 触发冻结,variation 维持大值不被基线"吃掉"
- 偏差稳住 ±2% 达 10s 后,Origin 一次性重锁,variation 突降 → 防污染 + 慢速重学基线
---
## 5. 需警惕的问题(直击要害)
1. **采样混叠**:用 600ms 上报窗去采一个 5s 阶跃量。后台若按单次 variation 做实时判断,会看到同一个齿被多次采到不同高度,叠加 600ms/5s 相位漂移 → 看似"忽大忽小"。
**后台不能拿单次 variation 当绝对阈值**,应看趋势或直接用 MCU 已判好的 `car_state`
2. **2 字节截断**`variation` 仅发 2B(≤65535)。CAPVD≈131072 量级,正常 Δf/f 才百分之几,一般到不了 65535;但 **冻结场景下偏差若超 65535 会回绕**
→ 建议加饱和:`if (variation > 0xFFFF) variation = 0xFFFF;`
3. **锯齿谷值≈0 误导"无车确认"**:若有逻辑用 `variation < 小值` 判"绝对空闲",会在每个 5s 边界被误触发。
→ 判空闲以 `car_state` / `loop_VD_FLAG` 为准,variation 仅作辅助幅度参考。
4. **稳定期 window=100 → 正常 500 的切换**:上电 1s 尺度基线,128 样本后切 5s 尺度。过渡期 variation 锯齿周期从 1s 突变到 5s,后台做周期特征分析要注意此拐点。
---
## 6. 待现场验证
- `loop_CAP_OK` 的 ~10ms 为 devlog 设计值。**实际周期取决于 TMR3 时钟与线圈频率**,建议现场用示波器量相邻两次 `CAP_OK` 间隔确认。
---
## 7. 后续可选改进方向
- 将 variation 改为上报 **斜率 / 趋势** 而非瞬时差,削掉锯齿混叠
- 补 variation **饱和保护 + 随包上报当前状态(跟踪 / 冻结 / 有车)**,让后台区分锯齿谷与真空闲