Files

419 lines
18 KiB
C
Raw Permalink 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.
#include "fault_cheak/faultcheck_task.h"
#include "app_init/app_init.h"
#include "app_init/task_lock.h"
#include "mylog/mylog.h"
#include "publicdata/publicdata.h"
#include "flash_file_mgr/fault_flash_impl.h"
#include "app_rtc/app_rtc.h"
#include "wdt_task/wdt_task.h"
#include "collect_ctrl/yk_ctrl.h"
#include "flowctrl/flowctrl_task.h"
/* 本任务ID定义:用于统一索引任务表、日志与锁资源。 */
#define FAULTCHECK_TASK_ID (TASK_ID_FaultCheck)
/* 获取本任务睡眠时间(ms)。 */
#define FAULTCHECK_SLEEP_TIME_MS() (MY_GET_SLEEP_TIME(FAULTCHECK_TASK_ID))
/* 本任务锁操作宏:简化锁接口调用。 */
#define FAULTCHECK_LOCK_INIT() (u8_task_lock_ctrl(FAULTCHECK_TASK_ID, TASK_LOCK_OP_INIT))
#define FAULTCHECK_LOCK_TAKE() (u8_task_lock_ctrl(FAULTCHECK_TASK_ID, TASK_LOCK_OP_TAKE))
#define FAULTCHECK_LOCK_GIVE() (u8_task_lock_ctrl(FAULTCHECK_TASK_ID, TASK_LOCK_OP_GIVE))
/* 本任务喂狗宏:标记本任务周期正常运行。 */
#define FAULTCHECK_FEED_DOG() (v_wdt_setFlag(FAULTCHECK_TASK_ID))
/* 本任务打印接口。 */
#define FAULTCHECK_LOG(fmt, ...) MYLOG_MSG(FAULTCHECK_TASK_ID, (fmt), ##__VA_ARGS__)
S_HIS_FAULT_MNG s_hisFaultMng; //故障告警信息记录
REAL_FAULT_DATA_T s_real_fault; //实时故障告警记录存储
#if 1 //故障检测
/**
* ************************************************************************
* @brief - 遥信数据故障检查- 多次调用 因此统一函数接口
*
* @param[in] u8_yx_state - 遥信状态 0正常 1故障
* @param[in] e_info - 对应故障信息
* @param[in] f_site - 故障位置
* @param[in] data1 - 数据1
* @param[in] data2 - 数据2
*
*
* @author jiankalka
* @date 2025-09-09
* ************************************************************************
*/
static void v_fault_yx_action_cheak(U8_T u8_yx_state, E_FAULT_INFO e_info , E_FAULT_SITE f_site, S16_T data1 , S16_T data2)
{
U8_T u8_fault_in_flag = u8_cheak_fault_flag(e_info , f_site); //故障存在标志
if(u8_yx_state == 1 && u8_fault_in_flag == 0) //故障动作 且故障不存在,则设置故障动作
v_set_fault_data(f_site,E_FAULT,e_info,0,data1,data2);
else if(u8_yx_state == 0 && u8_fault_in_flag != 0) //故障恢复 且故障仍然存在,则设置故障恢复
v_set_fault_data(f_site,E_RES,e_info,0,data1,data2);
}
/** 遥控命令与反馈不一致时的防抖:u8_slot 1=拒动类 2=粘连类,同一时间只累计一类(整桩或单枪 deb 块独立) */
typedef struct
{
U8_T u8_slot; /* 0 未在防抖累计;1 拒动;2 粘连 */
U32_T u32_sec0; /* 当前 u8_slot 对应异常持续计时的起点秒 */
} S_FAULT_KM_MISMATCH_DEB;
/** 交流、母联、各枪直流 13004/13005 防抖块在 s_km_deb[] 中的下标;枪 g 的 13004/13005 为 DC04_BASE+g、DC05_BASE+g */
typedef enum
{
E_FAULT_KM_DEB_AC = 0,
E_FAULT_KM_DEB_BUS = 1,
E_FAULT_KM_DEB_DC04_BASE = 2,
E_FAULT_KM_DEB_DC05_BASE = 2 + GUN_MAX_CNT,
E_FAULT_KM_DEB_COUNT = 2 + 2 * GUN_MAX_CNT
} E_FAULT_KM_DEB_IDX;
static S_FAULT_KM_MISMATCH_DEB s_km_deb[E_FAULT_KM_DEB_COUNT];
/**
* @brief 接触器命令与反馈不一致:NUM_10 秒防抖后置故障或恢复
* @param[in] f_site E_WHOLE_PILE 走 v_set_fault_data;枪位 E_GUN+枪号 走 v_flow_set_fault_data
* @param[in] u8_action_type 拔枪恢复等,与 v_flow_set_fault_data 一致
* @param[in] s16_data1 故障记录 data1(交流/母联为遥控命令,直流枪为命令或正极反馈见调用处)
* @param[in] s16_data2 故障记录 data2(交流/母联为单路反馈;直流枪为负极 KM 遥信)
*/
static void v_fault_km_mismatch_debounce_cheak(S_FAULT_KM_MISMATCH_DEB *p_deb, U8_T u8_mismatch, U8_T u8_slot, E_FAULT_INFO e_info, S16_T s16_data1, S16_T s16_data2, E_FAULT_SITE f_site, U8_T u8_action_type)
{
if (u8_mismatch == 0) /* 本类异常已消失 */
{
if (p_deb->u8_slot == u8_slot) /* 正在累计的正是本类:清零防抖状态 */
{
p_deb->u8_slot = 0;
p_deb->u32_sec0 = 0;
}
if (u8_cheak_fault_flag(e_info, f_site) != 0) /* 列表中仍有本码则恢复 */
{
if (f_site == E_WHOLE_PILE)
v_set_fault_data(f_site, E_RES, e_info, u8_action_type, s16_data1, s16_data2);
else
v_set_fault_data(f_site, E_RES, e_info, u8_action_type, s16_data1, s16_data2);
}
return;
}
/* 本类异常成立:若刚切换异常类型或未开始计时,则重新开始 NUM_10 秒窗口 */
if (p_deb->u8_slot != u8_slot || p_deb->u32_sec0 == 0)
{
p_deb->u8_slot = u8_slot;
p_deb->u32_sec0 = get_current_seconds();
}
if (u32_safe_seconds_since(p_deb->u32_sec0) > NUM_10) /* 防抖时间到 */
{
if (u8_cheak_fault_flag(e_info, f_site) == 0) /* 尚未登记 */
{
if (f_site == E_WHOLE_PILE)
v_set_fault_data(f_site, E_FAULT, e_info, u8_action_type, s16_data1, s16_data2);
else
{
v_set_fault_data(f_site, E_FAULT, e_info, u8_action_type, s16_data1, s16_data2);
}
}
}
}
/**
* @brief 单枪直流输出接触器:e_yk_get_ctrl_cmd(DC_CONT1/2) 与 u16_fault_get_sys_data(KM/流程/时长)
* 13004 空闲粘连、13005 充电中拒动,均经 v_fault_km_mismatch_debounce_cheak
* @param[in] u8_gunNo 枪索引 0..GUN_MAX_CNT-1
*/
static void v_fault_dc_output_km_check_gun(U8_T u8_gunNo)
{
E_FAULT_SITE f_dc_site;
E_CMD e_cmd_dc;
E_YK_CTRL_TYPE e_ky_dc;
U16_T u16_st;
U16_T u16_pos;
U16_T u16_neg;
U16_T u16_char;
if (u8_gunNo >= GUN_MAX_CNT)
return;
f_dc_site = (E_FAULT_SITE)(E_GUN + u8_gunNo);
e_ky_dc = (u8_gunNo == 0u) ? E_KY_TYPE_DC_CONT1 : E_KY_TYPE_DC_CONT2;
e_cmd_dc = e_yk_get_ctrl_cmd(e_ky_dc);
u16_pos = u16_fault_get_sys_data(u8_gunNo, E_FAULT_GET_DATA_GUN_DC_KM_POS, 0);
u16_neg = u16_fault_get_sys_data(u8_gunNo, E_FAULT_GET_DATA_GUN_DC_KM_NEG, 0);
u16_st = u16_fault_get_sys_data(u8_gunNo, E_FAULT_GET_DATA_FLOW_STATE, 0);
u16_char = u16_fault_get_sys_data(u8_gunNo, E_FAULT_GET_DATA_CHAR_TIME, 0);
if (u16_st == (U16_T)E_FLOW_FREE)
{
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_DC04_BASE + u8_gunNo],
(U8_T)(e_cmd_dc == CMD_OFF && (u16_pos == 1u || u16_neg == 1u)),
2, E_FAULT_13004, (S16_T)u16_pos, (S16_T)u16_neg, f_dc_site, 0);
}
if (u16_st == (U16_T)E_FLOW_CHARGE_RUNING && u16_char > NUM_60)
{
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_DC05_BASE + u8_gunNo],
(U8_T)(e_cmd_dc == CMD_ON && (u16_pos == 0u || u16_neg == 0u)),
1, E_FAULT_13005, (S16_T)u16_pos, (S16_T)u16_neg, f_dc_site, 1);
}
}
/**
* ************************************************************************
* @brief - 桩故障信息检查
*
*
*
* @author jiankalka
* @date 2025-09-09
* ************************************************************************
*/
void v_fault_action_cheak()
{
U16_T u16_yx_emergency = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_EMERGENCY, 0); //急停
U16_T u16_yx_door = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_DOOR, 0); //门禁
U16_T u16_yx_warter = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_WARTER, 0); //水浸
U16_T u16_yx_spd = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_SPD, 0); //防雷状态
U16_T u16_yx_smoke = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_SMOKE, 0); //烟感
U16_T u16_yx_door_en = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_DOOR_EN, 0); //门禁使能
U16_T u16_gunTemp_thrd = u16_fault_get_sys_data(WHOLE_PILE,E_FAULT_GET_DATA_GUN_TEMP_THRESHOLD,0); //枪温阈值 0.1度
U16_T u16_ac_km_en = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_AC_CONTACT_EN, 0); //交流接触器检测使能
U16_T u16_bus_km_en = u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_BUS_KM_EN, 0); //母联继电器命令/反馈检测使能(双枪及以上)
U16_T u16_yx_DC_FUSE ; //直流熔断器状态
U16_T u16_gunTemp_plus,u16_gunTemp_minus;
U8_T u8_gunNo;
E_CMD e_cmd_ac;
U8_T u8_ac_km_fb;
E_CMD e_cmd_bus;
U8_T u8_bus_km_fb;
v_fault_yx_action_cheak(u16_yx_emergency ,E_FAULT_13017, E_WHOLE_PILE,0,0); //急停 故障动作检查
if(u16_yx_door_en) //门禁使能 检测
v_fault_yx_action_cheak(u16_yx_door ,E_FAULT_13018, E_WHOLE_PILE,0,0); //门禁 故障动作检查
v_fault_yx_action_cheak(u16_yx_warter ,E_FAULT_13033, E_WHOLE_PILE,0,0); //水浸 故障动作检查
v_fault_yx_action_cheak(u16_yx_spd ,E_FAULT_13001, E_WHOLE_PILE,0,0); //防雷状态 故障动作检查
v_fault_yx_action_cheak(u16_yx_smoke ,E_FAULT_13032, E_WHOLE_PILE,0,0); //烟感 故障动作检查
for (u8_gunNo = 0; u8_gunNo < GUN_MAX_CNT; u8_gunNo++)
{
//直流熔断器状态
u16_yx_DC_FUSE = u16_fault_get_sys_data(u8_gunNo, E_FAULT_GET_DATA_GUN_DC_FUSE, 0); //
v_fault_yx_action_cheak(u16_yx_DC_FUSE ,E_FAULT_13006, (E_FAULT_SITE)(E_GUN + u8_gunNo),0,0); //直流熔断器状态 故障动作检查
//枪温阈值检测
u16_gunTemp_plus = u16_fault_get_sys_data(u8_gunNo ,E_FAULT_GET_DATA_GUN_TEMP ,0 ); //正极枪温值
u16_gunTemp_minus = u16_fault_get_sys_data(u8_gunNo ,E_FAULT_GET_DATA_GUN_TEMP ,1 ); //负极枪温值
u16_gunTemp_plus = (u16_gunTemp_plus > u16_gunTemp_minus)?u16_gunTemp_plus:u16_gunTemp_minus;
v_fault_yx_action_cheak((u16_gunTemp_plus > u16_gunTemp_thrd) ,E_FAULT_13014, (E_FAULT_SITE)(E_GUN + u8_gunNo),u16_gunTemp_plus,u16_gunTemp_thrd); //直流熔断器状态 故障动作检查
v_fault_dc_output_km_check_gun(u8_gunNo); //直流输出接触器 13004/13005(见 static 实现)
}
if (u16_ac_km_en) //交流接触器使能:遥控与反馈比对,防抖后判 13003 拒动 / 13002 粘连;使能 0 不检测、不清计时
{
e_cmd_ac = e_yk_get_ctrl_cmd(E_KY_TYPE_AC1);
u8_ac_km_fb = (U8_T)u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_AC_KM, 0);
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_AC], (U8_T)(e_cmd_ac == CMD_ON && u8_ac_km_fb == 0), 1, E_FAULT_13003, (S16_T)e_cmd_ac, (S16_T)u8_ac_km_fb, E_WHOLE_PILE, 0);
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_AC], (U8_T)(e_cmd_ac == CMD_OFF && u8_ac_km_fb == 1), 2, E_FAULT_13002, (S16_T)e_cmd_ac, (S16_T)u8_ac_km_fb, E_WHOLE_PILE, 0);
}
if (u16_bus_km_en) //母联:e_yk_get_ctrl_cmd(E_KY_TYPE_DC_CONT_BUS) 与 YX_PILE_BUS_KM,防抖后判 13023 拒动 / 13024 粘连
{
e_cmd_bus = e_yk_get_ctrl_cmd(E_KY_TYPE_DC_CONT_BUS);
u8_bus_km_fb = (U8_T)u16_fault_get_sys_data(WHOLE_PILE, E_FAULT_GET_DATA_BUS_KM, 0);
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_BUS], (U8_T)(e_cmd_bus == CMD_ON && u8_bus_km_fb == 0), 1, E_FAULT_13023, (S16_T)e_cmd_bus, (S16_T)u8_bus_km_fb, E_WHOLE_PILE, 0);
v_fault_km_mismatch_debounce_cheak(&s_km_deb[E_FAULT_KM_DEB_BUS], (U8_T)(e_cmd_bus == CMD_OFF && u8_bus_km_fb == 1), 2, E_FAULT_13024, (S16_T)e_cmd_bus, (S16_T)u8_bus_km_fb, E_WHOLE_PILE, 0);
}
}
#endif
#if 1 //拔枪恢复故障检查
/****************************************************
*函数名称: v_fault_res_cheak()
*功能说明: 拔枪故障恢复检查
*参数说明:
* 输入参数:
* 输出参数: void
****************************************************/
void v_fault_res_cheak(U8_T u8_gunNo)
{
U8_T i;
HIS_FAULT_DATA_T fault_data;
Comm_Time curTime;
U32_T u32_now_time;
static U32_T u32_gun_free_time[GUN_MAX_CNT] = {0}; //枪空闲时间-从工作变到空闲的时间 时间戳
U8_T u8_gunLink = u16_fault_get_sys_data(u8_gunNo,E_FAULT_GET_DATA_GUN_LINK,0); //枪连接标志
U8_T u8_gunWork = u16_fault_get_sys_data(u8_gunNo,E_FAULT_GET_DATA_GUN_CHAR_FLAG,0); //充电标志 1充电中 0未充电
//获取当前时间
GetCurrentTime(&curTime);
u32_now_time = xDate2Seconds(&curTime); //获取当前时间 时间戳
//更新工作空闲时间
if(u8_gunWork == 1)
{
u32_gun_free_time[u8_gunNo] = 0; //工作中,时间清零
}
else //非工作 获取当前时间
{
if(u32_gun_free_time[u8_gunNo] == 0) u32_gun_free_time[u8_gunNo] = u32_now_time;
}
//故障数量检查
if(s_real_fault.u8_fault_cnt == 0 &&
s_real_fault.u8_warn_cnt == 0) //不存在故障 则不需要判断故障恢复
return;
//判断拔枪恢复 或 充电完成5分钟后恢复条件是否满足
if(u8_gunLink == 1 && //枪连接 且时间没有到到超时时间,不做恢复判断
(u32_gun_free_time[u8_gunNo] == 0 || (u32_now_time - u32_gun_free_time[u8_gunNo]) < FAULT_GUN_NOLINK_RES_TIME))
return;
//遍历所有故障信息 检查故障恢复内容
for(i=0;i<CURR_FAULT_MAX_CNT;i++)
{
if(s_real_fault.fault_data[i].e_ingun == (u8_gunNo+1+E_GUN) && //故障归属本枪(故障存储枪号从1000开始,+E_GUN) 且为 拔枪恢复
s_real_fault.fault_data[i].u8_type == 1)
{
memset(&fault_data,0,sizeof(HIS_FAULT_DATA_T));
memcpy(&fault_data.s_occur_time, &curTime, sizeof(Comm_Time)); //发生时间
fault_data.e_site = (E_FAULT_SITE)(u8_gunNo + E_GUN);
fault_data.ActType = E_RES;
fault_data.e_fault_info = s_real_fault.fault_data[i].e_mag;
//v_hisFault_save_record(&fault_data); //保存动作记录
if(s_real_fault.u8_fault_cnt != 0)
s_real_fault.u8_fault_cnt -- ;
memset(&s_real_fault.fault_data[i],0,sizeof(Fault_data));
}
}
for(i=0;i<CURR_ALARM_MAX_CNT;i++)
{
if(s_real_fault.warn_data[i].e_ingun == (u8_gunNo+1+E_GUN) && s_real_fault.warn_data[i].u8_type == 1) //拔枪恢复
{
memset(&fault_data,0,sizeof(HIS_FAULT_DATA_T));
memcpy(&fault_data.s_occur_time, &curTime, sizeof(Comm_Time)); //发生时间
fault_data.e_site = (E_FAULT_SITE)(u8_gunNo + E_GUN);
fault_data.ActType = E_RES;
fault_data.e_fault_info = s_real_fault.warn_data[i].e_mag;
//v_hisFault_save_record(&fault_data); //保存动作记录
if(s_real_fault.u8_warn_cnt != 0)
s_real_fault.u8_warn_cnt -- ;
memset(&s_real_fault.warn_data[i],0,sizeof(Fault_data));
}
}
}
#endif
#if 1 //故障信息打印
/**
* ************************************************************************
* @brief - 故障信息打印
*
*
*
* @author jiankalka
* @date 2025-09-10
* ************************************************************************
*/
static void v_fault_info_print()
{
U8_T i,mag[FAULT_GET_MAG_MAX_LEN]={0};
char c_site_mag[NUM_30] = {0};
E_FAULT_INFO e_info;
E_FAULT_SITE e_site;
if(s_real_fault.u8_fault_cnt != 0 || s_real_fault.u8_warn_cnt != 0) //存在故障 或者告警
{
FAULTCHECK_LOG("**** Fault=%d, Warn=%d ****\n",
s_real_fault.u8_fault_cnt,s_real_fault.u8_warn_cnt);
for(i=0;i<CURR_FAULT_MAX_CNT;i++)
{
if(s_real_fault.fault_data[i].e_mag != 0)
{
e_info = s_real_fault.fault_data[i].e_mag;
e_site = s_real_fault.fault_data[i].e_ingun;
v_fault_get_site_mag(e_site,c_site_mag,NUM_30);
v_get_fault_info(e_info , (char*)mag,FAULT_GET_MAG_MAX_LEN);
FAULTCHECK_LOG("%s Fault %d %s\n",c_site_mag,e_info,mag);
}
}
for(i=0;i<CURR_ALARM_MAX_CNT;i++)
{
if(s_real_fault.warn_data[i].e_mag != 0)
{
e_info = s_real_fault.warn_data[i].e_mag;
e_site = s_real_fault.warn_data[i].e_ingun;
v_fault_get_site_mag(e_site,c_site_mag,NUM_30);
v_get_fault_info(e_info , (char*)mag,FAULT_GET_MAG_MAX_LEN);
FAULTCHECK_LOG("%s Warn %d %s\n",c_site_mag,e_info,mag);
}
}
FAULTCHECK_LOG("*************************************\n",
s_real_fault.u8_fault_cnt,s_real_fault.u8_warn_cnt);
}
}
#endif
//故障记录相关初始化
void v_fault_data_init(void)
{
/* 统一走 flash_file_mgr 初始化,避免与 BSP 初始化逻辑分叉。 */
#if (FAULT_FLASH_MGR_ENABLE)
v_fault_flash_init();
#endif
//初始化后 增加历史故障数量打印
FAULTCHECK_LOG("history fault count: %d", u16_fault_get_his_count());
}
void v_fault_task(void *argument)
{
uint16_t sleep_time_ms;
uint32_t last_send_time;
uint32_t current_time;
v_fault_data_init();
(void)argument;
(void)FAULTCHECK_LOCK_INIT();
sleep_time_ms = FAULTCHECK_SLEEP_TIME_MS();
last_send_time = get_current_seconds();
U8_T u8_gunNo, u8_gunCnt = u16_fault_get_sys_data(0,E_FAULT_GET_DATA_GUN_CNT,0); //枪数量
for (;;) {
FAULTCHECK_FEED_DOG();
current_time = get_current_seconds();
if ((TASK_RUN_PRINT_TIME != 0U) && (u32_safe_seconds_since(last_send_time) >= TASK_RUN_PRINT_TIME)) {
if (FAULTCHECK_LOCK_TAKE() == 1U) {
FAULTCHECK_LOG("faultcheck task is runing, sleep time is %ums", sleep_time_ms);
(void)FAULTCHECK_LOCK_GIVE();
}
last_send_time = current_time;
}
//故障信息打印
if (FUALT_INFO_PRINT_TIME != 0 && u32_safe_seconds_since(last_send_time) >= FUALT_INFO_PRINT_TIME) {
v_fault_info_print(); //故障信息打印
last_send_time = current_time;
}
for (u8_gunNo = 0; u8_gunNo < u8_gunCnt; u8_gunNo++)
{
v_fault_res_cheak(u8_gunNo); //故障拔枪恢复检测
}
v_fault_action_cheak() ; //故障动作检查
// 处理缓存中的故障动作
v_fault_cache_process();
mSleep(sleep_time_ms);
}
}