Files
DLD154Pro/docs/devlog.md
T
wangfq 2e4e40935c fix(DLD154Pro): 电容档位勘误 — 一级调频实为 33nF/66nF (0=66nF低频, 1=33nF高频)
现场评估实锤: 检测频率 56255Hz + 电感 121.276μH → 反推 C=66.00nF 零误差,
用户确认 154Pro 仅两档 33nF/66nF。此前代码与文档标注'0=33nF, 1=0nF'为错误认知。

- peripheral_main.c: 3 处注释修正 (引脚/调频逻辑/默认接入)
- DLD154Pro硬件资源.md / product-manual.md / technical-spec.md: 6 处修正
- devlog: 置顶勘误条目 (报告 L=121.276μH 正确; 小程序电容档表需按产品 33/66nF)
2026-08-27 15:17:43 +08:00

777 lines
33 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.
# DLD154Pro 开发日志
> MCU: CH591R (RISC-V, BLE) @60MHz | 线圈通道: 1路 | 调试口: RS485 / BLE
---
## 2026-08-27 — 电容档位勘误:一级调频实为 33nF/66nF(现场评估实锤)
### 背景
小程序现场评估报告(E04E7AA1DEA4, V3.05)检测频率 56255Hz + 电感 121.276μH → 反推 `C = 1/(4π²f²L) = 66.00nF` **零误差**;用户确认 154Pro 只有两档 **33nF / 66nF**。此前代码与文档全部标注"0=33nF(低频), 1=0nF(高频)"为**错误认知**(高频不接电容不可能振荡,当时注释就存疑)。
### 实际档位(用户确认 + 报告反推实锤)
| FLEVEL (PA12) | 电容 | 档位 | 证据 |
|---|---|---|---|
| 0 (FLEVEL_LOW) | **66nF** | **低频(默认)** | 报告 f=56255Hz, L=121.276μH → C=66.00nF 零误差 |
| 1 (FLEVEL_HIGH) | **33nF** | 高频 | 两档 33/66nF(用户确认) |
### 修正(9 处)
| 文件 | 处数 | 内容 |
|------|------|------|
| `APP/peripheral_main.c` | 3 | 引脚注释 / 调频逻辑注释 / 默认接入注释 |
| `docs/DLD154Pro硬件资源.md` | 1 | FLEVEL 行 |
| `docs/product-manual.md` | 2 | §3 频率档位说明 / §4 配置表 |
| `docs/technical-spec.md` | 3 | 架构图 / 电气参数 / 引脚表 |
### 影响
- 报告 L=121.276μH **正确**(66nF 低频档);此前按旧注释推 33nF→242μH 是错判方向
- 小程序"识别电容档"逻辑仍有缺陷:报告内部不一致(检测表隐含 66nF、几何表判 76nF——76nF 是 DLD110S 的档),**需按产品档表(33/66nF)修正,不能通用 vd960Loop 四档表 {33,43,66,76}**
- 频率上报 +360 补偿评估端未减(0.64% 系统误差,影响小)
- devlog 2026-07 历史条目"33nF"为早期认知,保留
---
## 2026-08-27 — RS485 协议省 Flash 减配(文档如实标注未实现,V3.05 固件 + 协议 V1.8
### 背景
本地调整 RS485 侧代码减少 Flash 占用:注释掉一批低频/非核心协议分支与调试打印。**原则:代码未实现的功能,协议文档在相应指令旁如实标注"未实现"**,避免文档承诺 ≠ 固件实现。
### 固件改动(本地,未提交)
| 文件 | 改动 |
|------|------|
| `APP/include/cmcng.h` | 版本 **V3.04 → V3.05**FIRMWARE_VER 字符串 + SUB 宏同步) |
| `APP/rs485_modbus.c` | FC 0x03(读保持寄存器)/0x10(批量写)/0x11Report Slave ID)分发注释;IR 0x0006/0x0007Variation/0x000AFreq Sens/0x000BCondition/0x000CDIP Virtual)注释;HR 0x00000x0004/0x0009/0x000A 写 case 注释(FC 0x06 仅剩 0x0010/0x0011/0x0012 |
| `APP/include/rs485_modbus.h` | `MB_MAX_READ_REGS 125→60→40``MB_MAX_DATA_BYTES 250→80`(40×2=80 匹配,原 60 会越界 40B,同日修正) |
| `APP/rs485_700bs.c` | 0x3D DIP 查询分支注释 + 4 处调试 PRINT 注释 |
| `APP/peripheral_main.c` | `BREATH_OPTO_DUTY_STEP 32→64`(注释"~0.5s 周期"未同步,实际 2 步≈0.25s |
| `APP/peripheral.c` | OTA 跳转前 `mDelaymS(5)` 注释 |
### 文档同步(本次落地)
| 文件 | 标注 |
|------|------|
| `docs/rs485-modbus-protocol.md` V1.7→**V1.8** | §3.1 DI 0x0008 Init Flag 未实现(恒 0);§3.2 IR 0x0006/0x0007/0x000A/0x000B/0x000C 未实现(Variation 改读全数据块 0x010A/0x010B);§3.3 HR 全部标注(FC 0x06 仅 0x0010/0x0011/0x0012 可写);§4.3/4.5/4.8 未实现横幅;§5 功能码矩阵 0x03/0x10/0x11 → ✗;§6.3 仅 0x06;§7 0x3D/Init_B 对照标注;§8 版本历史 V1.8 |
| `docs/rs485-700bs-protocol.md` | §4.4 0x3D 未实现注记(V3.05 起减配不响应);§5 速查表 + §6 兼容对照同步 |
### 保留能力(减配后仍可用)
- FC 0x02 读离散输入(车辆/故障/继电器/光耦)✅
- FC 0x04 读输入寄存器 + **全数据块 0x01000x0112**(含 Variation 0x010A/0x010B)✅
- FC 0x06 写:0x0010 主动上报使能 / 0x0011 活动阈值 / 0x0012 复位(0x2C2C)✅
- 700BS 0xFA / 0x1B / 0x2C / 0xAA 心跳 ✅
### ⚠ 遗留提醒
1. ~~**宏越界**`MB_MAX_READ_REGS=60` 但 `MB_MAX_DATA_BYTES=80` → 主机查 60 寄存器时 `data_buf` 越界 40B。~~**已修(同日)**`MB_MAX_READ_REGS 60→40`40 寄存器 × 2B = 80B 缓冲匹配;全数据块 19 寄存器不受影响
2. 协议文档 V1.8 已标注;`DLD154Tool` GUI 若暴露 FC 0x03/0x10/0x11 按钮需同步禁用(三层一致性)
---
## 2026-08-26 — V3.040x24 追加 LOOP_MEASURE_BASE 归一化基数(与 DLD110S 对齐)
### 背景
DLD110S 2026-08-26 实测发现小程序评估把 variation 归一化基数写错(照搬 DLD154V4B 的 131072DLD110S/154Pro 实为 524288 2^19 @60MHz)→ 所有百分比放大 4 倍。根治方案:固件 0x24 显式上报基数。DLD110S 已完成(协议 V1.1),**DLD154Pro 同步对齐**。
### 改动
| 文件 | 改动 |
|------|------|
| `APP/include/cmcng.h` | 版本 V3.03→V3.04;新增 `#define LOOP_MEASURE_BASE 524288L` |
| `APP/dbn_ble_srv.c` | 0x24 读参响应尾部追加 3B LELOOP_MEASURE_BASE(响应 8B→11B,仍单包 ≤14B,无分包) |
| `docs/ble-protocol.md` | §5.4 响应表加偏移 8-10 + 换算公式 + 背景说明 |
| `docs/product-manual.md` | 版本号 V3.04 + 版本历史 |
| `docs/technical-spec.md` | 版本号 V3.04 + 版本历史 |
### 对照 110S 差异结论(不需要改的部分)
- **断开次数双变量**:154Pro 不需要——LED 快闪不依赖 cut_amount 次数(走 `g_disconnect_active`),`g_loop_cut_amount` 本身就是上电持续累计,无 3 次上限
- **0x24 偏移 7 direction_mode**154Pro 已经是完整字节(dbn_ble_srv.c:637),与 110S V4.31 语义一致
- **重连 g_loop_cut_last = 0**154Pro 已有(peripheral_main.c:815
- ⚠ 位含义差异:两产品 direction_mode 低 4 位语义不同(110S=方向/触发;154Pro=输出融合模式 7 种),小程序按产品区分
### 涉及文件
| 文件 | 内容 |
|------|------|
| `BLE/DLD154Pro_Peripheral_28K/APP/include/cmcng.h` | V3.04 + LOOP_MEASURE_BASE |
| `BLE/DLD154Pro_Peripheral_28K/APP/dbn_ble_srv.c` | 0x24 追加 3B |
| `docs/ble-protocol.md` / `product-manual.md` / `technical-spec.md` | 同步 V3.04 |
---
## 2026-08-25 — 蓝牙小程序接口协议文档
### 背景
根据 `dbn_ble_srv.c`+ peripheral.c/gattprofile.c/storage.h/cmcng.h)整理蓝牙小程序与芯片交互的完整接口协议,供小程序开发对接。
### 文档要点
| 章节 | 内容 |
|------|------|
| §1 BLE 服务 | 服务 0xFFE0Char1(0xFFE1 RW 命令下发)、Char4(0xFFE4 Notify 响应/上报)MTU 协商 + notify ≤ MTU3 |
| §2 帧格式 | Magic(8F/7F)+Header+Len+CMD+Data+XOR+SUM;校验从 Header 起 |
| §3 分包 | 发送按 14B 写死分包(MTU=23 旧假设);Header=(amount<<4)\|seq |
| §4-5 命令 | 0x10/0x1F/0x23/0x24/0x31/0x8A/0x92/0xC5 逐字段 |
| §6 主动上报 | 0xC0 线圈动态(type=5,含频率+360 补偿、variation 3B 有符号) |
| §7 坑清单 | sensitvity 1~4(≠vd960Loop 0~3)、0xC5 超时疑 bug、0x8A 写表依赖 para_store_init、notify 超限静默丢弃 |
### 关键发现(源码事实)
1. **sensitvity 协议层 1~4**,内部 `g_freq_sens = sensitvity 1`0~3 索引灵敏度表 {108,54,28,14}),0x24 回读 +1——**与 vd960Loop 的 0~3 不同**
2. **0xC5 超时疑似 bug**`timeout_counter = timeout_min × 60 × 100`,若意图 ms 应为 ×1000(现场验证)
3. 0x8A 写灵敏度表不直接更新 RAM,依赖 `para_store_init()` 重读
4. 0x1F/0x92 复位/出厂类命令无响应帧
### 涉及文件
| 文件 | 内容 |
|------|------|
| `docs/ble-protocol.md` | 新增(依据 dbn_ble_srv.c 整理,固件 V3.03 |
---
## 2026-07-31 — 发布 V3.03
### 变更摘要
| 变更 | 说明 |
|------|------|
| 硬件看门狗 (WWDG) | 使能窗口看门狗,TMR1 ISR 5ms tick 驱动 `g_wdg_counter`,主循环 `poll_wdg()` 每 500ms 喂狗,超时 ~558ms 自动复位 |
| OTA 安全 | 跳转 OTA 前 `WWDG_ResetCfg(DISABLE)` 关闭看门狗,防止 OTA 期间超时复位 |
| 固件版本 | V3.02 → V3.03 |
### 涉及文件
| 文件 | 变更 |
|------|------|
| `peripheral_main.c` | +`poll_wdg()` + `g_wdg_counter`;移除 `u32CountWdt``main()``WWDG_ResetCfg(ENABLE)` |
| `peripheral.c` | OTA 跳转前 `WWDG_ResetCfg(DISABLE)` |
| `cmcng.h` | `FIRMWARE_VER` 3.02→3.03 |
---
## 2026-07-31 — 发布 V3.02
### 变更摘要
| 变更 | 说明 |
|------|------|
| `g_loop_cut_amount` 累加修复 | 重连路径补充 `g_loop_cut_last = 0` 边沿记忆清零,放开 3 次上限 |
| Modbus 主动上报线圈事件 | 线圈断开/重连立即触发主动上报(对齐 700BS) |
| 0x2C 复位指令重构 | 700BS: `SYS_ResetExecute()` MCU 全复位;Modbus: HR 0x0012=0x2C2C |
| DLD154Tool v1.0.0 | 版本显示 + PyInstaller 打包;Modbus 复位按钮 |
| RS485 初始化时序 | 移至 `para_store_init()` 之后 |
| 光耦呼吸加速 | 红灯在非复位模式下光耦有信号时加速 (~0.5s),便于现场判断光耦状态 |
### 涉及文件
| 文件 | 变更 |
|------|------|
| `peripheral_main.c` | cut_amount 修复 + RS485 时序 + 光耦呼吸加速 (BREATH_OPTO_DUTY_STEP=32) |
| `rs485_700bs.c` | `handle_reset_init()``SYS_ResetExecute()` |
| `rs485_modbus.c/h` | +HR 0x0012 (System Cmd) |
| `protocol_modbus.py` / `main.py` | +`build_reset_mcu()` + 复位按钮 |
| `DLD154Tool.spec` / `.gitignore` | PyInstaller 打包配置 |
| `rs485-modbus-protocol.md` | V1.6→V1.7 |
| `devlog.md` / `product-manual.md` / `technical-spec.md` | V3.02 文档同步 |
## 2026-07-30 — Modbus RTU V1.6 私有协议编码实现
### 背景
根据 `docs/rs485-modbus-protocol.md` V1.6 规范,实现完整 Modbus RTU 从机协议(含主动上报私有扩展)。
与 700BS 协议共享 UART0 物理层,通过 `g_fm_700bs_disable` 互斥切换。
### 新增文件
| 文件 | 行数 | 说明 |
|------|------|------|
| `APP/include/rs485_modbus.h` | 52 | API + 协议常量宏 (MB_IR_FULL_BLOCK_START/COUNT, MB_HR_AUTO_RPT_ENABLE/ACTIVE_THRESHOLD, 上报间隔) |
| `APP/rs485_modbus.c` | 815 | 完整 Modbus 实现: CRC16 查表 + 6 个 FC 处理函数 + 全数据块组装 + 主动上报调度 + 车间距/通过时间测量 |
### 实现的功能码
| FC | 功能 | 关键细节 |
|----|------|---------|
| 0x02 | 读离散输入 | 9-bit 位图, GPIOB_ReadPortPin 直读光耦 |
| 0x03 | 读保持寄存器 | 含 HR 0x0010(主动上报使能) 和 0x0011(活动阈值) |
| 0x04 | 读输入寄存器 | 基础 IR 0x00000x000C + 全数据块 0x01000x0112 (19 reg = 38B) |
| 0x06 | 写单寄存器 | 值域校验 + 只读拦截 + 连锁写入: Fusion Mode→direction_mode, Hold Time→g_hold_time, Freq Level→loopFreq_Level |
| 0x10 | 批量写寄存器 | 逐寄存器同 FC 0x06 逻辑 |
| 0x11 | Report Slave ID | "DLD154Pro\0" + loop1_LOOP_OK 状态 |
### 全数据块 (0x01000x0112)
```
灵敏度 | 频率档 | 融合模式 | car_state | 线圈状态(bit0=断开/bit1=稳定) | 光耦状态
频率Hz(32b) | CAPVD(32b) | Variation(32b signed)
断开累计(32b) | 继电器吸合累计(32b)
Time Type(0=间隙/1=通过/0xFFFF=无效) | 时间值10ms(32b)
```
- Variation = `loop1_CAPVD loop1_Origin`,实时计算
- 频率 = `FREQ_SYS * LPCNT / CAPVD + 360`,与 700BS 一致
- 光耦 = `GPIOB_ReadPortPin(Pin_10) == 0`,直读硬件
### 主动上报 3 级速率调度
| 状态 | 条件 | 间隔 | 迟滞 |
|------|------|------|------|
| 事件 | 继电器翻转 (relay1_state 边沿) | 立即 | — |
| 活动 | \|Variation\| ≥ 阈值 (HR 0x0011, 默认 10) | 150ms (30 tick) | — |
| 空闲 | \|Variation\| < 阈值 | 800ms (160 tick) | 连续 2 次低于阈值才降速 |
- 帧格式复用 FC 0x04 响应,与轮询完全一致
- 上报前先调 `update_misc_time()` 更新 gap/pass time
### 车间距 / 通过时间
- 单位: 10ms (`mstick()/2`)
- 继电器 0→1 吸合沿 → `_misc_time_value = now _last_relay_off_10ms`, `_misc_time_type = 0`
- 继电器 1→0 释放沿 → `_misc_time_value = now _last_relay_on_10ms`, `_misc_time_type = 1`
- `_relay_engage_cnt` 在每次吸合沿递增 (全数据块 0x010E0x010F)
### 改造现有文件
| 文件 | 变更 |
|------|------|
| `rs485_700bs.h` | +`rs485_send()` 声明; +`extern _rx_buf/_rx_len/_rx_last_tick` |
| `rs485_700bs.c` | `_rx_buf`/`_rx_len`/`_rx_last_tick``static`; `rs485_send``static` |
| `peripheral_main.c` | +`#include "rs485_modbus.h"`; `gpio_uart_init``modbus_init()`; `Main_Circulation``g_fm_700bs_disable` 分派 700BS/Modbus |
### 关键设计决策
- **与 700BS 共享 ISR**: 不创建第二个 UART0_IRQHandlerModbus 从共享 `_rx_buf` 读取
- **帧超时判定**: `mstick() _rx_last_tick ≥ 2` (10ms), 对齐 9600 的 t3.5≈4ms
- **写穿透**: Holding Register 写入后立即同步到 RAM 全局变量,不等待 flash 持久化 (flash 写入由调用方处理)
- **CRC 错误静默**: 符合 Modbus 标准——CRC 不匹配时不回应
### 影响
- RS485 物理层零改动,Modbus/700BS 通过 BLE 小程序切换
- 主动上报默认关闭 (`_auto_rpt_enable = 0`),需通过 HR 0x0010 使能
- Holding Register 写操作不写 flash,若需持久化需额外调用 `write_cfg_to_store`
---
## 2026-07-30 — 输出融合模式枚举再次重排:地感且光耦后移
### 变更
将「地感且光耦」从值 1 移到值 3(排到后面),混行/ETC 前移:
```
旧 (V1.4): 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
新 (V1.5): 0=或 1=混行 2=ETC 3=且 4=仅地感 5=仅光耦 6=复位
```
### 涉及文件
| 文件 | 变更 |
|------|------|
| `storage.h` | `DLD_OUTPUT_MODE` 枚举顺序:AND_RADAR 从 line 2 移至 line 4 |
| `peripheral_main.c` | 注释块 MODE N 标签 + 内联模式号 (0/1/5→0/3/5, 2/3→1/2) |
| `docs/technical-spec.md` | §6.1 融合模式表重排; §6.2/6.3 标题模式号更新; §7.2 LED 行改写为非数字区间 |
| `docs/product-manual.md` | §4.6 融合模式表重排 + 默认值 1→4 (仅地感); 模式号引用更新 |
| `docs/rs485-modbus-protocol.md` | §6.5 融合模式表重排 + 状态机标题模式号更新; V1.4→V1.5 |
| `docs/devlog.md` | 本条目 |
### 影响
- 代码全用符号名,无行为影响
- 已有 flash 配置的 `fusion_mode` 旧值语义与新模式不兼容,需重新设置
---
## 2026-07-29 — 输出融合模式枚举重排
### 变更
枚举值重新分配,将高频使用的融合模式前置:
```
旧: 0=复位 1=仅地感 2=仅光耦 3=或 4=且 5=混行 6=ETC
新: 0=或 1=且 2=混行 3=ETC 4=仅地感 5=仅光耦 6=复位
```
### 涉及文件
| 文件 | 变更 |
|------|------|
| `storage.h` | `DLD_OUTPUT_MODE` 枚举顺序重排 |
| `peripheral_main.c` | 注释号同步更新 (0→6, 1→4, 2/3/4→0/1/5, 5/6→2/3); L1279 `>= RADAR_ONLY` 区间判断→精确 `!=LOOP_ONLY && !=LOOP_X_RESET` 比较; 工厂默认 `direction_mode=0x04` (仅地感) |
| `docs/technical-spec.md` | §6 融合模式表 + 状态机标题 |
| `docs/product-manual.md` | §4.6 融合模式表 |
| `docs/rs485-modbus-protocol.md` | V1.3→V1.4: §3.3 默认值、§4.3/4.4 示例、§6.5 表格、复位注释 |
| `docs/devlog.md` | 本条目 |
### 影响
- 已有测试设备的 flash 配置 (`direction_mode` 低 4 位) 需要重新设置,旧值与新模式语义不兼容
- 代码逻辑(命名常量比较)不受影响,仅枚举值和注释变更
---
## 2026-07-29 — 发布 V3.01 版本文档:技术规格书 + 产品说明书
### 文档产出
| 文档 | 路径 | 内容 |
|------|------|------|
| 技术规格书 | `docs/technical-spec.md` | 系统架构、电气参数、IO 引脚分配、检测算法全链路(频率测量/IIR/斜率限幅/灵敏度表/进入确认/平坦性离开/基线跟踪/冻结超时)、时序状态机、7 种输出融合模式状态机、指示灯、上电稳定期、线圈故障处理、通信协议(BLE/700BS/Modbus)、Flash 存储布局 |
| 产品说明书 | `docs/product-manual.md` | 面向终端用户:产品概述、技术参数、硬件接口(端子定义/指示灯)、BLE 配置项、灵敏度档位、输出模式、输出融合模式(含人车混行防砸和ETC工作原理)、安装指南、故障排查、RS485总线集成速查、订购信息 |
### 源数据来源
- `peripheral_main.c`: 算法参数 (MEASUREMENT_BASE=524288, ALFA_CAP1=79, MAX_SLOPE_RATE=5%, ENTRY_CONFIRM=3, FREEZE_TIMEOUT=1000, WINDOW_ORIGIN=500, STABLE_SAMPLES=128)
- `cmcng.h`: 版本号 (FW 3.01 / HW 3.01), 全局变量声明
- `storage.h`: Flash 布局, 配置结构体, `DLD_OUTPUT_MODE` 枚举
- `dbn_ble_srv.h`: BLE 命令码
- `docs/DLD154Pro硬件资源.md`: IO 分配
- `docs/rs485-modbus-protocol.md` / `docs/rs485-700bs-protocol.md`: 通信协议
### 与 DLD154V4B 的关键差异
| 项目 | DLD154V4B | DLD154Pro |
|------|-----------|-----------|
| MCU | AT32F421 (ARM M4) | CH591R (RISC-V) |
| 配置方式 | 物理 DIP 开关 | BLE 小程序 |
| 通信接口 | TTL Tx 调试口 | RS485 (双协议) + BLE |
| 继电器 | 2 路 | 1 路 |
| 指示灯 | 红+绿+黄 (3 LED) | 红呼吸+绿 (2 LED) |
| 光耦 | 无 | 有 (7 种融合模式) |
---
## 2026-07-28 (傍晚) — 光耦参与模式下 LEDA 同步继电器状态
光耦参与模式 (MODE 2-6) 下,绿色 LED 原先跟随线圈 `FLAG_IN`/`FLAG_OUT` 变化,
在雷达单独触发(如人车混行防砸窗口)时 LED 不亮。修正为:
- TMR1 ISR 50ms 块末尾,`g_output_radar_mode >= 2` 且正常运行(非断开/非稳定期)时,
LEDA 直接跟随 `g_loop_acs_info.relay1_state`
- 断开/稳定期 200ms 闪烁优先级不变(5ms 段优先处理)
> 效果:继电器吸合→绿灯亮,继电器释放→绿灯灭,与线圈或雷达触发源无关。
---
## 2026-07-28 (午后) — 光耦输出模式完整实现:6 种融合逻辑 + 状态机
### 架构
`opt_input_poll()` 处理光耦输入 → 产出 `g_opt_trigger` (1=有效) → TMR1 ISR 继电器输出段 `case 0` 根据 `g_output_radar_mode` 做融合判决。
```
光耦 PB10 → 3样本多数表决防抖 → opt_input_poll() → g_opt_trigger
线圈 VD_FLAG/FLAG_OUT → coil_sig ──────────→ 融合判决 → RLY1
g_output_radar_mode
```
### 各模式实现
| 模式 | 值 | `opt_input_poll()` | 继电器 `case 0` 融合公式 |
|------|-----|-------------------|--------------------------|
| LOOP_X_RESET | 0 | 光耦复位 (400ms低→上升沿→SYS_ResetExecute) | `coil_sig` |
| LOOP_ONLY | 1 | return, g_opt_trigger=0 | `coil_sig` |
| RADAR_ONLY | 2 | g_opt_trigger = 光耦信号 | `g_opt_trigger` |
| LOOP_OR_RADAR | 3 | g_opt_trigger = 光耦信号 | `coil_sig \|\| g_opt_trigger` |
| LOOP_AND_RADAR | 4 | g_opt_trigger = 光耦信号 | `coil_sig && g_opt_trigger` |
| HUMAN_VD_MIX | 5 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
| ETC | 6 | 状态机 (见下) | `coil_sig \|\| g_opt_trigger` |
> 注: `coil_sig = (loop1_VD_FLAG | loop1_FLAG_OUT)` — 含离开脉冲保持
### HUMAN_VD_MIX 状态机 (人车混行防砸)
```
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
WINDOW (3s 防砸窗口)
│ 雷达触发 → g_opt_trigger=1 → 继电器吸合, 窗口复位
│ 线圈上线 → 回到 ARMED
│ 3s 超时无触发 → 回到 IDLE, 落杆
```
定时参数: `OPT_VM_WINDOW_TICK = 600` (600×5ms = 3s)
### ETC 状态机
```
IDLE (雷达屏蔽, 仅线圈)
│ 线圈检测到车
ARMED (雷达解禁, 线圈||雷达)
│ 两者均释放
DEBOUNCE (500ms 防抖)
│ 线圈/雷达重新触发 → 回到 ARMED
│ 500ms 超时 → 回到 IDLE, 落杆
```
定时参数: `OPT_ETC_DEBOUNCE_TICK = 100` (100×5ms = 500ms)
### 光耦防抖
所有非复位模式共用 3 样本多数表决 (`OPT_DEBOUNCE_CNT=6`): 最近 3 次采样中 ≥2 票即判定有效,等效 ~30ms 消抖。
### 文件变更
| 文件 | 变更 |
|------|------|
| `peripheral_main.c` | +`g_opt_trigger` 全局变量, `opt_input_poll()` 重写 (120→180行), TMR1 ISR `case 0` 融合判决 |
| `cmcng.h` | +`extern uint8_t g_opt_trigger` |
---
## 2026-07-28 — 光耦输出模式升级:`DLD_OUTPUT_MODE` 枚举 + `direction_mode` 低四位取值
### 背景
光耦输入功能从原来的「二值化开关」(使能/复位)升级为 **7 种输出模式**
`direction_mode` 字节的低四位选择。`g_fm_radar_input_disable`(来自 `function_mode` bit1
更名为 `g_output_radar_mode`,语义从布尔值变为枚举值。
### `DLD_OUTPUT_MODE` 枚举
```c
typedef enum _DLD_OUTPUT_MODE
{
OUTPUT_MODE_LOOP_X_RESET = 0, // 光耦输入为复位信号,仅地感检测输出
OUTPUT_MODE_LOOP_ONLY, // 仅地感,光耦输入无效
OUTPUT_MODE_RADAR_ONLY, // 仅光耦(雷达输出接光耦输入),地感无效
OUTPUT_MODE_LOOP_OR_RADAR, // 地感或雷达
OUTPUT_MODE_LOOP_AND_RADAR, // 地感和雷达
OUTPUT_MODE_HUMAN_VD_MIX, // 人车混行防砸:有车后光耦/地感"或",离场 3s 内光耦有效持续防砸
OUTPUT_MODE_ETC, // ETC:有车后光耦/地感"或",光耦断开需 500ms 防抖才释放继电器
}DLD_OUTPUT_MODE;
```
### 变量与取值变更
| 项目 | 旧 | 新 |
|------|-----|-----|
| 全局变量名 | `g_fm_radar_input_disable` | `g_output_radar_mode` |
| 符号类型 | bit (0/1) | `uint8_t` (0~6) |
| 取值来源 | `(function_mode >> 1) & 0x01` | `direction_mode & 0x0F` |
| 解析位置 | `peripheral_main.c:para_store_init()` + `dbn_ble_srv.c:unpack_pkg_set_cjq_param()` | 同上 |
| BLE 回读字段 | `g_function_mode` | `g_loop_cng_unit.direction_mode` (完整 8 位) |
| `opt_input_poll` 门控 | `if (g_fm_radar_input_disable == 0)` → 雷达模式 return | `if (g_output_radar_mode)` → 非 0 模式 return |
### 实现状态
| 模式 | 状态 | 说明 |
|------|------|------|
| 0 — LOOP_X_RESET | ✅ 已实现 | PB10 低电平 ≥400ms80 tick×5ms)后上升沿 `SYS_ResetExecute()` 芯片复位 |
| 1~6 | ❌ 未实现 | `opt_input_poll()` 中直接 return |
### 文件变更
| 文件 | 变更 |
|------|------|
| `storage.h` | +`DLD_OUTPUT_MODE` 枚举 (7 种模式) |
| `cmcng.h` | `g_fm_radar_input_disable``g_output_radar_mode` |
| `peripheral_main.c` | 变量更名 + 解析路径改 `direction_mode & 0x0F` |
| `dbn_ble_srv.c` | 同上 + BLE 回读改用 `direction_mode` 完整字段 |
---
## 2026-07-22 — BLE 新增 RS485 地址/波特率读写 + 空闲关蓝牙超时 + 功能码细分
### 新增 BLE 命令
**`CMD_DBN_RW_UART_BAUD (0x31)`** — 读写 RS485 通信参数:
| 字节偏移 | 字段 | 说明 |
|---------|------|------|
| [4] | RW | 0=读, 1=写 |
| [5] | BT_close_min | 蓝牙空闲超时关闭时间 (分钟), 0=不关闭 |
| [6:8] | baud_rate | RS485 波特率 (3 字节, little-endian) |
| [9] | rs485_id | RS485 从机地址 (1-247) |
| [10:12] | reserved | 预留 |
- 读:返回当前存储值 + status=0
- 写:写入 RAM 并持久化到 DataFlash (`ADDR_BT_Close_TIMEOUT_Offset` 起 5 字节)
### Flash 存储布局
```
0x10 ADDR_BT_Close_TIMEOUT_Offset 1B 蓝牙空闲超时 (分钟)
0x11 Addr_RS485_Baud_Offset 3B RS485 波特率 (LE32)
0x14 Addr_RS485_ID_Offset 1B RS485 从机地址
```
出厂默认:RS485 ID=1, 波特率=9600, 蓝牙超时=0(不关闭)
### 功能码细分 (g_function_mode)
`g_function_mode` 取自 `direction_mode` 高 4 位,低 2 位细分:
| bit | 字段 | 0 | 1 |
|-----|------|---|---|
| bit0 | `g_fm_700bs_disable` | **700BS 协议** | Modbus 协议 |
| bit1 | `g_fm_radar_input_disable` | **光耦输入使能** | 光耦输入复位 |
> RS485 将支持两种协议:700BS(后续上传)和 Modbus。通过小程序设置 `direction_mode` 高 4 位的 bit0 切换。
### 文件变更
| 文件 | 变更 |
|------|------|
| `dbn_ble_srv.h` | +`CMD_DBN_RW_UART_BAUD 0x31` |
| `cmcng.h` | +extern 声明: `fm_700bs_disable`, `fm_radar_input_disable`, uart/bt 配置 |
| `storage.h` | +Flash 地址宏: BT_timeout, RS485_baud, RS485_ID |
| `peripheral_main.c` | +全局变量定义, factory_dev 默认值, para_store_init 恢复 |
| `dbn_ble_srv.c` | +`CMD_DBN_RW_UART_BAUD` handler, unpack 中解析 function_mode bits |
### 待办
- [ ] RS485 700BS 协议定义
- [ ] RS485 Modbus 协议定义
- [ ] RS485 串口中断收发实现 (UART0)
- [ ] 蓝牙空闲超时自动关闭逻辑
---
## 2026-07-21 — 灵敏度等级与 ΔL/L 的物理关系分析
### 参数表
```c
// sens_in: 进入阈值, sens_out: 离开阈值 (0=最低, 3=最高)
SensTable = { 108, 54, 28, 14 }; // 进入
SensTable1 = { 81, 32, 16, 12 }; // 离开
```
### 计算链路
**Step 1:阈值差值**
```c
loop1_dlt_ORG = (Origin * sens) >> 16; // = Origin × sens / 65536
```
**Step 2:进入判定**
```c
if (CAPVD < Origin - dlt_ORG) // ← ΔCAPVD / Origin > sens / 65536
```
**Step 3CAPVD → 电感**
线圈振荡频率 `f ∝ 1/√L`,周期 `T ∝ √L`。测量窗 CAPVD 正比于平均周期:
```
ΔCAPVD / Origin = ΔT / T₀ = (√L - √L₀) / √L₀
```
对微小变化泰勒展开:`dT/T ≈ dL/(2L)`,即:
```
ΔL / L ≈ 2 × ΔCAPVD / Origin
```
**Step 4:最终 ΔL/L 公式**
```
ΔL/L_entry = 2 × sens_in / 65536
ΔL/L_exit = 2 × sens_out / 65536
```
### 灵敏度等级对应 ΔL/L
| 等级 | sens_in | ΔL/L 进入 | sens_out | ΔL/L 离开 | 迟滞比 |
|------|---------|----------|----------|----------|--------|
| 低 (0) | 108 | **0.330%** | 81 | **0.247%** | 1.33 |
| 中 (1) | 54 | **0.165%** | 32 | **0.098%** | 1.69 |
| 高 (2) | 28 | **0.085%** | 16 | **0.049%** | 1.75 |
| 最高(3) | 14 | **0.043%** | 12 | **0.037%** | 1.17 |
### 物理验证
典型 100μH 线圈:
- 现代轿车经过:ΔL/L ≈ 5%–15%,任一灵敏度均能可靠触发
- 高灵敏度 0.085%:足够敏感,需注意温漂(~20°C 引起约 0.1% 的感量偏移)和邻道串扰
- 迟滞比 1.33–1.75:防止车辆边界状态反复跳变,低灵敏度迟滞最小
### 快速换算
`sens` 值直接对应 **千分之 2×sens 的感量变化百分比**——除以 1000 就是 ΔL/L(%)。
---
## 2026-07-21 (午后) — 修复灵敏度 bug + 有限存在时间 + 版本号
### BLE 灵敏度无法修改
**根因:** 硬件适配时删了 `poll_sens_key()`,在 `INIT_VD()` 中硬编码了 `g_freq_sens = 2`
但未在 BLE 参数解包 `unpack_pkg_set_cjq_param()` 中同步更新,导致小程序修改灵敏度无效。
**修复:**
- `peripheral_main.c`: `g_freq_sens``INIT_VD()` 移到 `para_store_init()`
从存储的 `g_loop_cng_unit.sensitvity` 读取:`(sensitvity > 0) ? (sensitvity - 1) : 0`
- `dbn_ble_srv.c`: `unpack_pkg_set_cjq_param()` 中同样增加 `g_freq_sens` 同步更新,
确保 BLE 小程序实时修改后立即生效
### 有限存在时间公式对齐
`dbn_ble_srv.c``g_hold_time` 计算写的是 `exist_mode * 30 * 20`
`para_store_init()` 中用的是 `exist_mode * 20 * 5`50ms tick)。
统一为 `20 * 5`(对应参数值 × 100ms × 5s 基础周期)。
### 版本号
- 固件: `4.01``3.00`
- 硬件: `1.00``3.01`
---
## 2026-07-21 — 项目初始化:从 DLD110SV4 复制基线 + 按硬件资源文档调整 IO
### 背景
DLD154Pro 是 DLD110SV4 的硬件升级版(同 MCU CH591R),核心变更:
- 继电器 双路→单路(删 RLY2
- 删除拨码开关(灵敏度改由小程序设置)
- 线圈调频 两级→一级(删 PA13 FLEVEL_L
- 新增 RS485 接口(PA14/PA15/PA13,协议待定)
- 新增光耦输入(PB10,逻辑待定)
- 指示灯从单色→双色(LEDA 绿 + LEDB 红呼吸灯)
- DEBUG UART0 被 RS485 占用,删除全部
### 仓库
- 远程: http://118.178.252.17:3000/wangfq/DLD154Pro
- 本地: `/home/wfq/projects/vd_detector/DLD154Pro`
- commit `5f5f697`: init 基线
- commit `91ba844`: feat 硬件适配
### IO 宏重定义
| 引脚 | 旧(DLD110SV4) | 新(DLD154Pro) |
|------|--------------|---------------|
| PA8 | RLY1 (存在) | RLY1 (存在,不变) |
| PB23 | RLY2 (功能/脉冲) | **LEDB (红色呼吸灯)** |
| PA12 | FLEVEL_H (33nF) | FLEVEL (33nF,一级) |
| PA13 | FLEVEL_L (10nF) | **UART0_RE (RS485 方向)** |
| PA14 | KEY_SA1 / DEBUG_TX | **UART0_TX (RS485)** |
| PA15 | KEY_SA2 / DEBUG_RX | **UART0_RX (RS485)** |
| PB10 | - | **IN_1 (光耦输入)** |
| PB22 | LEDA (绿色) | LEDA (绿色,不变) |
### 删除项
- `RLY2_ON/OFF` 宏及全部 RLY2 输出逻辑
- `KEY_SA1/KEY_SA2` 宏及 `poll_sens_key()` 函数
- `FLEVEL_L_LOW/HIGH`, `FLEVEL_H_LOW/HIGH` → 改为 `FLEVEL_LOW/HIGH`
- `g_flag_output`, `g_xn_counter` 全局变量
- DEBUG UART0 初始化 (`gpio_uart_init``#ifdef DEBUG` 块)
- `Main_Circulation``#ifdef DEBUG` PRINT 块
- TMR1_ISR 中 `_cnt` / `g_flag_output` DEBUG 定时器
- TMR0_ISR 中 `g_xn_counter` DEBUG 计数器
- `para_store_init()` 中频率四档 switch → 双档 if/else
### 新增/预留
- RS485 引脚宏: `RS485_TX_PIN`, `RS485_RX_PIN`, `RS485_RE_PIN`, `RS485_RE_TX()`, `RS485_RE_RX()`(仅初始化引脚,协议待定)
- 光耦输入宏: `OPT_IN1`(仅初始化 PB10 输入上拉,逻辑待定)
- LEDB 宏: `LEDB_ON/OFF`PB23,低电平有效)
- `g_freq_sens = 2` 默认最高灵敏度(取代 poll_sens_key 拨码逻辑)
### 继电器输出简化
| 模式 | 旧 (双继电器) | 新 (单继电器) |
|------|-------------|---------------|
| case 0: 存在输出 | RLY1 跟随 VD, RLY2 跟随 VD | RLY1 跟随 VD |
| case 1: 进入脉冲 | RLY2=存在, RLY1=进入脉冲 | RLY1=进入脉冲 |
| case 2: 离开脉冲 | RLY2=存在, RLY1=离开脉冲 | RLY1=离开脉冲 |
| default | RLY2=存在 | RLY1=存在 |
### 保留(协议兼容)
- `storage.h``Loop_ACS_Info.relay2_cng/relay2_state` 字段保留,默认值=0
- `dbn_ble_srv.c:468` 上报字节 relay2 位自动为 0(字段初始化为 0 后无写入)
### 待办
- [x] RS485 通信协议定义 + UART0 中断/收发实现 ~~(2026-07-24 完成)~~
- [ ] 光耦输入逻辑(与其他检测器联动 / 综合判断)
- [ ] IAP/OTA 项目文件中的 DLD110S 引用更新(`592OnlyUpdateApp_*`
- [ ] `.mrs/` 工作区文件清理(大量 DLD110S 历史快照)
---
## 2026-07-2324 — RS485 700BS 协议实现 & 四级灵敏度
### RS485 700BS 从机协议
| 项目 | 说明 |
|------|------|
| 物理层 | RS485 半双工, 9600 8N1, PA14=TX PA15=RX PA13=RE |
| 帧格式 | 主机 3 字节 (STX ADDR XOR), 从机 3~9 字节变长 |
| 心跳 | 空闲 5s / 故障(线圈断开) 1s / 事件(car_state翻转)立即 |
| 命令 | 0xFA 查询状态, 0x1B 查询频率, 0x2C 复位线圈, 0x3D 查询DIP |
**文件:** `APP/rs485_700bs.c` (新增), `APP/include/rs485_700bs.h` (新增)
### 踩坑记录
1. **UART0 API 不兼容** — CH592 SDK 中 `UART0_GetITFlag()` 是无参宏(非函数),`UART0_ClearITFlag()` 不存在。改用 `switch(UART0_GetITFlag())` 标准模式,参考 UART1 例程。
2. **`while(R8_UART0_TFC == 0)` 死循环** — TX FIFO 空时条件永真,主循环卡死导致地感不工作。修正为 `!= 0`(等 FIFO 空再写下一字节)。
3. **`rs485_init()` 从未被调用** — `gpio_uart_init()` 只写了注释 `/* 由 rs485_init() 统一初始化 */` 但未实际调用,UART0/GPIO 未配置。修复:替换注释为函数调用。
4. **频率始终为 0**`g_loop_acs_info.frequent` 只在 BLE 报告路径 `usart_packet_processing_acs_loop` 中更新,BLE 断开时永不执行 → freq=0。
5. **频率非实时** — 改用 `g_loop_acs_info.loop_capvd` 仍有问题:该值被 `flag_change` 门控冻结(上电/车辆进出时 `flag_change=1`→capvd 不更新,清零只在 BLE 报告路径)。最终方案:直接使用 `loop1_CAPVD``vd1_task()` 每次实时 IIR 滤波值),不经过 BLE 通道。
**最终频率计算:**
```c
freq = (uint64_t)FREQ_SYS * loop1_LPCNT / loop1_CAPVD + 360
```
### 四级灵敏度
`MAX_LOOP_SENS_AMOUNT`: 3 → 4
新增第四档:进入阈值 14, 离开阈值 12 (ΔL/L≈0.04%),适用于极高灵敏度场景(如摩托车/小型车辆检测)。需注意温漂影响——20°C 温度变化可引起约 0.1% 感量偏移,第四档信噪比余量仅约 2:1。
---
## 2026-07-24 (傍晚) — 光耦输入复位功能 & mstick() 时间单位修正
### 光耦输入复位 (`opt_input_poll`)
| 项目 | 说明 |
|------|------|
| 引脚 | PB10 (IN_1), 内部上拉, 光耦干接点输入 |
| 使能条件 | `g_fm_radar_input_disable == 1` |
| 触发逻辑 | 干接点接通(PB10=0) ≥500ms → 断开(上升沿) → `SYS_ResetExecute()` |
| 消抖 | <500ms 短脉冲上升沿清零计时, 不触发 |
**关键修复:PB10 数字输入使能**
`R32_PIN_CONFIG2` 寄存器中 `RB_PIN_PB10_15_DIS` 默认置位(关闭数字输入省电)。`GPIOB_ModeCfg(..., GPIO_ModeIN_PU)` 只配置了上下拉和方向,数字输入通路在更底层被掐断。修复:`R32_PIN_CONFIG2 &= ~(1UL << 26)`
### mstick() 时间单位修正
`mstick()` = `TimingDelayInc`,在 TMR1 ISR (5ms 间隔) 中递增。**单位是 5ms/tick,不是毫秒。**
| 位置 | 原来 | 修正后 | 实际时间 |
|------|------|--------|---------|
| `opt_input_poll` 阈值 | `>= 500` | `>= 100` | 500ms |
| `RS485_HEARTBEAT_MS` | 5000 | 1000 | 5s |
| `RS485_FAULT_MS` | 1000 | 200 | 1s |
> 帧超时 `mstick() - _rx_last_tick > 10`=50ms)保留未改,对 9600 波特率够用。