Files
DLD154V4B/docs/devlog.md
T
wangfq 60413be73f feat(V4B): 方案B实验 V4.05 — USE_SLOW_RELEASE=0 + 调深释放阈值表 ReleaseTable_B
对比路线(与V4.04方案A A/B): 释放走快滤波(无慢滤波状态, 消除悬停风险),
手感对齐改由调深释放表 {80,42,27,18}(原始{60,32,21,14}加深30%)承担。

⚠关键认知(仿真+单测双确认): 释放方向是CAPVD向Origin恢复,
dlt增大(调深)→释放线降低→释放更早(与'调深=更严格'直觉相反)。
仿真预测: 深信号(≥0.2%)原始表更接近PD132T; 浅信号(0.1%)加深表更接近。

单测: tests/test_planb_release.c 新增(滞回为正✓/加深表释放≤原始表✓/释放时刻合理✓)
     test_release_slow_filter.c(方案A)仍通过, 两方案可回归
文档: devlog V2.14 + technical-spec §4.3.3 方案B段
2026-09-01 13:48:22 +08:00

33 KiB
Raw Blame History

DLD154V4B 开发日志

MCU: AT32F421F8P7 (Cortex-M4, 120MHz) | 线圈通道: 1路 | 调试口: TTL Tx


2026-09-01 — 方案B 实验:快滤波释放 + 调深释放阈值表(固件 V4.05)

固件版本:V4.05cmcng.hFIRMWARE_VER="4.05" + MAIN=4/SUB=5)。devlog 修订 V2.14。 状态:实验对比版——与 V4.04(方案A)现场 A/B 对比后定稿,二选一保留。

背景

V4.04(方案A:慢滤波释放 α21 + 进入 snap)已修两现象,但现场想对比另一条路线:不用慢滤波状态(消除任何滤波悬停风险),改由释放阈值表承担手感对齐。

