Files
DLD154V4B/docs/devlog.md
wangfq 266ffc5909 docs: 四文档更新至 V2.6 — 单路 IIR + WINDOW_ORIGIN=500
- devlog: 新增 V2.6 架构简化章节 + 两阶段基线策略
- release-notes: V2.5→V2.6, 更新 M4 优化表(双路→单路 IIR)
- product-manual: V2.5→V2.6 + 版本历史
- technical-spec: §4.2 重写为单路 IIR ALFA_CAP1=79 @10ms,
  §4.3.2 去除 CAPVD_fast 引用, §4.4.3 两阶段基线表,
  §15 新增 V2.1 修订记录
2026-06-29 19:16:11 +08:00

18 KiB
Raw Blame History

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.mdM1H + 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 宏

新增编译开关,一行切换离开判据:

#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。

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

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 — 时序参数修正 & 接口更正

时序参数修正

OUT_DELAY 和 PULSE_DELAY 之前沿用 M1H 的值1.9s / 950ms现修正为 500ms

参数 M1H 旧值 DLD154V4B 新值
OUT_DELAY 1.9s (38 tick) 500ms (10 tick)SW_4 控制开关
PULSE_DELAY 950ms (19 tick) 500ms (10 tick),固定

SW_4 语义0 = 无离开延时立即脉冲1 = 离开延时 500ms。删除 OUT_DELAY_FAST / PULSE_DELAY_FAST 宏,因只有一组值。

// TaskLoop.h
#define OUT_DELAY       10    // 离开防抖 500ms仅 SW_4=ON 时生效)
#define PULSE_DELAY     10    // 脉冲宽度 500ms

// TaskLoop.c
if (SET_DLY) {
    loop1_OUTCNT++;
    if (loop1_OUTCNT > OUT_DELAY) { ... }  // 500ms 延时
} else {
    // 无离开延时:立即 FLAG_PLUSE
}

接口修正

  • 去除所有 RS485 相关描述:本产品只有 TTL 电平 UART Tx 调试口
  • 产品手册端子定义RS485-A/B → Tx TTL 调试输出
  • 技术规格书 §9整节从 RS485 协议改为 TTL Tx 调试接口说明

2026-06-26 — M4 核心优化:双路 IIR + 进入确认 + 斜率限幅

背景

DLD154V4B 的 8051 时代设计在 M4 上可以做得更好。8051 的 50ms tick 是 CPU 限制,不是最优选择。

三项改进

1. 10ms tick + 双路 IIR

滤波器 α τ 用途
CAPVD (慢速) 18/256 ≈ 0.07 135ms 基线跟踪,等效原 50ms 的 79/256
CAPVD_fast (快速) 128/256 = 0.5 28ms 进入/离开检测判定

tick 提升到 10ms但通过调整 α 保持与 50ms 设计相同的滤波强度。快速 IIR 用于检测,慢速 IIR 用于基线,两路各司其职。

2. 斜率限幅

EMI/闪电等瞬态干扰会造成 CAPVD 瞬间跳变。物理车辆不可能让线圈频率瞬间改变 >5%

max_step = CAPVD × 5 / 100;        // 5% 限幅
if (|delta| > max_step) delta = clamp(delta, -max_step, max_step);

尖峰被截断,真实车辆信号(缓慢的频率漂移)不受影响。

3. 进入确认

原设计:单次 CAPVD < Origin-dlt → 立即 VD_FLAG=1同 8051

新设计CAPVD_fast 连续 3 次低于阈值 → 才判定有车

if (CAPVD_fast < Origin - dlt)
    entry_cnt++;
    if (entry_cnt >= 3) { VD_FLAG = 1; ... }
else
    entry_cnt = 0;  // 一旦恢复就重置

对真实车辆CAPVD_fast τ=28ms3 次确认 = 30ms加上 IN_DELAY 500ms = 总响应 ~530ms比原来的 550ms 还快。

