# DLD154V4B 技术规格书 > 单路线圈车辆检测器 | 固件版本: V1.5 | 文档版本: V1.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() — 每 5ms tick 执行 │ │ ├── IIR 滤波 (ALFA_CAP1 = 79/256) │ │ ├── 基线跟踪 (100 窗口滑动平均) │ │ ├── 进入/离开检测 │ │ ├── 时序状态机 (IN/OUT/PULSE/HOLD) │ │ └── 平坦性离开判定 (CN200910309382) │ ├── 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 滤波 ```c // α = Flt_Reg / 256 = 79 / 256 ≈ 0.3086 if (Value > CAPVD) CAPVD += ((Value - CAPVD) * 79) >> 8; else CAPVD -= ((CAPVD - Value) * 79) >> 8; ``` | 参数 | 值 | 说明 | |------|-----|------| | α | 79/256 ≈ 0.3086 | 指数平滑系数 | | 响应速度 | ~3 次达 63% | ~15ms @5ms tick | | 噪声抑制 | 良好 | 单次野值影响 < 31% | ### 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 进入检测 ```c dlt_ORG = (Origin * SensTable[SENS]) >> 16; // /65536 if (CAPVD > Origin + dlt_ORG) { // 频率上升超过阈值 → 有车 // 进入 IN_DELAY (500ms) 防抖 } ``` > **注**:有车时线圈电感减小 → 频率上升 → CAPVD > Origin。公式为 `CAPVD > Origin + dlt_ORG`(判定上升量)。 #### 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 | 平坦确认次数 | **整数化适配:** 专利原实现用 float(Hz 频率值),DLD154V4B 用 uint32 定点(Origin ≈ 131K)。导数计算用 int32 整数差分,阈值 /K1、/K2 做整数除法,精度足够。 ### 4.4 基线跟踪 ```c // 有车时冻结,无车时 100 窗口滑动平均 if (!VD_FLAG && !FLAG_OUT) { if (CAPVD - Origin < dlt_ORG * 4) { // Origin 污染保护 ORG_SUM += CAPVD; if (++ORG_CNT >= 100) { Origin = ORG_SUM / 100; ORG_SUM = ORG_CNT = 0; } } else { // 冻结:CAPVD 偏离 Origin 超过进入阈值的 4 倍 ORG_SUM = ORG_CNT = 0; } } ``` | 设计决策 | 原因 | |---------|------| | 有车时冻结基线 | 防止把车辆的影响"学"进基线(仿 TLD-110) | | 100 窗口跟踪 | 缓慢跟踪温漂,但不响应车辆 | | 4× 冻结阈值 | 防止异常 CAPVD 上升污染基线(V1.5 新增) | ### 4.5 Origin 污染保护(V1.5) **问题**:实测发现车辆驶入时 Xn 偶尔先增大再减小。无车状态下 Origin 跟踪上升被污染到虚高值,导致离开时 `|f - f_b|` 远超阈值 → 绿灯常亮、永远不释放。 **修复**:基线跟踪前增加保护条件: ```c // 仅当 CAPVD 偏离 Origin < dlt_ORG × 4 时才更新基线 // 超出则冻结+重置累计 if (CAPVD - Origin < dlt_ORG * 4) update_moving_average(...); else freeze(); ``` | 场景 | Origin | CAPVD | dev | 4×阈值 | 结果 | |------|--------|-------|-----|--------|------| | 正常无车 | 127080 | 127081 | +1 | 276 | 跟踪 ✓ | | 异常上升 | 127085 | 127884 | +799 | 276 | 冻结 ✓ | --- ## 5. 时序状态机 ### 5.1 状态转移 ``` IN_DELAY=10 OUT_DELAY=38 [空闲] ──有车──→ [进入延时] ──超时──→ [有车确认] ↑ │ │ 车辆离开 │ ↓ └──脉冲结束───── [脉冲输出] ←──超时── [离开延时] PULSE_DELAY=19 ``` ### 5.2 时序参数 | 参数 | Tick (50ms) | 时间 (SW_4=OFF) | 时间 (SW_4=ON 快速) | 说明 | |------|------------|-----------------|--------------------|------| | IN_DELAY | 10 | **500 ms** | 500 ms(不变) | 进入确认防抖 | | OUT_DELAY | 38 / 10 | **1.9 s** | **500 ms** | 离开确认防抖 | | PULSE_DELAY | 19 / 10 | **950 ms** | **500 ms** | 脉冲输出宽度 | | HOLD_TIME | 5×1200 | **~5 min** | ~5 min(不变) | 有限存在超时 | | LC_HOLD_TIME | 4×1200 | **~4 min** | ~4 min(不变) | 安全复位超时 | | STABLE_SAMPLES | 128 tick | **~128 ms** | 128 ms(不变) | 上电稳定期 | > **SW_4 快速模式**:当 SW_4=ON 时,OUT_DELAY 和 PULSE_DELAY 均缩短为 10 tick(500 ms),用于快速落杆场景。IN_DELAY 和其他参数不受影响。 ### 5.3 系统 Tick 来源 TMR15 每 5ms 产生一次中断,`TM1cnt` 计数到 10 后触发 vd1_task(50ms 周期)。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 # 主检测逻辑 (~868 行 V1.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 行 | 增加平坦性判定、污染保护 | **删除的死代码:** - 二阶差分滤波(计算但从未参与判决) - FltHistoryManager(20+ 未用字段) - StageRangeConfig(区间约束未引用) - 动态窗口切换(LOOP_WINDOW_SIZE_LOW → FAST) - 中间层时序状态(PLUSE_IN_F / PLUSE_IN) --- ## 12. 性能基准 ### 12.1 检测性能 | 指标 | 值 | 说明 | |------|-----|------| | 进入检测延迟 | < 3 ms (测量) + 500 ms (防抖) | 电信号延迟 | | 离开检测延迟 | < 3 ms (测量) + 平坦性确认 + 1.9 s (防抖) | 含双重确认 | | 误检率(单阈值) | — | 基准参考 | | 误检率(平坦性) | 显著降低 | 大车多峰场景 | | 频率分辨率 | < 0.01% | 取决于线圈 Q 值 | | 温漂补偿 | 自动(100 窗口基线跟踪) | 仅无车时 | ### 12.2 CPU 占用 | 任务 | 频率 | CPU 占用 @120MHz | 说明 | |------|------|-----------------|------| | TMR3 ISR (捕获) | 50k/s @100kHz | ~2.1% | 每边沿约 50 周期 | | TMR15 ISR (tick) | 200/s | < 1% | LED + 计数 | | vd1_task | 20/s | < 1% | 滤波 + 检测 | | 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 防抖 ``` 置 0 回退到传统 `cnt_release >= 3`,方便对比测试两种方案的差异。 --- ## 14. 关键专利 | 专利号 | 名称 | 权利人 | 应用 | |--------|------|--------|------| | CN200910309382 | 一种防误检环形线圈车辆检测器 | 中山大学 张辉/黄永强/陈古典 | 平坦性三条件离开判定 | DLD154V4B V1.4 起实现该专利的整数化版本,用于大车通行时的离开判定,有效抑制频率曲线多峰导致的多次误触发。 --- ## 15. 修订记录 | 版本 | 日期 | 说明 | |------|------|------| | V1.0 | 2026-06-24 | 技术规格书初版 |