Initial commit: CCU621_M firmware project with BLE debug link support.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-08 17:28:36 +08:00
commit 9ceb218f80
1597 changed files with 724159 additions and 0 deletions
+325
View File
@@ -0,0 +1,325 @@
#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