#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= 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); } }