对瞬态干扰:单个尖峰无法连续 3 次 → 被过滤。

对比

指标 8051 原设计 M4 优化
tick 周期 50ms 10ms
IIR τ (检测) 135ms 28ms (5× 快)
IIR τ (基线) 135ms 135ms (相同)
进入判定 单次阈值 3 次连续确认
瞬态抑制 斜率限幅 + 确认
进入响应 ~550ms ~530ms
误触发风险

兼容性

  • 离开检测路径不变cnt_release 平坦性均已带确认)
  • 灵敏度表、IN_DELAY、OUT_DELAY 等参数不变
  • 可通过 ENTRY_CONFIRM 宏调整确认次数,MAX_SLOPE_RATE 调整限幅强度

2026-06-26 — CAPVD_fast 初始化修复

问题

M4 V2.0 引入双路 IIR 后,进入检测使用 CAPVD_fast(快速 IIRα=0.5)。但 CAPVD_fast 始终为 0导致首次进入判定就触发有车。

根因

// 原代码(错误):
if (loop1_CAPVD_fast != 0) {
    loop1_CAPVD_fast = (loop1_CAPVD_fast + loop1_CAPVD) / 2;
}

TMR3 ISR 首次捕获时直接设置 loop1_CAPVD(不为 0INIT_VDCAPVD_fast 初始化为 0。vd1_task 进入时 CAPVD != 0if (CAPVD_fast != 0) 永远为 false → CAPVD_fast 保持 0 不更新。

修复

条件反转:== 0 时首次锁定当前 CAPVD 值,之后正常执行快速 IIR。

// 修复后:
if (loop1_CAPVD_fast == 0) {
    loop1_CAPVD_fast = loop1_CAPVD;  // 首次直接锁定
} else {
    loop1_CAPVD_fast = (loop1_CAPVD_fast + loop1_CAPVD) / 2;
}

2026-06-26 — 稳定期绕过 IIR 和斜率限幅

问题

上电后很快输出有车状态。日志显示:

First_capSum:177406, Origin:177406         ← 首测为瞬态高值
Loop stable, Origin:149755                  ← 稳定期后 Origin 仍偏高
Car_In, Value:128654, Origin:149755         ← Origin - Value = 21067 >> dlt=82

根因

V2.0 引入的 5% 斜率限幅 在稳定期内仍然生效。首测 CAPVD=177406 是瞬态高值(~38% 偏高),斜率限幅让 CAPVD 在 128 个采样周期内只能缓慢下降到 149755 — 无法在稳定期内充分收敛。100 窗口滑动平均被前半段的高值污染,导致 Origin 停在 149755远高于真实值 ~128688。

修复

稳定期内不走 IIR 和斜率限幅——直接用 raw Value 建立基线:

if (!g_loop_stable) {
    /* 稳定期内不做斜率限幅和 IIR — 直接用 Value 快速收敛到真实基线 */
    loop1_CAPVD = loop1_Value;
    loop1_CAPVD_fast = loop1_Value;
    // ... 滑动平均跟踪 ...
    return;
}

稳定期结束后恢复正常 IIR + 斜率限幅用于检测。

场景 修复前 修复后
首测瞬态 177406 被限幅缓慢下降 直接被 128688 覆盖
Origin 收敛 149755 (偏离 +16%) ~128688 (正确)
稳定期结束 Origin 偏离 → 误判有车 Origin 准确 → 正常检测

2026-06-29 — 基线冻结超时自动恢复

问题

V1.5 引入的 Origin 污染保护机制在 CAPVD 异常偏高时永久冻结基线。如果线圈因环境变化温度漂移、器件老化、更换线圈稳定在新的频率值Origin 永远不会更新 → 绿灯常亮、永久误判有车。

方案

在冻结路径上增加超时自动恢复 + 稳定性验证

#define FREEZE_TIMEOUT          3000  // ~30s @ 10ms/tick
#define FREEZE_STABILITY_RATE   2     // 稳定性窗口: 参考值的 ±2%

if (dev >= dlt_ORG × 4) {
    if (freeze_cnt == 0)
        freeze_ref = CAPVD;           // 记录冻结起始值
    else if (|CAPVD - freeze_ref| > freeze_ref × 2%)
        reset(freeze_cnt, freeze_ref); // 波动过大 → 重新计时

    freeze_cnt++;
    if (freeze_cnt >= 3000) {
        Origin = CAPVD;               // 连续30s稳定在±2%窗口内 → 接受
    }
}

行为表格

场景 CAPVD 行为 稳定性检查 结果
车辆驶入Xn 先增) 偏高 2~3s 后下降 中途恢复 → freeze_cnt 清零 正常冻结保护 ✓
温度漂移 缓慢爬升到新值并稳定 爬升阶段频繁重置;稳定后连续 10s Origin 更新 ✓
更换线圈 瞬间跳到新频率 稳定后连续 10s Origin 更新 ✓
车辆缓慢驶入CAPVD 持续爬升) 持续偏高且不断上升 每超出 ±2% 就重置 → 永远到不了 10s 不触发更新

