- vd960Loop/docs/devlog.md: 组包端改动(uint32->int32,方案B,饱和防回绕), 背景/影响范围/验证 - vd960DBN/docs/devlog.md: 接收端4处联动(结构体/解析步长/符号扩展/ fast_mode abs阈值), 缓冲核查 两端均标注必须同版本发布
263 lines
11 KiB
Markdown
263 lines
11 KiB
Markdown
# vd960Loop 开发日志
|
||
|
||
> MCU: AT32F421 (Cortex-M4, 120MHz) | 线圈通道: 4路 | 调试口: TTL Tx (3.3V 9600 8N1)
|
||
|
||
---
|
||
|
||
## 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 只取最新一个做 IIR,10ms 轮询时 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 保持 5ms,TM1cnt 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 | 去掉快速 IIR,ALFA_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→实际频率转换 |
|