feat(vd960Loop): V1.03 — 上电自检基准判稳同步 V4B V4.23

绿灯上电自检快闪: 原固定 128 样本(≈1.3s)即判稳, 与基准是否真稳无关;
stable_cnt 仅 init_vd_single 清零, 有限存在超时/安全复位(LC_Reset=1)
重学阶段残留计数 → 二次稳定期 1 样本瞬间判稳 (同 V4B 旧缺陷)。

修复 (四路 unit 独立):
- TaskLoop.h: +STABLE_ORIGIN_PPT 1 / STABLE_SETTLE_WINDOWS 2 /
  STABLE_MAX_SAMPLES 500(≈5s兜底); Loop154_Unit +settle_cnt
- TaskLoop.c vd1_task_per_channel 稳定期: 每窗(100样本≈1s)完成比较
  Origin 均值漂移 ≤0.1% → settle++, 否则清零; 判稳=最少128样本+
  连续2窗稳定 或 500 样本兜底; 判稳退出清零
- init_vd_single / 有限存在超时 / 安全复位超时重学路径统一清零自检计数
- poll_green_led 条件不变: 绿灯闪至本路基准稳定才停 (四路独立)

验证: tests/test_stable_settle.c 5 项 PASS (常量200/首窗尖峰400/
      持续漂移500兜底/重学复位200防呆/Origin=0守卫);
      gcc -fsyntax-only TaskLoop.c 0 error
文档: vd960Loop/docs/devlog V1.03 置顶; DLD960_技术规格书/产品手册
      V1.04 (上电稳定期/绿灯自检语义 + 修订记录)
cmcng.h: FIRMWARE_VER "1.02"→"1.03" (MAIN=1/SUB=3, SSUB=1保持)

