绿灯上电自检快闪: 原固定 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)与四路独立闪烁
250 lines
12 KiB
C
250 lines
12 KiB
C
/**
|
||
**************************************************************************
|
||
* @file TaskLoop.h
|
||
* @version v2.0
|
||
* @date 2025-09-08 (original), 2026-06-25 (rewrite: DLD154V4B algo × 4ch)
|
||
* @brief 四路线圈检测 — 移植自 DLD154V4B 算法
|
||
*
|
||
* 算法来源: DLD154V4B vd1_task() + 平坦性离开 (CN200910309382)
|
||
* 改动: 单路全局变量 → Loop154_Unit 结构体数组,四路独立
|
||
**************************************************************************
|
||
*/
|
||
|
||
#ifndef __TASKLOOP_H__
|
||
#define __TASKLOOP_H__
|
||
|
||
#include <stdint.h>
|
||
#include <stddef.h>
|
||
|
||
/*===========================================================================
|
||
* 时序参数(每 tick = 50ms,由 TMR15 5ms×10 产生)
|
||
* 主循环: vTaskDelay(10ms), M4 优化
|
||
*===========================================================================*/
|
||
#define HOLD_TIME (5 * 1200) // 有限存在保持(约 5 分钟)
|
||
#define LC_HOLD_TIME (4 * 1200) // 安全复位时间(约 4 分钟)
|
||
#define IN_DELAY 10 // 进入防抖 500ms
|
||
#define OUT_DELAY 10 // 离开防抖 500ms
|
||
#define PULSE_DELAY 10 // 脉冲宽度 500ms
|
||
|
||
/*===========================================================================
|
||
* 滤波参数 — M4 优化版 (V2.0+)
|
||
* tick 提升到 10ms,滤波系数同步调整,保持等效时间常数
|
||
*===========================================================================*/
|
||
#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 // 稳定期最少样本数 (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)
|
||
*===========================================================================*/
|
||
#define FREEZE_TIMEOUT 1000 // 冻结超时: ~10s @ 10ms/tick
|
||
#define FREEZE_STABILITY_RATE 2 // 稳定性窗口: 参考值的 ±2%
|
||
|
||
/*===========================================================================
|
||
* 看门狗 (IWDT) - 对齐 DLD154V4B 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
|
||
|
||
/*===========================================================================
|
||
* 离开检测: 1 = 平坦性三条件 (CN200910309382), 0 = cnt_release 防抖
|
||
*===========================================================================*/
|
||
#define USE_FLATNESS_EXIT 1
|
||
|
||
/*===========================================================================
|
||
* 平坦性参数
|
||
*===========================================================================*/
|
||
#define K1 8
|
||
#define K2 8
|
||
#define SLOPE_FLAT_THRESH 100
|
||
#define MIN_DELTA2 5
|
||
#define MIN_DELTA3 2
|
||
#define FLAT_CONFIRM_CNT 3
|
||
#define WINDOW_ORIGIN 500 // 基线跟踪窗口 (500 × 10ms = 5s)
|
||
|
||
/*===========================================================================
|
||
* 频率测量
|
||
* MEASUREMENT_BASE = 2^17 ≈ 131072
|
||
* LPCNT = MEASUREMENT_BASE / Xn, 使 Value 归一化到 ~131072
|
||
*===========================================================================*/
|
||
#define MEASUREMENT_BASE 131072
|
||
|
||
/*===========================================================================
|
||
* 通道数量
|
||
*===========================================================================*/
|
||
#define LOOP_CAPTURE_MAX 4
|
||
|
||
/*===========================================================================
|
||
* 主动上报 — 杂项类型 (misc_type 低2bit)
|
||
*===========================================================================*/
|
||
#define MISC_TYPE_TIME 0 // 时间量 (通过时间/车间距)
|
||
#define MISC_TYPE_CUT 1 // 线圈断开次数
|
||
#define MISC_TYPE_FLOW 2 // 车流量数
|
||
#define MISC_TYPE_RELAY 3 // 继电器输出次数
|
||
#define MISC_TYPE_COUNT 4 // 总类型数
|
||
|
||
/*
|
||
* 主动上报 — 间隔 (50ms tick)
|
||
*===========================================================================*/
|
||
#define REPORT_IDLE_TICKS 12 // 空闲稳定: 12×50ms = 600ms
|
||
#define REPORT_EVENT_TICKS 3 // 事件/变化: 3×50ms = 150ms
|
||
|
||
/*===========================================================================
|
||
* 灵敏度表(4级: 0=低, 3=高)
|
||
* 进入阈值 = Origin × SensTable[SENS] / 65536
|
||
* 离开阈值 = Origin × SensTable_1[SENS] / 65536
|
||
*===========================================================================*/
|
||
extern const uint16_t SensTable[4];
|
||
extern const uint16_t SensTable_1[4];
|
||
|
||
/*===========================================================================
|
||
* Forward declaration
|
||
*===========================================================================*/
|
||
struct tskTaskControlBlock;
|
||
typedef struct tskTaskControlBlock* TaskHandle_t;
|
||
|
||
/*===========================================================================
|
||
* 单通道状态结构体 — 对齐 DLD154V4B 全局变量
|
||
*===========================================================================*/
|
||
typedef struct {
|
||
uint8_t loop_num; // 通道编号 0~3
|
||
|
||
/*--- 捕获 & 测量 ---*/
|
||
uint16_t loop_Xn; // 相邻边沿周期差
|
||
uint16_t loop_CapThis, loop_CapLast;
|
||
uint16_t loop_LPCNT, loop_CapCnt;
|
||
uint32_t loop_CapSum, loop_Value;
|
||
uint32_t loop_CAPVD; // IIR 滤波后的频率值
|
||
uint32_t loop_Origin; // 基线(无车参考值)
|
||
uint32_t loop_ORG_SUM;
|
||
uint16_t loop_ORG_CNT;
|
||
uint16_t loop_dlt_ORG; // 当前灵敏度阈值
|
||
uint8_t Flt_Reg; // IIR 滤波系数
|
||
|
||
/*--- M4 优化: 进入确认 + 冻结超时 ---*/
|
||
uint8_t loop_entry_cnt; // 进入确认计数
|
||
uint16_t loop_freeze_cnt; // 冻结持续计数
|
||
uint32_t loop_freeze_ref; // 冻结参考值
|
||
|
||
/*--- 标志位 ---*/
|
||
uint8_t loop_INI_LOOP;
|
||
uint8_t loop_CAP_OK; // 新测量数据就绪
|
||
uint8_t loop_VD_FLAG; // 有车标志
|
||
uint8_t loop_VD_HOLD; // 有限存在计时启用
|
||
uint8_t loop_RF_FLAG; // 本 tick 收到线圈振荡边沿
|
||
uint8_t loop_LOOP_OK; // 线圈连接正常
|
||
uint8_t loop_LOOP_OK0; // 上周期连接状态
|
||
uint8_t loop_FLAG_IN; // 进入延时中
|
||
uint8_t loop_FLAG_OUT; // 离开延时中
|
||
uint8_t loop_FLAG_PLUSE; // 脉冲输出中
|
||
uint8_t loop_SensLevel; // 灵敏度等级 0~3
|
||
uint8_t loop_cnt_release; // 离开防抖计数
|
||
uint8_t loop_stable; // 数值已稳定
|
||
|
||
#if USE_FLATNESS_EXIT
|
||
/*--- 平坦性离开状态 ---*/
|
||
uint8_t exit_state; // 0=追踪斜率, 1=等待平坦
|
||
uint16_t max_slope; // 第一上升坡面最大 |f'|
|
||
uint16_t max_slope_rate; // 最大 |f''|
|
||
uint16_t delta2; // Δ2: 一阶平坦阈值
|
||
uint16_t delta3; // Δ3: 二阶平坦阈值
|
||
int32_t prev_capvd; // 上一帧 CAPVD
|
||
int32_t prev_first_deriv; // 上一帧一阶导数
|
||
uint8_t slope_flat_cnt; // 斜率趋零连续计数
|
||
uint8_t flat_ok_cnt; // 平坦条件满足连续计数
|
||
#endif
|
||
|
||
/*--- 计数器 ---*/
|
||
uint16_t Hold_CNT;
|
||
uint16_t hold_time; // 有限存在时长 (tick 数)
|
||
uint16_t relay_delay; // 继电器延时 (tick 数)
|
||
uint8_t INCNT, OUTCNT;
|
||
|
||
/*--- 输出配置 ---*/
|
||
uint8_t SET_PLUS; // 0=脉冲, 1=存在输出
|
||
uint8_t SET_DLY; // 离开延时: 0=无, 1=500ms
|
||
uint8_t SET_SAFE; // 1=安全复位
|
||
|
||
/*--- 安全复位 ---*/
|
||
uint8_t LC_HOLD;
|
||
uint8_t LC_Reset;
|
||
uint32_t LC_Hold_CNT;
|
||
|
||
/*--- 断开检测 ---*/
|
||
uint8_t power_up_state; // 上电后是否曾连接
|
||
uint8_t disconnect_count; // 断开次数 (0~3)
|
||
uint8_t disconnect_active; // 当前断开中
|
||
uint8_t fault_phase;
|
||
uint16_t fault_tick;
|
||
|
||
/*--- 稳定期 ---*/
|
||
uint16_t stable_cnt; // 稳定期累计样本 (每次 CAP_OK +1)
|
||
uint16_t settle_cnt; // 基准稳定连续窗口计数 (窗=100样本≈1s, 漂移≤0.1%则+1)
|
||
|
||
/*--- 调试 ---*/
|
||
uint32_t xn_counter;
|
||
|
||
/*--- 主动上报杂项计数 ---*/
|
||
uint32_t flow_count; // 车流量累计
|
||
uint32_t relay_count; // 继电器动作次数
|
||
uint32_t passtime_start; // 进场 时间戳(50ms tick)
|
||
uint32_t last_exit_tick; // 上次离场 时间戳(50ms tick)
|
||
uint32_t misc_value; // 当前要上报的杂项值
|
||
} Loop154_Unit;
|
||
|
||
/*===========================================================================
|
||
* 全局状态
|
||
*===========================================================================*/
|
||
typedef struct {
|
||
uint32_t report_counter; // 上报间隔计数器 (50ms tick)
|
||
uint32_t misc_counter; // 杂项时间戳计数器 (50ms tick, 自由运行不复位)
|
||
uint8_t report_misc_round; // 空闲轮转: 0=MISC_TYPE_TIME, 1=CUT, 2=FLOW, 3=RELAY
|
||
Loop154_Unit loop_unit[LOOP_CAPTURE_MAX];
|
||
} Loop154_States;
|
||
|
||
extern Loop154_States g_loop_states;
|
||
|
||
/*===========================================================================
|
||
* 全局变量
|
||
*===========================================================================*/
|
||
extern uint32_t g_sys_freq;
|
||
extern uint8_t g_input_div;
|
||
extern uint32_t g_safe_max_cnt;
|
||
|
||
/*===========================================================================
|
||
* 函数声明
|
||
*===========================================================================*/
|
||
void loop_task_function(void *pvParameters);
|
||
void usart_task_function(void *pvParameters);
|
||
void led_indicator_task_function(void *pvParameters);
|
||
|
||
void vd1_task_per_channel(Loop154_Unit *unit);
|
||
void init_vd_single(Loop154_Unit *unit);
|
||
void INIT_VDs(Loop154_States *loops);
|
||
|
||
void poll_red_pwm(void);
|
||
void poll_green_led(Loop154_Unit *unit);
|
||
void poll_yellow_led_single(Loop154_Unit *unit);
|
||
|
||
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 set_loops_relay_on(uint8_t loop_num);
|
||
void set_loops_relay_off(uint8_t loop_num);
|
||
|
||
void poll_wdg(void);
|
||
extern volatile uint16_t g_wdg_counter; // 看门狗活性计数 (TMR15 5ms 递增)
|
||
|
||
extern TaskHandle_t usart_task_handler;
|
||
|
||
#endif /* __TASKLOOP_H__ */
|