Files
vd_960/vd960Loop/docs/devlog.md
T
wangfq e919ff477a docs(协议): variation 值域勘误 V1.07 — ±8388607 → −8388608 ~ +8388607
统一为 3B 补码标准值域 (-2^23 ~ +2^23-1), 对齐代码负向饱和边界 0x800000
- DLD960Loop_串口通信协议.md: variation 字段值域修正 + 修订记录 V1.07
- variation-analysis.md: 头部版本引用/§1/§5.1 表格/§5.6.3 口径小注同步
- devlog.md: 2026-08-25 条目追加勘误说明
代码无改动 (main.c 饱和边界本就正确)
2026-08-25 09:49:11 +08:00

318 lines
13 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.
# vd960Loop 开发日志
> MCU: AT32F421 (Cortex-M4, 120MHz) | 线圈通道: 4路 | 调试口: TTL Tx (3.3V 9600 8N1)
---
## 2026-08-25 — variation ↔ ΔL/ΔL-L 物理对应分析与工具
### 背景
后台需要把上报的 `variation`(CAPVD 计数域)换算成物理电感变化量,用于标定灵敏度、分析车辆信号强度。
### 核心推导
CAPVD ∝ 周期 T = 2π√(LC),即 **CAPVD ∝ √L 而非 L**
```
variation/Origin = 1 √(1 + ΔL/L₀) 精确
ΔL/L₀ ≈ 2 × variation/Origin 一阶(残差 <0.2%
Δf/f ≈ variation/Origin 频域对应
```
- 系数 2 来源于 √(1+x) ≈ 1+x/2 展开
- 符号:车辆进入 ΔL<0 → variation 恒为正,与 V1.05 协议语义一致
- **电容档无关性**Origin 与 CAPVD 均 ∝ √Cvariation/Origin 中 C 消掉 → 33/43/66/76nF 四档共用同一换算表,现场换档不换标定
### 灵敏度档位 → ΔL/L 触发阈值(SensTable {216,108,36,10}
| SENS | Δf/f 进入 (=SensTable/65536) | ΔL/L 进入 ≈ 2× |
|------|------------------------------|-----------------|
| 0 低 | 0.330% | 0.659% |
| 1 中 | 0.165% | 0.330% |
| 2 高 | 0.055% | 0.110% |
| 3 最高 | 0.015% | 0.031% |
交叉验证:DLD154Pro 技术文档 sens_in {108,54,28,14} 标注 ΔL/L = 0.330%/0.165%/0.085%/0.043%,恰为 SensTable/65536 的 2 倍——产品线口径一致。
### 改动
| 文件 | 内容 |
|------|------|
| `docs/variation-analysis.md` | 新增 §9(物理链路/公式/档位表/电容无关性/示例/注意事项) |
| `tools/variation_calc.py` | 新增换算工具:正向(freq+cap+variation+origin→L₀,ΔL,ΔL/L)、反推、3B LE 补码解析(V1.05)、灵敏度对照、交互模式 |
### 验证
工具四模式实测通过,正反算自洽(ΔL/L=0.33% ↔ variation=216 @ Origin=131072)。
### 协议文字勘误(协议 V1.07)
用户指出 §5.6.3 记录的口径差异应直接改协议:原文 `±8388607` 不对称,负向边界少了 1。统一为 **8388608 ~ +8388607**3B 补码标准值域 −2²³ ~ +2²³−1,对齐代码负向饱和边界 0x800000),后台按文档实现时不会对 0x800000 边界犯嘀咕。
| 文件 | 变更 |
|------|------|
| `DLD960Loop_串口通信协议.md` | variation 字段值域文字修正 + 修订记录 V1.07 |
| `variation-analysis.md` | 头部版本引用 → V1.07;§1 值域;§5.1 表格;§5.6.3 口径小注改写 |
代码无改动(`main.c` 饱和边界本就是 8388608 ~ +8388607)。
---
## 2026-07-14 — variation 上报量 2B→3B 有符号 (协议 V1.05)
### 背景
`uart_report_packet_loop_acs` 上报的变化量 `variation` 用于**后台离线跟踪分析车检器算法**(判决裕量、基线跟踪行为)。原实现为 **2 字节无符号 + 取绝对值**,存在两个致命缺陷:
1. **回绕污染**`variation` 是 CAPVD 域的量(量级 ~131072,非 Hz)。大车/大金属全覆盖时偏差可超 65535 → 2B 回绕成小值,后台看到"大信号突然变小"的假象,分析数据作废。
2. **方向丢失**`|Origin CAPVD|` 抹掉符号,分不清"车/金属进入(CAPVD 掉到基线下)"与"反向漂移/异常抬升(CAPVD 升到基线上)",两者判决意义相反。
### 改动 (组包段)
```c
// 旧: uint32_t variation = |Origin - CAPVD| (2B LE)
// 新: 3B LE 有符号补码, 方案B定义
int32_t variation = (int32_t)unit->loop_Origin - (int32_t)unit->loop_CAPVD;
if (variation > 8388607) variation = 8388607; // +2^23-1 饱和防回绕
if (variation < -8388608) variation = -8388608; // -2^23 饱和
// 低字节在前, 发 3 字节
```
- **方案B**`variation = Origin CAPVD`。**正值** = 当前值低于基线(车/裕量方向,与旧版语义连续);**负值** = 反向漂移。
- **饱和限幅** ±2²³,彻底杜绝回绕。
- 每通道单元 **11B → 12B**,整帧 52B → **56B**(仍 < `BUFF_STACK_SIZE=64`,缓冲安全)。
### 影响范围 & 联动
| 端 | 变更 |
|------|------|
| `main.c` 组包 | `uint32_t``int32_t`3B LE + 饱和 |
| 协议文档 | `DLD960Loop_串口通信协议.md` V1.05:字段表、Len 47→51、示例报文重算 |
| **vd960DBN** | 解析步长 11→12、misc 偏移右移 1B、3B 解码 + **bit23 符号扩展**、fast_mode 改 `abs(variation)` |
⚠️ **Loop 固件与 DBN 固件必须同版本发布**——步长死绑定,任一端用旧固件则 4 通道数据整体错位。
### 验证
本地 gcc 隔离单测(编解码往返 / 符号扩展 / 双向饱和 / 方向语义 / fast_mode)全通过。关键:大车 diff=100000 旧版回绕成 34464,新版正确保留 100000。
---
## 2026-06-26 — 多项可配置化改造
### 1. 上报频率从 raw CAPVD 改为实际线圈频率
`uart_report_packet_loop_acs``CMD_DBN_GET_MCJQ_PARAM` 中,频率字段原来直接上报 `loop_CAPVD`(IIR 累加值),现改为经过公式转换的实际频率:
```c
freq = (sclk_freq × input_div × LPCNT) / CAPVD
```
使用 `uint64_t` 先乘后除避免整数截断,`LPCNT>0 && CAPVD>0` 防除零。
### 2. 有限存在时长可配置 (hold_time)
- `Loop154_Unit` 新增 `uint16_t hold_time` 字段
- `storage.c``exist_mode` 计算: `hold_time = exist_mode × 20 × 5`tick 数,每 tick 50ms
- `vd1_task_per_channel` 判定有车时: 若 `hold_time > 0``loop_VD_HOLD = 1`,启用有限存在计时
- `TMR15_GLOBAL_IRQHandler`: `Hold_CNT > unit->hold_time` 替代固定 `HOLD_TIME`
- 超时后执行通道完整重启(`LC_Reset=1, loop_INI_LOOP=1`),相当于线圈重启重建基线,避免继电器释放后立即重新吸合
- `exist_mode=0` 时不启用有限存在,兼容无限制存在场景
### 3. 离开延时可配置 (relay_delay)
- `Loop154_Unit` 新增 `uint16_t relay_delay` 字段
- `storage.c``delay_time` 计算: `relay_delay = delay_time × 2`tick 数)
- `TMR15_GLOBAL_IRQHandler`: `OUTCNT > unit->relay_delay` 替代固定 `OUT_DELAY`
### 4. vTaskDelay 修正: 10ms → 50ms
`loop_task_function` 的主循环 `vTaskDelay``10ms` 改为 `50ms`,对齐 DLD154V4B 原始设计(TMR15 5ms×10)。
**影响:**
- 基线更新周期: 100×10ms=1s → 100×50ms=5s(对齐原始设计,Origin 更稳定)
- CPU 占用: 主循环轮询频率降低 5×,节省 CPU
**原因:** TMR3 ISR ~1ms 产出一个 CAP_OK 样本,50ms 内有 ~50 个样本。`vd1_task_per_channel` 每个 tick 只取最新一个做 IIR10ms 轮询时 CAP_OK 总是 ready,改为 50ms 不影响有效测量速率——采集由 TMR3 ISR 硬件驱动,基线更新速率受 `vd1_task` tick 限制。
---
## 2026-06-29 — DLD154V4B V2.0~V2.5 M4 优化移植
> 参考: DLD154V4B 单路 M4 优化版算法,移植到 vd960Loop 四路并联
### 1. 时序加速: vTaskDelay 50ms → 10ms
主循环 tick 从 50ms 提升到 **10ms**(加速 5×)。TMR15 ISR 保持 5msTM1cnt 10 分频得到 50ms 中断,`Hold_CNT/OUTCNT/INCNT` 仍以 50ms 为单位。
**影响:**
- 检测响应更快:进入确认 3×10ms=30ms 即可判定
- 冻结超时 1000×10ms=10s
- WINDOW_ORIGIN=500 → 基线跟踪窗口 500×10ms=5s(等效原 100×50ms
### 2. 斜率限幅 (Slope Limiter)
```c
MAX_SLOPE_RATE = 5% // 单次 IIR 输入变化不超过 CAPVD 的 5%
```
IIR 之前先对 `loop_Value` 做斜率限幅:与当前 `loop_CAPVD` 比较,变化幅度限制在 ±5% 以内(下限 100),防止突发电磁干扰污染 IIR 状态。
### 3. 进入确认 (Entry Confirm)
```c
ENTRY_CONFIRM = 3 // 连续 3 次低于阈值才判定有车
```
替代原来的单次触发:`loop_CAPVD < (Origin - dlt_ORG)` 计数 `loop_entry_cnt++`,达到 3 次才置 `loop_VD_FLAG=1`。中途高于阈值则清零,消除偶发毛刺导致的误触发。
### 4. 基线冻结超时 (Freeze Timeout)
```c
FREEZE_TIMEOUT = 1000 // 10s @10ms/tick
FREEZE_STABILITY_RATE = 2 // 稳定性窗口 ±2%
```
有车期间基线被冻结(`ORG_CNT/ORG_SUM` 清零不更新),但新增超时机制:
- 冻结时记录参考值 `loop_freeze_ref`
- 若 CAPVD 波动超过 ±2%,重新计时(车还在动)
- 若 CAPVD 在 ±2% 内稳定超过 10s,强制 `Origin = CAPVD`(视为长时间停车,基线应更新)
- 解决长时间停车导致基线永久偏离的问题
### 5. IIR 简化: 双路 → 单路
初始移植了双路 IIR(慢速 α=18/256 + 快速 α=0.5),经测试发现快速 IIR 引入额外噪声,最终**去掉快速 IIR**,仅保留慢速:
```c
ALFA_CAP1 = 79 // α = 79/256 ≈ 0.31, @10ms → τ ≈ 32ms
```
斜率限幅直接对慢速 IIR 输入做限制,简化逻辑且效果一致。
### 6. 稳定期快速收敛
稳定期 `!loop_stable` 绕过 IIR + 斜率限幅:
- 直接用 `loop_CAPVD = loop_Value`raw value
- `update_moving_average` 窗口改为 **100**(小窗口快速收敛)
- 128 样本约 1.28s 完成初始化
稳定后切换回正常 IIR + WINDOW_ORIGIN=500 慢跟踪。
### 7. 参数修正
| 参数 | 旧值 | 新值 | 说明 |
|------|------|------|------|
| `WINDOW_ORIGIN` | 100 | 500 | 基线窗口 5s @10ms |
| `update_moving_average` window | `uint8_t` | `uint16_t` | 修复 500→256 溢出 |
| `loop_entry_cnt` | — | `uint8_t` | 新增: 进入确认计数器 |
| `loop_freeze_cnt` | — | `uint16_t` | 新增: 冻结持续计数 |
| `loop_freeze_ref` | — | `uint32_t` | 新增: 冻结参考值 |
---
## 2026-07-03 — 时间量上报单位改为 10ms
### 背景
`MISC_TYPE_TIME` 上报的通过时间 / 车间距原来以 5ms 为单位(直接 `report_counter - 时间戳`),与外部协议期望的 10ms 单位不一致。
### 方案
内部时间戳 `report_counter` / `passtime_start` / `last_exit_tick` 保持 5ms 精度不动,仅在上报 `misc_value``/2` 转为 10ms
```c
// 进场 — 车间距 (10ms)
misc_value = (report_counter - last_exit_tick) / 2;
// 离场 — 通过时间 (10ms)
misc_value = (report_counter - passtime_start) / 2;
```
### 影响范围
| 位置 | 变更 |
|------|------|
| `TaskLoop.c` 进场路径 | `misc_value` /2 |
| `TaskLoop.c` 离场 flatness | `misc_value` /2 |
| `TaskLoop.c` 离场 cnt_release | `misc_value` /2 |
| `TaskLoop.h` 注释 | 标注 `/2→10ms` |
---
## 2026-07-03 — 时间量上报单位改为 50ms
### 背景
上一步 `misc_value` 以 10ms 为单位(内部 5ms tick `/2`),但协议期望 50ms。统一为 50ms 后与 `Hold_CNT/OUTCNT/INCNT` 一致。
### 方案
1. **`report_counter` 移入 50ms tick 块**:原来在 5ms ISR 外层 `++`,现移到 `if (TM1cnt >= 10)` 内部,每次加 1 = 50ms
2. **去掉 `/2`**`misc_value = report_counter - timestamp`(直接减,无除法)
3. **上报间隔宏同步**`REPORT_IDLE_TICKS 120→12``REPORT_EVENT_TICKS 30→3`
### 影响范围
| 文件 | 变更 |
|------|------|
| `TaskLoop.c` ISR | `report_counter++` 从 5ms 外层移入 50ms 块 |
| `TaskLoop.c` 进场/离场 | 去掉 `/2`,注释 10ms→50ms |
| `TaskLoop.h` | `REPORT_*_TICKS` /10,注释 5ms→50ms |
| `main.c` | 间隔注释更新 |
---
## 2026-07-03 — ARMCC 编译修复 + 时间戳/上报完善 (V2.8~V3.1)
### 1. ARMCC 编译错误修复 (V2.8)
- **#991**: `g_loop_states` 初始化去多余嵌套大括号 `{{0}, {{{0}}}}``{0}`
- **#177-D**: 删除未引用变量 `_counter1_init`
- **#188-D**: 7处 `at32_led_*()` 调用加 `(led_type)` 强转
### 2. 车间距时间补齐 (V2.9)
`Loop154_Unit` 新增 `last_exit_tick` 字段:
- **进场**: `misc_value = misc_counter - last_exit_tick`(车间距,首车=0
- **离场**: 记录 `last_exit_tick = misc_counter``misc_value = misc_counter - passtime_start`(通过时间)
- 四通道独立计算,50ms tick 单位
### 3. report_counter 清零导致下溢修复 (V3.0)
**根因**: `report_counter` 被 UART 上报清零后,`last_exit_tick`/`passtime_start` 存旧值,再次进场时差值下溢 → `0xFFFFFFF7`
**修复**: 新增 `misc_counter` 独立自由运行计数器(50ms,永不归零),所有时间戳操作改用 `misc_counter`
```
Loop154_States:
report_counter → 上报间隔调度 (会清零)
misc_counter → 时间戳 (永不清零)
```
`report_counter` 只负责上报调度,`misc_counter` 负责时间量计算,互不干扰。
### 4. 上电 3 秒抑制上报 (V3.1)
`uart_report_packet_loop_acs` 开头新增检查:`misc_counter < 60`3s @50ms)时跳过上报并清零 `report_counter`,等线圈基线稳定后再开始主动上报。
---
## 修订记录
| 版本 | 时间 | 说明 |
|------|------|------|
| V3.1 | 2026-07-03 | 上电3秒抑制主动上报 |
| V3.0 | 2026-07-03 | misc_counter 自由运行替代 report_counter 做时间戳 |
| V2.9 | 2026-07-03 | 补齐车间距时间 (gap time) |
| V2.8 | 2026-07-03 | ARMCC 编译修复 (多余大括号/未引用变量/枚举混用) |
| V2.7 | 2026-07-03 | report_counter 改 50ms tick,时间量单位 10ms→50ms |
| V2.6 | 2026-07-03 | misc_value 时间量单位 5ms→10ms |
| V2.5 | 2026-06-29 | 稳定期窗口 100 快速收敛 |
| V2.4 | 2026-06-29 | 去掉快速 IIRALFA_CAP1=79 @10ms |
| V2.3 | 2026-06-29 | 基线冻结超时 + 稳定性检查 |
| V2.2 | 2026-06-29 | 进入确认 ENTRY_CONFIRM=3 |
| V2.1 | 2026-06-29 | 斜率限幅 MAX_SLOPE_RATE=5% |
| V2.0 | 2026-06-29 | vTaskDelay 50→10ms, 双路 IIR 移植 |
| V1.3 | 2026-06-26 | vTaskDelay 10→50ms 对齐原始设计 |
| V1.2 | 2026-06-26 | hold_time/relay_delay 可配置,有限存在完整重启 |
| V1.1 | 2026-06-26 | 频率上报 CAPVD→实际频率转换 |