9ceb218f80
Co-authored-by: Cursor <cursoragent@cursor.com>
326 lines
13 KiB
C
326 lines
13 KiB
C
#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
|