#include "flowctrl/insulation_ctrl.h" #include "flowctrl/flowctrl_task.h" #include "collect_ctrl/collect_task.h" #include typedef struct { U32_T u32_ins_timer; //绝缘开始秒数存储,用于与当前时间比较 F32_T f32_ADC_VOL1[2]; //控制大地闭合后,ADC_VOL1[0]正对地电压,ADC_VOL1[1]负对地电压 F32_T f32_R_min; //绝缘检测失败阈值(100欧/伏) F32_T f32_R_max; //绝缘检测告警阈值(500欧/伏) F32_T f32_R_m; //控制大地闭合后,最小电阻值; F32_T f32_ADC_VOL2[2]; //控制绝缘检测光电继电器闭合后,ADC_VOL2[0]正对地电压,ADC_VOL2[1]负对地电压 F32_T f32_ins_RZ; //控制绝缘检测光电继电器闭合后,正对地电阻 F32_T f32_ins_RF; //控制绝缘检测光电继电器闭合后,负对地电阻 F64_T f64_V1; F64_T f64_V2; U8_T u8_step; //绝缘步骤控制 }INS_EXTE_DATA; //绝缘检测相关数据 INS_EXTE_DATA s_ins_ctrl[GUN_MAX_CNT]; static void v_insulation_Calculate(U8_T gunNo,U8_T *u8_result,F32_T *f32_rz, F32_T *f32_rf) ; #if 1 //外部数据获取 /** * ************************************************************************ * @brief - 获取直流母线adc采样电压值 * * @param[in] u8_gunNo - 枪号 0-1 * @param[in] u8_type - 数据类型 1直流母线正对地电压 0直流母线负对地电压 * * @return F32_T - * * @author jiankalka * @date 2025-11-14 * ************************************************************************ */ static F32_T f32_insl_get_adc_vol(U8_T u8_gunNo, U8_T u8_type ) { F32_T f32_ret; f32_ret = u8_type?f32_get_gun_yc_data(ADC_GUN_VOLT_PLUS,u8_gunNo):f32_get_gun_yc_data(ADC_GUN_VOLT_MINUS,u8_gunNo); return f32_ret; } #endif #if 1 //对外提供控制接口 /* 函数功能:绝缘控制终止 断开大地与光电继电器 输入:U8_T gunNo 充电枪号 */ void v_insulation_stop(U8_T gunNo) { INS_EXTE_DATA *ins_data = NULL; if (gunNo >= GUN_MAX_CNT) return; ins_data = &(s_ins_ctrl[gunNo]); switch(gunNo) //大地、光电继电器控分 { case 0: GUN1_INS_CTL(0); GUN1_UBAL_CTL(0); break; case 1: GUN2_INS_CTL(0); GUN2_UBAL_CTL(0); break; } ins_data->u8_step = 0; //绝缘检测终止,step置0 ins_data->u32_ins_timer = 0; //绝缘检测终止,u32_insu_timer置0 } /** * ************************************************************************ * @brief - 绝缘检查动作执行 * * @param[in] gunNo - 枪号 0-1 * @param[in] f32_rz - 正对地电阻 * @param[in] f32_rf - 负对地电阻 * * @return S8_T - -1 未完成 0失败 1成功 2成功但告警 * * @author jiankalka * @date 2025-11-14 * ************************************************************************ */ S8_T s8_insulation_action(U8_T gunNo ,F32_T *f32_rz, F32_T *f32_rf) { S8_T s8_ret = -1; U8_T u8_result = 1; //1:绝缘检测中; 2:大地闭合阶段绝缘检测失败; 3:光电继电器闭合阶段绝缘检测失败; 4:绝缘检测告警,但可以正常充电; 5:绝缘检测正常 v_insulation_Calculate(gunNo,&u8_result,f32_rz,f32_rf); //绝缘监测执行 //FLOWCTRL_LOG("insulation res = %d\n",u8_result); if(u8_result == 1) //绝缘检测中; { s8_ret = -1; } else if(u8_result == 5) //绝缘监测正常 { s8_ret = 1; } else if(u8_result == 4) //绝缘监测告警 { s8_ret = 2; } else //绝缘监测失败 { s8_ret = 0; } return s8_ret; } #endif #if 1 //绝缘监测控制 /* 函数功能:进行绝缘检测流程 计算绝缘检测电阻 输入:U8_T gunNo 充电枪号 输出:绝缘检测结果:U8_T *u8_result 1:绝缘检测中; 2:大地闭合阶段绝缘检测失败; 3:光电继电器闭合阶段绝缘检测失败; 4:绝缘检测告警,但可以正常充电; 5:绝缘检测正常 *f32_rz 正对地电阻 *f32_rf 负对地电阻 备注:绝缘流程及公式说明 1、控制系统接大地(PE)高压继电器®闭合 U𝑃:充电机输出正极(DC+)对大地(PE)的电压值 U𝑁:大地(PE)对充电机输出负极(DC-)的电压值 V1 = U𝑁/801.5K - U𝑃/801.5K (1)如果U𝑃>U𝑁: R𝑁 = (801.5K × U𝑁)/(U𝑃 − U𝑁) 判断 R𝑁绝缘达标,控制短接正桥臂电阻的光电继电器®闭合,不符合直接报绝缘故障; (2)如果U𝑃<U𝑁:R𝑃 = (801.5K × U𝑃)/(U𝑁 − U𝑃) 判断 R𝑃绝缘达标,控制短接正桥臂电阻的光电继电器®闭合,不符合直接报绝缘故障; (3)如果U𝑃=U𝑁,控制短接正桥臂电阻的光电继电器®闭合; 2、闭合光电继电器® 绝缘电阻值计算 U𝑃′:充电机输出正极(DC+)对大地(PE)的电压值 U𝑁′:大地(PE)对充电机输出负极(DC-)的电压值 V2 = U𝑁′/801.5K - U𝑃′/801.5K R𝑃 = (U𝑁′ × U𝑃 − U𝑁 × U𝑃′)/(U𝑁′ × V1 − U𝑁 × V2) R𝑁 = (U𝑃 × U𝑁′ − U𝑃′ × U𝑁)/(U𝑃′ × V1 − U𝑃 × V2) */ static void v_insulation_Calculate(U8_T gunNo,U8_T *u8_result,F32_T *f32_rz, F32_T *f32_rf) { INS_EXTE_DATA *ins_data = NULL; float volt = 0.0; if (gunNo >= GUN_MAX_CNT || u8_result == NULL || f32_rz == NULL || f32_rf == NULL) return; ins_data = &(s_ins_ctrl[gunNo]); F32_T f32_vol1 = f32_insl_get_adc_vol(gunNo,1); //直流母线 正对地电压 F32_T f32_vol2 = f32_insl_get_adc_vol(gunNo,0); //直流母线 负对地电压 //FLOWCTRL_LOG("INS adcV=%f,%f\n",f32_vol1,f32_vol2); if(ins_data->u8_step == 0) { if(ins_data->u32_ins_timer == 0) //参数初始化 { memset(ins_data,0,sizeof(INS_EXTE_DATA)); //开始绝缘检测前,对本枪绝缘检测数据存储结构体初始化 volt = f32_vol1 + f32_vol2; //绝缘检测开始前获取当前回路输出电压,计算出该电压等级下绝缘告警与失败的电阻值 ins_data->f32_R_min = 100 * volt; ins_data->f32_R_max = 500 * volt; ins_data->u32_ins_timer = get_current_seconds(); //记录绝缘检测开始的时间 FLOWCTRL_LOG("Gun%d(0-N) INS start, adcV=%f,%f\n",gunNo,f32_vol1,f32_vol2); switch(gunNo) //绝缘检测开始,大地控合,光电继电器控分 { case 0: GUN1_INS_CTL(1); GUN1_UBAL_CTL(0); break; case 1: GUN2_INS_CTL(1); GUN2_UBAL_CTL(0); break; } *u8_result = 1; // 1:绝缘检测中; } else if(u32_safe_seconds_since(ins_data->u32_ins_timer) > 1) //大地控合1S后开始采集电压,进行绝缘电阻计算 { ins_data->f64_V1 = (f32_vol2 - f32_vol1) / 801500; if(f32_vol1 == f32_vol2) //正对地与负对地电压相等,控合光电继电器,进入下一步 { switch(gunNo) { case 0: GUN1_UBAL_CTL(1); break; case 1: GUN2_UBAL_CTL(1); break; } ins_data->u8_step = 1; *u8_result = 1; // 1:绝缘检测中; } else if (f32_vol1 > f32_vol2) { ins_data->f32_R_m = (801500 * f32_vol2) / (f32_vol1 - f32_vol2); *f32_rf = ins_data->f32_R_m; //负对地电压小,只计算负对地电阻 *f32_rz = FLT_MAX; //正对地赋值为最大值 } else { ins_data->f32_R_m = (801500 * f32_vol1) / (f32_vol2 - f32_vol1); *f32_rz = ins_data->f32_R_m; //正对地电压小,只计算负对地电阻 *f32_rf = FLT_MAX; //负对地赋值为最大值 } if(ins_data->f32_R_m < ins_data->f32_R_min) //判定不达标,大地控合阶段绝缘检测失败,断开大地与光电继电器,返回1 { FLOWCTRL_LOG("Gun%d(0-N) INS1 fail, adcV=%f,%f\n",gunNo,f32_vol1,f32_vol2); FLOWCTRL_LOG("R= %f ,%f\n",ins_data->f32_R_m,ins_data->f32_R_min); switch(gunNo) { case 0: GUN1_INS_CTL(0); GUN1_UBAL_CTL(0); break; case 1: GUN2_INS_CTL(0); GUN2_UBAL_CTL(0); break; } *u8_result = 2; //2:大地闭合阶段绝缘检测失败; } else //判定达标,控合光电继电器,step置1,进入下一阶段, { switch(gunNo) { case 0: GUN1_UBAL_CTL(1); break; case 1: GUN2_UBAL_CTL(1); break; } //FLOWCTRL_LOG("Close opto relay\n"); ins_data->f32_ADC_VOL1[0] = f32_vol1; //保存此时的采样值 在第二部计算时使用 ins_data->f32_ADC_VOL1[1] = f32_vol2; ins_data->u8_step = 1; *u8_result = 1 ; // 1:绝缘检测中; } } } else if (ins_data->u8_step == 1) { if(u32_safe_seconds_since(ins_data->u32_ins_timer) > 2)//光电继电器控合1s后,开始绝缘计算 { volt = f32_vol1 + f32_vol2; //光电继电器闭合后,采集DC+、DC-对地电压 ins_data->f32_R_min = 100 * volt; ins_data->f32_R_max = 500 * volt; ins_data->f64_V2 = f32_vol2/801500 - f32_vol1/801500; //计算 V2 ins_data->f32_ADC_VOL2[0] = f32_vol1; ins_data->f32_ADC_VOL2[1] = f32_vol2; ins_data->f32_ins_RZ = (ins_data->f32_ADC_VOL2[1]*ins_data->f32_ADC_VOL1[0] - ins_data->f32_ADC_VOL1[1]*ins_data->f32_ADC_VOL2[0]) /(ins_data->f32_ADC_VOL2[1]*ins_data->f64_V1 - ins_data->f32_ADC_VOL1[1]*ins_data->f64_V2); ins_data->f32_ins_RF = (ins_data->f32_ADC_VOL1[0]*ins_data->f32_ADC_VOL2[1] - ins_data->f32_ADC_VOL2[0]*ins_data->f32_ADC_VOL1[1]) /(ins_data->f32_ADC_VOL2[0]*ins_data->f64_V1 - ins_data->f32_ADC_VOL1[0]*ins_data->f64_V2); FLOWCTRL_LOG("1 V+gnd=%.2f, V-gnd=%.2f\n",ins_data->f32_ADC_VOL1[0],ins_data->f32_ADC_VOL1[1]); FLOWCTRL_LOG("2 V+gnd=%.2f, V-gnd=%.2f\n",ins_data->f32_ADC_VOL2[0],ins_data->f32_ADC_VOL2[1]); FLOWCTRL_LOG("V1: %.10f ,V2: %.10f\n",ins_data->f64_V1,ins_data->f64_V2); ins_data->f32_ins_RZ = fabs(ins_data->f32_ins_RZ); ins_data->f32_ins_RF = fabs(ins_data->f32_ins_RF); *f32_rz = ins_data->f32_ins_RZ; *f32_rf = ins_data->f32_ins_RF; switch(gunNo) //绝缘计算完成,大地与光耦控分 { case 0: GUN1_INS_CTL(0); GUN1_UBAL_CTL(0); break; case 1: GUN2_INS_CTL(0); GUN2_UBAL_CTL(0); break; } ins_data->u8_step = 0; //绝缘检测完成,step置0 ins_data->u32_ins_timer = 0; //绝缘检测完成,u32_insu_timer置0 FLOWCTRL_LOG("Th: min=%.2f, max=%.2f\n",ins_data->f32_R_min,ins_data->f32_R_max); FLOWCTRL_LOG("R+gnd=%.2f, R-gnd=%.2f\n",ins_data->f32_ins_RZ,ins_data->f32_ins_RF); //光电继电器闭合后,直流回路绝缘情况判定 if(ins_data->f32_ins_RF < ins_data->f32_R_min || ins_data->f32_ins_RZ < ins_data->f32_R_min ) { *u8_result = 3; //3:光电继电器闭合阶段绝缘检测失败; } else if (ins_data->f32_ins_RF <= ins_data->f32_R_max || ins_data->f32_ins_RZ <= ins_data->f32_R_max ) { *u8_result = 4; //4:绝缘检测告警,但可以正常充电; } else { *u8_result = 5; //5:绝缘检测正常 } } } } #endif