Files
DLD154V4B/docs/devlog.md

307 lines
10 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.
# DLD154V4B 开发日志
> MCU: AT32F421F8P7 (Cortex-M4, 120MHz) | 线圈通道: 1路 | 调试口: TTL Tx
---
## 2026-06-23 — 跳出框框:去掉 >>6 精度浪费
### 背景
DLD154V4B 的检测算法继承自 M1HSTC12C5202, 2008和 TLD-110P87LPC762, 2003但有几个关键硬件差异
| 特性 | M1H / TLD-110 | DLD154V4B |
|------|--------------|-----------|
| 主频 | ~12MHz (8051) | 120MHz (Cortex-M4) |
| 分频芯片 | CD4060 (Pin5, ÷32) | **无**,直连 PA7 |
| MCU 内分频 | 无 | TIM3 DIV_4 → **DIV_2** |
| 有效分频比 | ÷32 | ÷2 |
| 捕获方式 | PCA 周期捕获 / 门控计数 | TIM3_CH2 硬件输入捕获 |
### 问题:<<6 和 >>6 的精度浪费
原始代码的数据流存在一个"膨胀再压缩"的精度陷阱:
```
TMR3 ISR:
Xn = 周期差值 (4800 ticks @ DIV_4)
LPCNT = (32768 << 6) / Xn = 437 ← 窗口开大 64×降噪
Value = Σ 437次 Xn ≈ 2,097,600 ← 437 样本精密累加
vd1_task:
tmp = Value >> 6 = 32,775 ← 6bit 精度全部丢弃!
CAPVD = IIR(tmp...) ← IIR 只看到 ~6 样本有效信息
```
`<<6``>>6` 在数学上互相抵消——437 个样本累加,然后右移 6 位,等效仅用 ~7 个样本437/64 ≈ 6.8)。窗口开大降噪了,但精度被自己扔掉了。
### 方案:去掉 <<6/>>6用 MEASUREMENT_BASE
```
TMR3 ISR:
LPCNT = 131072 / Xn = 27~54 ← 自适应窗口,不丢精度
Value = Σ Xn ≈ 131072 ← 直接作为检测输入
vd1_task:
CAPVD = IIR(Value) ← 全精度参与滤波
```
| 参数 | 旧方案 | 新方案 |
|------|--------|--------|
| LPCNT (100kHz, DIV_2) | — | **54** |
| 测量窗口 | 17.5ms (DIV_4) | **~1ms** |
| 有效精度/窗口 | ~6 样本 (>>6 后) | **54 样本 (全保留)** |
| Origin 范围 | ~32K | **~131K** |
| 灵敏度阈值 | 百分比公式,自动按比例缩放 ✓ | 同 ✓ |
| 进入响应 | ~50ms | **~3ms** |
### 同步改进
| # | 改动 | 原因 |
|---|------|------|
| 1 | TIM3 分频 DIV_4 → DIV_2 | 提高采样率,中断率 2× 仍安全 (CPU<3%) |
| 2 | MEASUREMENT_BASE = 131072 (2^17) | 平衡精度和 Origin 范围 |
| 3 | 去除所有 >>6 | 保留全采样精度 |
| 4 | 离开增加 `cnt_release >= 3` 防抖 | 防瞬间噪声导致误落杆 |
| 5 | 基线冻结 + 100 窗口慢跟踪 | 仿 TLD-110有车不更新基线 |
### 为什么不需要 CD4060 外部分频
AT32F421 的 TIM3 有内置输入分频器,配合 120MHz 主频:
| 线圈频率 | DIV_2 中断率 | CPU 占用 (50周期/ISR) |
|---------|------------|----------------------|
| 100 kHz | 50k/s | 2.1% |
| 150 kHz | 75k/s | 3.1% |
| 200 kHz | 100k/s | 4.2% |
均在安全范围内,无需外部分频芯片。
### 对比 M1H/TLD-110
| 指标 | M1H (CD4060÷32) | DLD154V4B (新) |
|------|----------------|---------------|
| 测量间隔 | ~50ms (固定) | **~1ms (自适应)** |
| 进入防抖 | 500ms IN_DELAY | 500ms IN_DELAY |
| 离开防抖 | 1.9s OUT_DELAY | **3次连续确认** + 1.9s OUT_DELAY |
| 基线跟踪 | 100次 (有车也跟) | 100次 (有车冻结) |
---
## 2026-06-23 — 精简重构,对齐参考实现
- 删除二阶差分滤波(计算但从未参与判决)
- 删除 FltHistoryManager 死代码20+ 未用字段)
- 删除 StageRangeConfig区间约束未引用
- 删除动态窗口切换LOOP_WINDOW_SIZE_LOW→FAST
- 时序状态机简化:去掉 PLUSE_IN_F/PLUSE_IN 中间层
- 拨码去抖 10→5对齐 M1H
- 代码量1177→706 行(-40%
---
## 2026-06-22 — 参考分析
见 [reference_analysis.md](reference_analysis.md)M1H + TLD-110 完整算法分析。
---
## 2026-06-23 — 指示灯行为规范化
### LED 硬件对应
| 硬件 | 引脚 | 宏 | 行为 |
|------|------|-----|------|
| 红灯 | PB1 | *(无宏, TMR14 PWM)* | 始终呼吸,不干预 |
| 绿灯 (LEDA) | PA9 | `LEDA_ON`/`LEDA_OFF` | 自检慢闪 / 有车亮 / 无车灭 |
| 黄灯 (LEDC) | PA10 | `LED_YELLOW_ON`/`OFF` | 故障快闪 / 断开次数编码 |
> 注: `LEDA` 宏在 BSP 遗留代码中指向 PB1红灯已修正为 PA9绿灯。`LEDB` 宏无实际 IO已删除。
### 绿灯行为
| 状态 | 绿灯 |
|------|------|
| 上电自检 (Origin 未确立) | 慢闪 200ms |
| 数值稳定期 (128 样本 ≈ 128ms) | 慢闪 200ms |
| 正常工作,无车 | 灭 |
| 正常工作,有车 | 亮 |
| 线圈断开中 | **灭**(黄灯快闪负责故障指示) |
### 黄灯行为
| 条件 | 黄灯 |
|------|------|
| 上电后从未接线圈 | 快闪 200ms |
| 线圈当前断开中 | 快闪 200ms |
| 重连后,断开过 1 次 | 1 短闪 (80ms 亮) + 1.2s 间隔 |
| 重连后,断开过 2 次 | 2 短闪 + 1.2s 间隔 |
| 重连后,断开过 3+ 次 | 3 短闪 + 1.2s 间隔 |
| 正常,无断开记录 | 灭 |
> "不接线圈上电,上电后再接线圈"不计入断开次数。
---
## 2026-06-23 — 上电稳定期 & 线圈重连
### 上电稳定期
Origin 首次确立后,线圈振荡需要时间稳定。新增 `g_loop_stable` 标志:
- `INIT_VD()``g_loop_stable = 0`
- `vd1_task()`: 稳定期内只做 IIR + 基线跟踪,**跳过进入检测**
- 128 样本 (~128ms) 后 `g_loop_stable = 1`,正式启用检测
- 安全复位时重置 `g_loop_stable = 0`
### 线圈重连状态保持
断开时**不丢 VD_FLAG**,重连后**快速收敛 IIR**
```
断开: 保留 loop1_VD_FLAG仅关断继电器
重连: loop1_CAPVD = 0 → 首个样本直锁 Value → IIR 后续正常跟踪
```
| 断开前 | 断开期间 | 重连后 | 检测结果 |
|--------|---------|--------|---------|
| 有车 | 车还在,绿灯灭 | 车还在 | CAPVD < Origin-dlt → VD_FLAG=1 → 绿灯亮 |
| 有车 | 车离开 | 车离开 | CAPVD ≈ Origin → cnt_release→3 → VD_FLAG=0 |
| 无车 | 车进入 | 车进入 | CAPVD < Origin-dlt → VD_FLAG=1 → 绿灯亮 |
---
## 2026-06-23 — 移植平坦性离开判定CN200910309382
### 来源
专利 CN200910309382中山大学张辉/黄永强/陈古典)提出**平坦性三条件判定法**
解决大车通行时频率曲线的负波峰和近零波谷导致单一阈值法多次误触发的问题。
### 算法
```
车辆到达 → 单一阈值法 f(i) - f_b > Δ1 (沿用 SensTable)
车辆离开 → 平坦性三条件 同时满足:
① |f - f_b| < Δ1 频率回归基频 (SensTable_1)
② |f'| < Δ2 一阶导数近零
③ |f''| < Δ3 二阶导数近零
```
**Phase 1** (g_exit_state=0): 车辆进入线圈后,追踪第一上升坡面,
记录最大 |f'| 和 |f''|。当斜率连续 3 次降到 `SLOPE_FLAT_THRESH` 以下,
计算动态阈值:
```
Δ2 = max_slope / K1 (K1=8)
Δ3 = max_slope_rate / K2 (K2=8)
```
**Phase 2** (g_exit_state=1): 每帧检查三条件。连续 3 次全部满足 → 车辆离开。
### 与传统方法对比
| 方法 | 离开判据 | 大车防误检 |
|------|---------|-----------|
| M1H/TLD-110 | 单一滞回阈值 | ❌ 多峰可能多次触发 |
| 原 cnt_release | 连续 3 次超阈值 | ⚠️ 固定阈值,大车波谷可能误判 |
| **平坦性判定** | |f-f_b|+一阶+二阶 三条件 | ✅ 动态阈值,跟随坡面特征 |
### 参数说明
| 常量 | 值 | 含义 |
|------|-----|------|
| K1, K2 | 8 | 动态阈值除数(专利推荐值) |
| SLOPE_FLAT_THRESH | 100 | 斜率趋零判断阈值 |
| MIN_DELTA2 | 5 | Δ2 下限(防除数过小) |
| MIN_DELTA3 | 2 | Δ3 下限 |
| FLAT_CONFIRM_CNT | 3 | 平坦连续确认次数 |
### 整数化适配
专利原实现使用 floatHz 频率值DLD154V4B 用 uint32 定点Origin≈131K
导数计算同样用 int32 整数差分,阈值 /K1、/K2 做整数除法,精度足够。
---
## 2026-06-23 — Origin 污染保护 & 宏开关
### USE_FLATNESS_EXIT 宏
新增编译开关,一行切换离开判据:
```c
#define USE_FLATNESS_EXIT 1 // 1=平坦性, 0=cnt_release防抖
```
所有平坦性状态变量和逻辑用 `#if USE_FLATNESS_EXIT` 包裹。
### Origin 基线污染保护
**问题**:实测发现车辆驶入时 Xn 偶尔先增大再减小。无车状态下 Origin 跟踪上升,
被污染到虚高值。进入检测虽触发,但离开时 Origin 冻在虚高处,
`|f-f_b|` 远超 SensTable_1 阈值 → 绿灯常亮、永远不释放。
**根因**CAPVD 异常上升期间moving average 持续将虚高值写入 Origin。
**修复**:在基线跟踪前增加保护条件:
```c
dev = CAPVD - Origin;
if (dev < dlt_ORG × 4)
update_moving_average(...); // 安全跟踪
else
freeze; // 冻结 + 重置累计
```
冻结阈值 = 进入阈值的 4 倍,随灵敏度自动缩放。
| 场景 | CAPVD | Origin | dev | 阈值(×4) | 结果 |
|------|-------|--------|-----|----------|------|
| 正常无车 | 127081 | 127080 | +1 | 276 | 跟踪 ✓ |
| 异常上升 | 127884 | 127085 | +799 | 276 | 冻结 ✓ |
---
## 2026-06-24 — SW4 快速模式 & 接口修正
### SW4 行为修正
**旧行为**SW_4=ON 时 FLAG_OUT 立即跳到 FLAG_PLUSE跳过离开延时FLAG_PLUSE 仍用正常 PULSE_DELAY950ms。语义混乱——名字叫"延时"实际是跳过延时。
**新行为**SW_4 重定义为**快速模式**。ON 时 OUT_DELAY 和 PULSE_DELAY 均缩短为 10 tick500msOFF 时维持原值1.9s/950ms
```c
// TaskLoop.h 新增
#define OUT_DELAY_FAST 10 // 500ms
#define PULSE_DELAY_FAST 10 // 500ms
// TaskLoop.c 运行时选择
uint16_t out_delay = SET_DLY ? OUT_DELAY_FAST : OUT_DELAY;
uint16_t pulse_delay = SET_DLY ? PULSE_DELAY_FAST : PULSE_DELAY;
```
适用范围ETC 收费站等需要快速落杆的场景。
### 接口修正
- 去除所有 RS485 相关描述:本产品只有 TTL 电平 UART Tx 调试口,无 RS485 通信能力
- 产品手册端子定义RS485-A/B → Tx TTL 调试输出
- 技术规格书 §9整节从 RS485 协议改为 TTL Tx 调试接口说明
### 文档同步
- 产品手册 + 技术规格书同步更新SW4 描述、端子定义、时序参数表
- README.md 同步更新
## 修订记录
| 版本 | 时间 | 说明 |
|------|------|------|
| V1.6 | 2026-06-24 | SW4 快速模式修正RS485→TTL Tx 接口更正 |
| V1.5 | 2026-06-23 | Origin 污染保护、USE_FLATNESS_EXIT 开关 |
| V1.4 | 2026-06-23 | 移植 CN200910309382 平坦性离开判定 |
| V1.3 | 2026-06-23 | 指示灯行为、稳定期、重连状态保持 |
| V1.2 | 2026-06-23 | <<6/>>6 精度浪费分析与改进 |
| V1.1 | 2026-06-23 | 精简重构,对齐 M1H/TLD-110 |
| V1.0 | 2026-06-22 | 参考分析文档 |