最后一行是关键:如果没有稳定性检查,车辆缓慢驶入时 CAPVD 持续偏高 10s 也会触发 Origin 更新——这是错误的。


2026-06-29 — 架构简化:单路 IIR ALFA_CAP1=79 + WINDOW_ORIGIN=500

背景

双路 IIR慢速 α=18/256 + 快速 α=0.5)在 ALFA_CAP1=18 时斜率限幅参考 CAPVD 拖累了快速通路, 多次修补后发现:ALFA_CAP1=79 @10ms 本身就 τ≈32ms已经足够快,无需双路复杂度。

改动

项目 改前 改后
ALFA_CAP1 18 (@10ms, τ=135ms) 79 (@10ms, τ=32ms)
IIR 路数 双路(慢+快) 单路
WINDOW_ORIGIN 100 (1s) 500 (5s)
稳定期窗口 500 100
update_moving_average window uint8_t uint16_t
快速 IIR 输入 CAPVD慢速输出滞后 已删除
斜率限幅 快/慢双参考CAPVD + CAPVD_fast 单参考 CAPVD

保留的 V2 保护机制

  • 斜率限幅 (MAX_SLOPE_RATE=5%)
  • 进入确认 (ENTRY_CONFIRM=3)
  • 基线冻结超时 (10s + ±2% 稳定性检查)
  • 稳定期绕过 IIR/限幅 (V2.2)

两阶段基线策略

稳定期: 100 样本 × 10ms = 1s   → 快速收敛,开机即用
正常:   500 样本 × 10ms = 5s   → 强噪声抑制,稳定跟踪

修订记录

版本 时间 说明
V2.6 2026-06-29 架构简化: 单路 IIR ALFA_CAP1=79, WINDOW_ORIGIN=500, 稳定期100
V2.5 2026-06-29 冻结超时 30s→10s加快环境变化响应
V2.4 2026-06-29 冻结超时增加稳定性检查: ±2% 窗口内连续稳定
V2.3 2026-06-29 基线冻结超时: 持续偏高后强制更新 Origin防止死锁
------ ------ ------
V2.2 2026-06-26 稳定期绕过 IIR/斜率限幅,用 Value 直接收敛基线
V2.1 2026-06-26 CAPVD_fast 初始化修复(条件反转为 ==0 首次锁定)
V2.0 2026-06-26 M4 优化: 双路 IIR + 斜率限幅 + 进入确认tick 10ms
V1.7 2026-06-26 vTaskDelay 10→50ms 修正(对齐原始 TMR15 5ms×10 设计);基线更新 1s→5s
V1.6 2026-06-24 时序修正OUT_DELAY/PULSE_DELAY→500msRS485→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 参考分析文档