feat(V4B): Debug串口打印重组 — 频率/采样/基准全量输出 (V4.20)

现场有影响算法的异常待分析, 扩充调试输出:
1. 周期状态行(2s, DBG|前缀): f频率kHz/Xn/LPCNT/Value/CAPVD/slow/Origin/dlt/SENS/VD/FRZ/LIM/LOOP/STBL
   - calc_freq_khz(): f=60000×LPCNT/CAPVD (60MHz捕获时钟, 无车≈99kHz/深车124kHz验证✓)
   - g_slope_limit_cnt: 斜率限幅截断计数(EMI线索, 周期清零)
2. 事件行(EVT|前缀): enter_try(进入线首中)/leave_try(离开线首中)/loop_disconnect/loop_reconnect
   - 原有 Car_In/Car_OFF/Loop stable/Baseline timeout 保留
3. cmcng.h 新增 DEBUG_ENABLE 开关(1=开现场分析 0=关发布)

文档: devlog V2.18
This commit is contained in:
wangfq
2026-09-02 09:49:24 +08:00
parent 5b0a4c26d7
commit 278d470b60
3 changed files with 103 additions and 7 deletions
+45
View File
@@ -4,6 +4,51 @@
---
## 2026-09-01 — Debug 串口打印重组:频率/采样/基准全量输出(固件 V4.20)
> **固件版本:V4.20**。devlog 修订 V2.18。
> **目的**:现场有影响算法的异常情况待分析,扩充调试输出便于定位。
### 打印内容(TTL 调试口,波特率 230400)
**① 周期状态行(每 2s,前缀 `DBG|`**——频率/采样/基准全量:
```
DBG|t=2000ms f=99kHz Xn=600 LPCNT=218 Value=131072 CAPVD=131072 slow=131072 Origin=131072 dlt=32 SENS=3 VD=0 FRZ=0/0 LIM=0 LOOP=1 STBL=1
```
| 字段 | 含义 |
|------|------|
| f | 线圈振荡频率 kHz=60000×LPCNT/CAPVD,无车≈100 |
| Xn / LPCNT | 瞬时周期 / 自适应窗口 |
| Value / CAPVD / slow | 原始采样 / 主滤波 / 慢滤波(方案A) |
| Origin / dlt | 基准值 / 当前阈值(无车=进入线,有车=释放线) |
| SENS / VD | 灵敏度档 / 车辆状态 |
| FRZ | freeze_cnt / freeze_ref(基线冻结状态) |
| LIM | 斜率限幅截断计数(2s 内 EMI/干扰次数,周期清零) |
| LOOP / STBL | 线圈状态 / 稳定期标志 |
**② 事件行(前缀 `EVT|`**
- `enter_try`:进入线第一次命中(定位触发来源)
- `leave_try`:离开线第一次命中(定位释放来源)
- `loop_disconnect` / `loop_reconnect`:线圈断开/重连(带断开计数、断开瞬间 Xn/CAPVD/Origin/频率)
- 原有 `Car_In`/`Car_OFF`/`Loop stable`/`Baseline timeout`/`SENS changed` 保留
**③ 调试开关**cmcng.h):
```c
#define DEBUG_ENABLE 1 // 1=开启(现场分析) 0=关闭(发布)
```
### 辅助实现
- `calc_freq_khz(capvd, lp_cnt)`f_kHz = 60000×LPCNT/CAPVD60MHz 捕获时钟),验证:无车 99kHz / 深车 124kHz ✓
- `g_slope_limit_cnt`:斜率限幅截断计数(IIR 输入被 5% 限幅截断时 +1,周期打印带出后清零)
### 待办
- 现场抓数:串口 230400 收 `DBG|`/`EVT|` 行,异常复现时完整记录(至少覆盖异常前后 30s)
- 分析:重点看 f 是否突变(线圈/干扰)、Origin 是否异常更新(freeze 误触发)、LIM 是否高频(EMI)
---
## 2026-09-01 — 方案B 调校定稿:发布版本号 V4.20
> **固件版本:V4.20**cmcng.hFIRMWARE_VER="4.20" + MAIN=4/SUB=20)。devlog 修订 V2.17。
@@ -26,6 +26,14 @@
#include <stdint.h>
#ifndef DEBUG_ENABLE
#define DEBUG_ENABLE 1 // 1=调试串口打印开启(现场分析) 0=关闭(发布), V4.20
#endif
#if DEBUG_ENABLE
#ifndef DEBUG
#define DEBUG
#endif
#endif
#ifdef DEBUG
#define PRINT(X...) printf(X)
#else
@@ -681,6 +681,22 @@ void TMR15_GLOBAL_IRQHandler(void)
}
}
/*===========================================================================
* 调试打印辅助 — V4.20 debug 打印重组 (2026-09-01)
*
* calc_freq_khz: 由窗口量反算线圈振荡频率
* f = 捕获时钟(60MHz) / Xn_avg, Xn_avg = CAPVD / LPCNT
* → f_kHz = 60000 × LPCNT / CAPVD
* 无车: CAPVD≈131072, LPCNT≈218 → ≈99.8kHz; 有车: Xn↓ → f↑
*===========================================================================*/
uint32_t g_slope_limit_cnt = 0; // 斜率限幅截断计数 (EMI/干扰线索, 周期打印带出)
static uint32_t calc_freq_khz(uint32_t capvd, uint16_t lp_cnt)
{
if (capvd == 0) return 0;
return (60000UL * lp_cnt) / capvd;
}
/*===========================================================================
* vd1_task — 核心检测算法(对齐 M1H VD1_TASK
*
@@ -710,8 +726,8 @@ void vd1_task(void)
int32_t raw_delta = (int32_t)loop1_Value - (int32_t)loop1_CAPVD;
int32_t max_step = (int32_t)(loop1_CAPVD * MAX_SLOPE_RATE / 100);
if (max_step < 100) max_step = 100;
if (raw_delta > max_step) raw_delta = max_step;
if (raw_delta < -max_step) raw_delta = -max_step;
if (raw_delta > max_step) { raw_delta = max_step; g_slope_limit_cnt++; }
if (raw_delta < -max_step) { raw_delta = -max_step; g_slope_limit_cnt++; }
uint32_t clamped_value = (uint32_t)((int32_t)loop1_CAPVD + raw_delta);
loop1_CAPVD = get_flt_value(clamped_value, loop1_CAPVD);
}
@@ -784,6 +800,12 @@ void vd1_task(void)
/*--- 进入确认 — 连续 ENTRY_CONFIRM 次低于阈值才判有车 ---*/
if (loop1_CAPVD < (loop1_Origin - loop1_dlt_ORG)) {
if (loop1_entry_cnt == 0) {
/* 过渡事件: 第一次命中进入线 (定位"为什么开始进入") */
PRINT("EVT|enter_try Value:%d CAPVD:%d Origin:%d dlt:%d f:%dkHz LPCNT:%d Xn:%d\n",
loop1_Value, loop1_CAPVD, loop1_Origin, loop1_dlt_ORG,
calc_freq_khz(loop1_CAPVD, loop1_LPCNT), loop1_LPCNT, loop1_Xn);
}
loop1_entry_cnt++;
if (loop1_entry_cnt >= ENTRY_CONFIRM) {
PRINT("Car_In, Value:%d, CAPVD:%d, Origin:%d, dlt:%d\\n",
@@ -899,6 +921,18 @@ void vd1_task(void)
#else
if ((loop1_Origin - loop1_dlt_ORG) < loop1_CAPVD) { // 方案B/原逻辑: 快滤波直接判释放
#endif
if (loop1_cnt_release == 0) {
/* 过渡事件: 第一次命中离开线 (定位"为什么开始释放") */
PRINT("EVT|leave_try Value:%d CAPVD:%d slow:%d Origin:%d dlt:%d f:%dkHz LPCNT:%d Xn:%d\n",
loop1_Value, loop1_CAPVD,
#if USE_SLOW_RELEASE
loop1_CAPVD_slow,
#else
loop1_CAPVD,
#endif
loop1_Origin, loop1_dlt_ORG,
calc_freq_khz(loop1_CAPVD, loop1_LPCNT), loop1_LPCNT, loop1_Xn);
}
loop1_cnt_release++;
if (loop1_cnt_release >= 3) {
PRINT("Car_OFF, Value:%d CAPVD:%d Origin:%d dlt:%d\n",
@@ -936,6 +970,7 @@ void loop_task_function(void *pvParameters)
g_disconnect_active = 0; // 重连,清除断开标记
loop1_CAPVD = 0; // 强制 IIR 从首个有效值重新收敛
loop1_CAPVD_slow = 0; // 方案A: 释放慢滤波同步收敛
PRINT("EVT|loop_reconnect\n");
}
if (loop1_CAP_OK) {
@@ -971,22 +1006,30 @@ void loop_task_function(void *pvParameters)
}
g_fault_phase = 0;
g_fault_tick = 0;
PRINT("EVT|loop_disconnect cnt=%d Xn:%d CAPVD:%d Origin:%d f:%dkHz\n",
g_disconnect_count, loop1_Xn, loop1_CAPVD, loop1_Origin,
calc_freq_khz(loop1_CAPVD, loop1_LPCNT));
}
vTaskDelay(150);
}
/*--- 调试输出(每 2 秒) ---*/
/*--- 调试输出(每 2 秒): V4.20 重组 — 频率/采样/基准全量状态 ---*/
#ifdef DEBUG
{
static uint32_t _dbg_cnt = 0;
_dbg_cnt++;
if (_dbg_cnt >= 200) { // 200 × 10ms = 2s
_dbg_cnt = 0;
PRINT("SET_DLY:%d, SAFE:%d, Xn:%d, LPCNT:%d, "
"CAPVD:%d, Origin:%d, VD:%d\n",
SET_DLY, SET_SAFE, loop1_Xn, loop1_LPCNT,
loop1_CAPVD, loop1_Origin, loop1_VD_FLAG);
PRINT("DBG|t=%ums f=%dkHz Xn=%d LPCNT=%d Value=%d CAPVD=%d slow=%d "
"Origin=%d dlt=%d SENS=%d VD=%d FRZ=%d/%d LIM=%d LOOP=%d STBL=%d\n",
_dbg_cnt * 10,
calc_freq_khz(loop1_CAPVD, loop1_LPCNT),
loop1_Xn, loop1_LPCNT, loop1_Value, loop1_CAPVD, loop1_CAPVD_slow,
loop1_Origin, loop1_dlt_ORG, loop1_SensLevel, loop1_VD_FLAG,
loop1_freeze_cnt, loop1_freeze_ref, g_slope_limit_cnt,
loop1_LOOP_OK, g_loop_stable);
g_slope_limit_cnt = 0; // 限幅计数按周期清 (统计最近 2s)
}
}
#endif