方案B 配置(TaskLoop.h

含义
USE_SLOW_RELEASE 0 释放走快滤波(α79@10ms, τ≈22ms),无慢滤波状态
USE_PLANB_TABLE 1 释放判定用 ReleaseTable_B(调深表)
ReleaseTable_B {80, 42, 27, 18} 原始表 {60,32,21,14} 加深 ~30%

各档滞回验证:ReleaseTable_B < SensTable(进入表)→ 滞回为正,无结构假释放。

⚠ 关键认知:加深方向的物理含义(仿真+单测双重确认)

释放方向是 CAPVD 从车辆深度向 Origin 恢复(从深往浅)。释放线 = Origin − dlt

  • dlt 增大(调深)→ 释放线降低 → CAPVD 恢复中更早碰到 → 释放更早(与"调深=更严格"的直觉相反)
  • 单测 tests/test_planb_release.c:4 档 × 4 速度全部确认"加深表释放 ≤ 原始表"(如 SENS=3, 3s 抬:原始@2960ms → 加深@2930ms

仿真预测(现场实测验证点)

板信号深度 加深表 vs PD132T 结论
≥0.2%200cnt+ 加深表比 PD132T 早(差 3~6 counts 深信号下原始表 {60,32,21,14} 更接近 PD132T
~0.1%100cnt 加深表与 PD132T 差 ~1.3 counts 浅信号下加深表更接近

现场验证:若实测"加深表释放比 V4.04 更早(板抬更低就释放)",说明方向如仿真;若与 PD132T 手感更近,则加深表定稿;否则 USE_PLANB_TABLE=0 一行切回原始表对比。

单测

  • tests/test_planb_release.c 新增(gcc 编译通过):滞回为正 ✓ / 加深表释放不晚于原始表 ✓ / 释放时刻合理 ✓
  • tests/test_release_slow_filter.c(方案A 单测)仍通过,两方案可回归

与方案A 的取舍(待现场数据)

  • 方案A:释放曲线"跟手速"与 PD132T 同构(τ 对齐),但有慢滤波悬停状态(V4.04 已 snap 堵死)
  • 方案B:无慢滤波状态(结构简单),但释放曲线是"速度无关的固定偏移",深信号下与 PD132T 有固有偏差
  • HR0/2 假释放:方案B 结构性免疫(快滤波进入后已同步到车辆深度,无悬停)

文档同步

  • technical-spec §4.3.3 补方案B 实验说明
  • analysis/docs/filter-coefficient-79-vs-64.md §4.5 方案B 段(待补)

2026-09-01 — 方案A 现场复核修正:RELEASE_ALFA 18→21 + 进入 snap(固件 V4.04

固件版本:V4.04cmcng.hFIRMWARE_VER="4.04" + MAIN=4/SUB=4)。devlog 修订 V2.13。

背景(现场复核)

方案A(V4.03)落地后金属板复测,两个现象:

  1. 慢速抬板释放高度 V4B 仍比 PD132T 高一点,且跟手速有关(抬得越慢越接近)
  2. 定在 HR0/2(释放高度一半)保持 ~1s,V4B 释放继电器,PD132T 不释放

根因分析

现象 根因 证据
1 释放偏高 τ 对齐用了近似口径:方案A α18 精确 τ≈137msPD132T α79@43.7ms 精确 τ≈118ms(α=79 时 T×256/α 近似公式高估 19.6%+ V4B 释放 3 次确认 30ms 仿真:2s 抬升 V4B +14mm、8s 抬升 +2mm,与现场"跟手速有关"吻合
2 HR0/2 假释放 双滤波结构(快进+慢出):进入由快滤波(τ≈22ms)30ms 确认,释放判定用慢滤波——进入确认瞬间慢滤波还悬在基线附近,残余信号落在窄带(SENS=3 时 0.032%~0.044%)时释放条件瞬时为真 → 3 次确认数满 → 假释放。PD132T 进出共用同一滤波,进入确认时滤波值已沉过离开线,结构性免疫 仿真:0.10% 板 HR0/2 放置 V4B 释放@0.18sPD132T 不释放

修正(V4.04

  1. RELEASE_ALFA 18 → 21:精确 τ = T/ln(1−α) = 10/ln(121/256) ≈ 117ms,对齐 PD132T α79@43.7ms 精确 τ≈118ms。仿真释放高度差 3s 抬升 +9mm → +3mm(剩余为 3 次确认 30ms 固有延迟)
  2. 进入确认 snaploop1_CAPVD_slow = loop1_CAPVD(进入线档3 0.032% 恒深于离开线 0.021%,snap 后释放条件结构性为假)→ HR0/2 假释放窗口彻底消除

验证

  • tests/test_release_slow_filter.c 更新 ALFA_SLOW=21:τ fast=30ms/slow=120ms(理论 22/117ms);释放时机差 200ms ✓
  • 仿真(Origin=100000, SENS=3):α21+snap 下 0.10% 板 HR0/2 放置,原版释放@0.18s → 未释放 ✓
  • ⚠ 待板级:真机金属板复测确认释放高度对齐 + HR0/2 保持不再释放

文档同步

  • technical-spec §4.3.3 补 V4.04 修正说明
  • analysis/docs/filter-coefficient-79-vs-64.md §4.4 方案A 同步 α21 + snap
  • release-notes 待发布时更新

2026-08-31 — 释放手感对齐 PD132T:释放慢滤波(方案 A,固件 V4.03)

固件版本:V4.03cmcng.hFIRMWARE_VER="4.03" + MAIN=4/SUB=3;⚠ 顺带修正字符串 "4.00" 与数字 4/2 不一致的历史问题)。devlog 修订 V2.12。

背景(现场测试)

PD132T 替换交付后金属板测试(从上往下接近触发、从下往上离开释放):触发高度两边一致,释放高度不一致——V4B 刚离开触发位置一点点就释放,PD132T 要离得更远才释放。

根因分析

V4B PD132T
检测节拍 10ms 43.7ms
IIR 系数 ALFA_CAP1=79 79(SET_FLT=ON)/64(OFF)
τ ≈32ms ≈142~175ms
释放确认 3×10ms 单次
  • 判定公式与阈值表完全一致(Origin-dlt_ORG) < CAPVD,表 {60,32,21,14} 已对齐)
  • 差异在 CAPVD 恢复速度V4B 快 4.4~5.5× → 刚离开即恢复过浅阈值 → 早释放
  • 释放阈值浅(进入的 20%)放大差异;触发阈值深 + 接近过程信号斜率大 → 触发高度差不明显

方案 A 实现(USE_SLOW_RELEASE

  • 新增独立慢滤波 loop1_CAPVD_slow(α=18/256 @10ms → τ≈142ms,复刻 PD132T 恢复速度),吃原始 Value(不经斜率限幅)
  • 离开判定改用慢滤波值,进入路径不变
  • 开关 USE_SLOW_RELEASETaskLoop.h 默认 1,0=原快滤波释放,现场可对比回退)
  • 同步:INIT_VD 复位、稳定期直锁、线圈重连强制收敛
  • ⚠ 若现场 PD132T SET_FLT=ON(α64 → τ≈175ms),调 RELEASE_ALFA 15(τ≈170ms)更贴近

验证

  • tests/test_release_slow_filter.cgcc 单测):τ fast=30ms/slow=140ms(理论 32/142ms);模拟金属板离开(信号每 10ms +80),释放时机 fast=150ms/slow=410ms差 260ms
  • 括号结构三版本(原始/改动/回退)计数一致,无结构影响
  • ⚠ 待板级:真机金属板测试确认释放高度对齐;MRS 编译

文档同步

  • technical-spec §4.3.3 模式 1 补 V4.03 慢滤波说明
  • release-notes 待发布时更新

2026-08-28 — 灵敏度进入/离开对齐 PD132T(V2.11

背景

客户现场在用 PD132T8051),替换 DLD154V4B(同款芯片平台 AT32F421 的单路产品)。交付要求:平滑——灵敏度表现一致、触发/释放手感无感

对照 PD132T 源码(SensTable {300,60,32,21} / SensTable1 {60,32,21,14},阈值 Origin×表>>16离开阈值受 SET_ASB 拨码控制,出厂默认 OFF → 恒 14):

进入表对比:

PD132T Δf/f V4B 原 Δf/f 差异
0 0.458% 0.330% V4B 灵敏 1.39×
1 0.092% 0.165% V4B 钝 1.79×
2 0.049% 0.055% 几乎一致
3 0.032% 0.031% 几乎一致

离开表对比(PD132T SENUP 标贴 OFF → 电平1 → SET_ASB=1 → 分档 {60,32,21,14} = 出厂默认态):

PD132T 离开 V4B 原离开 差异
0 0.092%60 0.165%108 V4B 钝 1.8×,释放偏慢 ⚠
1 0.049%32 0.110%72 V4B 钝 2.25×
2 0.032%21 0.027%18 V4B 灵敏 1.16×
3 0.021%14 0.021%14 一致

决定

// TaskLoop.c
const uint16_t SensTable[4]   = {300, 60, 32, 21};   // V2.11(全档与 PD132T 完全一致)
const uint16_t SensTable_1[4] = { 60, 32, 21, 14};   // V2.11(与 PD132T 完全一致)
  • 进入表全档与 PD132T 完全一致216/108/36/20 → 300/60/32/21,Δf/f 0.33%/0.16%/0.055%/0.031% → 0.458%/0.092%/0.049%/0.032%
  • 离开表 {108,72,18,14} → {60,32,21,14}(对齐 PD132T SENUP 标贴 OFF=SET_ASB=1 的分档释放,出厂默认态;拨码低有效,若现场 SENUP 标贴 ON 需改恒 14 表)
  • 等效手感修正:V4B IIR τ=32ms vs 142ms、节拍 10ms vs 43.7ms → 同档位下 V4B 检测更快;3 次进入确认 → 调表后仍比 PD132T 抗瞬态误触
  • 增强滤波 FLT 不纳入对齐:现场少用(2026-08-28 决策),V4B 恒 79 + 斜率限幅组合更优

相关交付文档

  • 完整交付对齐分析:vd-analysis/docs/pd132t-to-v4b-delivery-alignment.md
  • 决策记录:脉冲模式不比较(现场少用);有限存在搁置待确认 V4B 是否启用

2026-08-28 — 新增 IWDT 硬件看门狗(V2.10)

背景

V4B 是全产品线唯一无看门狗的型号(对比:M1H 有 WDT_CONTR、PD132 系有 IWDG/WWDG、154Pro V3.03 有 WWDG 558ms)。现场若主循环卡死/FreeRTOS 调度异常,表现为"假活"——指示灯正常但检测逻辑已死,只能断电恢复。

实现(对齐 154Pro V3.03 双保险模式)

// main(): wdt_init() — IWDT 分频16 + 重装载4095, 使能后立即喂一次
// TMR15 ISR: g_wdg_counter++ (5ms)
// 主循环: poll_wdg() — 计数达 100 (500ms) 才 wdt_counter_reload()
  • 超时 ≈ 1.64sLSI≈40kHz16×4096/40k),喂狗周期 500ms,余量 >3×
  • 双保险语义:ISR 死 → 计数不涨 → 永不喂狗;主循环死 → poll_wdg 不执行 → 超时复位
  • FreeRTOS 调度失败/任务创建失败 → 无人喂狗 → 复位(避免"假活"

涉及文件

文件 变更
src/main.c Timr6_Init() 后调 wdt_init()
src/TaskLoop.c +g_wdg_counter + wdt_init() + poll_wdg()TMR15 ISR 计数;主循环喂狗
inc/TaskLoop.h +WDT 宏 + extern + 函数声明

验证

  • 隔离测试(host gcc mock wdt_* 驱动)5 项断言全过:init 配置、10s 喂狗 20 次(500ms 精确)、ISR 死不喂狗、边界 99/100 tick
  • 待现场验证:实际复位时间(LSI 实际频率),用 RST_REASON 类机制确认复位源

⚠ 现场发现并修复:WDT_DIV 传值 bugV2.10.1

现象:现场实测 WDT_COUNTER_LIMIT=100(500ms 喂狗)不断复位重启,改为 50(250ms)才正常。

根因wdt_divider_set() 参数是枚举值不是分频数值——WDT_CLK_DIV_16 = 0x02,寄存器只取低 3 位。宏误写 WDT_DIV=160b10000)→ 寄存器写入 0 = WDT_CLK_DIV_4实际分频 4,实际超时 410ms < 喂狗周期 500ms → 每次喂狗前已超时,不断复位。

修复#define WDT_DIV 2(枚举值)+ 调用处显式 (wdt_division_type) 转换;隔离测试升级 mock 为"寄存器 3bit 截断 + 反推实际分频",复现 bug 机制并断言修复后超时 1638ms > 500ms。

对照教训vd960Loop 原实现用 wdt_divider_set(WDT_CLK_DIV_64) 枚举写法 ✓ 无此问题——AT32 WDT 分频参数一律用枚举常量,勿传数值


2026-08-28 — 平坦性离开判定默认关闭(现场实测不理想)

背景

同一现场(广告杆/道闸)与 V2.8 SENS=3 调档同源。广告杆落杆误触发排查中发现,平坦性三条件离开判定(CN200910309382V1.4 移植)在真实场景响应不理想

  • 平坦性依赖"第一上升坡面"动态计算 Δ2/Δ3,车辆离开缓慢/多次驻留时,坡面特征不稳定,Δ2/Δ3 失真
  • 三条件(|f-fb|<dlt && |f'|<Δ2 && |f''|<Δ3)对离开过程平坦度要求苛刻,现场车辆(半挂、缓慢通过)离开确认滞后/不触发
  • 与简单 cnt_release 防抖对比实测,平坦性未体现出大车防误触优势,反而引入离开延迟

决定

// TaskLoop.h
#define USE_FLATNESS_EXIT   0   // V2.9 默认: 简单 cnt_release 防抖
  • 离开判定切回滞回 + 连续 3 次确认(Origin-dlt) < CAPVDcnt_release>=3),与 DLD154Pro 当前行为一致
  • 平坦性代码完整保留在 #if USE_FLATNESS_EXIT 内,可一行开启做现场对比
  • 全部平坦性状态变量/初始化/进入重置均带 #if 包裹,改 0 直接编译剔除,无残留引用

同步文档

  • technical-spec.md §4.3.3:模式 1 标为默认(V2.9 起),模式 2 标"默认禁用(#if 0,代码保留)";修正模式 1 伪代码方向错误(CAPVD < Origin + dlt(Origin - dlt) < CAPVD
  • product-manual.md / release-notes.md / roadmap.md:离开判定口径统一为"滞回 + 连续确认(平坦性可选)"
  • 版本历史补 V2.7/V2.8(此前 release-notes/product-manual 缺行),本次记 V2.9

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(不为 0),INIT_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   → 强噪声抑制,稳定跟踪

2026-06-30 — 项目文档补全

  • 验收标准 V1.0: 环路车辆检测器验收标准文档,涵盖电气特性、检测精度、响应时间、环境适应性
  • 发展路线图 V1.0: M1H→V4B 演进回顾 + V3.0 目标规划

2026-08-27 — 灵敏度最高档调整:SENS=3 阈值 10→20(防误触发)

改动

文件 内容
src/TaskLoop.c SensTable[3] 10→20(Δf/f 0.015%→0.031%,ΔL/L 0.031%→0.061%);SensTable_1[3] 9→14(滞回 90%→70%
src/main.c 注释掉重复定义 g_input_div = 1TaskLoop.c:23 已有定义,清理 ODR 重复)

原因(现场)

现场广告杆/道闸落杆时最高灵敏度档(10/9)易误触发——落杆机械动作 + 电机电磁扰动使 CAPVD 波动越过 0.015% Δf/f 阈值,误判有车(落杆瞬间继电器误动作)。提高至 20(0.031% Δf/f)并加大滞回(离开 14/进入 20 = 70%),落杆扰动不再越线,正常车辆信号(轿车典型 ΔL/L 1~5%)不受影响。

文档同步

  • docs/technical-spec.md §4.3.1 灵敏度表 + 表格(含 ΔL/L 口径说明)
  • docs/reference_analysis.md §5.6 灵敏度表

修订记录

版本 时间 说明
V2.10 2026-08-28 新增 IWDT 硬件看门狗(超时≈1.64s,双保险喂狗);修复 WDT_DIV 分频枚举传值 bug(勿传 16,用 WDT_CLK_DIV_16
V2.11 2026-08-28 灵敏度 0/1 档对齐 PD132T216/108→300/60,Δf/f 0.33%/0.16%→0.46%/0.09%),客户现场替换平滑交付
V2.9 2026-08-28 平坦性离开判定默认关闭(现场实测不理想),切回简单 cnt_release 防抖
V2.8 2026-08-27 灵敏度最高档 SENS=3 阈值 10→20、离开 9→14(防误触发);清理 g_input_div 重复定义
V2.7 2026-06-30 验收标准 + 发展路线图文档
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 参考分析文档