Files
DLD154V4B/docs/technical-spec.md
wangfq 935e11e006 docs: 四文档同步更新至 V2.5
- devlog: 修订记录修正 30s→10s, 新增 V2.5
- release-notes: V1.6→V2.5, 新增 M4 优化特性 + 完整版本历程
- product-manual: V1.5→V2.5, 补充 V1.6~V2.5 版本历史
- technical-spec: V1.5→V2.5, 重写 §§4.2-4.5/5.2/12.1/13:
  - §4.2: 双路 IIR 架构(慢速基线 τ=135ms + 快速检测 τ=28ms)
  - §4.3.2: 进入确认机制(CAPVD_fast + ENTRY_CONFIRM=3)
  - §4.4: 斜率限幅 5% + 基线更新速率 1s (10ms tick)
  - §4.5: 冻结超时恢复演进史 V1.5→V2.5,完整逻辑 + 常量表
  - §5.2: Tick 改为 10ms,新增 FREEZE_TIMEOUT 参数
  - §12.1: 进入延迟 ~530ms,瞬态抑制,温漂 1s 补偿
  - §13: 新增 M4 优化编译选项
2026-06-29 10:57:24 +08:00

714 lines
25 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 技术规格书
> 单路线圈车辆检测器 | 固件版本: V2.5 | 文档版本: V2.0
> 本文档面向工程开发、系统集成及故障深度分析
---
## 1. 系统架构
### 1.1 硬件架构
```
┌──────────────────────────────────┐
线圈 ────────────┤ PA7 (TIM3_CH2) AT32F421F8P7 │
│ 输入捕获 Cortex-M4 ├──── PB1 (TMR14 PWM) ──── 红灯
│ 120MHz / 64KB │
DIP ×5 ─────────┤ PA0~PA4 (GPIO) ├──── PA9 (GPIO) ──────── 绿灯
│ │
Tx ─────────────┤ USART (TTL) ├──── PA10 (GPIO) ─────── 黄灯
│ │
│ PA5 (GPIO) ──┼──── RLY2 继电器
│ PA6 (GPIO) ──┼──── RLY1 继电器
│ │
│ SWD (PA13/PA14) ────────────────┼──── 调试接口
└──────────────────────────────────┘
```
### 1.2 软件架构
```
FreeRTOS Kernel (CMSIS-RTOS v2)
├── loop_task (主检测任务)
│ ├── vd1_task() — 每 ~10ms 执行 (M4 优化)
│ │ ├── 双路 IIR 滤波 (慢速 α=18/256, 快速 α=0.5)
│ │ ├── 斜率限幅 (MAX_SLOPE_RATE=5%)
│ │ ├── 基线跟踪 (100 窗口滑动平均)
│ │ ├── 进入确认 (ENTRY_CONFIRM=3 次)
│ │ ├── 离开检测 (平坦性 / cnt_release)
│ │ ├── 时序状态机 (IN/OUT/PULSE/HOLD)
│ │ └── 冻结超时恢复 (10s + ±2% 稳定性检查)
│ ├── poll_sw_state() — 拨码去抖
│ ├── poll_green_led() — 绿灯驱动
│ └── poll_yellow_led() — 黄灯故障编码
├── TMR3_ISR() — 线圈频率捕获
├── TMR15_ISR() — 5ms 系统 tick (LED 驱动)
└── TMR14_PWM() — 红灯呼吸
```
---
## 2. 电气参数
| 参数 | 最小值 | 典型值 | 最大值 | 单位 | 备注 |
|------|--------|--------|--------|------|------|
| 供电电压 (VDD) | 10 | 12 / 24 | 30 | V | 宽压输入 |
| 功耗 | — | 0.5 | 2 | W | 含继电器吸合 |
| 工作温度 | -40 | — | +85 | °C | 工业级 |
| 存储温度 | -55 | — | +125 | °C | — |
| 线圈电感范围 | 50 | 200 | 1000 | μH | 超出范围可工作但精度下降 |
| 线圈频率范围 | 30 | 100 | 200 | kHz | — |
| 线圈 Q 值 | 5 | — | — | — | 过低导致振荡不稳定 |
| 继电器触点电压 | — | — | 250 | VAC | — |
| 继电器触点电流 | — | — | 3 | A | — |
| GPIO 输出电压 | 0 | 3.3 | 3.6 | V | CMOS 电平 |
| GPIO 输出电流 | — | — | 25 | mA | 单引脚最大 |
| ESD 防护 | ±2 | — | — | kV | HBM |
---
## 3. IO 引脚分配
### 3.1 完整引脚表
| 引脚 | 标识 | 功能 | 方向 | 外设 | 初始状态 | 备注 |
|------|------|------|------|------|---------|------|
| PA0 | SA_1 | 灵敏度 bit0 | IN | GPIO, 上拉 | — | DIP 开关 |
| PA1 | SA_2 | 灵敏度 bit1 | IN | GPIO, 上拉 | — | DIP 开关 |
| PA2 | SW_3 | 存在/脉冲选择 | IN | GPIO, 上拉 | — | 0=存在, 1=脉冲 |
| PA3 | SW_4 | 离开延时 | IN | GPIO, 上拉 | — | 0=无, 1=500ms |
| PA4 | SW_5 | 安全复位 | IN | GPIO, 上拉 | — | 1=复位 |
| PA5 | RLY2 | 继电器 2 | OUT | GPIO PP | 0 (开路) | 辅助输出 |
| PA6 | RLY1 | 继电器 1 | OUT | GPIO PP | 0 (开路) | 主输出 |
| **PA7** | **LP** | 线圈频率捕获 | IN | **TIM3_CH2** | — | **核心输入** |
| PA9 | LEDA | 绿灯 | OUT | GPIO PP | 0 (灭) | 有车/自检 |
| PA10 | LEDC | 黄灯 | OUT | GPIO PP | 0 (灭) | 故障诊断 |
| PB1 | LEDA_RED | 红灯 | ALT | TMR14_CH1 PWM | — | 呼吸灯 |
| PA13 | SWDIO | 调试数据 | I/O | SWD | — | 仅调试 |
| PA14 | SWCLK | 调试时钟 | IN | SWD | — | 仅调试 |
### 3.2 拨码开关逻辑
```c
// DIP 开关读取与解码
SENS = 3 - (sw & 0x03);
// SA_2:SA_1 = 11 → SENS = 0 (低灵敏)
// SA_2:SA_1 = 10 → SENS = 1
// SA_2:SA_1 = 01 → SENS = 2
// SA_2:SA_1 = 00 → SENS = 3 (最高灵敏)
SET_PLUS = (sw >> 2) & 0x01; // PA2 = SW_3
SET_DLY = (sw >> 3) & 0x01; // PA3 = SW_4
SET_SAFE = (sw >> 4) & 0x01; // PA4 = SW_5
```
**拨码去抖**:连续 5 次读取一致才生效(对齐 M1H 参考实现)。
---
## 4. 检测算法
### 4.1 频率测量
#### 4.1.1 硬件链路
DLD154V4B **不使用** CD4060 外部分频芯片。线圈直接驱动 PA7 (TIM3_CH2),利用 AT32F421 内置 TIM3 输入分频器 DIV_2 (÷2)。
| 对比项 | M1H/TLD-110 | DLD154V4B |
|--------|-------------|-----------|
| 外部分频 | CD4060 Pin5 (÷32) | **无(直连)** |
| MCU 内部分频 | 无 | TIM3 DIV_2 (÷2) |
| 总分频比 | ÷32 | **÷2** |
| 中断率 @100kHz | ~3.1k/s | **50k/s** |
| CPU 占用 @120MHz | — | < 3% |
#### 4.1.2 捕获流程
```
线圈边沿 → PA7 (TIM3_CH2)
TIM3 自由运行 (16-bit, 120MHz/DIV_2 = 60MHz 时钟)
└─ 每个边沿 → CH2 捕获 → 读 CCR2
TMR3 ISR:
CCR2_now → 存为 CapThis
Xn = CapThis - CapLast (相邻边沿周期差)
处理 16-bit 溢出: if (Xn & 0x8000) Xn += 0x10000
CapLast = CapThis
LPCNT = MEASUREMENT_BASE / Xn (自适应窗口)
CapSum += Xn
CapCnt++
CapCnt >= LPCNT ?
YES → Value = CapSum (≈ MEASUREMENT_BASE)
CapCnt = CapSum = 0
loop1_CAP_OK = 1 (通知 vd1_task)
```
#### 4.1.3 关键常量
```c
#define MEASUREMENT_BASE 131072 // 2^17
#define g_input_div 2 // TIM3 DIV_2
```
| 线圈频率 | Xn @DIV_2 | LPCNT | 测量窗口 | Value 范围 |
|---------|-----------|-------|---------|-----------|
| 50 kHz | 1200 | 109 | 2.2 ms | ~130800 |
| 100 kHz | 600 | 218 | 2.2 ms | ~130800 |
| 150 kHz | 400 | 328 | 2.2 ms | ~131200 |
| 200 kHz | 300 | 437 | 2.2 ms | ~131100 |
> **设计要点**LPCNT 自适应使不同频率下 Value 归一化到 ~131072百分比阈值灵敏度直接适用无需频率补偿。
#### 4.1.4 精度陷阱(已修复)
旧代码存在 `<<6``>>6` 互相抵消的精度浪费:
```
旧: LPCNT = (32768 << 6) / Xn = 437 → 窗口 17.5ms
Value >>= 6 → 等效 7 样本精度
新: LPCNT = 131072 / Xn = 27~54 → 窗口 ~1ms
不做右移 → 全样本精度
```
**改进效果**:响应速度提升 16 倍,精度保留全部采样信息。
### 4.2 IIR 滤波M4 优化:双路 IIR
V2.0 起采用双路 IIR 架构,将基线跟踪与检测判定解耦:
```c
#define ALFA_CAP1 18 // 慢速 IIR: α = 18/256 ≈ 0.07, τ≈135ms
#define ALFA_FAST 128 // 快速 IIR: α = 128/256 = 0.5, τ≈28ms
```
| 滤波器 | α | τ @10ms | 输入 | 用途 |
|--------|---|---------|------|------|
| CAPVD (慢速) | 18/256 ≈ 0.07 | 135ms | Value经斜率限幅 | 基线跟踪 |
| CAPVD_fast (快速) | 128/256 = 0.5 | 28ms | CAPVD慢速滤波后 | 进入/离开检测判定 |
**为什么需要双路:**
- 基线跟踪需要**慢响应**,避免将车辆的频率偏移"学"进基线(τ=135ms等效 M1H 的 79/256 @50ms
- 检测判定需要**快响应**,快速捕捉车辆进入/离开(τ=28ms5× 快于旧设计)
- 快速 IIR 输入来自慢速 IIR 的输出,继承斜率限幅的瞬态抑制能力
**进入确认**:快速 IIR 连续 3 次低于阈值才判定有车,单次瞬态干扰被过滤。
```c
// 快速 IIR: α=0.5 → (old + new) / 2
loop1_CAPVD_fast = (loop1_CAPVD_fast + loop1_CAPVD) / 2;
// 进入确认
if (CAPVD_fast < Origin - dlt_ORG) {
if (++entry_cnt >= 3)
VD_FLAG = 1; // 确认有车
} else {
entry_cnt = 0; // 恢复到阈值以上则重置
}
```
| 参数 | 值 | 说明 |
|------|-----|------|
| α_slow | 18/256 ≈ 0.07 | 慢速 IIR 指数平滑系数 |
| α_fast | 128/256 = 0.5 | 快速 IIR 指数平滑系数 |
| 慢速 τ | ~135ms | 等效 50ms tick 的 79/256 |
| 快速 τ | ~28ms | 5× 快于旧设计 |
| ENTRY_CONFIRM | 3 | 连续确认次数 |
### 4.3 检测判据
#### 4.3.1 灵敏度表
```c
const uint16_t SensTable[4] = {216, 108, 36, 10}; // 进入阈值
const uint16_t SensTable_1[4] = {108, 72, 18, 9}; // 离开阈值(滞回 ~50%
```
| SENS | SensTable | 进入阈值 (×Origin/65536) | SensTable_1 | 离开阈值 (×Origin/65536) |
|------|-----------|-------------------------|-------------|-------------------------|
| 0 (低) | 216 | 0.33% | 108 | 0.16% |
| 1 | 108 | 0.16% | 72 | 0.11% |
| 2 | 36 | 0.055% | 18 | 0.027% |
| 3 (高) | 10 | 0.015% | 9 | 0.014% |
#### 4.3.2 进入检测M4 优化:确认机制)
```c
// 使用快速 IIR (CAPVD_fast) 提高响应速度
// 连续 ENTRY_CONFIRM 次低于阈值才判定有车
if (CAPVD_fast < Origin - dlt_ORG) {
entry_cnt++;
if (entry_cnt >= ENTRY_CONFIRM) { // 3 次连续确认
VD_FLAG = 1; FLAG_IN = 1;
entry_cnt = 0;
}
} else {
if (entry_cnt > 0) entry_cnt = 0; // 恢复则重置
}
```
| 对比 | 8051/M1H 旧设计 | M4 优化 |
|------|----------------|---------|
| 判定依据 | CAPVD慢速 IIR | **CAPVD_fast**(快速 IIR5× 响应) |
| 确认方式 | 单次阈值 | **连续 3 次确认** |
| 瞬态抑制 | 无 | **斜率限幅 + 确认双重保护** |
| 进入响应 | ~550ms (50ms tick + 500ms IN_DELAY) | **~530ms** (10ms tick + 3×10ms + 500ms) |
| 误触发风险 | 中 | **低** |
#### 4.3.3 离开检测(滞回)
##### 模式 1简单防抖 (USE_FLATNESS_EXIT=0)
```c
dlt_ORG = (Origin * SensTable_1[SENS]) >> 16; // 更小的离开阈值
if (CAPVD < Origin + dlt_ORG) {
if (++cnt_release >= 3) { // 连续 3 次确认
VD_FLAG = 0; FLAG_OUT = 1;
}
} else {
cnt_release = 0; // 回落立即重置
}
```
##### 模式 2平坦性判定 (USE_FLATNESS_EXIT=1) — 默认
基于专利 **CN200910309382**(中山大学),解决大车通行时频率多峰导致的多次误触发。
**算法架构:**
```
车辆到达 → 单一阈值法 (沿用 SensTable)
▼ Phase 1: g_exit_state = 0 (追踪第一上升坡面)
│ 追踪最大 |f'| 和 |f''|
│ 当 |f'| 连续 3 次 < SLOPE_FLAT_THRESH:
│ Δ2 = max_slope / K1 (一阶平坦阈值)
│ Δ3 = max_slope_rate / K2 (二阶平坦阈值)
│ g_exit_state = 1
▼ Phase 2: g_exit_state = 1 (平坦性判定)
三条件同时满足:
① |f - f_b| < dlt_ORG (频率回归基频)
② |f'| < Δ2 (一阶导数近零)
③ |f''| < Δ3 (二阶导数近零)
连续 FLAT_CONFIRM_CNT(3) 次全部满足 → 车辆离开
```
**参数表:**
| 常量 | 值 | 含义 |
|------|-----|------|
| 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 做整数除法,精度足够。
### 4.4 基线跟踪M4 优化:斜率限幅 + 冻结超时)
#### 4.4.1 斜率限幅
EMI/闪电等瞬态干扰会造成 CAPVD 瞬间跳变。物理车辆不可能让线圈频率瞬间改变 >5%
```c
#define MAX_SLOPE_RATE 5 // 单次最大变化 5%
int32_t raw_delta = Value - CAPVD;
int32_t max_step = CAPVD * MAX_SLOPE_RATE / 100;
if (max_step < 100) max_step = 100; // 最小限幅,防止低 Origin 时锁死
if (raw_delta > max_step) raw_delta = max_step;
if (raw_delta < -max_step) raw_delta = -max_step;
uint32_t clamped_value = CAPVD + raw_delta;
CAPVD = get_flt_value(clamped_value, CAPVD); // 慢速 IIR
```
尖峰被截断,真实车辆信号(缓慢的频率漂移)不受影响。
#### 4.4.2 基线跟踪规则
```c
// 仅无车 + 无离开延时中 → 跟踪基线
if (!VD_FLAG) {
int32_t dev = CAPVD - Origin;
if (dev < dlt_ORG * 4) {
// CAPVD 未显著偏离 → 正常跟踪
loop1_freeze_cnt = 0;
update_moving_average(&ORG_SUM, &ORG_CNT, &Origin, CAPVD, 100);
} else {
// CAPVD 异常偏高 → 冻结 + 超时恢复逻辑
}
}
```
| 设计决策 | 原因 |
|---------|------|
| 有车时冻结基线 | 防止把车辆的影响"学"进基线(仿 TLD-110 |
| 100 窗口滑动平均 | 缓慢跟踪温漂,但不响应车辆 |
| 4× 冻结阈值 | 防止异常 CAPVD 上升污染基线V1.5 |
| 5% 斜率限幅 | 过滤 EMI/闪电尖峰,保护 IIRV2.0 |
| 冻结超时 + 稳定性检查 | 防止永久冻结死锁V2.3~2.5 |
#### 4.4.3 基线更新速率
`vd1_task` 每 ~10ms 执行一次。空闲时每次累加 CAPVD 到 `ORG_SUM`,满 100 次后取平均更新 Origin
```
100 样本 × 10ms/tick = 1000ms = 1 秒
```
| 产品 | 窗口大小 | 更新周期 | 空闲时跟踪 | 有车时冻结 |
|------|---------|---------|-----------|-----------|
| **DLD154V4B** | 100 次 | **1000ms** | ✅ | ✅ |
| **M1H** | 100 次 | 5000ms | ✅ | ❌(有车也跟踪) |
| **TLD-110** | 16 次 | ~800ms | ✅ | ✅ |
> **注意**V2.0 将 tick 从 50ms 提升到 10ms基线更新从每 5 秒加速到每 1 秒 —— 对温漂的跟踪能力显著提升,同时保持 100 窗口的抗噪能力。
### 4.5 Origin 污染保护与冻结超时恢复V1.5 → V2.5
#### 4.5.1 问题演进
| 版本 | 问题 | 方案 | 遗留问题 |
|------|------|------|---------|
| V1.5 | 车辆驶入时 Xn 先增Origin 被污染后无法释放 | 4×阈值冻结 | 环境变化时永久冻结,需复位 |
| V2.3 | 永久冻结导致死锁 | 冻结超时30s 后强制更新) | 波动值也可能超时触发 |
| V2.4 | 波动值被误判为"新常态" | 稳定性检查±2% 窗口) | — |
| V2.5 | 30s 等待太长 | 缩短到 10s | — |
#### 4.5.2 当前完整逻辑
```c
if (dev < dlt_ORG * 4) {
/* 正常范围 → 跟踪,清零冻结状态 */
loop1_freeze_cnt = 0;
update_moving_average(...);
} else {
/* 异常偏高 → 冻结 + 超时 + 稳定性验证 */
if (loop1_freeze_cnt == 0)
loop1_freeze_ref = CAPVD; // 记录冻结起始值
else if (|CAPVD - freeze_ref| > freeze_ref * FREEZE_STABILITY_RATE / 100)
reset(freeze_cnt, freeze_ref); // 波动 > ±2% → 重新计时
loop1_freeze_cnt++;
if (loop1_freeze_cnt >= FREEZE_TIMEOUT) { // 10s @ 10ms/tick
Origin = CAPVD; // 连续稳定 → 接受为新基线
}
}
```
#### 4.5.3 关键常量
| 常量 | 值 | 说明 |
|------|-----|------|
| 冻结触发阈值 | dlt_ORG × 4 | CAPVD 偏离 Origin 的倍数 |
| FREEZE_TIMEOUT | 1000 | ~10s @ 10ms/tick |
| FREEZE_STABILITY_RATE | 2 | 稳定性窗口:参考值的 ±2% |
| 基线窗口 | 100 | 滑动平均样本数(更新周期 ~1s |
---
## 5. 时序状态机
### 5.1 状态转移
```
IN_DELAY=10 OUT_DELAY=10
[空闲] ──有车──→ [进入延时] ──超时──→ [有车确认]
↑ │
│ 车辆离开 (+ SW_4离开延时)
│ ↓
└──脉冲结束───── [脉冲输出] ←──超时── [离开延时]
PULSE_DELAY=10
```
### 5.2 时序参数
| 参数 | Tick (10ms) | 时间 | 说明 |
|------|------------|------|------|
| IN_DELAY | 50 | **500 ms** | 进入确认防抖3 次 IIR 确认 + 500ms IN_DELAY |
| OUT_DELAY | 50 | **500 ms** | 离开防抖(仅 SW_4=ON 时生效OFF 时为 0 |
| PULSE_DELAY | 50 | **500 ms** | 脉冲输出宽度 |
| HOLD_TIME | 5×1200 | **~5 min** | 有限存在超时 |
| LC_HOLD_TIME | 4×1200 | **~4 min** | 安全复位超时 |
| STABLE_SAMPLES | 128 tick | **~128 ms** | 上电稳定期 |
| FREEZE_TIMEOUT | 1000 | **~10 s** | 基线冻结超时(连续稳定后更新 Origin |
> **M4 优化**V2.0 将 tick 从 50ms (TMR15 5ms×10) 提升到 10ms (vTaskDelay 10ms)。IIR 系数同步调整(α 从 79/256→18/256保持等效时间常数。进入确认 3×10ms + 500ms IN_DELAY = ~530ms比旧设计 (50ms + 500ms = 550ms) 略快。基线更新从 5s 加速到 1s。
### 5.3 系统 Tick 来源
TMR15 每 5ms 产生一次中断,`TM1cnt` 计数到 10 后触发 vd1_task50ms 周期。TMR15 ISR 同时驱动 LED。
---
## 6. 指示灯状态机
### 6.1 三 LED 驱动架构
```
TMR15 ISR (每 5ms)
├── 红灯 PB1 — TMR14 PWM 呼吸(硬件自主,不需软件干预)
├── 绿灯 PA9 — poll_green_led() 每 tick 更新
└── 黄灯 PA10 — poll_yellow_led() 每 tick 更新
```
> **设计原则**:三 LED 由 TMR15 ISR 统一驱动单点控制。vd1_task 只设标志位ISR 据此刷新硬件。
### 6.2 绿灯行为表
```c
void poll_green_led(void) {
if (loop1_INI_LOOP || !g_loop_stable) {
// 自检 / 稳定期:慢闪 200ms
blink_200ms();
} else if (g_disconnect_active) {
// 当前断开中:强制灭
LEDA_OFF;
} else if (VD_FLAG || FLAG_IN || FLAG_OUT) {
// 有车 / 进入 / 离开延时中:亮
LEDA_ON;
} else {
// 无车:灭
LEDA_OFF;
}
}
```
### 6.3 黄灯行为表
| 条件 | 行为 | 参数 | 诊断含义 |
|------|------|------|---------|
| `g_disconnect_active == 1` | **快闪** | 200ms 亮 / 200ms 灭 | 线圈当前断开中 |
| `!g_loop_power_up_state` | **快闪** | 200ms 亮 / 200ms 灭 | 上电后从未连接线圈 |
| `g_disconnect_count == 1` | **1 短闪** | 80ms 亮 / 200ms 灭 → 1.2s 灭(循环) | 断开 1 次,已恢复 |
| `g_disconnect_count == 2` | **2 短闪** | 同上 | 断开 2 次 |
| `g_disconnect_count >= 3` | **3 短闪** | 同上 | 断开 3+ 次 |
| 正常 | **灭** | — | 一切正常 |
```c
void poll_yellow_led(void) {
if (g_disconnect_active || !g_loop_power_up_state)
fast_blink_200ms(); // 断开中快闪
else if (g_disconnect_count > 0)
n_short_flash(g_disconnect_count); // N 短闪编码
else
led_off(); // 正常
}
```
> **注意**"上电后不接线,之后再接线圈"不计入断开次数(`g_loop_power_up_state` 控制)。只有已连接过的线圈断开才计入 `g_disconnect_count`。
---
## 7. 上电稳定期
### 7.1 背景
Origin 首次确立后,线圈振荡未真正稳定。立即启用检测容易误判为有车(绿灯常亮)。
### 7.2 实现
```c
#define STABLE_SAMPLES 128 // ~128ms
if (!g_loop_stable) {
// 仅跟踪基线,不检测车辆
update_moving_average(&ORG_SUM, &ORG_CNT, &Origin, CAPVD, 100);
if (++_stable_cnt >= STABLE_SAMPLES)
g_loop_stable = 1; // 稳定确认,正式启用检测
return; // 跳过进入/离开判断
}
```
稳定期间绿灯继续慢闪(`poll_green_led` 条件包含 `!g_loop_stable`)。
安全复位时 `loop1_LC_Reset` 重置 `g_loop_stable = 0`
---
## 8. 线圈重连逻辑
### 8.1 设计目标
断开时不丢 VD_FLAG车辆仍在线圈上方重连后快速收敛 IIR。
### 8.2 状态机
```
断开检测: loop1_RF_FLAG == 0 (没有收到边沿)
├─ loop1_LOOP_OK = 0
├─ g_disconnect_active = 1
├─ g_disconnect_count++ (≤3)
├─ 保留 loop1_VD_FLAG ← 关键:不丢有车状态
├─ 关断继电器输出
└─ 绿灯强制灭
重连检测: loop1_RF_FLAG == 1 (重新收到边沿)
├─ loop1_LOOP_OK = 1
├─ g_disconnect_active = 0
├─ loop1_CAPVD = 0 ← 触发快速收敛
└─ vd1_task: CAPVD == 0 → CAPVD = Value (直锁首个样本)
```
### 8.3 断开-重连场景矩阵
| 断开前 | 断开期间 | 重连后 | VD_FLAG | 绿灯 | 继电器 |
|--------|---------|--------|---------|------|--------|
| 有车 | 车仍在 | 车仍在 | 1 → 保持 | 恢复亮 | 恢复输出 |
| 有车 | 车离开 | 无车 | 1 → cnt_release→3 → 0 | 灭 | 释放 |
| 无车 | 车进入 | 有车 | 0 → CAPVD>Origin+dlt → 1 | 亮 | 吸合 |
---
## 9. 调试接口 (TTL Tx)
### 9.1 物理层
| 参数 | 值 |
|------|-----|
| 接口 | TTL 电平 UART Tx |
| 电平 | 3.3V CMOS |
| 波特率 | 9600默认 |
| 数据位 | 8 |
| 停止位 | 1 |
| 校验 | 无 |
| 用途 | 调试信息输出(频率、状态、标志位) |
### 9.2 数据格式
> 调试输出内容待后续版本补充。当前版本可通过 TTL 串口输出检测状态和原始频率值,用于开发调试和现场调参。
---
## 10. 故障检测
### 10.1 检测项
| 检测项 | 判定条件 | 触发动作 |
|--------|---------|---------|
| 线圈断开 | `loop1_RF_FLAG == 0` 持续 | 黄灯快闪 / 继电器释放 |
| 线圈短路 | Xn 持续为 0 或极小 | 黄灯快闪 / 继电器释放 |
| 频率过低 | Value 持续 < MIN_FREQ | 黄灯编码闪烁 |
| 频率过高 | Value 持续 > MAX_FREQ | 黄灯编码闪烁 |
### 10.2 黄灯编码设计
断开次数编码提供了比 TLD-110 的均匀闪烁更丰富的诊断信息:
- **快闪=当前故障** → 现场立即处理
- **N短闪=历史故障** → 判断是偶发还是持续问题
---
## 11. 代码架构
### 11.1 目录结构
```
DLD154V4B/
├── utilities/at32f421_freertos_demo/
│ ├── src/
│ │ └── TaskLoop.c # 主检测逻辑 (~945 行 V2.5)
│ ├── inc/
│ │ └── TaskLoop.h # 全局变量和函数声明
│ └── ... # FreeRTOS + HAL 框架
├── docs/
│ ├── product-manual.md # 产品手册
│ ├── technical-spec.md # 本文档
│ ├── devlog.md # 开发日志
│ └── reference_analysis.md # M1H/TLD-110 参考分析
└── README.md
```
### 11.2 代码精简历程
| 版本 | 代码量 | 说明 |
|------|--------|------|
| 原始 | ~1177 行 | 包含二阶滤波、FltHistoryManager 等死代码 |
| V1.1 | ~706 行 | 精简重构,-40% |
| V1.5 | ~868 行 | 增加平坦性判定、污染保护 |
| V2.5 | ~945 行 | 增加双路 IIR、斜率限幅、进入确认、冻结超时+稳定性 |
**删除的死代码:**
- 二阶差分滤波(计算但从未参与判决)
- FltHistoryManager20+ 未用字段)
- StageRangeConfig区间约束未引用
- 动态窗口切换LOOP_WINDOW_SIZE_LOW → FAST
- 中间层时序状态PLUSE_IN_F / PLUSE_IN
---
## 12. 性能基准
### 12.1 检测性能
| 指标 | 值 | 说明 |
|------|-----|------|
| 进入检测延迟 | < 3 ms (测量) + 3×10ms (确认) + 500 ms (防抖) = **~530 ms** | M4 优化,比旧 550ms 略快 |
| 离开检测延迟 | < 3 ms (测量) + 平坦性确认 + 500 ms (防抖) | 含双重确认 |
| 误检率(单阈值) | — | 基准参考 |
| 误检率(平坦性) | 显著降低 | 大车多峰场景 |
| 频率分辨率 | < 0.01% | 取决于线圈 Q 值 |
| 温漂补偿 | 自动100 窗口基线跟踪,更新周期 ~1s | 仅无车时;冻结超时 10s |
| 瞬态抑制 | 5% 斜率限幅 + 3 次进入确认 | EMI/闪电免疫 |
### 12.2 CPU 占用
| 任务 | 频率 | CPU 占用 @120MHz | 说明 |
|------|------|-----------------|------|
| TMR3 ISR (捕获) | 50k/s @100kHz | ~2.1% | 每边沿约 50 周期 |
| TMR15 ISR (tick) | 200/s | < 1% | LED + 计数 |
| vd1_task | 100/s | < 1% | 滤波 + 检测M4 10ms tick |
| FreeRTOS 开销 | — | < 1% | 任务调度 |
| **总计** | — | **< 5%** | 余量充足 |
### 12.3 RAM 占用
| 模块 | 大小 | 说明 |
|------|------|------|
| 全局检测变量 | ~100 B | 状态、计数、滤波值 |
| FreeRTOS 堆栈 | ~4 KB | 任务栈 + 系统堆 |
| 剩余 | ~11 KB | 可用于扩展功能 |
---
## 13. 编译选项
```c
// TaskLoop.h
#define USE_FLATNESS_EXIT 1 // 1 = 平坦性离开判定 (CN200910309382)
// 0 = 简单 cnt_release 防抖
// M4 优化参数
#define MAX_SLOPE_RATE 5 // 斜率限幅: 单次最大变化 5%
#define ENTRY_CONFIRM 3 // 进入确认: 连续 N 次低于阈值
#define FREEZE_TIMEOUT 1000 // 冻结超时: ~10s @ 10ms/tick
#define FREEZE_STABILITY_RATE 2 // 稳定性窗口: 参考值的 ±2%
```
---
## 14. 关键专利
| 专利号 | 名称 | 权利人 | 应用 |
|--------|------|--------|------|
| CN200910309382 | 一种防误检环形线圈车辆检测器 | 中山大学 张辉/黄永强/陈古典 | 平坦性三条件离开判定 |
DLD154V4B V1.4 起实现该专利的整数化版本,用于大车通行时的离开判定,有效抑制频率曲线多峰导致的多次误触发。
---
## 15. 修订记录
| 版本 | 日期 | 说明 |
|------|------|------|
| V1.0 | 2026-06-24 | 技术规格书初版V1.5 固件) |
| V2.0 | 2026-06-29 | 更新至 V2.5 固件:双路 IIR、斜率限幅、进入确认、冻结超时+稳定性 |