待现场验证: 绿灯自检时长(干净≈2s/扰动3~4s/兜底5s)与四路独立闪烁
This commit is contained in:
wangfq
2026-09-02 17:02:15 +08:00
parent 77b667f1a0
commit b90842f89d
7 changed files with 264 additions and 13 deletions
@@ -33,7 +33,10 @@
#define ALFA_CAP1 79 // IIR α = 79/256 ≈ 0.31 (@10ms → τ≈32ms)
#define MAX_SLOPE_RATE 5 // 斜率限幅: 单次最大变化 5%
#define ENTRY_CONFIRM 3 // 进入确认: 连续 N 次低于阈值
#define STABLE_SAMPLES 128 // 稳定期样本数
#define STABLE_SAMPLES 128 // 稳定期最少样本数 (128×10ms≈1.3s)
#define STABLE_ORIGIN_PPT 1 // 基准稳定判据: 窗口均值漂移 ≤ Origin×0.1%
#define STABLE_SETTLE_WINDOWS 2 // 连续 2 窗(100样本/窗≈1s)漂移达标 → 判稳
#define STABLE_MAX_SAMPLES 500 // 硬兜底 ≈5s (防环境长期不稳绿灯无限自检)
/*===========================================================================
* 基线冻结超时 (V2.3~V2.5)
@@ -182,7 +185,8 @@ typedef struct {
uint16_t fault_tick;
/*--- 稳定期 ---*/
uint16_t stable_cnt;
uint16_t stable_cnt; // 稳定期累计样本 (每次 CAP_OK +1)
uint16_t settle_cnt; // 基准稳定连续窗口计数 (窗=100样本≈1s, 漂移≤0.1%则+1)
/*--- 调试 ---*/
uint32_t xn_counter;
@@ -16,10 +16,10 @@
#include <stdint.h>
#define PRODUCT_MODEL "DLD960"
#define FIRMWARE_VER "1.02"
#define FIRMWARE_VER "1.03"
#define HARDWARE_VER "1.00"
#define FIRMWARE_VER_MAIN 1
#define FIRMWARE_VER_SUB 2
#define FIRMWARE_VER_SUB 3
#define FIRMWARE_VER_SSUB 1
#define HARDWARE_VER_MAIN 1
#define HARDWARE_VER_SUB 0
@@ -154,6 +154,7 @@ void init_vd_single(Loop154_Unit *unit)
unit->SET_SAFE = 1;
unit->stable_cnt = 0;
unit->settle_cnt = 0; // V1.03: 自检计数从零开始
unit->xn_counter = 0;
}
@@ -318,6 +319,8 @@ void TMR15_GLOBAL_IRQHandler(void)
unit->loop_INI_LOOP = 1;
unit->loop_LOOP_OK0 = 0;
unit->loop_stable = 0;
unit->stable_cnt = 0; // V1.03: 重学自检计数从零开始
unit->settle_cnt = 0;
unit->loop_ORG_CNT = 0;
unit->loop_ORG_SUM = 0;
unit->last_exit_tick = g_loop_states.misc_counter;
@@ -337,6 +340,8 @@ void TMR15_GLOBAL_IRQHandler(void)
unit->loop_INI_LOOP = 1;
unit->loop_LOOP_OK0 = 0;
unit->loop_stable = 0;
unit->stable_cnt = 0; // V1.03: 二次稳定期从零开始
unit->settle_cnt = 0;
#if USE_FLATNESS_EXIT
unit->exit_state = 0;
unit->max_slope = 0;
@@ -459,15 +464,40 @@ void vd1_task_per_channel(Loop154_Unit *unit)
unit->loop_CAPVD = get_flt_value(clamped_value, unit->loop_CAPVD);
}
/*--- 2. 稳定期:绕过 IIR 和斜率限幅,小窗口快速收敛 ---*/
/*--- 2. 稳定期:绕过 IIR 和斜率限幅,小窗口快速收敛;
* 基准值稳定(连续窗口 Origin 漂移达标)后才结束自检 (V1.03, 对齐V4B V4.23) ---*/
if (!unit->loop_stable) {
uint32_t _prev_origin = unit->loop_Origin;
uint8_t _win_done;
unit->loop_CAPVD = unit->loop_Value;
update_moving_average(&unit->loop_ORG_SUM, &unit->loop_ORG_CNT,
&unit->loop_Origin, unit->loop_CAPVD, 100);
_win_done = update_moving_average(&unit->loop_ORG_SUM, &unit->loop_ORG_CNT,
&unit->loop_Origin, unit->loop_CAPVD, 100);
unit->stable_cnt++;
if (unit->stable_cnt >= STABLE_SAMPLES) {
/* 每窗(100样本≈1s)完成时比较 Origin 均值漂移;
* 漂移 ≤ Origin×STABLE_ORIGIN_PPT/1000 → settle 计数+1, 否则清零
* (首个窗口常与捕获首窗 Origin 偏差大, 自然多等一窗再判稳) */
if (_win_done) {
uint32_t _drift = (unit->loop_Origin > _prev_origin)
? (unit->loop_Origin - _prev_origin)
: (_prev_origin - unit->loop_Origin);
uint32_t _band = (uint32_t)(unit->loop_Origin * STABLE_ORIGIN_PPT / 1000);
if (_drift <= _band) {
if (unit->settle_cnt < 0xFFFF) unit->settle_cnt++;
} else {
unit->settle_cnt = 0;
}
}
/* 判稳条件: 最少样本 + 连续 2 窗基准稳定; 硬兜底 STABLE_MAX_SAMPLES */
if ((unit->stable_cnt >= STABLE_SAMPLES &&
unit->settle_cnt >= STABLE_SETTLE_WINDOWS) ||
unit->stable_cnt >= STABLE_MAX_SAMPLES) {
unit->loop_stable = 1;
unit->stable_cnt = 0; // 计数清零: 重连/安全复位二次稳定期从零开始
unit->settle_cnt = 0;
PRINT("Loop%d stable, Origin:%d\n", unit->loop_num + 1, unit->loop_Origin);
}
return;