Files
DLD154V4B/utilities/at32f421_freertos_demo/inc/TaskLoop.h
T
wangfq 16eed844a6 feat(V4B): V4.36.20 — 最低工作电感量 COIL_L_MIN_UH=20µH, 低于按线圈断开指示
用户需求: 设定最低电感量工作值(默认 20µH, 43nF 低频档口径, 宏定义);
线圈电感量低于该值 → 黄灯快闪以线圈断开状态指示
- TaskLoop.h: 新增 COIL_L_MIN_UH 20; 频率窗上限 125→171kHz (=L 20.06µH,
  43nF: L=2.533e7/(f²×43)) — 20~38µH 小线圈转为可正常工作(含现场 21/23µH)
- poll_yellow_led 模式1: g_coil_fault==2 归入断开级快闪(!LOOP_OK/reconn_stab 同级)
- 一长一短(模式5)仅保留 coil_fault==1 (L 偏大 f<18kHz)
- coil_monitor 防抖 1s 不变; 继电器/判定逻辑不动(仅指示级)
- test: 171 正常/172(L<20µH) 偏小, L 偏大 17; 全绿
语法0 error, 4测试全绿; spec V2.37 / devlog V2.56
2026-09-07 09:08:37 +08:00

231 lines
14 KiB
C
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.
/**
**************************************************************************
* @file TaskLoop.h
* @version v2.0
* @date 2025-09-08 (original), 2026-06-23 (simplified)
* @brief 地感功能实现 — 精简版,对齐 M1H/TLD-110 参考实现
**************************************************************************
* Copyright notice & Disclaimer
* * Create 2025-09-08 by wangfq
* * Simplify 2026-06-23: 去除二阶滤波、StageRangeConfig 等未使用模块
**************************************************************************
*/
#ifndef __TASKLOOP_H__
#define __TASKLOOP_H__
#include <stdint.h>
#include <stddef.h>
/*===========================================================================
* 时序参数(每 tick ≈50ms,由 TMR15 5ms×10 产生),对齐 M1H 参考实现
*===========================================================================*/
#define HOLD_TIME (5 * 1200) // 有限存在保持(约 5 分钟)
#define LC_HOLD_TIME (4 * 1200) // 安全复位时间(约 4 分钟)
#define IN_DELAY 10 // 进入防抖 500ms
#define OUT_DELAY 10 // 离开防抖 500ms(仅 SW_4=ON 时生效)
#define PULSE_DELAY 10 // 脉冲宽度 500ms
/*===========================================================================
* 滤波参数 — M4 优化版
*
* 与 M1H (8051, 50ms tick) 的关键差异:
* - tick 提升到 10msALFA_CAP1=79 @10ms (τ≈32ms, 等效原 79@50ms 的 5× 响应速度)
* - 斜率限幅 (MAX_SLOPE_RATE) 过滤瞬态尖峰
* - 进入确认 (ENTRY_CONFIRM) 替代单次阈值判定
*===========================================================================*/
#define ALFA_CAP1 79 // IIR α = 79/256 ≈ 0.31 (@10ms → τ≈32ms)
#define RELEASE_ALFA 21 // 释放慢滤波 α = 21/256 ≈ 0.082 (@10ms → 精确τ≈117ms, V4.04: 对齐 PD132T α79@43.7ms 精确τ≈118ms; 原18→精确τ137ms偏慢)
#define REL_ALFA 46 // V4.36.19: 低Q 释放平滑 α=46/256≈0.18 (@10ms → τ≈50ms): 复刻打印降采样平均效应, 只用于低Q 释放判定抗抖
#define REL_BAND_LO_MULT 150 // V4.36.19: 低Q 释放带回加宽 % (dlt_rel×1.5: 23→35@SENS3): 释放提前+σ余量, 防边界试探锁死
#define USE_SLOW_RELEASE 0 // 方案A总开关: 1=释放走慢滤波(对齐PD132T) 0=原快滤波释放
#define USE_PLANB_TABLE 1 // 方案B (V4.06): 快滤波释放 + 灵敏度表现场调校
// 1=进入加深/释放调浅双表(见 TaskLoop.c, SENS=3: 25/12 现场实测接近PD132T)
// 0=原始PD132T对齐表 {300,60,32,21}/{60,32,21,14}
// 历史: V4.05 曾用 ReleaseTable_B 加深释放表(实验失败, 方向反)
// V4.06 改为 SENS=3 进入21→25+释放14→12, 等比推全档
#define MAX_SLOPE_RATE 5 // 斜率限幅: 单次最大变化 5% (物理限制, 拒绝 EMI 尖峰)
/* V4.36.15: 重连判稳门控 (无车断开重连: 值稳定才放行, 不稳黄灯续闪) */
#define STABILIZE_STEP_TICKS 20 // 判稳步进: 20 样本≈200ms
#define STABILIZE_STEPS_OK 3 // 连续 3 步(600ms)漂移≤dlt/2 → 无漂移
#define STABILIZE_MAX_MS 5000 // 判稳兜底: 超时强制放行(避免永久无输出)
/* V4.36.8: 进入/释放确认样本数 — 按线圈 Q 档 (Q∝1/f 代理, 低Q抖动大需更多样本防误判) */
#define ENTRY_CONFIRM 3 // 进入确认基准(高Q): 连续 N 次低于阈值才判定有车
#define ENTRY_CONFIRM_HI 3 // 高Q(f<=80k) 进入确认样本
#define ENTRY_CONFIRM_MID 4 // 中Q(80~100k)
#define ENTRY_CONFIRM_LO 5 // 低Q(f>100k): 抖动大, 多样本防假进入
#define REL_CONFIRM_HI 3 // 高Q 释放确认样本
#define REL_CONFIRM_MID 4 // 中Q
#define REL_CONFIRM_LO 5 // 低Q: 释放边界抖动, 多样本防输出抖落
#define FREEZE_TIMEOUT 1000 // 基线冻结超时: ~10s @ 10ms/tick, 持续偏高且稳定后强制更新基线
#define FREEZE_STABILITY_RATE 2 // 冻结稳定性窗口: 参考值的 ±2% (CAPVD 需在此范围内才累计超时)
#define ENV_WARN_WAIT 200 // 环境预判 (V4.31): dev>+4dlt 高位连续 ~2s → 黄灯预判锁存(回摆保持)
#define ENV_RECOVER_WAIT 200 // 恢复确认 (V4.31): 新基线替换后 环境空闲连续 ~2s 才解除预判, 黄灯灭
#define COIL_F_OK_MIN_KHZ 18 // 线圈频率合理窗 (V4.36.18): 默认低频档口径, <18kHz → L偏大 (≈双 250µH+ 大线圈放行)
#define COIL_L_MIN_UH 20 // V4.36.20: 最低工作电感量 µH (43nF 低频档口径): L<此值 → 按线圈断开快闪指示
#define COIL_F_OK_MAX_KHZ 171 // 线圈频率合理窗 (V4.36.20): >171kHz → L<20µH(COIL_L_MIN_UH) 断开级偏小 (43nF: L=2.533e7/(f²×43); 原125=38µH 放宽至 20µH)
#define COIL_CAL_C_NF 43 // 标定等效谐振电容 nF (V4.34): 三极管库存板 低频档(66nF名义, R19在/R27空)实测 C_eff≈43 (41.3~45.5; 0Ω板68仅实验口径, 产品不用)
// 旧43 = 5.1K电阻旧板带病特性(三极管开关未饱和导通, 第二颗33nF未全量并入), 作废
#define COIL_CAL_C_NF_33 34 // 高频档(33nF名义)标定值: 实测 C_eff≈34.4 (33.8~35.0, 3组) — 用33nF档时改 COIL_CAL_C_NF 为34
#define COIL_DEF_C_NF 66 // 名义默认档电容 (保留: 注释/文档口径; 计算用 COIL_CAL_C_NF)
/*===========================================================================
* 离开检测模式
* 1 = 平坦性三条件判定 (CN200910309382), 0 = 简单 cnt_release 防抖
*===========================================================================*/
#define USE_FLATNESS_EXIT 0
/*===========================================================================
* 看门狗 (IWDT) - V2.10 新增
* 双保险模式: TMR15 ISR 5ms 递增 g_wdg_counter, 主循环 poll_wdg() 每 500ms 喂狗
* 超时 = WDT_DIV x (WDT_RLD+1) / LSI(约40kHz) 约 1.64s
*===========================================================================*/
#define WDT_COUNTER_LIMIT 100 // 喂狗周期 500ms (TMR15 5ms x 100)
#define WDT_DIV 2 // IWDT 分频枚举值: 2 = WDT_CLK_DIV_16 (实际分频 16; 勿传 16!)
#define WDT_RLD 4095 // 12bit 重装载 -> 超时约 1.64s
#define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500 × 10ms = 5s)
/*===========================================================================
* 频率测量参数
* MEASUREMENT_BASE: 自适应测量窗口目标值 (≈131072)
* LPCNT = MEASUREMENT_BASE / Xn, 使 Value ≈ MEASUREMENT_BASE
* 121072 = 2^17, 兼顾精度和 Origin 范围
*===========================================================================*/
#define MEASUREMENT_BASE 131072 // 2^17
/*===========================================================================
* 灵敏度表 — 对齐 M1H
* 进入阈值 = Origin × SensTable[SENS] / 65536
* 离开阈值 = Origin × SensTable_1[SENS] / 65536 (滞回 ~50%
*===========================================================================*/
extern const uint16_t SensTable[4];
extern const uint16_t SensTable_1[4];
/*===========================================================================
* 全局状态变量 — 捕获 & 测量
*===========================================================================*/
extern uint32_t g_sys_freq; // 系统时钟频率
extern uint8_t g_input_div; // TIM3 输入分频倍数
extern uint16_t loop1_Xn; // 当前相邻边沿周期差
extern uint16_t loop1_CapThis; // 本次捕获值
extern uint16_t loop1_CapLast; // 上次捕获值
extern uint16_t loop1_LPCNT; // 每 Value 需累加 LPCNT 次 Xn
extern uint16_t loop1_CapCnt; // 当前窗口已累加次数
extern uint32_t loop1_CapSum; // 当前窗口累加和
extern uint32_t loop1_Value; // 一个测量窗口的原始 ΣXn
extern uint32_t loop1_CAPVD; // IIR 滤波后的频率值
extern uint32_t loop1_CAPVD_slow; // 释放判定慢滤波值 (方案A: 独立 IIR, 精确τ≈117ms, 对齐 PD132T 释放手感)
extern uint32_t loop1_Origin; // 基线(无车时的参考频率)
extern uint32_t loop1_ORG_SUM; // 基线跟踪累加和
extern uint16_t loop1_ORG_CNT; // 基线跟踪计数(窗口=100
extern uint16_t loop1_dlt_ORG; // 当前灵敏度阈值
extern uint8_t Flt_Reg; // IIR 滤波系数
/*===========================================================================
* 全局状态变量 — 标志位
*===========================================================================*/
extern uint8_t loop1_INI_LOOP; // 初始化阶段
extern uint8_t loop1_CAP_OK; // 新测量数据就绪
extern uint8_t loop1_VD_FLAG; // 有车标志
extern uint8_t loop1_VD_HOLD; // 有限存在计时启用
extern uint8_t loop1_RF_FLAG; // 本 tick 收到线圈振荡边沿
extern uint8_t loop1_LOOP_OK; // 线圈连接正常
extern uint8_t loop1_LOOP_OK0; // 线圈连接正常(上周期)
extern uint8_t loop1_FLAG_IN; // 进入延时中
extern uint8_t loop1_FLAG_OUT; // 离开延时中
extern uint8_t loop1_FLAG_PLUSE; // 脉冲输出中
extern uint8_t loop1_SensLevel; // 当前灵敏度等级 (0~3)
extern uint8_t g_loop_stable; // 线圈数值已稳定 (0=稳定中, 1=稳定)
/* 离开防抖计数器(连续 CAPVD 恢复到阈值以上才释放) */
extern uint8_t loop1_cnt_release; // 离开防抖计数
/* 进入确认 (M4 优化) */
extern uint8_t loop1_entry_cnt; // 进入确认计数
extern uint16_t loop1_freeze_cnt; // 基线冻结持续计数
extern uint32_t loop1_freeze_ref; // 冻结参考值
#if USE_FLATNESS_EXIT
extern uint8_t g_exit_state; // 离开检测: 0=追踪斜率, 1=等待平坦
extern uint16_t g_max_slope; // 第一上升坡面最大 |f'|
extern uint16_t g_max_slope_rate; // 第一上升坡面最大 |f''|
extern uint16_t g_delta2; // Δ2: 一阶平坦阈值
extern uint16_t g_delta3; // Δ3: 二阶平坦阈值
extern int32_t g_prev_capvd; // 上一帧 CAPVD (差分用)
extern int32_t g_prev_first_deriv; // 上一帧一阶导数
extern uint8_t g_slope_flat_cnt; // 斜率趋零连续计数
extern uint8_t g_flat_ok_cnt; // 平坦条件满足连续计数
#endif
/*===========================================================================
* 全局状态变量 — 计数器
*===========================================================================*/
extern uint16_t Hold_CNT; // 有限存在计数器
extern uint8_t loop1_INCNT; // 进入延时计数
extern uint8_t loop1_OUTCNT; // 离开延时/脉冲宽度计数
extern uint8_t TM1cnt; // 50ms tick 分频计数
extern volatile uint16_t g_wdg_counter; // 看门狗活性计数 (TMR15 5ms 递增)
/*===========================================================================
* 拨码开关状态
*===========================================================================*/
extern uint8_t SET_PLUS; // 0=存在输出, 1=脉冲输出
extern uint8_t SET_DLY; // 离开延时: 0=无, 1=500ms
extern uint8_t SET_SAFE; // 1=安全复位拨下
/*===========================================================================
* 拨码开关去抖变量
*===========================================================================*/
extern uint8_t sw0, sw1, swok, swcnt;
extern uint8_t SENS, SENS_LAST;
/*===========================================================================
* 安全复位相关
*===========================================================================*/
extern uint8_t loop1_LC_HOLD; // 安全复位计时中
extern uint8_t loop1_LC_Reset; // 触发安全复位
extern uint32_t LC_Hold_CNT; // 安全复位计数器
extern uint16_t g_safe_max_cnt; // 安全复位超时
/*===========================================================================
* 故障指示相关 — 黄灯 LEDC (PA10)
*
* 行为:
* - 当前断开中 或 上电后从未接线圈:快闪 (200ms)
* - 线圈已恢复连接, 断开过 N 次:N 短闪 (N≤3)
* - 线圈正常连接, 无断开记录:灭
*
* 注: 绿灯 LEDA (PA9) 由 poll_green_led() 控制;
* 红灯 (PB1) 始终 PWM 呼吸, 不需软件干预.
*===========================================================================*/
extern uint8_t g_loop_power_up_state; // 上电后线圈是否曾连接 (0=否, 1=是)
extern uint8_t g_disconnect_count; // 当前上电周期内线圈断开次数 (0~3)
extern uint8_t g_disconnect_active; // 当前处于断开状态 (0=连接/从未连, 1=断开中)
extern uint8_t g_fault_phase; // 黄灯闪烁阶段
extern uint16_t g_fault_tick; // 黄灯闪烁计时器 (每5ms+1)
/*===========================================================================
* 调试计数器
*===========================================================================*/
extern uint32_t g_xn_counter; // 边沿总数(用于调试输出)
/*===========================================================================
* 函数声明
*===========================================================================*/
void loop_task_function(void *pvParameters);
void poll_sw_state(void);
uint32_t get_flt_value(uint32_t new_value, uint32_t last_Value);
uint8_t update_moving_average(uint32_t* p_sum, uint16_t* p_cnt,
uint32_t* p_origin, uint32_t new_value,
uint16_t window);
void poll_yellow_led(void);
void poll_green_led(void);
void LEDA_ON_OFF(void);
void vd1_task(void);
void wdt_init(void);
void poll_wdg(void);
#endif /* __TASKLOOP_H__ */