Files
DLD154V4B/docs/technical-spec.md

20 KiB
Raw Blame History

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 拨码开关逻辑

// 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 关键常量

#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 滤波

// α = 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 灵敏度表

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 进入检测

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)
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 基线跟踪

// 有车时冻结,无车时 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| 远超阈值 → 绿灯常亮、永远不释放。

修复:基线跟踪前增加保护条件:

// 仅当 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 tick500 ms用于快速落杆场景。IN_DELAY 和其他参数不受影响。

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 绿灯行为表

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+ 次
正常 一切正常
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 实现

#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 行 增加平坦性判定、污染保护

删除的死代码:

  • 二阶差分滤波(计算但从未参与判决)
  • FltHistoryManager20+ 未用字段)
  • 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. 编译选项

// 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 技术规格书初版