Files

326 lines
13 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 "flowctrl/insulation_ctrl.h"
#include "flowctrl/flowctrl_task.h"
#include "collect_ctrl/collect_task.h"
#include <float.h>
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