feat(V4B): 释放手感对齐 PD132T — 释放慢滤波(方案A, 固件 V4.03)

现场金属板测试: 灵敏度表已对齐, 但释放高度 V4B 比 PD132T 低
(刚离开触发位置即释放 vs 需离更远)。根因: IIR 滤波时间常数差异
(V4B 10ms+α79→τ32ms vs PD132T 43.7ms+α79/64→τ142~175ms),
释放阈值浅(进入20%)放大差异。

修复(USE_SLOW_RELEASE 开关, 默认 1):
- 新增独立慢滤波 loop1_CAPVD_slow(α=18/256 @10ms→τ≈142ms),
  吃原始 Value 不经斜率限幅, 复刻 PD132T 恢复速度
- 离开判定改用慢滤波值, 进入路径不变
- RELEASE_ALFA=18 可调(PD132T SET_FLT=ON 时用 15≈τ170ms)
- 同步: INIT_VD/稳定期/线圈重连
- 版本 V4.03(顺带修正 cmcng.h 字符串"4.00"与数字 4/2 不一致)

验证: gcc 单测 tests/test_release_slow_filter.c
τ fast=30ms/slow=140ms; 释放时机差 260ms ✓
文档: technical-spec §4.3.3 + devlog V2.12
待板级: 真机金属板测试 + MRS 编译
This commit is contained in:
wangfq
2026-08-31 16:52:45 +08:00
parent f0f2c29a04
commit 9391e1b808
6 changed files with 172 additions and 3 deletions
+84
View File
@@ -0,0 +1,84 @@
/*
* test_release_slow_filter.c — 方案A 释放慢滤波单测
*
* 验证: V4B 主滤波(ALFA=79 @10ms, τ≈32ms) vs 释放慢滤波(ALFA=18 @10ms, τ≈142ms)
* 在"金属板离开"(信号缓慢恢复)场景下,慢滤波释放时机应显著晚于快滤波,
* 从而对齐 PD132T 释放手感。
*
* 编译: gcc -o /tmp/test_release_slow test_release_slow_filter.c && /tmp/test_release_slow
*/
#include <stdio.h>
#include <stdint.h>
#include <assert.h>
#include <math.h>
#define ALFA_FAST 79
#define ALFA_SLOW 18
#define TICK_MS 10
/* 与 TaskLoop.c get_flt_value 同构 */
static uint32_t flt(uint32_t new_v, uint32_t last_v, uint32_t alfa)
{
uint32_t delta = (new_v > last_v) ? (new_v - last_v) : (last_v - new_v);
uint32_t scaled = (delta * alfa) >> 8;
return (new_v > last_v) ? last_v + scaled : last_v - scaled;
}
static void test_tau(void)
{
/* 阶跃响应: 从 100000 跳到 99000, 算 63.2% 收敛时间 */
uint32_t v_fast = 100000, v_slow = 100000;
int t_fast = -1, t_slow = -1;
double target_fast = 100000 - 0.632 * 1000; /* 63.2% of 1000 */
double target_slow = 100000 - 0.632 * 1000;
for (int t = 1; t <= 100; t++) {
v_fast = flt(99000, v_fast, ALFA_FAST);
v_slow = flt(99000, v_slow, ALFA_SLOW);
if (t_fast < 0 && v_fast <= target_fast) t_fast = t;
if (t_slow < 0 && v_slow <= target_slow) t_slow = t;
}
printf("[tau] fast=%dms slow=%dms (理论 32ms/142ms)\n", t_fast * TICK_MS, t_slow * TICK_MS);
assert(t_fast * TICK_MS <= 60); /* 快滤波 τ < 60ms */
assert(t_slow * TICK_MS >= 100); /* 慢滤波 τ > 100ms */
assert(t_slow > t_fast * 3); /* 慢/快 > 3× */
printf("[OK] tau 差异符合预期\n");
}
static void test_release_timing(void)
{
/* 模拟: Origin=100000, 档0: 进入阈值300→dlt_enter=457, 离开阈值60→dlt_leave=91
* 有车: Value=99000(CAPVD 收敛)
* 离开: 金属板缓慢上移, 信号每 10ms 恢复 +80(模拟手速)
* 释放条件: CAPVD 恢复到 Origin-dlt_leave = 99909 */
const uint32_t Origin = 100000;
const uint32_t dlt_leave = (Origin * 60) >> 16; /* = 91 */
const uint32_t release_line = Origin - dlt_leave; /* = 99909 */
uint32_t v_fast = 99000, v_slow = 99000;
int rel_fast = -1, rel_slow = -1;
uint32_t value = 99000;
for (int t = 1; t <= 200; t++) {
/* 金属板离开: 信号恢复(每 10ms +80) */
value += 80;
if (value > Origin) value = Origin;
v_fast = flt(value, v_fast, ALFA_FAST);
v_slow = flt(value, v_slow, ALFA_SLOW);
if (rel_fast < 0 && v_fast >= release_line) rel_fast = t;
if (rel_slow < 0 && v_slow >= release_line) rel_slow = t;
}
printf("[release] fast=%dms slow=%dms 差=%dms\n",
rel_fast * TICK_MS, rel_slow * TICK_MS, (rel_slow - rel_fast) * TICK_MS);
assert(rel_fast > 0 && rel_slow > 0);
assert(rel_slow > rel_fast); /* 慢滤波释放必晚于快滤波 */
assert((rel_slow - rel_fast) * TICK_MS >= 100); /* 释放延迟差 ≥100ms(等效高度差明显) */
printf("[OK] 慢滤波释放显著晚于快滤波, 对齐 PD132T 手感\n");
}
int main(void)
{
printf("=== 方案A 释放慢滤波单测 ===\n");
test_tau();
test_release_timing();
printf("\n全部通过 ✓\n");
return 0;
}