/****************************************************************************** 版权所有: 文件名称: switch.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-04-15 功能说明: DTU核心处理程序以开关为单位,循环处理。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" #ifdef CPU_FUXI #include "rt_clib.h" #include "fourier.h" #endif /*------------------------------- 宏定义 -------------------------------------- */ #ifdef CPU_FUXI #define AUTO_ADJUST_NUM 1 // 自动校准时平均的次数 #else #define AUTO_ADJUST_NUM 50 // 自动校准时平均的次数 #endif #define MEA_CAL_NUMBER 5 // 实际测量时平均的次数 //#define MEA_CAL_HARMONIC 14 //(CFG_ADC_DOTS_PER_PERIOD/2) // 谐波计算的次数 /*------------------------------ 全局变量 ------------------------------------- */ int g_sw_init; // SW是否初始化 struct ui g_ui[UI_NUM]; // 电压电流模拟量计算的综合结构 struct ui_jy g_ui_jy[3]; // 方向判断中的记忆电压 struct ui120 Us1_120,Us2_120; struct ui_p0 g_ui_p0[SWITCH_NUM_MAX]; //零序功率 int g_ui_angle0; // 角度计算时,作为参考电压通道在g_ui中的索引 int g_prot_index; // 保护计算时,采样通道中采样点的索引 struct sw g_sw[SWITCH_NUM_EXT]; // 开关综合结构 struct sw_public g_sw_pub; // 开关公共部分综合结构 int g_mea_cnt = 0; // 测量计数 int g_harmonic_num = 13; // 默认计算13次谐波 // 谐波系数修正 float g_harmonic_factor[CFG_ADC_DOTS_PER_PERIOD/2] = { 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, 1.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0, }; // 开关开入名称 const s8 *g_sw_di_name[SW_DI_NUM] = { "开关合位", // 1 "开关分位", "未储能", "已储能", "隔离刀合位", "隔离刀分位", "接地刀合位", "接地刀分位", "低气压告警", "低气压闭锁", // 10 "自动化投退", "常规保护", "集中式", "重合闸投入", "重合闸停用", "馈线自动化", "智能分布式", "就地FA闭锁", "联络/分段模式", "带电显示器有压", "分闸出口压板状态", // 20 "合闸出口压板状态", "手动合闸", "手动分闸", "驱动器异常", "母线侧硬件残压", "线路侧硬件残压", "控制回路断线", "合闸回路监视", "分闸回路监视", "HQ开入", // 30 "TQ开入", "电源侧瞬压", "负荷侧瞬压", "开关远方", "脉冲计数1", "脉冲计数2", #ifdef DO_KOUT_CHECK "开出自检", #else "开入3", #endif #ifdef CUSTOMIZE_BZT // 备自投 "备自投", "#1进线合位", "#1进线分位", "#2进线合位", "#2进线分位", "备自投-合位", "备自投-分位", "闭锁备自投", "备自投-失压分闸" #endif }; // 开关开出名称 const s8 * g_sw_do_name[SW_DO_NUM] = { "合闸", "跳闸", "保护合闸", "保护分闸", "遥控合闸", "遥控分闸", "瞬压复归", "瞬压复归1", "瞬压闭锁", "储能信号",//"开出11", "保护动作开出", "同期合闸开出", #ifdef CUSTOMIZE_BZT //备自投 "备自投-#1进线合闸", "备自投-#1进线分闸", "备自投-#2进线合闸", "备自投-#2进线分闸", "备自投-分段合闸", "备自投-分段分闸", "备自投-进线1失压分闸", "备自投-进线2失压分闸", #endif #if defined SW_FAIL_SINGLE_OUT "开关失灵", #endif }; const s8 * g_sw_led_name[SW_LED_NUM]= { "合位灯", "分位灯", "未储能灯", "过流灯", "接地灯", "常规保护灯", "就地FA灯", "集中FA灯", "分布式灯", "重合闸灯", "重合闸充电灯", "跳闸灯", "故障告警灯", "闭锁灯", "动作灯", "重合闭锁灯", "重合+FA闭锁灯", "开关传动灯", "联络灯", "分段灯", "充电灯", "隔离刀闸灯", "接地刀闸灯", #if !defined CPU_FUXI "综合合位灯", "综合分位灯", "XT灯", "YT灯", "X+Y灯", "自动解列功能灯", "同期合闸功能灯", "停用保护及FA灯", "停用自动解列灯", "停用同期合闸灯", #endif }; // 开关模拟量名称 //!!!更改模拟量名称可能会对以下宏有影响,请注意 const struct mea_desc g_sw_ac_desc[SW_AC_NUM_ALL] = { #ifdef DISP_MEA_CN {"保护IA",UNIT_A5,UNIT_ANG}, {"保护IB",UNIT_A5,UNIT_ANG}, {"保护IC",UNIT_A5,UNIT_ANG}, {"保护I0",UNIT_A5,UNIT_ANG}, #ifdef SW_AC_I0S_SAMPLE {"保护I0s",UNIT_A5,UNIT_ANG}, #endif {"测量IA",UNIT_A5,UNIT_ANG}, {"测量IB",UNIT_A5,UNIT_ANG}, {"测量IC",UNIT_A5,UNIT_ANG}, {"总有功",UNIT_W,UNIT_NULL}, {"A相有功",UNIT_W,UNIT_NULL}, {"B相有功",UNIT_W,UNIT_NULL}, {"C相有功",UNIT_W,UNIT_NULL}, {"总无功",UNIT_Var,UNIT_NULL}, {"A相无功",UNIT_Var,UNIT_NULL}, {"B相无功",UNIT_Var,UNIT_NULL}, {"C相无功",UNIT_Var,UNIT_NULL}, {"功率因素",UNIT_COS,UNIT_NULL}, #else {"BIA",UNIT_A5,UNIT_ANG}, {"BIB",UNIT_A5,UNIT_ANG}, {"BIC",UNIT_A5,UNIT_ANG}, {"I0",UNIT_I0A,UNIT_ANG}, #ifdef SW_AC_I0S_SAMPLE {"I0s",UNIT_A5,UNIT_ANG}, #endif {"CIA",UNIT_A5,UNIT_ANG}, {"CIB",UNIT_A5,UNIT_ANG}, {"CIC",UNIT_A5,UNIT_ANG}, {"P",UNIT_W,UNIT_NULL}, {"Pa",UNIT_W,UNIT_NULL}, {"Pb",UNIT_W,UNIT_NULL}, {"Pc",UNIT_W,UNIT_NULL}, {"Q",UNIT_Var,UNIT_NULL}, {"Qa",UNIT_Var,UNIT_NULL}, {"Qb",UNIT_Var,UNIT_NULL}, {"Qc",UNIT_Var,UNIT_NULL}, #ifdef FUN_YC_POWER_S {"S",UNIT_Var,UNIT_NULL}, #endif {"COS",UNIT_COS,UNIT_NULL}, #endif {"BI_UNB",UNIT_Per,UNIT_NULL}, {"CI_UNB",UNIT_Per,UNIT_NULL}, {"脉冲计数1",UNIT_GE,UNIT_NULL}, {"脉冲计数2",UNIT_GE,UNIT_NULL}, {"速断电流定值",UNIT_NULL,UNIT_NULL}, {"速断保护时间",UNIT_NULL,UNIT_NULL}, {"过流电流定值",UNIT_NULL,UNIT_NULL}, {"过流保护时间",UNIT_NULL,UNIT_NULL}, {"零序电流定值",UNIT_NULL,UNIT_NULL}, {"零序保护时间",UNIT_NULL,UNIT_NULL}, {"零序保护模式",UNIT_NULL,UNIT_NULL}, {"一次重合闸时间",UNIT_NULL,UNIT_NULL}, {"二次重合闸时间",UNIT_NULL,UNIT_NULL}, {"得电闭合时间",UNIT_NULL,UNIT_NULL}, {"无压分闸闭锁时间",UNIT_NULL,UNIT_NULL}, {"工作模式",UNIT_NULL,UNIT_NULL}, #ifdef METERING_ENERGY {"计量UAB",UNIT_V220,UNIT_NULL}, // yc 17 {"计量UBC",UNIT_V220,UNIT_NULL}, {"计量UCA",UNIT_V220,UNIT_NULL}, {"计量UA",UNIT_V220,UNIT_NULL}, {"计量UB",UNIT_V220,UNIT_NULL}, {"计量UC",UNIT_V220,UNIT_NULL}, {"计量IA",UNIT_A5,UNIT_NULL}, {"计量IB",UNIT_A5,UNIT_NULL}, {"计量IC",UNIT_A5,UNIT_NULL}, {"计量I0",UNIT_A5,UNIT_NULL}, {"计量有功功率",UNIT_W,UNIT_NULL}, {"计量A相有功功率",UNIT_W,UNIT_NULL}, {"计量B相有功功率",UNIT_W,UNIT_NULL}, {"计量C相有功功率",UNIT_W,UNIT_NULL}, {"计量无功功率",UNIT_Var,UNIT_NULL}, {"计量A相无功功率",UNIT_Var,UNIT_NULL}, {"计量B相无功功率",UNIT_Var,UNIT_NULL}, {"计量C相无功功率",UNIT_Var,UNIT_NULL}, {"计量视在功率",UNIT_Var,UNIT_NULL}, {"计量A相视在功率",UNIT_Var,UNIT_NULL}, {"计量B相视在功率",UNIT_Var,UNIT_NULL}, {"计量C相视在功率",UNIT_Var,UNIT_NULL}, {"计量功率因数",UNIT_COS,UNIT_NULL}, {"计量A相功率因数",UNIT_COS,UNIT_NULL}, {"计量B相功率因数",UNIT_COS,UNIT_NULL}, {"计量C相功率因数",UNIT_COS,UNIT_NULL}, {"计量频率",UNIT_Hz,UNIT_NULL}, #else {"YC1",UNIT_NULL,UNIT_NULL}, // yc 17 {"YC2",UNIT_NULL,UNIT_NULL}, {"YC3",UNIT_NULL,UNIT_NULL}, {"YC4",UNIT_NULL,UNIT_NULL}, {"YC5",UNIT_NULL,UNIT_NULL}, {"YC6",UNIT_NULL,UNIT_NULL}, {"YC7",UNIT_NULL,UNIT_NULL}, {"YC8",UNIT_NULL,UNIT_NULL}, {"YC9",UNIT_NULL,UNIT_NULL}, {"YC10",UNIT_NULL,UNIT_NULL}, {"YC11",UNIT_NULL,UNIT_NULL}, {"YC12",UNIT_NULL,UNIT_NULL}, #endif }; // 计量模块电度值 const struct mea_desc g_dd_desc[SW_DD_NUM_ALL]= { {"当前正向有功", UNIT_kWh,UNIT_NULL}, //6401 {"当前正向无功", UNIT_kVarh,UNIT_NULL}, //6402 {"当前一象限无功", UNIT_kVarh,UNIT_NULL}, //6403 {"当前四象限无功", UNIT_kVarh,UNIT_NULL}, //6404 {"当前反向有功", UNIT_kWh,UNIT_NULL}, //6405 {"当前反向无功", UNIT_kVarh,UNIT_NULL}, //6406 {"当前二象限无功", UNIT_kVarh,UNIT_NULL}, //6407 {"当前三象限无功", UNIT_kVarh,UNIT_NULL}, //6408 {"15分冻结正向有功", UNIT_kWh,UNIT_NULL}, //6409 {"15分冻结正向无功", UNIT_kVarh,UNIT_NULL}, //640A {"15分冻结一象限无功", UNIT_kVarh,UNIT_NULL}, //640B {"15分冻结四象限无功", UNIT_kVarh,UNIT_NULL}, //640C {"15分冻结反向有功", UNIT_kWh,UNIT_NULL}, //640D {"15分冻结反向无功", UNIT_kVarh,UNIT_NULL}, //640E {"15分冻结二象限无功", UNIT_kVarh,UNIT_NULL}, //640F {"15分冻结三象限无功", UNIT_kVarh,UNIT_NULL}, //6410 {"日冻结正向有功", UNIT_kWh,UNIT_NULL}, //6411 {"日冻结冻结正向无功", UNIT_kVarh,UNIT_NULL}, //6412 {"日冻结一象限无功", UNIT_kVarh,UNIT_NULL}, //6413 {"日冻结四象限无功", UNIT_kVarh,UNIT_NULL}, //6414 {"日冻结反向有功", UNIT_kWh,UNIT_NULL}, //6415 {"日冻结反向无功", UNIT_kVarh,UNIT_NULL}, //6416 {"日冻结二象限无功", UNIT_kVarh,UNIT_NULL}, //6417 {"日冻结三象限无功", UNIT_kVarh,UNIT_NULL}, //6418 {"潮变冻结正向有功", UNIT_kWh,UNIT_NULL}, //6419 {"潮变冻结正向无功", UNIT_kVarh,UNIT_NULL}, //641A {"潮变冻结一象限无功", UNIT_kVarh,UNIT_NULL}, //641B {"潮变冻结四象限无功", UNIT_kVarh,UNIT_NULL}, //641C {"潮变冻结反向有功", UNIT_kWh,UNIT_NULL}, //641D {"潮变冻结反向无功", UNIT_kVarh,UNIT_NULL}, //641E {"潮变冻结二象限无功", UNIT_kVarh,UNIT_NULL}, //641F {"潮变冻结三象限无功", UNIT_kVarh,UNIT_NULL}, //6420 #ifdef METERING_ENERGY {"当前A相有功", UNIT_kWh, UNIT_NULL}, {"当前B相有功", UNIT_kWh, UNIT_NULL}, {"当前C相有功", UNIT_kWh, UNIT_NULL}, {"当前A相正向有功", UNIT_kWh, UNIT_NULL}, {"当前B相正向有功", UNIT_kWh, UNIT_NULL}, {"当前C相正向有功", UNIT_kWh, UNIT_NULL}, {"当前A相反向有功", UNIT_kWh, UNIT_NULL}, {"当前B相反向有功", UNIT_kWh, UNIT_NULL}, {"当前C相反向有功", UNIT_kWh, UNIT_NULL}, {"当前总有功", UNIT_kWh, UNIT_NULL}, {"当前总无功", UNIT_kWh, UNIT_NULL}, #endif }; // 开关公共开入名称 const s8 *g_pub_di_name[PUB_DI_NUM] = { "远方", "就地", "检修状态投入", "柜门打开", "复归信号", "交流失电", "电池活化状态", "电池欠压", "电源模块故障", "电容器动作", "直流电源欠压", "内阻异常", "FA解锁", "装置复位", "功能总压板", "信号复归+FA 解锁", "非电量1", "非电量2", "非电量3", "非电量4", "非电量5", "非电量6", "开入1", "开入2", "开入3", "开入4", "开入5", "开入6", #ifdef YX_DI_ERROR "遥信自检", #else "开入7", #endif #ifdef KZ_OUT_TT "控制出口压板", #else "开入8", #endif }; // 开关公共开出名称 const s8 * g_pub_do_name[PUB_DO_NUM] = { "电池活化", "活化退出", "电压合格率清零", "预控开出", "解除闭锁", "远方重启", "远方复归", #ifdef YK_FG_FAJS "远方复归&FA解锁", // 远方复归+FA解锁 #endif "重合软压板合", "重合软压板分", #if defined BHFA_YB_YK #if defined GD_AREA_ECZD_2020 "停用保护总软压板合", "停用保护总软压板分", #else "功能总投入软压板合", "功能总投入软压板分", #endif "保护出口软压板合", "保护出口软压板分", "常规保护软压板合", "常规保护软压板分", "馈线自动化软压板合", "馈线自动化软压板分", "智能分布式软压板合", "智能分布式软压板分", #else #if defined GD_AREA_ECZD_2020 "停用保护总软压板合", "停用保护总软压板分", #else "自动功能软压板合", "自动功能软压板分", #endif "保护投入软压板合", "保护投入软压板分", #endif "同期合闸软压板合", "同期合闸软压板分", "集中式软压板-合", "集中式软压板-分", #ifdef YK_SOFT_YB "遥控软压板-合", "遥控软压板-分", #endif #ifdef YK_FA_ENBLE "FA遥控闭锁-合", "FA遥控闭锁-分", #endif #ifdef YK_FA_S_L_ENBLE "分段/联络-合", "分段/联络-分", #endif "自动解列软压板合", "自动解列软压板分", #ifdef METERING_ENERGY "遥控电度清零", "遥控线损事件清零", #endif #ifdef FUNC_DRIVE "传动接收软压板合", "传动接收软压板分", "传动指令", #endif #ifdef FUNC_DRIVE_JY "不停电传动功能", #endif #ifdef FUNC_RESET_EQU "重启装置", #endif "开出01", "开出02", "开出03", "开出04", "开出05", "开出06", "开出07", "开出08", "开出09", "开出10", }; const s8 * g_pub_led_name[PUB_LED_NUM]= { "电源灯", "运行灯", "通信灯", "通信状态灯", "电池灯", "异常灯", #if defined GD_AREA_ECZD_2020 "运行告警灯", #endif "动作灯", "远方灯", "就地灯", "串口1", "串口2", "串口3", "串口4", "网口1", "网口2", "网口3", "级联异常灯", "间隔1通讯灯", "间隔2通讯灯", "间隔3通讯灯", "间隔4通讯灯", "间隔5通讯灯", "间隔6通讯灯", "规约通信异常灯", #ifdef KZ_OUT_TT "控制闭锁灯", #endif }; // 开关公共模拟量名称 const struct mea_desc g_pub_ac_desc[PUB_AC_NUM_ALL] = { #ifdef DISP_MEA_CN {"母线UA1",UNIT_V100,UNIT_ANG}, {"母线UB1",UNIT_V100,UNIT_ANG}, {"母线UC1",UNIT_V100,UNIT_ANG}, {"母线UAB1",UNIT_V100,UNIT_ANG}, {"母线UBC1",UNIT_V100,UNIT_ANG}, {"母线UCA1",UNIT_V100,UNIT_ANG}, {"母线U01",UNIT_V100,UNIT_ANG}, {"母线US1",UNIT_V220,UNIT_ANG}, {"线路UA2",UNIT_V100,UNIT_ANG}, {"线路UB2",UNIT_V100,UNIT_ANG}, {"线路UC2",UNIT_V100,UNIT_ANG}, {"线路UAB2",UNIT_V100,UNIT_ANG}, {"线路UBC2",UNIT_V100,UNIT_ANG}, {"线路UCA2",UNIT_V100,UNIT_ANG}, {"线路U02",UNIT_V100,UNIT_ANG}, {"线路US2",UNIT_V220,UNIT_ANG}, {"V_UNB1",UNIT_Per,UNIT_NULL}, {"V_UNB2",UNIT_Per,UNIT_NULL}, {"工频1",UNIT_Hz,UNIT_NULL}, {"工频2",UNIT_Hz,UNIT_NULL}, #else {"UA1",UNIT_V100,UNIT_ANG}, {"UB1",UNIT_V100,UNIT_ANG}, {"UC1",UNIT_V100,UNIT_ANG}, {"UAB1",UNIT_V100,UNIT_ANG}, {"UBC1",UNIT_V100,UNIT_ANG}, {"UCA1",UNIT_V100,UNIT_ANG}, {"U01",UNIT_V100,UNIT_ANG}, {"US1",UNIT_V220,UNIT_ANG}, {"UA2",UNIT_V100,UNIT_ANG}, {"UB2",UNIT_V100,UNIT_ANG}, {"UC2",UNIT_V100,UNIT_ANG}, {"UAB2",UNIT_V100,UNIT_ANG}, {"UBC2",UNIT_V100,UNIT_ANG}, {"UCA2",UNIT_V100,UNIT_ANG}, {"U02",UNIT_V100,UNIT_ANG}, {"US2",UNIT_V220,UNIT_ANG}, {"V_UNB1",UNIT_Per,UNIT_NULL}, {"V_UNB2",UNIT_Per,UNIT_NULL}, {"UF1",UNIT_Hz,UNIT_NULL}, {"UF2",UNIT_Hz,UNIT_NULL}, #endif {"直流电压1",UNIT_V050,UNIT_NULL}, {"直流电压2",UNIT_V050,UNIT_NULL}, {"DltUab",UNIT_V100,UNIT_NULL}, {"DltUbc",UNIT_V100,UNIT_NULL}, {"DltUca",UNIT_V100,UNIT_NULL}, {"ArgUab",UNIT_ANG,UNIT_NULL}, {"ArgUbc",UNIT_ANG,UNIT_NULL}, {"ArgUca",UNIT_ANG,UNIT_NULL}, {"温度",UNIT_TEMP,UNIT_NULL}, #ifdef TMP_CHIP_AHT20 {"湿度",UNIT_HUMI,UNIT_NULL}, #endif {"Ver",UNIT_NULL,UNIT_NULL}, #ifdef BATTERY_WITH_COMM {"活化放电时长",UINT_Hour,UNIT_NULL}, {"当前放电时长",UINT_Hour,UNIT_NULL}, #endif #ifdef DEV_GPS_ATGM332D #ifndef GPS_JWD_SPLIT {"经度",UNIT_ANG,UNIT_NULL}, {"纬度",UNIT_ANG,UNIT_NULL}, #else {"经度-度",UNIT_ANG,UNIT_NULL}, {"纬度-分",UNIT_ANG,UNIT_NULL}, {"经度-秒",UNIT_ANG,UNIT_NULL}, {"纬度-度",UNIT_ANG,UNIT_NULL}, {"纬度-分",UNIT_ANG,UNIT_NULL}, {"纬度-秒",UNIT_ANG,UNIT_NULL}, #endif {"卫星个数",UNIT_GE,UNIT_NULL}, #endif {"YC1",UNIT_NULL,UNIT_NULL}, {"YC2",UNIT_NULL,UNIT_NULL}, {"YC3",UNIT_NULL,UNIT_NULL}, {"YC4",UNIT_NULL,UNIT_NULL}, {"YC5",UNIT_NULL,UNIT_NULL}, {"YC6",UNIT_NULL,UNIT_NULL}, {"YC7",UNIT_NULL,UNIT_NULL}, {"YC8",UNIT_NULL,UNIT_NULL}, {"A相故障电流",UNIT_A5,UNIT_ANG}, {"B相故障电流",UNIT_A5,UNIT_ANG}, {"C相故障电流",UNIT_A5,UNIT_ANG}, {"零序电流",UNIT_A5,UNIT_ANG}, #ifdef BATTERY_BP_L500 {"电池内阻",UINT_mVperA,UNIT_NULL}, {"电池温度",UNIT_TEMP,UNIT_NULL}, {"电池实时电量",UNIT_Per,UNIT_NULL}, {"电池放电电流",UINT_mA,UNIT_NULL}, {"电池充电电流",UINT_mA,UNIT_NULL}, #endif }; /*------------------------------ 函数声明 ------------------------------------- */ int _sw_cal_mea(void); void _sw_cal_average(int cal_num); float _sw_ui_e_k(int index); void _sw_auto_adjust_pq(void); void _sw_get_dots(void); void _sw_cal_fft(void); void _sw_cal_effect(void); void _sw_cal_angle(void); void _sw_cal_ri_correct(void); void _sw_min_max(int ui_index,u32 *p_min,u32*p_max); void _fz_min_max(int ui_index1,int ui_index2,u32 *p_min,u32*p_max); float _sw_base_angle(int ui_index); int _sw_save_dc_factor(float dc1_H, float dc1_L,float dc2_H, float dc2_L); void _sw_temp_factor(void); /*------------------------------ 外部函数 ------------------------------------- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性. */ /****************************************************************************** 函数名称: sw_init 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 线路开关初始化 参数说明: 返回值: 0: 成功 其它: 失败 修改记录: */ int sw_init(void) { int sw, i, type, ui; float f; // 初始化为固定默认值,只有上电初始化才运行一次 if (g_sw_init == 0) { memset(&g_ui, 0, sizeof(g_ui)); memset(&g_sw_pub, 0, sizeof(g_sw_pub)); memset(&g_sw_pub.di, SW_DI_TYPE_OFF, sizeof(g_sw_pub.di)); memset(&g_sw_pub.di_cfg_index, INDEX_INVALLID, sizeof(g_sw_pub.di_cfg_index)); memset(&g_sw_pub.do_cfg_index, INDEX_INVALLID, sizeof(g_sw_pub.do_cfg_index)); memset(&g_sw_pub.ac_cfg_index, INDEX_INVALLID, sizeof(g_sw_pub.ac_cfg_index)); memset(&g_sw_pub.led_cfg_index, INDEX_INVALLID, sizeof(g_sw_pub.led_cfg_index)); for (i = 0; i < UI_NUM; i++) { g_ui[i].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[i].ui_base_make = -1; g_ui[i].e_factor0 = 1.0; // 使用理论默认值初始化m2_factor_k,防止初始化时使用此值的定值出错, // 导致保护逻辑出错(例如,跳位有流告警) if (i < PUB_AC_NUM) { g_ui[i].m2_factor_k = rt_round(factor_e_k(EQU_SCALE_PT_DEFAULT) * Q08_BASE); } else { g_ui[i].m2_factor_k = rt_round(factor_e_k(EQU_SCALE_CT_DEFAULT) * Q08_BASE); } g_ui[i].m2_factor_c = rt_round(1.0 * Q16_BASE); } for (sw = 0; sw < SWITCH_NUM_MAX; sw++) { memset(&g_sw[sw], 0, sizeof(g_sw[i])); memset(&g_sw[sw].di, SW_DI_TYPE_OFF, sizeof(g_sw[sw].di)); memset(&g_sw[sw].di_cfg_index, INDEX_INVALLID, sizeof(g_sw[sw].di_cfg_index)); memset(&g_sw[sw].do_cfg_index, INDEX_INVALLID, sizeof(g_sw[sw].do_cfg_index)); memset(&g_sw[sw].ac_cfg_index, INDEX_INVALLID, sizeof(g_sw[sw].ac_cfg_index)); memset(&g_sw[sw].led_cfg_index, INDEX_INVALLID, sizeof(g_sw[sw].led_cfg_index)); } } g_sw_init = 0; // 检查装置配置 if (equ_config_null()) { return -1; } // DI通道 for (i = 0; i < g_equ_config->di_num; i++) { if (g_equ_config_di[i].owner > SWITCH_NUM_MAX) { rt_printf("switch_init(own):i=%d,owner=%d,SWITCH_NUM_MAX=%d.\r\n", i, g_equ_config_di[i].owner, SWITCH_NUM_MAX); continue; } // 如果是其它类型(type == 0),不处理 type = g_equ_config_di[i].type; if (type == 0) { continue; } type--; if (g_equ_config_di[i].owner == 0) { if (type < PUB_DI_NUM) { g_sw_pub.di_cfg_index[type] = i; } else { rt_printf("switch_init(di):i=%d,type=%d,DI_NUM=%d.\r\n", i, type, PUB_DI_NUM); } } else { sw = g_equ_config_di[i].owner - 1; if (type < SW_DI_NUM) { g_sw[sw].di_cfg_index[type] = i; } else { rt_printf("switch_init(di):i=%d,type=%d,DI_NUM=%d,sw=%d.\r\n", i, type, SW_DI_NUM, sw); } } } // DO通道 for (i = 0; i < g_equ_config->do_num; i++) { if (g_equ_config_do[i].owner > SWITCH_NUM_MAX) { rt_printf("switch_init(own):i=%d,owner=%d,SWITCH_NUM_MAX=%d.\r\n", i, g_equ_config_do[i].owner, SWITCH_NUM_MAX); continue; } // 如果是其它类型(type == 0),不处理 type = g_equ_config_do[i].type; if (type == 0) { continue; } type--; if (g_equ_config_do[i].owner == 0) { if (type < PUB_DO_NUM) { g_sw_pub.do_cfg_index[type] = i; } else if (type < PUB_DO_LED_NUM) { s16 slot, index; g_sw_pub.led_cfg_index[type - PUB_DO_NUM] = i; slot = g_equ_config_do[i].slot; index = g_equ_config_do[i].index; g_led_slot[slot].sn[index].sw = 0; g_led_slot[slot].sn[index].no = type - PUB_DO_NUM; index++; if (index > g_led_slot[slot].num) { g_led_slot[slot].num = index; } } else { rt_printf("switch_init(do):i=%d,type=%d,PUB_DO_NUM + PUB_LED_NUM=%d.\r\n", i, type, PUB_DO_NUM + PUB_LED_NUM); } } else { sw = g_equ_config_do[i].owner - 1; if (type < SW_DO_NUM) { g_sw[sw].do_cfg_index[type] = i; } else if (type < SW_DO_LED_NUM) { s16 slot, index; g_sw[sw].led_cfg_index[type - SW_DO_NUM] = i; slot = g_equ_config_do[i].slot; index = g_equ_config_do[i].index; g_led_slot[slot].sn[index].sw = sw + 1; g_led_slot[slot].sn[index].no = type - SW_DO_NUM; index++; if (index > g_led_slot[slot].num) { g_led_slot[slot].num = index; } } else { rt_printf("switch_init(do):i=%d,type=%d,SW_DO_LED_NUM=%d,sw=%d.\r\n", i, type, SW_DO_LED_NUM, sw); } } } // AC通道 for (i = 0; i < g_equ_config->ac_num; i++) { if (g_equ_config_ac[i].owner > SWITCH_NUM_MAX) { rt_printf("switch_init(own):i=%d,owner=%d,SWITCH_NUM_MAX=%d.\r\n", i, g_equ_config_ac[i].owner, SWITCH_NUM_MAX); continue; } // 如果是其它类型(type == 0),不处理 type = g_equ_config_ac[i].type; if (type == 0) { continue; } type--; if (g_equ_config_ac[i].owner == 0) { if (type < PUB_AC_NUM) { // 索引 ui = type; g_sw_pub.ac_cfg_index[type] = i; } else { rt_printf("switch_init(ac):i=%d,type=%d,AC_NUM=%d.\r\n", i, g_equ_config_ac[i].type, PUB_AC_NUM); continue; } } else { sw = g_equ_config_ac[i].owner - 1; if (type < SW_AC_NUM) { ui = UI_SW_INDEX(sw, type); // 索引 g_sw[sw].ac_cfg_index[type] = i; } else { rt_printf("switch_init(ac):i=%d,type=%d,AC_NUM=%d,sw=%d.\r\n", i, type, SW_AC_NUM, sw); continue; } } // 通道索引 g_ui[ui].chn_index = equ_get_ac_channel(g_equ_config_ac[i].slot, g_equ_config_ac[i].index); // 系数 factor_e_c_get(g_equ_config_ac[i].slot, g_equ_config_ac[i].index, &f); g_ui[ui].e_factor0 = f / factor_e_k(g_equ_config_ac[i].scale); g_ui[ui].m2_factor_k = rt_round(factor_e_k(g_equ_config_ac[i].scale) * Q08_BASE); #ifdef PROTECT_AC_ADJUST factor_p_e_c_get(g_equ_config_ac[i].slot, g_equ_config_ac[i].index, &f); // 保护校准系数 #endif g_ui[ui].m2_factor_c = rt_round(f * Q16_BASE); factor_p_c_get(g_equ_config_ac[i].slot, g_equ_config_ac[i].index, &f); g_ui[ui].p_factor = f; // 一二变比 g_ui[ui].e_ps = factor_e_ps(equ_get_ac_scale(g_equ_config_ac[i].slot, g_equ_config_ac[i].index)); // 暂时屏蔽,看看不使用PQ校准的效果 // factor_pq_get(g_equ_config_ac[i].slot,g_equ_config_ac[i].index,g_ui[ui].pq_factor); } // 计算角度时的基准通道 if (g_ui[PUB_AC_UA1].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_angle0 = PUB_AC_UA1; } else if (g_ui[PUB_AC_UAB1].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_angle0 = PUB_AC_UAB1; } else if (g_ui[PUB_AC_UAB2].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_angle0 = PUB_AC_UAB2; } else { g_ui_angle0 = -1; } // 相电压合成线电压标志 if (g_ui[PUB_AC_UA1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UB1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UC1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UAB1].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UBC1].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UCA1].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_LV1; memcpy(&g_ui[PUB_AC_UAB1], &g_ui[PUB_AC_UA1], sizeof(g_ui[0])); g_ui[PUB_AC_UAB1].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UAB1].ui_base_make = PUB_AC_UA1; g_ui[PUB_AC_UAB1].e_factor0 = (g_ui[PUB_AC_UA1].e_factor0 + g_ui[PUB_AC_UB1].e_factor0) / 2; memcpy(&g_ui[PUB_AC_UBC1], &g_ui[PUB_AC_UA1], sizeof(g_ui[0])); g_ui[PUB_AC_UBC1].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UBC1].ui_base_make = PUB_AC_UA1; g_ui[PUB_AC_UBC1].e_factor0 = (g_ui[PUB_AC_UB1].e_factor0 + g_ui[PUB_AC_UC1].e_factor0) / 2; memcpy(&g_ui[PUB_AC_UCA1], &g_ui[PUB_AC_UA1], sizeof(g_ui[0])); g_ui[PUB_AC_UCA1].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UCA1].ui_base_make = PUB_AC_UA1; g_ui[PUB_AC_UCA1].e_factor0 = (g_ui[PUB_AC_UC1].e_factor0 + g_ui[PUB_AC_UA1].e_factor0) / 2; } if (g_ui[PUB_AC_UA2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UB2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UC2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UAB2].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UBC2].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UCA2].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_LV2; memcpy(&g_ui[PUB_AC_UAB2], &g_ui[PUB_AC_UA2], sizeof(g_ui[0])); g_ui[PUB_AC_UAB2].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UAB2].ui_base_make = PUB_AC_UA2; g_ui[PUB_AC_UAB2].e_factor0 = (g_ui[PUB_AC_UA2].e_factor0 + g_ui[PUB_AC_UB2].e_factor0) / 2; memcpy(&g_ui[PUB_AC_UBC2], &g_ui[PUB_AC_UA2], sizeof(g_ui[0])); g_ui[PUB_AC_UBC2].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UBC2].ui_base_make = PUB_AC_UA2; g_ui[PUB_AC_UBC2].e_factor0 = (g_ui[PUB_AC_UB2].e_factor0 + g_ui[PUB_AC_UC2].e_factor0) / 2; memcpy(&g_ui[PUB_AC_UCA2], &g_ui[PUB_AC_UA2], sizeof(g_ui[0])); g_ui[PUB_AC_UCA2].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UCA2].ui_base_make = PUB_AC_UA2; g_ui[PUB_AC_UCA2].e_factor0 = (g_ui[PUB_AC_UC2].e_factor0 + g_ui[PUB_AC_UA2].e_factor0) / 2; } // 合成UCA标志 if (g_ui[PUB_AC_UAB1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UBC1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UCA1].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_UCA1; memcpy(&g_ui[PUB_AC_UCA1], &g_ui[PUB_AC_UAB1], sizeof(g_ui[0])); g_ui[PUB_AC_UCA1].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UCA1].ui_base_make = PUB_AC_UAB1; g_ui[PUB_AC_UCA1].e_factor0 = (g_ui[PUB_AC_UAB1].e_factor0 + g_ui[PUB_AC_UBC1].e_factor0) / 2; } if (g_ui[PUB_AC_UAB2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UBC2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UCA2].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_UCA2; memcpy(&g_ui[PUB_AC_UCA2], &g_ui[PUB_AC_UAB2], sizeof(g_ui[0])); g_ui[PUB_AC_UCA2].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_UCA2].ui_base_make = PUB_AC_UAB2; g_ui[PUB_AC_UCA2].e_factor0 = (g_ui[PUB_AC_UAB2].e_factor0 + g_ui[PUB_AC_UBC2].e_factor0) / 2; } // U01 零序电压自产 if (g_ui[PUB_AC_UA1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UB1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UC1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_U01].chn_index == CFG_ADC_CHANNEL_ZERO && pRunSet->bTT_U0ZC) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_U01; memcpy(&g_ui[PUB_AC_U01], &g_ui[PUB_AC_UA1], sizeof(g_ui[0])); g_ui[PUB_AC_U01].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_U01].ui_base_make = PUB_AC_UA1; g_ui[PUB_AC_U01].e_factor0 = (g_ui[PUB_AC_UA1].e_factor0 + g_ui[PUB_AC_UB1].e_factor0 + g_ui[PUB_AC_UC1].e_factor0) / 3; } // U02 零序电压自产 if (g_ui[PUB_AC_UA2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UB2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UC2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_U02].chn_index == CFG_ADC_CHANNEL_ZERO && pRunSet->bTT_U0ZC) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_U02; memcpy(&g_ui[PUB_AC_U02], &g_ui[PUB_AC_UA2], sizeof(g_ui[0])); g_ui[PUB_AC_U02].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_U02].ui_base_make = PUB_AC_UA2; g_ui[PUB_AC_U02].e_factor0 = (g_ui[PUB_AC_UA2].e_factor0 + g_ui[PUB_AC_UB2].e_factor0 + g_ui[PUB_AC_UC2].e_factor0) / 3; } // 合成IB、I0标志 for (sw = 0; sw < SWITCH_NUM_MAX; sw++) { if (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IC)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IB)].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw[sw].ui_flags |= UI_FLAGS_MAKE_IB; memcpy(&g_ui[UI_SW_INDEX(sw, SW_AC_IB)], &g_ui[UI_SW_INDEX(sw, SW_AC_IA)], sizeof(g_ui[0])); g_ui[UI_SW_INDEX(sw, SW_AC_IB)].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[UI_SW_INDEX(sw, SW_AC_IB)].ui_base_make = UI_SW_INDEX(sw, SW_AC_IA); g_ui[UI_SW_INDEX(sw, SW_AC_IB)].e_factor0 = (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].e_factor0 + g_ui[UI_SW_INDEX(sw, SW_AC_IC)].e_factor0) / 2; } if (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_CIC)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw[sw].ui_flags |= UI_FLAGS_MAKE_CIB; memcpy(&g_ui[UI_SW_INDEX(sw, SW_AC_CIB)], &g_ui[UI_SW_INDEX(sw, SW_AC_CIA)], sizeof(g_ui[0])); g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].ui_base_make = UI_SW_INDEX(sw, SW_AC_CIA); g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].e_factor0 = (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].e_factor0 + g_ui[UI_SW_INDEX(sw, SW_AC_CIC)].e_factor0) / 2; } if (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IB)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IC)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_I0)].chn_index == CFG_ADC_CHANNEL_ZERO) { g_sw[sw].ui_flags |= UI_FLAGS_MAKE_I0; memcpy(&g_ui[UI_SW_INDEX(sw, SW_AC_I0)], &g_ui[UI_SW_INDEX(sw, SW_AC_IA)], sizeof(g_ui[0])); g_ui[UI_SW_INDEX(sw, SW_AC_I0)].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ui_base_make = UI_SW_INDEX(sw, SW_AC_IA); g_ui[UI_SW_INDEX(sw, SW_AC_I0)].e_factor0 = (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].e_factor0 + g_ui[UI_SW_INDEX(sw, SW_AC_IB)].e_factor0 + g_ui[UI_SW_INDEX(sw, SW_AC_IC)].e_factor0) / 3; } } #if 0 // 支持功率电压选择,计算方法等计算时再确定 // 确认是3表法还是2表法 for(sw=0; swbTT_U0ZC) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_U01; memcpy(&g_ui[PUB_AC_U01], &g_ui[PUB_AC_UA1], sizeof(g_ui[0])); g_ui[PUB_AC_U01].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_U01].ui_base_make = PUB_AC_UA1; g_ui[PUB_AC_U01].e_factor0 = (g_ui[PUB_AC_UA1].e_factor0 + g_ui[PUB_AC_UB1].e_factor0 + g_ui[PUB_AC_UC1].e_factor0) / 3; } // U02 零序电压自产 if (g_ui[PUB_AC_UA2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UB2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_UC2].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[PUB_AC_U02].chn_index == CFG_ADC_CHANNEL_ZERO && pRunSet->bTT_U0ZC) { g_sw_pub.ui_flags |= UI_FLAGS_MAKE_U02; memcpy(&g_ui[PUB_AC_U02], &g_ui[PUB_AC_UA2], sizeof(g_ui[0])); g_ui[PUB_AC_U02].chn_index = CFG_ADC_CHANNEL_ZERO; g_ui[PUB_AC_U02].ui_base_make = PUB_AC_UA2; g_ui[PUB_AC_U02].e_factor0 = (g_ui[PUB_AC_UA2].e_factor0 + g_ui[PUB_AC_UB2].e_factor0 + g_ui[PUB_AC_UC2].e_factor0) / 3; } return 0; } /****************************************************************************** 函数名称: sw_exit 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 线路开关退出 参数说明: 返回值: 0: 成功 其它: 失败 修改记录: */ int sw_exit(void) { return 0; } int sw_di_get(u32 sw, u32 no) { u8 v; if (no == 0) { return -1; } no--; if (sw == 0) { v = g_sw_pub.di[no]; } else { sw--; v = g_sw[sw].di[no]; } return v; } int sw_di_set(u32 sw, u32 no, u8 v) { if (no == 0) { return -1; } no--; if (sw == 0) { g_sw_pub.di[no] = v; } else { sw--; g_sw[sw].di[no] = v; } return 0; } /****************************************************************************** 函数名称: sw_do 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 针对线路开关执行开出动作 参数说明: sw 开关序号 index 开出索引 type 开出类型 返回值: 0: 成功 其它: 失败 修改记录: */ static int _sw_do(u32 slot, u32 index, int type) { int ret, do_num; do_num = equ_get_do_num(slot); if (do_num == 0) { return -1; } // 将辅助板的4个开出(64~67)映射到(0~3), // 解决32位宽度不够的问题,这样LED灯不允许配置成开出。 // 其它板不存在这个问题,例如开出板只有16个开出可配 if ((g_board_info[slot].type == BOARD_TYPE_AUX) || (g_board_info[slot].type == BOARD_TYPE_ZT)) { index = index % 32; } ret = 0; switch (type) { case SW_DO_TYPE_OFF: case SW_DO_TYPE_ON: ret = dido_do(slot, (1 << index), type); break; case SW_DO_TYPE_SELECT_ON: if (dido_do_have_select(slot, index)) { ret = dido_do(slot, (1 << do_num), 1); } break; case SW_DO_TYPE_SELECT_OFF: if (dido_do_have_select(slot, index)) { ret = dido_do(slot, (1 << do_num), 0); } break; default: ret = -3; break; } return ret; } int sw_do(u32 sw, u32 index, int type) { int ret; u32 slot; TRELAY_T *pR = &g_tRelay[sw]; if ((index == SW_DO_HZ || index == SW_DO_YKH || index == SW_DO_BHH) && (type == SW_DO_TYPE_ON)) { if (pR->run_stu.sw == 1) { pR->uRmtSW.bHz_Doing = 1; #ifdef FUNC_DRIVE gb_drive.bHz_Doing = 1; #endif } pR->uRmtSW.bTz_Doing = 0; #ifdef FUNC_DRIVE gb_drive.bTz_Doing = 0; #endif } if ((index == SW_DO_FZ || index == SW_DO_YKT || index == SW_DO_BHT) && (type == SW_DO_TYPE_ON)) { if (pR->run_stu.sw == 2) { pR->uRmtSW.bTz_Doing = 1; #ifdef FUNC_DRIVE gb_drive.bTz_Doing = 1; #endif } pR->uRmtSW.bHz_Doing = 0; #ifdef FUNC_DRIVE gb_drive.bHz_Doing = 0; #endif } if (sw >= SWITCH_NUM_MAX || index >= SW_DO_NUM) { return -1; } // 气压低闭锁分合闸 if (pRunSet->tSwSet[sw].bTT_QYD_BS && (g_sw[sw].di[SW_DI_QYD_BS] == SW_DI_TYPE_ON) && (index == SW_DO_HZ || index == SW_DO_FZ || index == SW_DO_YKH || index == SW_DO_YKT || index == SW_DO_BHH || index == SW_DO_BHT)) { return -2; } // 需要通道有配置 index = g_sw[sw].do_cfg_index[index]; if (index == INDEX_INVALLID || index >= g_equ_config->do_num) { return -3; } slot = g_equ_config_do[index].slot; index = g_equ_config_do[index].index; ret = _sw_do(slot, index, type); return ret; } /****************************************************************************** 函数名称: sw_do_pub 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 针对线路开关公共部门执行开出动作 参数说明: index 开出索引 type 开出类型 返回值: 0: 成功 其它: 失败 修改记录: */ int sw_do_pub(u32 index, int type) { int ret; u32 slot; if (index >= PUB_DO_NUM) { return -1; } index = g_sw_pub.do_cfg_index[index]; if (index == INDEX_INVALLID || index >= g_equ_config->do_num) { return -2; } slot = g_equ_config_do[index].slot; index = g_equ_config_do[index].index; ret = _sw_do(slot, index, type); return ret; } /****************************************************************************** 函数名称: sw_do_yk 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 预控继电器开出 参数说明: index 开出索引 type 开出类型 返回值: 0: 成功 其它: 失败 修改记录: */ int sw_do_yuk(int type) { int ret; u32 slot; int index; index = g_sw_pub.do_cfg_index[PUB_DO_YK]; if (index == INDEX_INVALLID || index >= g_equ_config->do_num) { return -2; } slot = g_equ_config_do[index].slot; index = g_equ_config_do[index].index; ret = _sw_do(slot, index, type); return ret; } /****************************************************************************** 函数名称: sw_v_m2_factor_k 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 得到一个保护定值计算用的理论转化系数。目前假设所有电压的系数都是一样, 从第一组电压中取出一个。 参数说明: 返回值: 修改记录: */ float sw_v_m2_factor_k(int id) { if (id < PUB_AC_NUM) { if (id == PUB_AC_US1) { if ((short)g_sw_pub.ac_cfg_index[PUB_AC_US1] == INDEX_INVALLID) { return g_ui[PUB_AC_UAB1].m2_factor_k; } else { if (g_ui[id].chn_index != CFG_ADC_CHANNEL_ZERO) { return g_ui[id].m2_factor_k; } } } else if (id == PUB_AC_US2) { if ((short)g_sw_pub.ac_cfg_index[PUB_AC_US2] == INDEX_INVALLID) { return g_ui[PUB_AC_UBC2].m2_factor_k; } else { if (g_ui[id].chn_index != CFG_ADC_CHANNEL_ZERO) { return g_ui[id].m2_factor_k; } } } else if (id == PUB_AC_U01) { if (g_ui[id].chn_index == CFG_ADC_CHANNEL_ZERO) { return g_ui[PUB_AC_UA1].m2_factor_k; } else { if (g_ui[id].chn_index != CFG_ADC_CHANNEL_ZERO) { return g_ui[id].m2_factor_k; } } } else if (id == PUB_AC_U02) { if (g_ui[id].chn_index == CFG_ADC_CHANNEL_ZERO) { return g_ui[PUB_AC_UA2].m2_factor_k; } else { if (g_ui[id].chn_index != CFG_ADC_CHANNEL_ZERO) { return g_ui[id].m2_factor_k; } } } else { // if(g_ui[id].chn_index != CFG_ADC_CHANNEL_ZERO) //{ return g_ui[id].m2_factor_k; //} } } return 1.0; } #ifdef FUNC_DRIVE_JY static void drive_ui_proc(void) { int i = 0, sw = 0; TSETSW *pSet = &pRunSet->tSwSet[sw]; if (!gb_drive.b_drive_on) { return; } for (i = 0; i < 1; i++) // 保护遥测值 { if (!gb_drive.tDriveUa1Time.boolTrip) { g_ui[PUB_AC_UA1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UA1] / 256.0)); g_ui[PUB_AC_UB1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UB1] / 256.0)); g_ui[PUB_AC_UC1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UC1] / 256.0)); g_ui[PUB_AC_UAB1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UAB1] / 256.0)); g_ui[PUB_AC_UBC1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UBC1] / 256.0)); g_ui[PUB_AC_UCA1].m2[i] = GetSetSQR(pSet->dU_drive_ua1, (pRunSet->dKU[PUB_AC_UCA1] / 256.0)); } if (!gb_drive.tDriveUa2Time.boolTrip) { g_ui[PUB_AC_UA2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UA2] / 256.0)); g_ui[PUB_AC_UB2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UB2] / 256.0)); g_ui[PUB_AC_UC2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UC2] / 256.0)); g_ui[PUB_AC_UAB2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UAB2] / 256.0)); g_ui[PUB_AC_UBC2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UBC2] / 256.0)); g_ui[PUB_AC_UCA2].m2[i] = GetSetSQR(pSet->dU_drive_ua2, (pRunSet->dKU[PUB_AC_UCA2] / 256.0)); } if (!gb_drive.tDriveU0Time.boolTrip) { g_ui[PUB_AC_U01].m2[i] = GetSetSQR(pSet->dU_drive_u0, (pRunSet->dKU[PUB_AC_U01] / 256.0)); } if (!gb_drive.tDriveITime.boolTrip) { g_ui[UI_SW_INDEX_BEGIN(sw) + SW_AC_IA].m2[i] = GetSetSQR(pSet->dU_drive_i, (g_ui[UI_SW_INDEX_BEGIN(sw) + SW_AC_IA].m2_factor_k / 256.0)); } if (!gb_drive.tDriveI0Time.boolTrip) { g_ui[UI_SW_INDEX_BEGIN(sw) + SW_AC_I0].m2[i] = GetSetSQR(pSet->dU_drive_i0, (g_ui[UI_SW_INDEX_BEGIN(sw) + SW_AC_I0].m2_factor_k / 256.0)); } } #if 0 //测量显示遥测值 g_sw_pub.ac_in[PUB_AC_UA1] =(pSet->dU_drive_ua1*Q16_BASE); g_sw_pub.ac_in[PUB_AC_UAB1] =(pSet->dU_drive_ua1*Q16_BASE); g_sw_pub.ac_in[PUB_AC_UA2] =(pSet->dU_drive_ua2*Q16_BASE); g_sw_pub.ac_in[PUB_AC_UAB2] =(pSet->dU_drive_ua2*Q16_BASE); g_sw_pub.ac_in[PUB_AC_U01] = (qs16)(pSet->dU_drive_u0*Q16_BASE); g_sw[sw].ac_in[SW_AC_IA] = (qs16)(pSet->dU_drive_i*Q16_BASE); g_sw[sw].ac_in[SW_AC_I0] = (qs16)(pSet->dU_drive_i0*Q16_BASE); #endif } #endif /****************************************************************************** 函数名称: sw_cal_protect 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 在保护5ms中断中计算基波的值。 参数说明: 返回值: 修改记录: */ void sw_cal_protect(void) { int sw, i, index; short *psam; qs08 angle; qs16 lncos, lnsin; struct ri_s16 ri16; struct ri_s16 ri16_2; struct ri_s32 ri; struct ri_s32 ri_2[2]; // 更新保护计算时采样点的索引 g_prot_index = g_adc_dots_index; extern DWORD dTcounterrem; dTcounterrem = dTCounter; // 计算模值平方 for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO) { continue; } // 检查硬件通道是否正常,如果不正常,ri清零;否则计算出ri。 if (equ_ac_channel_is_ok(g_ui[i].chn_index) == 0) { ri16.r = 0; ri16.i = 0; ri16_2.r = 0; ri16_2.i = 0; } else { psam = adc_fourier_address(g_ui[i].chn_index, g_prot_index); // 基波FFT fourier32(psam, &ri16, FOURIER_HARMONIC_1); // 二次谐波FFT if (i >= PUB_AC_NUM) { fourier32(psam, &ri16_2, FOURIER_HARMONIC_2); } } // 基波计算 ri.r = _MulFac_S(ri16.r, g_ui[i].m2_factor_c); // 电压电流实部 ri.i = _MulFac_S(ri16.i, g_ui[i].m2_factor_c); // 电压电流虚部 angle = rt_round((g_ui[i].p_factor + factor_p_k(g_ui[i].chn_index)) * 256); lncos = mCos(angle); lnsin = mSin(angle); g_ui[i].ri.r = _MulFac_S(ri.r, lncos) - _MulFac_S(ri.i, lnsin); g_ui[i].ri.i = _MulFac_S(ri.r, lnsin) + _MulFac_S(ri.i, lncos); g_ui[i].m2[0] = SQR(g_ui[i].ri.r, g_ui[i].ri.i); // 电压电流平方和 rt_stat_in(&g_ui[i].m2_stat, g_ui[i].m2[0]); // 二次谐波计算 if (i >= PUB_AC_NUM) { ri_2[0].r = _MulFac_S(ri16_2.r, g_ui[i].m2_factor_c); // 电压电流实部 ri_2[0].i = _MulFac_S(ri16_2.i, g_ui[i].m2_factor_c); // 电压电流虚部 #if 0 angle = rt_round(g_ui[i].p_factor*256); lncos = mCos(angle); lnsin = mSin(angle); #endif ri_2[1].r = _MulFac_S(ri_2[0].r, lncos) - _MulFac_S(ri_2[0].i, lnsin); ri_2[1].i = _MulFac_S(ri_2[0].r, lnsin) + _MulFac_S(ri_2[0].i, lncos); g_ui[i].m2[1] = SQR(ri_2[1].r, ri_2[1].i); // 电压电流平方和 } } #ifdef GD_AREA_ECZD_2020 // 计算正序和负序电压 // US1 if ((g_ui[PUB_AC_UA1].chn_index != CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UB1].chn_index != CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UC1].chn_index != CFG_ADC_CHANNEL_ZERO)) { _sw_cal_Xfl120(PUB_AC_UA1, &Us1_120); } else { Us2_120.vect1 = 0; Us2_120.vect2 = 0; } // US2 if ((g_ui[PUB_AC_UA2].chn_index != CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UB2].chn_index != CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UC2].chn_index != CFG_ADC_CHANNEL_ZERO)) { _sw_cal_Xfl120(PUB_AC_UA2, &Us2_120); } else { Us2_120.vect1 = 0; Us2_120.vect2 = 0; } #endif // 合成线电压1 if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_LV1) { g_ui[PUB_AC_UAB1].ri.r = g_ui[PUB_AC_UA1].ri.r - g_ui[PUB_AC_UB1].ri.r; g_ui[PUB_AC_UAB1].ri.i = g_ui[PUB_AC_UA1].ri.i - g_ui[PUB_AC_UB1].ri.i; g_ui[PUB_AC_UAB1].m2[0] = SQR(g_ui[PUB_AC_UAB1].ri.r, g_ui[PUB_AC_UAB1].ri.i); rt_stat_in(&g_ui[PUB_AC_UAB1].m2_stat, g_ui[PUB_AC_UAB1].m2[0]); g_ui[PUB_AC_UBC1].ri.r = g_ui[PUB_AC_UB1].ri.r - g_ui[PUB_AC_UC1].ri.r; g_ui[PUB_AC_UBC1].ri.i = g_ui[PUB_AC_UB1].ri.i - g_ui[PUB_AC_UC1].ri.i; g_ui[PUB_AC_UBC1].m2[0] = SQR(g_ui[PUB_AC_UBC1].ri.r, g_ui[PUB_AC_UBC1].ri.i); rt_stat_in(&g_ui[PUB_AC_UBC1].m2_stat, g_ui[PUB_AC_UBC1].m2[0]); g_ui[PUB_AC_UCA1].ri.r = g_ui[PUB_AC_UC1].ri.r - g_ui[PUB_AC_UA1].ri.r; g_ui[PUB_AC_UCA1].ri.i = g_ui[PUB_AC_UC1].ri.i - g_ui[PUB_AC_UA1].ri.i; g_ui[PUB_AC_UCA1].m2[0] = SQR(g_ui[PUB_AC_UCA1].ri.r, g_ui[PUB_AC_UCA1].ri.i); rt_stat_in(&g_ui[PUB_AC_UCA1].m2_stat, g_ui[PUB_AC_UCA1].m2[0]); } // 合成线电压2 if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_LV2) { g_ui[PUB_AC_UAB2].ri.r = g_ui[PUB_AC_UA2].ri.r - g_ui[PUB_AC_UB2].ri.r; g_ui[PUB_AC_UAB2].ri.i = g_ui[PUB_AC_UA2].ri.i - g_ui[PUB_AC_UB2].ri.i; g_ui[PUB_AC_UAB2].m2[0] = SQR(g_ui[PUB_AC_UAB2].ri.r, g_ui[PUB_AC_UAB2].ri.i); rt_stat_in(&g_ui[PUB_AC_UAB2].m2_stat, g_ui[PUB_AC_UAB2].m2[0]); g_ui[PUB_AC_UBC2].ri.r = g_ui[PUB_AC_UB2].ri.r - g_ui[PUB_AC_UC2].ri.r; g_ui[PUB_AC_UBC2].ri.i = g_ui[PUB_AC_UB2].ri.i - g_ui[PUB_AC_UC2].ri.i; g_ui[PUB_AC_UBC2].m2[0] = SQR(g_ui[PUB_AC_UBC2].ri.r, g_ui[PUB_AC_UBC2].ri.i); rt_stat_in(&g_ui[PUB_AC_UBC2].m2_stat, g_ui[PUB_AC_UBC2].m2[0]); g_ui[PUB_AC_UCA2].ri.r = g_ui[PUB_AC_UC2].ri.r - g_ui[PUB_AC_UA2].ri.r; g_ui[PUB_AC_UCA2].ri.i = g_ui[PUB_AC_UC2].ri.i - g_ui[PUB_AC_UA2].ri.i; g_ui[PUB_AC_UCA2].m2[0] = SQR(g_ui[PUB_AC_UCA2].ri.r, g_ui[PUB_AC_UCA2].ri.i); rt_stat_in(&g_ui[PUB_AC_UCA2].m2_stat, g_ui[PUB_AC_UCA2].m2[0]); } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_UCA1) // 合成线电压UCA1 { g_ui[PUB_AC_UCA1].ri.r = -g_ui[PUB_AC_UAB1].ri.r - g_ui[PUB_AC_UBC1].ri.r; g_ui[PUB_AC_UCA1].ri.i = -g_ui[PUB_AC_UAB1].ri.i - g_ui[PUB_AC_UBC1].ri.i; g_ui[PUB_AC_UCA1].m2[0] = SQR(g_ui[PUB_AC_UCA1].ri.r, g_ui[PUB_AC_UCA1].ri.i); rt_stat_in(&g_ui[PUB_AC_UCA1].m2_stat, g_ui[PUB_AC_UCA1].m2[0]); } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_UCA2) // 合成线电压UCA1 { g_ui[PUB_AC_UCA2].ri.r = -g_ui[PUB_AC_UAB2].ri.r - g_ui[PUB_AC_UBC2].ri.r; g_ui[PUB_AC_UCA2].ri.i = -g_ui[PUB_AC_UAB2].ri.i - g_ui[PUB_AC_UBC2].ri.i; g_ui[PUB_AC_UCA2].m2[0] = SQR(g_ui[PUB_AC_UCA2].ri.r, g_ui[PUB_AC_UCA2].ri.i); rt_stat_in(&g_ui[PUB_AC_UCA1].m2_stat, g_ui[PUB_AC_UCA2].m2[0]); } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_U01) { g_ui[PUB_AC_U01].ri.r = g_ui[PUB_AC_UA1].ri.r + g_ui[PUB_AC_UB1].ri.r + g_ui[PUB_AC_UC1].ri.r; g_ui[PUB_AC_U01].ri.i = g_ui[PUB_AC_UA1].ri.i + g_ui[PUB_AC_UB1].ri.i + g_ui[PUB_AC_UC1].ri.i; g_ui[PUB_AC_U01].m2[0] = SQR(g_ui[PUB_AC_U01].ri.r, g_ui[PUB_AC_U01].ri.i); rt_stat_in(&g_ui[PUB_AC_U01].m2_stat, g_ui[PUB_AC_U01].m2[0]); } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_U02) { g_ui[PUB_AC_U02].ri.r = g_ui[PUB_AC_UA2].ri.r + g_ui[PUB_AC_UB2].ri.r + g_ui[PUB_AC_UC2].ri.r; g_ui[PUB_AC_U02].ri.i = g_ui[PUB_AC_UA2].ri.i + g_ui[PUB_AC_UB2].ri.i + g_ui[PUB_AC_UC2].ri.i; g_ui[PUB_AC_U02].m2[0] = SQR(g_ui[PUB_AC_U02].ri.r, g_ui[PUB_AC_U02].ri.i); rt_stat_in(&g_ui[PUB_AC_U02].m2_stat, g_ui[PUB_AC_U02].m2[0]); } // 合成电流 for (sw = 0; sw < g_sw_num; sw++) { // IB if (g_sw[sw].ui_flags & UI_FLAGS_MAKE_IB) { index = UI_SW_INDEX(sw, SW_AC_IB); g_ui[index].ri.r = -g_ui[UI_SW_INDEX(sw, SW_AC_IA)].ri.r - g_ui[UI_SW_INDEX(sw, SW_AC_IC)].ri.r; g_ui[index].ri.i = -g_ui[UI_SW_INDEX(sw, SW_AC_IA)].ri.i - g_ui[UI_SW_INDEX(sw, SW_AC_IC)].ri.i; g_ui[index].m2[0] = SQR(g_ui[index].ri.r, g_ui[index].ri.i); rt_stat_in(&g_ui[index].m2_stat, g_ui[index].m2[0]); } // I0 if (g_sw[sw].ui_flags & UI_FLAGS_MAKE_I0) { index = UI_SW_INDEX(sw, SW_AC_I0); g_ui[index].ri.r = g_ui[UI_SW_INDEX(sw, SW_AC_IA)].ri.r + g_ui[UI_SW_INDEX(sw, SW_AC_IB)].ri.r + g_ui[UI_SW_INDEX(sw, SW_AC_IC)].ri.r; g_ui[index].ri.i = g_ui[UI_SW_INDEX(sw, SW_AC_IA)].ri.i + g_ui[UI_SW_INDEX(sw, SW_AC_IB)].ri.i + g_ui[UI_SW_INDEX(sw, SW_AC_IC)].ri.i; g_ui[index].m2[0] = SQR(g_ui[index].ri.r, g_ui[index].ri.i); rt_stat_in(&g_ui[index].m2_stat, g_ui[index].m2[0]); } #ifdef FUN_JDXX // 计算零序有功无功 if (pRunSet->tSwSet[sw].bTT_Power_v2 == 0) { if (g_ui[PUB_AC_U01].chn_index != CFG_ADC_CHANNEL_ZERO) { if (g_ui[UI_SW_INDEX(sw, SW_AC_I0)].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_p0[sw].p = _sw_p2(g_ui[PUB_AC_U01].ri.r, g_ui[PUB_AC_U01].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.i, g_ui[PUB_AC_U01].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].e_factor); g_ui_p0[sw].q = _sw_q2(g_ui[PUB_AC_U01].ri.r, g_ui[PUB_AC_U01].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.i, g_ui[PUB_AC_U01].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].e_factor); } if (g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_p0[sw].ps = _sw_p2(g_ui[PUB_AC_U01].ri.r, g_ui[PUB_AC_U01].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.i, g_ui[PUB_AC_U01].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].e_factor); g_ui_p0[sw].qs = _sw_q2(g_ui[PUB_AC_U01].ri.r, g_ui[PUB_AC_U01].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.i, g_ui[PUB_AC_U01].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].e_factor); } } else { g_ui_p0[sw].p = 0; g_ui_p0[sw].q = 0; g_ui_p0[sw].ps = 0; g_ui_p0[sw].qs = 0; } } else { if (g_ui[PUB_AC_U02].chn_index != CFG_ADC_CHANNEL_ZERO) { if (g_ui[UI_SW_INDEX(sw, SW_AC_I0)].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_p0[sw].p = _sw_p2(g_ui[PUB_AC_U02].ri.r, g_ui[PUB_AC_U02].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.i, g_ui[PUB_AC_U02].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].e_factor); g_ui_p0[sw].q = _sw_q2(g_ui[PUB_AC_U02].ri.r, g_ui[PUB_AC_U02].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].ri.i, g_ui[PUB_AC_U02].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0)].e_factor); } if (g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui_p0[sw].ps = _sw_p2(g_ui[PUB_AC_U02].ri.r, g_ui[PUB_AC_U02].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.i, g_ui[PUB_AC_U02].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].e_factor); g_ui_p0[sw].qs = _sw_q2(g_ui[PUB_AC_U02].ri.r, g_ui[PUB_AC_U02].ri.i, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.r, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].ri.i, g_ui[PUB_AC_U02].e_factor, g_ui[UI_SW_INDEX(sw, SW_AC_I0s)].e_factor); } } else { g_ui_p0[sw].p = 0; g_ui_p0[sw].q = 0; g_ui_p0[sw].ps = 0; g_ui_p0[sw].qs = 0; } } #endif } // 仅线电压需计算幅值 for (i = PUB_AC_UA1; i < PUB_AC_NUM; i++) { g_ui[i].fz = _AmXY(g_ui[i].ri.r, g_ui[i].ri.i); } #ifdef FUNC_DRIVE_JY drive_ui_proc(); #endif // 计算最大最小值 _sw_min_max(PUB_AC_UA1, &g_sw_pub.m2_min[0], &g_sw_pub.m2_max[0]); _sw_min_max(PUB_AC_UAB1, &g_sw_pub.m2_min[2], &g_sw_pub.m2_max[2]); _sw_min_max(PUB_AC_UAB2, &g_sw_pub.m2_min[3], &g_sw_pub.m2_max[3]); _fz_min_max(PUB_AC_UAB1, PUB_AC_UCA1, &g_sw_pub.fz_min[0], &g_sw_pub.fz_max[0]); _fz_min_max(PUB_AC_UAB2, PUB_AC_UCA2, &g_sw_pub.fz_min[1], &g_sw_pub.fz_max[1]); for (sw = 0; sw < g_sw_num; sw++) { for (i = UI_SW_INDEX(sw, SW_AC_IA); i <= UI_SW_INDEX(sw, SW_AC_IC); i++) { g_ui[i].fz = _AmXY(g_ui[i].ri.r, g_ui[i].ri.i); } _sw_min_max(UI_SW_INDEX_BEGIN(sw), &g_sw[sw].m2_min, &g_sw[sw].m2_max); _fz_min_max(UI_SW_INDEX(sw, SW_AC_IA), UI_SW_INDEX(sw, SW_AC_IC), &g_sw[sw].fz_min, &g_sw[sw].fz_max); } return; } /****************************************************************************** 函数名称: sw_cal_app 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 在测量线程中计算测量值 参数说明: 返回值: 修改记录: */ void _sw_cal_zl(void); int sw_cal_app(void) { _sw_temp_factor(); if (_sw_cal_mea() != 0) { return 0; } // 如果没有达到累计次数,直接返回。 g_mea_cnt++; if (g_mea_cnt < MEA_CAL_NUMBER) { return 0; } g_mea_cnt = 0; _sw_cal_average(MEA_CAL_NUMBER); return 0; } void sw_factor_cp(void) // 保存校正的系数,根据第一路电流的配置,是按CT默认100A校正还是51欧校正 { bool b100A = false; bool b50A = false; bool b20A = false; bool b10A = false; int i; for (i = 0; i < g_equ_config->ac_num; i++) { if (g_equ_config_ac[i].owner == 1 && g_equ_config_ac[i].type == (SW_AC_IA + 1)) // 根据开关1 IA的配置,保存相关的参数 { if (g_equ_config_ac[i].scale == EQU_SCALE_CT_DEFAULT) { b100A = true; } if (g_equ_config_ac[i].scale == EQU_SCALE_CT_10A_51) { b50A = true; } if (g_equ_config_ac[i].scale == EQU_SCALE_CT_10A_249) { b20A = true; } if (g_equ_config_ac[i].scale == EQU_SCALE_CT_10A_120) { b10A = true; } if (b100A) { rt_file_cp("/app/data/acfactor.bin", "/app/data/acfactor_100A.bin"); } if (b50A) { rt_file_cp("/app/data/acfactor.bin", "/app/data/acfactor_50A.bin"); } if (b20A) { rt_file_cp("/app/data/acfactor.bin", "/app/data/acfactor_20A.bin"); } if (b10A) { rt_file_cp("/app/data/acfactor.bin", "/app/data/acfactor_10A.bin"); } return; } } } /****************************************************************************** 函数名称: sw_auto_adjust 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 自动校准程序 U 100V,I 5A, 参数说明: 返回值: 0: 成功 其它: 失败 修改记录: */ struct pq_factor { int cfg_index; float pq[2]; }; struct pq_factor g_pq_factor[SWITCH_NUM_MAX][3]; int sw_auto_adjust(int ui_angle0) { float baseAng; int ret, i, j, sw; int cfg_index; float factor; float fv; float minfv, maxfv; float baseValue; u16 base_v = 0, base_i = 0; #ifdef PROTECT_AC_ADJUST float fv_p; #endif g_mea_cnt = 0; // 如果是单板测试,可能需要使用PUB_AC_UA2作为角度0参考 if (ui_angle0 != -1) { g_ui_angle0 = ui_angle0; } // 测量值复位 g_factor_version = ACFACTOR_FILE_VERSION; for (i = 0; i < UI_NUM; i++) { if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO) { continue; } g_ui[i].e_acc = 0; g_ui[i].e = 0; g_ui[i].p_acc = 0; g_ui[i].p = 0; g_ui[i].p_mark = 0; g_ui[i].e_factor = 1.0 / _sw_ui_e_k(i); g_ui[i].p_factor = 0; } for (sw = 0; sw < g_sw_num; sw++) { for (j = 0; j < 3; j++) { g_pq_factor[sw][j].cfg_index = -1; g_pq_factor[sw][j].pq[0] = 0; g_pq_factor[sw][j].pq[1] = 0; } } sw_stat_reset(); // 测量AUTO_ADJUST_NUM次 for (i = 0; i < AUTO_ADJUST_NUM; i++) // 计算多次幅值 { watchdog_feed_mainloop(); // 得到采样点 _sw_get_dots(); // fft _sw_cal_fft(); _sw_cal_ri_correct(); // 计算有效值 _sw_cal_effect(); // 计算角度 _sw_cal_angle(); // 延时20ms,并喂狗 #ifdef CPU_FUXI msleep(30); #else ustimer_delay(20 * USTIMER_MS); #endif watchdog_feed_mainloop(); } _sw_cal_average(AUTO_ADJUST_NUM); #if 0 // def PROTECT_AC_ADJUST factor_restore_default(); ustimer_delay(20*USTIMER_MS); #endif for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO) { continue; } fv = (float)g_ui[i].e / Q16_BASE; #ifdef PROTECT_AC_ADJUST fv_p = (float)_Mul_Div_U(sqrt_32fix(g_ui[i].m2[0]), 256, g_ui[i].m2_factor_k) / (float)Q16_BASE; #endif // 确定通道配置索引和基本值 if (i < PUB_AC_NUM) { cfg_index = g_sw_pub.ac_cfg_index[i]; // if(g_equ_config_ac[cfg_index].scale == EQU_SCALE_EVT_3V25_100V) //{ // 电子式相电压 // baseValue = 57.735; //} /* else if(g_equ_config_ac[cfg_index].scale == EQU_SCALE_EVT_6V50_100V) { // 电子式零序电压,为了校验方便,使用C相电压,换算零序为此值。 baseValue = 28.86751346; } */ // 自适应电压校准 if (fv > 200) // 220 { // 220V额定电压 baseValue = 220; // } else if (fv > (120.0 * 1.732)) // 207.84 { // 130V相电压合成线电压校准 // 因为罩式控制器在用100V校准时,PT切换不断的响, // 130V相电压可得到225V电源,可避免PT切换的异响 baseValue = 130 * 1.732; // 225.16 } else if (fv > 90 * 1.732) // 155.88 { // 100V相电压合成线电压校准 baseValue = 100 * 1.732; // 173.2 } else if (fv > 120.0) // 120 { // 130V 相电压校准 baseValue = 130; // 130 } else if (fv > 90.0) { // 100V 相电压校准 baseValue = 100; // 100 } else if (fv > 50.0) { // 100V 相电压校准 baseValue = 57.735; // 57.735 } else if (fv > 16.0) { // 100V 相电压校准 baseValue = 20; // 20 } else if (fv > 8.0) { // 10V 相电压校准 baseValue = 10; // 10 } else if (fv > 6.0) { baseValue = 6.5; } else if (fv > 2.0) { // 10V 相电压校准 baseValue = 3; // 10 } else if (fv > 1.5) { baseValue = 1.8763875; } else { // 57.735V 相电压校准 baseValue = 57.735; // 57.735 } } else { sw = (i - PUB_AC_NUM) / SW_AC_NUM; j = (i - PUB_AC_NUM) % SW_AC_NUM; cfg_index = g_sw[sw].ac_cfg_index[j]; // 电子式互感器I0使用5A校准 // if(g_equ_config_ac[cfg_index].scale == EQU_SCALE_ECT_1V_1A // || g_equ_config_ac[cfg_index].scale == EQU_SCALE_ECT_0V2_1A) if (g_equ_config_ac[cfg_index].scale == EQU_SCALE_ECT_1V_1A) { // 电子式CT使用1A。 baseValue = 1; } else if (g_equ_config_ac[cfg_index].scale == EQU_SCALE_CT_10A_249) { // 高精度零序电流互感器,小信号校正值 baseValue = 0.5; } else if (fv > 4) { baseValue = 5; } else if (fv > 2) { // 大容量校准时,例如16回路,标准源可能带不动5A负载。 baseValue = 3; } else { baseValue = 1; } } minfv = baseValue * 0.9; maxfv = baseValue * 1.1; // 检查幅值是否超范围 if (fv < minfv) { rt_printf("sw_auto_adjust(invalid):i=%d,fv=%f,minfv=%f\r\n", i, fv, minfv); continue; } else if (fv > maxfv) { rt_printf("sw_auto_adjust(err):i=%d,fv=%f,maxfv=%f\r\n", i, fv, maxfv); return -1; } // 得到并检查校正系数 factor = baseValue / fv; if (CheckFloatSet(&factor, MAX_FACTOR, MIN_FACTOR) > 0) { rt_printf("sw_auto_adjust(err):i=%d,fv=%f,factor=%f.\r\n", i, fv, factor); return -2; } // 保存校正系数 factor_e_c_set(g_equ_config_ac[cfg_index].slot, g_equ_config_ac[cfg_index].index, factor); #ifdef PROTECT_AC_ADJUST factor = baseValue / fv_p; rt_printf("fv_p=%f,baseValue=%f,factor=%f\r\n", fv_p, baseValue, factor); if (CheckFloatSet(&factor, MAX_FACTOR, MIN_FACTOR) > 0) { rt_printf("sw_auto_adjust(err) protect ac:i=%d,fv=%f,factor_p=%f.\r\n", i, fv, factor); return -2; } // 保存校正系数 factor_p_e_c_set(g_equ_config_ac[cfg_index].slot, g_equ_config_ac[cfg_index].index, factor); #endif // 保存校正成功配置通道值 if (i >= PUB_AC_NUM) { g_pq_factor[sw][j].cfg_index = cfg_index; } // 角度校准 baseAng = _sw_base_angle(i); fv = (float)g_ui[i].p / Q16_BASE; if (baseAng == 360.0) { factor = 0; } else { factor = baseAng - fv; } // 确保角度在正负180内。 if (factor > 180.0) { factor -= 360.0; } if (factor < -180.0) { factor += 360.0; } rt_printf("sw_auto_adjust(ang):i=%d,fv=%f,factor=%f.\r\n", i, fv, factor); if (factor < MIN_PHASE) { return -3; } else if (factor > MAX_PHASE) { return -4; } if (CheckFloatSet(&factor, MAX_PHASE, MIN_PHASE) > 0) { return -5; } // 如果是基准通道,就不更新角度校准值。 if (i != g_ui_angle0) { factor_p_c_set(g_equ_config_ac[cfg_index].slot, g_equ_config_ac[cfg_index].index, factor); } #if defined TMP_CHIP_AHT20 // 保存校正温度和基准值 factor_temp_set(g_equ_config_ac[cfg_index].slot, #if defined TMP_CHIP_AHT20 aht20_get_temp() #endif ); #endif if (i < PUB_AC_NUM) { base_v = baseValue; } else { base_i = baseValue; } } // 重新初始化 sw_init(); // 保存校正系数 ret = factor_write_all(base_v, base_i); if (ret != 0) { return -6; } sw_factor_cp(); soe_record_opt(EV_CHNZJS, 0); return 0; } float g_dc_factor[2][2] = { {1.0, 1.0}, {1.0, 1.0}, }; int sw_adjust_dc_0(void) { int i; float dc; for (i = 0; i < pRunSet->dDc_num; i++) { dc = dc_get(i); if (dc < 0.5 * dc_adjust[0]) { return -1; } if (dc > 1.5 * dc_adjust[0]) { return -2; } g_dc_factor[i][0] = dc; } return 0; } int sw_adjust_dc_1(void) { int i; float dc; for (i = 0; i < pRunSet->dDc_num; i++) { dc = dc_get(i); if (dc < 0.5 * dc_adjust[1]) { return -1; } if (dc > 1.5 * dc_adjust[1]) { return -2; } g_dc_factor[i][1] = dc; } _sw_save_dc_factor(g_dc_factor[0][1], g_dc_factor[0][0], g_dc_factor[1][1], g_dc_factor[1][0]); return 0; } /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /****************************************************************************** 函数名称: _sw_get_dots 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 获取采样点,供测量计算用 参数说明: 返回值: 修改记录: */ void xdl_smooth3(short in[], short out[], int N); void xdl_smooth5(short in[], short out[], int N); int _sw_check_tb_dots(unsigned long dot_index) { int i, j; if (pRunSet->dSmoothZero == 0) return 0; for (i = 0; i < CFG_ADC_CHANNEL; i++) { short pnSam[3] = {0}; long laaa; DWORD daaa; int caulp; if (!g_equ_adc_config[i]) // 通道无配置 { continue; } for (j = 0; j < CFG_ADC_DOTS_PER_PERIOD; j++) { caulp = (dot_index + j) & CFG_ADC_DOTS_MASK; // 取出连续三周波的同一对应点 pnSam[0] = g_adc_dots[i][(caulp - 1) & SAMLENGTH]; pnSam[1] = g_adc_dots[i][(caulp - SAMFREQ - 1) & SAMLENGTH]; pnSam[2] = g_adc_dots[i][(caulp - 2 * SAMFREQ - 1) & SAMLENGTH]; // 计算突变量并取绝对值,i(k)-2*i(k-N)+i(K-2N) laaa = (pnSam[0] - pnSam[1] * 2 + pnSam[2]); if (laaa < 0) { daaa = -laaa; // } else { daaa = laaa; } // 检查是否超过突变量门槛,且需满足3次,即对应相电流突变量满足要求 if (daaa > pRunSet->dSmoothZero) { rt_printf("\r\n chnel=%d zero=%d set=%d", i, daaa, pRunSet->dSmoothZero); return -1; } } } return 0; } void _sw_get_dots(void) { unsigned long i, loop, dots_index, dots_count_old; int cnt; int ret = 0; loop = 0; do { // 获取采样点的位置,如果最后一个周波跨界,调整采样点的位置。 #ifdef CPU_FUXI dots_count_old = g_adc_dots_index - CFG_ADC_DOTS_PER_PERIOD; // jack.liu 20200921 获取最后一个周波的采样点 #else dots_count_old = g_adc_dots_count - CFG_ADC_DOTS_PER_PERIOD; // 最后一个周波的采样点 #endif cnt = (dots_count_old & CFG_ADC_DOTS_MASK) - (CFG_ADC_DOTS_PER_CHANNEL - CFG_ADC_DOTS_PER_PERIOD); if (cnt > 0) { dots_count_old -= cnt; } dots_index = dots_count_old & CFG_ADC_DOTS_MASK; ret = _sw_check_tb_dots(dots_index); if (ret < 0) return; // 波形判断有突变,不处理采样 for (i = 0; i < CFG_ADC_CHANNEL; i++) { #if 0 if(g_equ_adc_config[i]) { xdl_smooth3(&g_adc_dots[i][dots_index],&g_adc_dots[i][CFG_ADC_DOTS_PER_CHANNEL],CFG_ADC_DOTS_PER_PERIOD); } #else memcpy(&g_adc_dots[i][CFG_ADC_DOTS_PER_CHANNEL], &g_adc_dots[i][dots_index], CFG_ADC_DOTS_PER_PERIOD * 2); #endif } loop++; if (loop > 5) { rt_printf("sw_get_dots:i=%d\r\n", loop); } } #ifdef CPU_FUXI while ((g_adc_dots_index - dots_count_old) > CFG_ADC_DOTS_PER_CHANNEL); #else while ((g_adc_dots_count - dots_count_old) > CFG_ADC_DOTS_PER_CHANNEL); #endif } /****************************************************************************** 函数名称: _sw_fft 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 计算FFT,一次计算两个通道 参数说明: ch0 通道0索引 ch1 通道1索引 p0 通道0结果,所有谐波的复数表示。 p1 通道1结果,所有谐波的复数表示。 返回值: 修改记录: */ void _sw_fft(int ch0, int ch1, complex *p0, complex *p1) { static complex k[CFG_ADC_DOTS_PER_PERIOD]; int i; // 初始化点 for (i = 0; i < CFG_ADC_DOTS_PER_PERIOD; i++) { k[i].r = g_adc_dots[ch0][CFG_ADC_DOTS_PER_CHANNEL + i]; k[i].i = g_adc_dots[ch1][CFG_ADC_DOTS_PER_CHANNEL + i]; } // 计算 fft(CFG_ADC_DOTS_PER_PERIOD, &k[0]); // 整理 for (i = 1; i <= g_harmonic_num; i++) { if (p0) { p0[i].r = (k[i].r + k[CFG_ADC_DOTS_PER_PERIOD - i].r) / CFG_ADC_DOTS_PER_PERIOD; p0[i].i = (k[i].i - k[CFG_ADC_DOTS_PER_PERIOD - i].i) / CFG_ADC_DOTS_PER_PERIOD; } if (p1) { p1[i].r = (k[i].i + k[CFG_ADC_DOTS_PER_PERIOD - i].i) / CFG_ADC_DOTS_PER_PERIOD; p1[i].i = (k[CFG_ADC_DOTS_PER_PERIOD - i].r - k[i].r) / CFG_ADC_DOTS_PER_PERIOD; } } } /****************************************************************************** 函数名称: _sw_cal_fft 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 计算所有通道的FFT 参数说明: 返回值: 修改记录: */ void _sw_cal_fft(void) { s32 i, index0; // fft index0 = UI_NUM; for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO) { continue; } // 检查硬件通道是否正常,如果不正常,ri清零;否则计算出ri。 if (equ_ac_channel_is_ok(g_ui[i].chn_index) == 0) { memset(&g_ui[i].h, 0, sizeof(g_ui[i].h)); continue; } if (index0 == UI_NUM) { index0 = i; } else { _sw_fft(g_ui[index0].chn_index, g_ui[i].chn_index, g_ui[index0].h, g_ui[i].h); index0 = UI_NUM; } } if (index0 != UI_NUM) { _sw_fft(g_ui[index0].chn_index, g_ui[index0].chn_index, g_ui[index0].h, NULL); } return; } /****************************************************************************** 函数名称: _sw_cal_h_sub 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 2个谐波向量减 参数说明: r 结果 a 向量a的g_ui索引 b 向量b的g_ui索引 返回值: 修改记录: */ void _sw_cal_h_sub(int r, int a, int b) { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[r].h[i].r = g_ui[a].h[i].r - g_ui[b].h[i].r; g_ui[r].h[i].i = g_ui[a].h[i].i - g_ui[b].h[i].i; } return; } /****************************************************************************** 函数名称: _sw_cal_h_sub2 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 谐波向量减,求Ib 参数说明: r 结果 o 向量o的g_ui索引 a 向量a的g_ui索引 b 向量b的g_ui索引 返回值: 修改记录: */ void _sw_cal_h_sub2(int r, int o, int a, int b) { int i; float factor_i0_ia = 1.0; if ((g_ui[o].m2_factor_k != 0) && (g_ui[o].m2_factor_k != g_ui[a].m2_factor_k)) { factor_i0_ia = (float)g_ui[a].m2_factor_k / g_ui[o].m2_factor_k; } for (i = 1; i <= g_harmonic_num; i++) { g_ui[r].h[i].r = g_ui[o].h[i].r * factor_i0_ia - g_ui[a].h[i].r - g_ui[b].h[i].r; g_ui[r].h[i].i = g_ui[o].h[i].i * factor_i0_ia - g_ui[a].h[i].i - g_ui[b].h[i].i; } return; } /****************************************************************************** 函数名称: _sw_cal_h_add 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 3个谐波向量加 参数说明: r 结果 a 向量a的g_ui索引 b 向量b的g_ui索引 c 向量c的g_ui索引 返回值: 修改记录: */ void _sw_cal_h_add(int r, int a, int b, int c) { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[r].h[i].r = g_ui[a].h[i].r + g_ui[b].h[i].r + g_ui[c].h[i].r; g_ui[r].h[i].i = g_ui[a].h[i].i + g_ui[b].h[i].i + g_ui[c].h[i].i; } return; } /****************************************************************************** 函数名称: _sw_cal_ri_correct 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 根据角度误差校正向量值 参数说明: 返回值: 修改记录: */ void _sw_cal_ri_correct(void) { s32 i, j; qs08 angle; qs16 lncos, lnsin, v; struct ri_s32 ri; for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO) { continue; } // 根据频率修正角度校正值,提高频率变化时的功率精度。 angle = rt_round((g_ui[i].p_factor + factor_p_k(g_ui[i].chn_index)) * 256); for (j = 1; j <= g_harmonic_num; j++) { lncos = mCos(angle * j); lnsin = mSin(angle * j); ri.r = rt_round(g_ui[i].h[j].r * Q16_BASE); ri.i = rt_round(g_ui[i].h[j].i * Q16_BASE); v = _MulFac_S(ri.r, lncos) - _MulFac_S(ri.i, lnsin); g_ui[i].h[j].r = (float)v / Q16_BASE; v = _MulFac_S(ri.r, lnsin) + _MulFac_S(ri.i, lncos); g_ui[i].h[j].i = (float)v / Q16_BASE; } } } /****************************************************************************** 函数名称: _sw_cal_unbalance 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 不平衡度计算 参数说明: 返回值: 修改记录: */ #ifdef asdfadasdfa void CalcuIx120(struct UI *pI, struct UI120 *pII) { long labc, lbc; labc = pI->lIaR - ((pI->lIbR + pI->lIcR) >> 1); lbc = pI->lIbI - pI->lIcI; lbc = _MulFac_S(lbc, 56756); //(1.732/2)*2^16=56756 pII->l1Cos = labc - lbc; pII->l2Cos = labc + lbc; labc = pI->lIaI - ((pI->lIbI + pI->lIcI) >> 1); lbc = pI->lIbR - pI->lIcR; lbc = _MulFac_S(lbc, 56756); //(1.732/2)*2^16=56756 pII->l1Sin = labc + lbc; pII->l2Sin = labc - lbc; pII->l0Cos = pI->lIaR + pI->lIbR + pI->lIcR; pII->l0Sin = pI->lIaI + pI->lIbI + pI->lIcI; pII->d1Modu = SQR(pII->l1Cos, pII->l1Sin); pII->d2Modu = SQR(pII->l2Cos, pII->l2Sin); pII->d0Modu = SQR(pII->l0Cos, pII->l0Sin); } #endif float _sw_cal_unbalance(int ui_index) { float abc, bc; float r1, r2, i1, i2; abc = g_ui[ui_index].h[1].r - (g_ui[ui_index + 1].h[1].r + g_ui[ui_index + 2].h[1].r) / 2; bc = g_ui[ui_index + 1].h[1].i - g_ui[ui_index + 2].h[1].i; bc = bc * (1.7320508 / 2); r1 = abc - bc; r2 = abc + bc; abc = g_ui[ui_index].h[1].i - (g_ui[ui_index + 1].h[1].i + g_ui[ui_index + 2].h[1].i) / 2; bc = g_ui[ui_index + 1].h[1].r - g_ui[ui_index + 2].h[1].r; bc = bc * (1.7320508 / 2); i1 = abc + bc; i2 = abc - bc; abc = sqrtf(r1 * r1 + i1 * i1); bc = sqrtf(r2 * r2 + i2 * i2); // rt_printf("%s\tabc=%f,\tbc=%f.\r\n",g_ui[ui_index].name,abc*g_ui[ui_index].e_factor,bc*g_ui[ui_index].e_factor); if (abc == 0.0) { return 100; } return bc / abc * 100; } /****************************************************************************** 函数名称: _sw_cal_unbalance 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 正负序计算 参数说明: 返回值: 修改记录: */ void _sw_cal_Xfl120(int ui_index, struct ui120 *pII) { float abc, bc; float r1, r2, i1, i2; abc = g_ui[ui_index].ri.r - (g_ui[ui_index + 1].ri.r + g_ui[ui_index + 2].ri.r) / 2; bc = g_ui[ui_index + 1].ri.i - g_ui[ui_index + 2].ri.i; bc = bc * (1.7320508 / 2); r1 = abc - bc; r2 = abc + bc; abc = g_ui[ui_index].ri.i - (g_ui[ui_index + 1].ri.i + g_ui[ui_index + 2].ri.i) / 2; bc = g_ui[ui_index + 1].ri.r - g_ui[ui_index + 2].ri.r; bc = bc * (1.7320508 / 2); i1 = abc + bc; i2 = abc - bc; pII->vect1 = (r1 * r1 + i1 * i1) / 9; pII->vect2 = (r2 * r2 + i2 * i2) / 9; } /****************************************************************************** 函数名称: _sw_cal_make 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量合成通道向量值 参数说明: 返回值: 修改记录: */ void _sw_cal_make(void) { int sw; // 合成电压 if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_LV1) { _sw_cal_h_sub(PUB_AC_UAB1, PUB_AC_UA1, PUB_AC_UB1); _sw_cal_h_sub(PUB_AC_UBC1, PUB_AC_UB1, PUB_AC_UC1); _sw_cal_h_sub(PUB_AC_UCA1, PUB_AC_UC1, PUB_AC_UA1); } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_LV2) { _sw_cal_h_sub(PUB_AC_UAB2, PUB_AC_UA2, PUB_AC_UB2); _sw_cal_h_sub(PUB_AC_UBC2, PUB_AC_UB2, PUB_AC_UC2); _sw_cal_h_sub(PUB_AC_UCA2, PUB_AC_UC2, PUB_AC_UA2); } // 合成UCA if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_UCA1) { { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[PUB_AC_UCA1].h[i].r = -g_ui[PUB_AC_UAB1].h[i].r - g_ui[PUB_AC_UBC1].h[i].r; g_ui[PUB_AC_UCA1].h[i].i = -g_ui[PUB_AC_UAB1].h[i].i - g_ui[PUB_AC_UBC1].h[i].i; } } } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_UCA2) { { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[PUB_AC_UCA2].h[i].r = -g_ui[PUB_AC_UAB2].h[i].r - g_ui[PUB_AC_UBC2].h[i].r; g_ui[PUB_AC_UCA2].h[i].i = -g_ui[PUB_AC_UAB2].h[i].i - g_ui[PUB_AC_UBC2].h[i].i; } } } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_U01) { { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[PUB_AC_U01].h[i].r = g_ui[PUB_AC_UA1].h[i].r + g_ui[PUB_AC_UB1].h[i].r + g_ui[PUB_AC_UC1].h[i].r; g_ui[PUB_AC_U01].h[i].i = g_ui[PUB_AC_UA1].h[i].i + g_ui[PUB_AC_UB1].h[i].i + g_ui[PUB_AC_UC1].h[i].i; } } } if (g_sw_pub.ui_flags & UI_FLAGS_MAKE_U02) { { int i; for (i = 1; i <= g_harmonic_num; i++) { g_ui[PUB_AC_U02].h[i].r = g_ui[PUB_AC_UA2].h[i].r + g_ui[PUB_AC_UB2].h[i].r + g_ui[PUB_AC_UC2].h[i].r; g_ui[PUB_AC_U02].h[i].i = g_ui[PUB_AC_UA2].h[i].i + g_ui[PUB_AC_UB2].h[i].i + g_ui[PUB_AC_UC2].h[i].i; } } } // 电压不平衡计算 g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE1] += _sw_cal_unbalance(PUB_AC_UA1); g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE2] += _sw_cal_unbalance(PUB_AC_UA2); // 开关电流 for (sw = 0; sw < g_sw_num; sw++) { // 合成电流IB if (g_sw[sw].ui_flags & UI_FLAGS_MAKE_IB) { _sw_cal_h_sub2(UI_SW_INDEX(sw, SW_AC_IB), UI_SW_INDEX(sw, SW_AC_I0), UI_SW_INDEX(sw, SW_AC_IA), UI_SW_INDEX(sw, SW_AC_IC)); } // 合成电流IB if (g_sw[sw].ui_flags & UI_FLAGS_MAKE_CIB) { _sw_cal_h_sub2(UI_SW_INDEX(sw, SW_AC_CIB), UI_SW_INDEX(sw, SW_AC_I0), UI_SW_INDEX(sw, SW_AC_CIA), UI_SW_INDEX(sw, SW_AC_CIC)); } // 合成电流I0 if (g_sw[sw].ui_flags & UI_FLAGS_MAKE_I0) { _sw_cal_h_add(UI_SW_INDEX(sw, SW_AC_I0), UI_SW_INDEX(sw, SW_AC_IA), UI_SW_INDEX(sw, SW_AC_IB), UI_SW_INDEX(sw, SW_AC_IC)); } // 电流不平衡计算 g_sw[sw].ac_in_acc[SW_AC_IN_BI_UNBALANCE] += _sw_cal_unbalance(UI_SW_INDEX(sw, SW_AC_IA)); // 电流不平衡计算 g_sw[sw].ac_in_acc[SW_AC_IN_CI_UNBALANCE] += _sw_cal_unbalance(UI_SW_INDEX(sw, SW_AC_CIA)); } } /****************************************************************************** 函数名称: _sw_cal_effect 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算有效值,累加结果。 参数说明: 返回值: 修改记录: */ void _sw_cal_effect(void) { int i, j; float f, re, im, sum; for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[i].ui_base_make == -1) { continue; } sum = 0.0; for (j = 1; j <= g_harmonic_num; j++) { re = g_ui[i].h[j].r; im = g_ui[i].h[j].i; f = sqrtf(re * re + im * im); f *= g_harmonic_factor[j]; // 谐波系数修正 sum += f * f; #if 0 if(i>=UI_SW_INDEX(1,SW_AC_IA) && i<=UI_SW_INDEX(1,SW_AC_I0)) { rt_printf("%s[%02d]:e=%f,p=%f.\r\n",g_ui[i].name,j,f*g_ui[i].e_factor,_sw_cal_angle0(re,im)); } #endif } f = sqrtf(sum); g_ui[i].e_acc += f * g_ui[i].e_factor; } return; } /****************************************************************************** 函数名称: _sw_cal_angle0 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 计算向量角度 参数说明: re 向量实部 im 向量虚部 返回值: 修改记录: */ #if 1 float _sw_cal_angle0(float re, float im) { float p; p = atan2f(im, re); p = p * 180 / pi; return p; } #else const int Angle_const[7] = { 0, 267, 577, 1000, 1732, 3732, 57400}; float _sw_cal_angle0(float re, float im) { float angle_arttg; float angle = 0; uint8 quad; if (re >= 0) { if (im >= 0) quad = 1; else { quad = 4; im = im * (-1); } } else { re = re * (-1); if (im >= 0) quad = 2; else { im = im * (-1); quad = 3; } } if (re <= 2) { switch (quad) { case 1: angle = 90; break; case 2: angle = 90; break; case 3: angle = 270; break; case 4: angle = 270; break; } } else { angle_arttg = (im * 1000) / re; if (angle_arttg <= Angle_const[1]) { angle = 0 + (angle_arttg - Angle_const[0]) * 57 / (1000 + Angle_const[0] * angle_arttg / 1000); } else if (angle_arttg <= Angle_const[2]) { angle = 15 + (angle_arttg - Angle_const[1]) * 57 / (1000 + Angle_const[1] * angle_arttg / 1000); } else if (angle_arttg <= Angle_const[3]) { angle = 30 + (angle_arttg - Angle_const[2]) * 57 / (1000 + Angle_const[2] * angle_arttg / 1000); } else if (angle_arttg <= Angle_const[4]) { angle = 45 + (angle_arttg - Angle_const[3]) * 57 / (1000 + Angle_const[3] * angle_arttg / 1000); } else if (angle_arttg <= Angle_const[5]) { angle = 60 + (angle_arttg - Angle_const[4]) * 57 / (1000 + Angle_const[4] * angle_arttg / 1000); } else if (angle_arttg <= Angle_const[6]) { angle = 75 + (angle_arttg - Angle_const[5]) * 57 / (1000 + Angle_const[5] * angle_arttg / 1000); } else { angle = 90; } switch (quad) { case 1: angle = angle; break; case 2: angle = 180 - angle; break; case 3: angle = 180 + angle; break; case 4: angle = 360 - angle; break; } } if ((re < 5) && (im < 5)) angle = 0; return (angle); } #endif /****************************************************************************** 函数名称: _sw_cal_angle_correct 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算角度时对角度进行校正,保证累加时不会出现计算错误。 参数说明: 返回值: 修改记录: */ void _sw_cal_angle_correct(qs16 *angle, int *mark) { if (*angle > ANGF180) { *angle -= ANG360; } if (*angle < ANGN180) { *angle += ANG360; } if (*mark == 0) { if (abs(*angle) < 90 * Q16_BASE) { *mark = 1; } else { *mark = -1; } } if (*mark == -1) { if (*angle >= 0) { *angle = 180 * Q16_BASE - *angle; } else { *angle = (-180) * Q16_BASE - *angle; } } } /****************************************************************************** 函数名称: _sw_cal_angle 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算角度,每次调用累加计算值。 参数说明: 返回值: 修改记录: */ void _sw_cal_angle(void) { int i; qs16 qs; float angle, angle0; // 检查是否有基准通道 if (g_ui_angle0 == -1) { return; } // 计算基准通道的角度 angle0 = _sw_cal_angle0(g_ui[g_ui_angle0].h[1].r, g_ui[g_ui_angle0].h[1].i); // angle0 += g_ui[g_ui_angle0].p_factor; // 计算相对角度 for (i = 0; i < UI_NUM; i++) { // 如果索引通道不存在,不需计算 if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[i].ui_base_make == -1) { continue; } angle = _sw_cal_angle0(g_ui[i].h[1].r, g_ui[i].h[1].i); // angle += g_ui[i].p_factor; angle -= angle0; qs = rt_round(angle * Q16_BASE); _sw_cal_angle_correct(&qs, &g_ui[i].p_mark); g_ui[i].p_acc += qs; } return; } /****************************************************************************** 函数名称: _sw_p2 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 根据电压电流向量计算p值 参数说明: ur 电压实部 ui 电压虚部 ir 电流实部 ii 电流虚部 k1 电压系数 k2 电流系数 返回值: p值 修改记录: */ float _sw_p2(float Ur, float Ui, float Ir, float Ii, float k1, float k2) { float p; p = Ur * Ir + Ui * Ii; p = p * k1 * k2; return p; } /****************************************************************************** 函数名称: _sw_q2 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 根据电压电流向量计算q值 参数说明: ur 电压实部 ui 电压虚部 ir 电流实部 ii 电流虚部 k1 电压系数 k2 电流系数 返回值: q值 修改记录: */ float _sw_q2(float Ur, float Ui, float Ir, float Ii, float k1, float k2) { float q; q = Ui * Ir - Ur * Ii; q = q * k1 * k2; return q; } /****************************************************************************** 函数名称: _sw_cal_pq_3m 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 3表法计算一个开关的pq,每次调用累加计算值。 参数说明: sw 开关序号 返回值: 修改记录: */ void _sw_cal_pq_3m(u32 sw) { u32 i, j, U, I, baseI; float p, q, pz, qz; if (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].chn_index != CFG_ADC_CHANNEL_ZERO) baseI = SW_AC_CIA; else baseI = 0; U = pRunSet->tSwSet[sw].bTT_Power_v2 ? PUB_AC_UA2 : PUB_AC_UA1; for (j = 0; j < 3; j++) { I = UI_SW_INDEX(sw, j + baseI); p = 0; q = 0; pz = 0; qz = 0; for (i = 1; i <= g_harmonic_num; i++) { p += _sw_p2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); q += _sw_q2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); } pz = p * (1 + g_ui[I].pq_factor[0]) - q * g_ui[I].pq_factor[1]; qz = q * (1 + g_ui[I].pq_factor[0]) + p * g_ui[I].pq_factor[1]; g_sw[sw].ac_in_acc[SW_AC_IN_P] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Q] += qz; if (j == 0) { g_sw[sw].ac_in_acc[SW_AC_IN_Pa] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Qa] += qz; } else if (j == 1) { g_sw[sw].ac_in_acc[SW_AC_IN_Pb] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Qb] += qz; } else if (j == 2) { g_sw[sw].ac_in_acc[SW_AC_IN_Pc] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Qc] += qz; } U++; } return; } /****************************************************************************** 函数名称: _sw_cal_pq_2m 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 2表法计算一个开关的pq,每次调用累加计算值。 参数说明: sw 开关序号 返回值: 修改记录: */ void _sw_cal_pq_2m(u32 sw) { u32 i, U, I, baseI; float p, q, pz, qz; // IA U = PUB_AC_UAB1; if (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].chn_index != CFG_ADC_CHANNEL_ZERO) baseI = SW_AC_CIA; else baseI = 0; if (pRunSet->tSwSet[sw].bTT_Power_v2) { U = PUB_AC_UAB2; } else if ((g_ui[PUB_AC_UAB1].chn_index == CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UAB2].chn_index != CFG_ADC_CHANNEL_ZERO)) { U = PUB_AC_UAB2; } I = UI_SW_INDEX(sw, baseI); p = 0; q = 0; for (i = 1; i <= g_harmonic_num; i++) { p += _sw_p2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); q += _sw_q2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); } pz = p * (1 + g_ui[I].pq_factor[0]) - q * g_ui[I].pq_factor[1]; qz = q * (1 + g_ui[I].pq_factor[0]) + p * g_ui[I].pq_factor[1]; ; g_sw[sw].ac_in_acc[SW_AC_IN_P] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Q] += qz; g_sw[sw].ac_in_acc[SW_AC_IN_Pa] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Qa] += qz; // IC U = PUB_AC_UBC1; if (pRunSet->tSwSet[sw].bTT_Power_v2) { U = PUB_AC_UBC2; } else if ((g_ui[PUB_AC_UBC1].chn_index == CFG_ADC_CHANNEL_ZERO) && (g_ui[PUB_AC_UBC2].chn_index != CFG_ADC_CHANNEL_ZERO)) { U = PUB_AC_UBC2; } I = UI_SW_INDEX(sw, 2 + baseI); p = 0; q = 0; for (i = 1; i <= g_harmonic_num; i++) { p += _sw_p2(-g_ui[U].h[i].r, -g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); q += _sw_q2(-g_ui[U].h[i].r, -g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); } pz = p * (1 + g_ui[I].pq_factor[0]) - q * g_ui[I].pq_factor[1]; qz = q * (1 + g_ui[I].pq_factor[0]) + p * g_ui[I].pq_factor[1]; ; g_sw[sw].ac_in_acc[SW_AC_IN_P] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Q] += qz; g_sw[sw].ac_in_acc[SW_AC_IN_Pc] += pz; g_sw[sw].ac_in_acc[SW_AC_IN_Qc] += qz; g_sw[sw].ac_in_acc[SW_AC_IN_Pb] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Qb] = 0; return; } /****************************************************************************** 函数名称: _sw_cal_pq 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算pq,区分3表法和2表法,每次调用累加计算值。 参数说明: 返回值: 修改记录: */ void _sw_cal_pq(void) { u32 sw, U; for (sw = 0; sw < g_sw_num; sw++) { bool b3U, b3I = false; U = pRunSet->tSwSet[sw].bTT_Power_v2 ? PUB_AC_UA2 : PUB_AC_UA1; b3U = (g_ui[U + 0].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[U + 1].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[U + 2].chn_index != CFG_ADC_CHANNEL_ZERO); b3I |= (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IB)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_IC)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].chn_index == CFG_ADC_CHANNEL_ZERO); // 测量电流未配置 b3I |= (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].chn_index != CFG_ADC_CHANNEL_ZERO && g_ui[UI_SW_INDEX(sw, SW_AC_CIC)].chn_index != CFG_ADC_CHANNEL_ZERO); if (b3U && b3I) // 有三相电压,且有三相测量电流或无AC 测量电流有三相保护电流,用三表法 { _sw_cal_pq_3m(sw); } else { _sw_cal_pq_2m(sw); } } } /****************************************************************************** 函数名称: _sw_cal_mea 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算,每次调用累加计算值 参数说明: 返回值: 修改记录: */ int _sw_cal_mea(void) { static int g_cal_step = 0; uint64_t us0; us0 = bsp_ustimer_get_origin(); if (g_cal_step == 0) { // 得到采样点 _sw_get_dots(); // fft _sw_cal_fft(); _sw_cal_ri_correct(); g_cal_step = 1; rt_stat_other_in(3, bsp_ustimer_get_duration(us0) / USTIMER_US); } else { // 得到合成通道的向量值 _sw_cal_make(); // 计算有效值 _sw_cal_effect(); // 计算角度 _sw_cal_angle(); // 计算PQ _sw_cal_pq(); g_cal_step = 0; rt_stat_other_in(4, bsp_ustimer_get_duration(us0) / USTIMER_US); } return g_cal_step; } #ifdef FUN_JDXX /********************************************************* 函数名称:isTakeIsVal 函数版本:v1.0 作 者: Xzy 日 期:2021.10.30 函数说明:是否取Is通道的值 参数说明:sw:开关号 I_chn:常规通道号 Is_chn:小值范围通道号 返 回 值:true:取Is的值 false:不取Is的值 **********************************************************/ static bool isTakeIsVal(int sw, int I_chn, int Is_chn) { float I_val, Is_val, err_val; if (g_ui[UI_SW_INDEX(sw, I_chn)].chn_index == CFG_ADC_CHANNEL_ZERO || g_ui[UI_SW_INDEX(sw, Is_chn)].chn_index == CFG_ADC_CHANNEL_ZERO) { return false; } I_val = (float)g_sw[sw].ac_in[I_chn] / 65536; Is_val = (float)g_sw[sw].ac_in[Is_chn] / 65536; if (Is_val == 0) err_val = 1; else err_val = ((float)abs(I_val * 1000 - Is_val * 1000)) / (Is_val * 1000); if (Is_val > 0.5 || err_val >= 0.05) return false; return true; } #endif /****************************************************************************** 函数名称: _sw_cal_average 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 测量计算平均值 参数说明: cal_num 平均的次数 返回值: 修改记录: */ void _sw_cal_average(int cal_num) { s32 i, sw; s32 temp; // 平均幅值和角度 for (i = 0; i < UI_NUM; i++) { if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[i].ui_base_make == -1) { continue; } // 幅值 g_ui[i].e = rt_round(g_ui[i].e_acc / cal_num * Q16_BASE); rt_stat_in(&g_ui[i].e_stat, g_ui[i].e); if (i < PUB_AC_NUM) { g_sw_pub.ac_in[i] = g_ui[i].e; } else { g_sw[(i - PUB_AC_NUM) / SW_AC_NUM].ac_in[(i - PUB_AC_NUM) % SW_AC_NUM] = g_ui[i].e; } // 角度 temp = (g_ui[i].p_acc + (cal_num / 2)) / cal_num; if (g_ui[i].p_mark == -1) { if (temp >= 0) { temp = 180 * Q16_BASE - temp; } else { temp = (-180) * Q16_BASE - temp; } } g_ui[i].p = temp; rt_stat_in(&g_ui[i].p_stat, g_ui[i].p); g_ui[i].e_acc = 0; g_ui[i].p_acc = 0; g_ui[i].p_mark = 0; } #ifdef FUN_JDXX // 电流值小于0.5A,取Is的,因为在这个范围I0s准确度高 for (sw = 0; sw < g_sw_num; sw++) { if (isTakeIsVal(sw, SW_AC_I0, SW_AC_I0s)) { g_sw[sw].ac_in[SW_AC_I0] = g_sw[sw].ac_in[SW_AC_I0s]; } } #endif // 角度清除 for (i = 0; i < UI_NUM; i++) { if (g_ui[i].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[i].ui_base_make == -1) { continue; } #ifdef MIN_SIGNAL_SAMPLE if (g_ui_angle0 == -1 || g_ui[g_ui_angle0].e < 0.1 * Q16_BASE) #else if (g_ui_angle0 == -1 || g_ui[g_ui_angle0].e < 10 * Q16_BASE) #endif { g_ui[i].p = ANGEL_INVALID; } } // 平均开关内部测量值:P,Q,COS,电流不平衡度 for (sw = 0; sw < g_sw_num; sw++) { #ifdef FUN_YC_POWER_S float p, q; p = g_sw[sw].ac_in_acc[SW_AC_IN_P] / cal_num; q = g_sw[sw].ac_in_acc[SW_AC_IN_Q] / cal_num; g_sw[sw].ac_in[SW_AC_IN_S] = sqrtf(p * p + q * q) * Q16_BASE; #endif g_sw[sw].ac_in[SW_AC_IN_P] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_P] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Q] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Q] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Pa] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Pa] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Pb] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Pb] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Pc] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Pc] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Qa] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Qa] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Qb] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Qb] / cal_num * Q16_BASE); g_sw[sw].ac_in[SW_AC_IN_Qc] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_Qc] / cal_num * Q16_BASE); // 如果电流反向,功率反向 if (pRunSet->tSwSet[sw].bTT_Current_Inv) { g_sw[sw].ac_in[SW_AC_IN_P] = -g_sw[sw].ac_in[SW_AC_IN_P]; g_sw[sw].ac_in[SW_AC_IN_Q] = -g_sw[sw].ac_in[SW_AC_IN_Q]; g_sw[sw].ac_in[SW_AC_IN_Pa] = -g_sw[sw].ac_in[SW_AC_IN_Pa]; g_sw[sw].ac_in[SW_AC_IN_Pb] = -g_sw[sw].ac_in[SW_AC_IN_Pb]; g_sw[sw].ac_in[SW_AC_IN_Pc] = -g_sw[sw].ac_in[SW_AC_IN_Pc]; g_sw[sw].ac_in[SW_AC_IN_Qa] = -g_sw[sw].ac_in[SW_AC_IN_Qa]; g_sw[sw].ac_in[SW_AC_IN_Qb] = -g_sw[sw].ac_in[SW_AC_IN_Qb]; g_sw[sw].ac_in[SW_AC_IN_Qc] = -g_sw[sw].ac_in[SW_AC_IN_Qc]; } if (g_ui[UI_SW_INDEX(sw, SW_AC_IA)].e > g_unit[g_sw_ac_desc[SW_AC_IA].unit].zero || g_ui[UI_SW_INDEX(sw, SW_AC_IB)].e > g_unit[g_sw_ac_desc[SW_AC_IB].unit].zero || g_ui[UI_SW_INDEX(sw, SW_AC_IC)].e > g_unit[g_sw_ac_desc[SW_AC_IC].unit].zero) { g_sw[sw].ac_in[SW_AC_IN_BI_UNBALANCE] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_BI_UNBALANCE] / cal_num * Q16_BASE); } else { g_sw[sw].ac_in[SW_AC_IN_BI_UNBALANCE] = 0; } if (g_ui[UI_SW_INDEX(sw, SW_AC_CIA)].e > g_unit[g_sw_ac_desc[SW_AC_CIA].unit].zero || g_ui[UI_SW_INDEX(sw, SW_AC_CIB)].e > g_unit[g_sw_ac_desc[SW_AC_CIB].unit].zero || g_ui[UI_SW_INDEX(sw, SW_AC_CIC)].e > g_unit[g_sw_ac_desc[SW_AC_CIC].unit].zero) { g_sw[sw].ac_in[SW_AC_IN_CI_UNBALANCE] = rt_round(g_sw[sw].ac_in_acc[SW_AC_IN_CI_UNBALANCE] / cal_num * Q16_BASE); } else { g_sw[sw].ac_in[SW_AC_IN_CI_UNBALANCE] = 0; } // TODO: // 功率因数,I1/I*COSφ1=COSφ ,I1基波电流有效值,I总电流有效值,COSφ1基波功率因数,COSφ含谐波电网的实际功率因数 if (_AbsL(g_sw[sw].ac_in[SW_AC_IN_Q]) > g_unit[g_sw_ac_desc[SW_AC_IN_Q].unit].zero) { g_sw[sw].ac_in[SW_AC_IN_COS] = _CosPQ((g_sw[sw].ac_in[SW_AC_IN_P] >> 14), (g_sw[sw].ac_in[SW_AC_IN_Q] >> 14)); } else if (g_sw[sw].ac_in[SW_AC_IN_P] >= Q16_BASE) { g_sw[sw].ac_in[SW_AC_IN_COS] = Q16_BASE; } else if (g_sw[sw].ac_in[SW_AC_IN_P] <= -Q16_BASE) { g_sw[sw].ac_in[SW_AC_IN_COS] = -Q16_BASE; } else { g_sw[sw].ac_in[SW_AC_IN_COS] = 0; } g_sw[sw].ac_in_acc[SW_AC_IN_P] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Q] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Pa] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Pb] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Pc] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Qa] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Qb] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_Qc] = 0; g_sw[sw].ac_in_acc[SW_AC_IN_BI_UNBALANCE] = 0; #if 0 //电子电流互感器小信号电压值 for(i=0;i<4;i++) { s16 cfg,scale; cfg = g_sw[sw].ac_cfg_index[SW_AC_IA+i]; if(cfg != INDEX_INVALLID) { scale = equ_get_ac_scale(g_equ_config_ac[cfg].slot,g_equ_config_ac[cfg].index); if(scale == EQU_SCALE_ECT_1V_1A || scale == EQU_SCALE_ECT_0V2_1A) { g_sw[sw].ac_in[SW_AC_IN_IA_ECT+i] = g_ui[UI_SW_INDEX(sw,SW_AC_IA+i)].e*g_e_k_ECVT[scale]; } } } #endif } // 其它测量值 // 频率 g_sw_pub.ac_in[PUB_AC_IN_F1] = (qs16)(freq_get(0) * Q16_BASE); // 第1路频率 g_sw_pub.ac_in[PUB_AC_IN_F2] = (qs16)(freq_get(1) * Q16_BASE); // 第2路频率 // 直流、温度 { float factor, t, f0, f1; #ifdef TMP_CHIP_AHT20 float h = 0.0; #endif #if defined TMP_CHIP_AHT20 t = aht20_get_temp(); h = aht20_get_humi(); #endif #ifdef DC_TEST_ONE f0 = (dc_get(0) - g_dcfactor[0].f_dcL) * g_dcfactor[0].f_dc + dc_adjust[0]; f1 = 0; #else f0 = (dc_get(0) - g_dcfactor[0].f_dcL) * g_dcfactor[0].f_dc + dc_adjust[0]; f1 = (dc_get(1) - g_dcfactor[1].f_dcL) * g_dcfactor[1].f_dc + dc_adjust[0]; #endif factor = 1.0; if (t > -80.0 && t < 125.0) { factor += (t - g_dc_temp) * pRunSet->f_temp_factor_dc / 1000000; } f0 /= factor; f1 /= factor; if (pRunSet->dDc_num == 1) f1 = 0; // 只有一个通道,将第二个直流通道强制=0 #ifdef CPU_FUXI if (f0 < tRunPara.wDC_ZERO) { f0 = 0.0; } if (f1 < tRunPara.wDC_ZERO) { f1 = 0.0; } #endif #ifdef TMP_CHIP_AHT20 g_sw_pub.ac_in[PUB_AC_IN_HUMI] = (qs16)(h * Q16_BASE); #endif g_sw_pub.ac_in[PUB_AC_IN_TEMP] = (qs16)(t * Q16_BASE); g_sw_pub.ac_in[PUB_AC_IN_UZ1] = (qs16)(f0 * Q16_BASE); g_sw_pub.ac_in[PUB_AC_IN_UZ2] = (qs16)(f1 * Q16_BASE); if (g_sw_pub.ac_in[PUB_AC_IN_UZ1] < 0) g_sw_pub.ac_in[PUB_AC_IN_UZ1] = 0; if (g_sw_pub.ac_in[PUB_AC_IN_UZ2] < 0) g_sw_pub.ac_in[PUB_AC_IN_UZ2] = 0; } // 电压不平衡度 if (g_ui[PUB_AC_UA1].e > g_unit[g_pub_ac_desc[PUB_AC_UA1].unit].zero || g_ui[PUB_AC_UB1].e > g_unit[g_pub_ac_desc[PUB_AC_UB1].unit].zero || g_ui[PUB_AC_UC1].e > g_unit[g_pub_ac_desc[PUB_AC_UC1].unit].zero) { g_sw_pub.ac_in[PUB_AC_IN_V_UNBALANCE1] = rt_round(g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE1] / cal_num * Q16_BASE); } else { g_sw_pub.ac_in[PUB_AC_IN_V_UNBALANCE1] = 0; } if (g_ui[PUB_AC_UA2].e > g_unit[g_pub_ac_desc[PUB_AC_UA2].unit].zero || g_ui[PUB_AC_UB2].e > g_unit[g_pub_ac_desc[PUB_AC_UB2].unit].zero || g_ui[PUB_AC_UC2].e > g_unit[g_pub_ac_desc[PUB_AC_UC2].unit].zero) { g_sw_pub.ac_in[PUB_AC_IN_V_UNBALANCE2] = rt_round(g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE2] / cal_num * Q16_BASE); } else { g_sw_pub.ac_in[PUB_AC_IN_V_UNBALANCE2] = 0; } g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE1] = 0; g_sw_pub.ac_in_acc[PUB_AC_IN_V_UNBALANCE2] = 0; g_sw_pub.ac_in[PUB_AC_IN_DLTUAB] = _AbsL(g_ui[PUB_AC_UAB1].e - g_ui[PUB_AC_UAB2].e); g_sw_pub.ac_in[PUB_AC_IN_DLTUBC] = _AbsL(g_ui[PUB_AC_UBC1].e - g_ui[PUB_AC_UBC2].e); g_sw_pub.ac_in[PUB_AC_IN_DLTUCA] = _AbsL(g_ui[PUB_AC_UCA1].e - g_ui[PUB_AC_UCA2].e); if (g_ui[PUB_AC_UAB1].e > 10 * Q16_BASE && g_ui[PUB_AC_UAB2].e > 10 * Q16_BASE) { g_sw_pub.ac_in[PUB_AC_IN_ARGUAB] = _AbsL(CalcAngSub(g_ui[PUB_AC_UAB1].ri.r, g_ui[PUB_AC_UAB1].ri.i, g_ui[PUB_AC_UAB2].ri.r, g_ui[PUB_AC_UAB2].ri.i)); } else { g_sw_pub.ac_in[PUB_AC_IN_ARGUAB] = 0; } if (g_ui[PUB_AC_UBC1].e > 10 * Q16_BASE && g_ui[PUB_AC_UBC2].e > 10 * Q16_BASE) { g_sw_pub.ac_in[PUB_AC_IN_ARGUBC] = _AbsL(CalcAngSub(g_ui[PUB_AC_UBC1].ri.r, g_ui[PUB_AC_UBC1].ri.i, g_ui[PUB_AC_UBC2].ri.r, g_ui[PUB_AC_UBC2].ri.i)); } else { g_sw_pub.ac_in[PUB_AC_IN_ARGUBC] = 0; } if (g_ui[PUB_AC_UCA1].e > 10 * Q16_BASE && g_ui[PUB_AC_UCA2].e > 10 * Q16_BASE) { g_sw_pub.ac_in[PUB_AC_IN_ARGUCA] = _AbsL(CalcAngSub(g_ui[PUB_AC_UCA1].ri.r, g_ui[PUB_AC_UCA1].ri.i, g_ui[PUB_AC_UCA2].ri.r, g_ui[PUB_AC_UCA2].ri.i)); } else { g_sw_pub.ac_in[PUB_AC_IN_ARGUCA] = 0; } // 版本号0x00010104 { g_sw_pub.ac_in[PUB_AC_IN_VER] = ((BYTE)((VER_NUM >> 0) & 0x0f) + ((BYTE)(VER_NUM >> 4) & 0x0f) * 10 + ((BYTE)(VER_NUM >> 8) & 0x0f) * 100 + ((BYTE)(VER_NUM >> 12) & 0x0f) * 1000 + ((BYTE)(VER_NUM >> 16) & 0x0f) * 10000) * Q16_BASE; } #if 0 //电子电压互感器小信号电压值 for(i=0;i<8;i++) { u8 evt[8]={PUB_AC_UA1,PUB_AC_UB1,PUB_AC_UC1,PUB_AC_U01,PUB_AC_UA2,PUB_AC_UB2,PUB_AC_UC2,PUB_AC_U02}; s16 cfg,scale; cfg = g_sw_pub.ac_cfg_index[evt[i]]; if(cfg != INDEX_INVALLID) { scale = equ_get_ac_scale(g_equ_config_ac[cfg].slot,g_equ_config_ac[cfg].index); if(scale == EQU_SCALE_EVT_3V25_100V || scale == EQU_SCALE_EVT_6V50_100V) { g_sw_pub.ac_in[PUB_AC_IN_UA1_EVT+i] = g_ui[evt[i]].e*g_e_k_ECVT[scale]; } } } #endif } void _sw_cal_zl(void) { // 直流、温度 { float factor, t, f0, f1; #if defined TMP_CHIP_AHT20 t = aht20_get_temp(); #endif f0 = (dc_get(0) - g_dcfactor[0].f_dcL) * g_dcfactor[0].f_dc + dc_adjust[0]; f1 = (dc_get(1) - g_dcfactor[1].f_dcL) * g_dcfactor[1].f_dc + dc_adjust[0]; factor = 1.0; if (t > -80.0 && t < 125.0) { factor += (t - g_dc_temp) * pRunSet->f_temp_factor_dc / 1000000; } f0 /= factor; f1 /= factor; g_sw_pub.ac_in[PUB_AC_IN_TEMP] = (qs16)(t * Q16_BASE); g_sw_pub.ac_in[PUB_AC_IN_UZ1] = (qs16)(f0 * Q16_BASE); g_sw_pub.ac_in[PUB_AC_IN_UZ2] = (qs16)(f1 * Q16_BASE); } } /****************************************************************************** 函数名称: _sw_auto_adjust_pq 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 自动校正PQ,累加校正系数 参数说明: 返回值: 修改记录: */ void _sw_auto_adjust_pq(void) { float RateP; float RateQ; u32 sw, i, j, U, I; float pp[3], qq[3]; RateP = (float)100 * 5 * 0.5; // U*I*COS60 RateQ = (float)100 * 5 * 0.866; // U*I*SIN60 for (sw = 0; sw < g_sw_num; sw++) { for (j = 0; j < 3; j++) { U = PUB_AC_UA1 + j; I = UI_SW_INDEX(sw, j); pp[j] = 0; qq[j] = 0; for (i = 1; i <= g_harmonic_num; i++) { pp[j] += _sw_p2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); qq[j] += _sw_q2(g_ui[U].h[i].r, g_ui[U].h[i].i, g_ui[I].h[i].r, g_ui[I].h[i].i, g_ui[U].e_factor, g_ui[I].e_factor); } g_pq_factor[sw][j].pq[0] += (RateQ * qq[j] + RateP * pp[j]) / (pp[j] * pp[j] + qq[j] * qq[j]) - 1; g_pq_factor[sw][j].pq[1] += (RateQ * pp[j] - RateP * qq[j]) / (pp[j] * pp[j] + qq[j] * qq[j]); } } return; } /****************************************************************************** 函数名称: _sw_ui_e_k 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 通过g_ui的索引得到对应通道的理论比例系数。 参数说明: ui_index 通道在g_ui中的索引值 返回值: 对应通道的理论比例系数。 修改记录: */ float _sw_ui_e_k(int ui_index) { int sw, i; if (ui_index < PUB_AC_NUM) { i = g_sw_pub.ac_cfg_index[ui_index]; } else { sw = (ui_index - PUB_AC_NUM) / SW_AC_NUM; i = (ui_index - PUB_AC_NUM) % SW_AC_NUM; i = g_sw[sw].ac_cfg_index[i]; } return factor_e_k(g_equ_config_ac[i].scale); } /****************************************************************************** 函数名称: _sw_min_max 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 计算g_ui中连续三个通道中的m2的最小值,最大值,供保护算法使用 参数说明: ui_index 通道在g_ui中的索引值 p_min 返回的最小值 p_max 返回的最大值 返回值: 修改记录: */ void _sw_min_max(int ui_index, u32 *p_min, u32 *p_max) { u32 min, max, m2; int i; min = -1; max = 0; for (i = 0; i < 3; i++) { if (g_ui[ui_index].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[ui_index].ui_base_make == -1) { ui_index++; continue; } m2 = g_ui[ui_index].m2[0]; if (m2 < min) { min = m2; } if (m2 > max) { max = m2; } ui_index++; } *p_min = min; *p_max = max; return; } /****************************************************************************** 函数名称: _fz_min_max 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2013-08-07 函数说明: 计算g_ui中连续通道中的幅值的最小值,最大值,供保护算法使用 参数说明: ui_index1 起始通道在g_ui中的索引值 ui_index2 结束通道在g_ui中的索引值 p_min 返回的最小值 p_max 返回的最大值 返回值: 修改记录: */ void _fz_min_max(int ui_index1, int ui_index2, u32 *p_min, u32 *p_max) { u32 min, max, m2; int i; min = -1; max = 0; for (i = ui_index1; i < ui_index2 + 1; i++) { if (g_ui[ui_index1].chn_index == CFG_ADC_CHANNEL_ZERO && g_ui[ui_index1].ui_base_make == -1) { ui_index1++; continue; } m2 = g_ui[ui_index1].fz; if (m2 < min) { min = m2; } if (m2 > max) { max = m2; } ui_index1++; } *p_min = min; *p_max = max; return; } /****************************************************************************** 函数名称: _sw_base_angle 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 自动校准时,通道的基本参考角度 参数说明: ui_index 通道在g_ui中的索引值 返回值: 参考的角度 修改记录: */ float _sw_base_angle(int ui_index) { static float angle_v[8] = {0, -120, 120, 0, -120, 120, 120, 120}; // U0、US使用UC角度 #ifdef SW_AC_I0S_SAMPLE static float angle_a[SW_AC_NUM] = {0, -120, 120, -120, -120, 0, -120, 120}; // I0使用IB值 #else static float angle_a[SW_AC_NUM] = {0, -120, 120, -120, 0, -120, 120}; // I0使用IB值 #endif float angle; if (ui_index < PUB_AC_NUM) { // 电压 // 将第2组电压映射到第一组上面 ui_index = ui_index % (PUB_AC_NUM / 2); // 得到基准电压 angle = angle_v[ui_index]; // 如果配置不是相电压,U01、US1减30度。 if ((g_ui[PUB_AC_UA1].chn_index == CFG_ADC_CHANNEL_ZERO) && (ui_index == PUB_AC_U01 || ui_index == PUB_AC_US1)) { angle -= 30; } } else { // 电流 ui_index = (ui_index - PUB_AC_NUM) % SW_AC_NUM; angle = angle_a[ui_index]; // 如果配置不是相电压,电流减30度。 if (g_ui[PUB_AC_UA1].chn_index == CFG_ADC_CHANNEL_ZERO) { angle -= 30; } } return angle; } /****************************************************************************** 函数名称: _sw_save_dc_factor 函数版本: 01.01 创建作者: sunxi 创建日期: 2013-08-07 函数说明: 将直流量校正系数保存到内部定值 参数说明: dc1 直流量1的校正系数 dc2 只流量2的校正系数 返回值: 0: 成功 其它: 失败 修改记录: */ int _sw_save_dc_factor(float dc1_H, float dc1_L, float dc2_H, float dc2_L) { struct dc_factor_save factor[2]; u8 id[8]; if (dc1_H != 0.0) { factor[0].dc_h = dc1_H; factor[0].adjust_set = DC_ADJUST; } if (dc1_L != 0.0) { factor[0].dc_l = dc1_L; factor[0].adjust_set = DC_ADJUST; } if (dc2_H != 0.0) { factor[1].dc_h = dc2_H; factor[1].adjust_set = DC_ADJUST; } if (dc2_L != 0.0) { factor[1].dc_l = dc2_L; factor[1].adjust_set = DC_ADJUST; } memcpy(id, g_auth_id, 8); if (dcfactor_createfile(&id[0], (u8 *)&factor) != 0) { rt_printf("直流系数文件保存失败\r\n"); return -1; } return 0; } float g_temp_factor[EQU_SLOT_AC_NUM]; void _sw_temp_factor(void) { int i; float t; #if defined TMP_CHIP_AHT20 t = aht20_get_temp(); #endif if (t < -80.0 || t > 125.0) { // 温度超范围,可能温度传感器坏,使用默认值 for (i = 0; i < EQU_SLOT_AC_NUM; i++) { g_temp_factor[i] = 1.0; } } else { // 在正常范围内,使用温度校正 for (i = 0; i < EQU_SLOT_AC_NUM; i++) { factor_temp_get(equ_ac_index_to_slot(i), &g_temp_factor[i]); g_temp_factor[i] = t - g_temp_factor[i]; g_temp_factor[i] *= pRunSet->f_temp_factor_ac / 1000000; g_temp_factor[i] += 1.0; } } for (i = 0; i < UI_NUM; i++) { if (g_ui[i].chn_index != CFG_ADC_CHANNEL_ZERO) { g_ui[i].e_factor = g_ui[i].e_factor0 * g_temp_factor[g_ui[i].chn_index / 16]; } else if (g_ui[i].ui_base_make != -1) { g_ui[i].e_factor = g_ui[i].e_factor0 * g_temp_factor[g_ui[g_ui[i].ui_base_make].chn_index / 16]; } } return; } int sw_get_chnl_ps(int index, bool prim) { int owner, type; owner = g_equ_config_ac[index].owner; type = g_equ_config_ac[index].type; if (owner == 0) { type -= 1; if (type == PUB_AC_U01 || type == PUB_AC_U02) // 零序 PT变比为默认10000/100 { if (prim) return 10000; else return 100; } else if (PUB_AC_UA2 || PUB_AC_UB2 || PUB_AC_UC2 || PUB_AC_UAB2 || PUB_AC_UBC2 || PUB_AC_UCA2) { // 采用PT2变比 dlj 2019-6-5 if (prim) return 10000; else return pRunSet->b_pt_two; } else if (type < PUB_AC_NUM) { if (prim) return 10000; else return pRunSet->a_pt_two; } } else { owner -= 1; type -= 1; if (type == SW_AC_I0) // 零序 CT变比 { if (prim) return pRunSet->ct0_one; else return pRunSet->ct0_two; } else if (type == SW_AC_IA || type == SW_AC_IB || type == SW_AC_IC) { if (prim) return pRunSet->ct_one; else return pRunSet->ct_two; } } return 1; } /** * @brief 将ms的时间戳转换为ns的结构体 * @author lch (lch_work@foxmail.com) * @version 1.0 * @date 20251222 * @param[in/out] {type} _ull_timestamp_ms * @return * struct timespec * @retval none * * @warning none * @note none */ void transform_msts_to_tts(uint64_t _ull_timestamp_ms, struct timespec *_t_ts) { // 计算秒(整数除法) _t_ts->tv_sec = _ull_timestamp_ms / 1000; // 计算纳秒:毫秒部分 * 1,000,000 _t_ts->tv_nsec = (_ull_timestamp_ms % 1000) * 1000000; } /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ int sw_stat_reset(void) { int i; for(i=0; i< UI_NUM; i++) { rt_stat_init(&g_ui[i].m2_stat,g_ui[i].name); rt_stat_init(&g_ui[i].e_stat,g_ui[i].name); rt_stat_init(&g_ui[i].p_stat,g_ui[i].name); } return 0; } int sw_pub_printf(void) { return 0; } int sw_pub_printf_v(void) { int i; // rt_printf("PUB AC通道模值:\r\n"); // rt_printf("name\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); rt_printf("PUB AC通道有效值:\r\n"); rt_printf("name\t\t\tmin\tmax\tavg\tsum\t\tcnt\r\n"); for(i=0; icnt) { avg = stat->sum/stat->cnt; } rt_printf("%-24s",stat->name); qs = _Mul_Div_U(sqrt_32fix(stat->min), 256, g_ui[i].m2_factor_k); rt_printf("%f\t", (float)qs/Q16_BASE); qs = _Mul_Div_U(sqrt_32fix(stat->max), 256, g_ui[i].m2_factor_k); rt_printf("%f\t", (float)qs/Q16_BASE); qs = _Mul_Div_U(sqrt_32fix(avg), 256, g_ui[i].m2_factor_k); rt_printf("%f\t", (float)qs/Q16_BASE); rt_printf("%-016d%d\r\n",stat->sum,stat->cnt); return; } #else void rt_stat_printf_m2(int i,struct rt_stat *stat) { uint32_t avg = 0; float k; if(stat->cnt) { avg = stat->sum/stat->cnt; } k = _sw_ui_e_k(i); rt_printf("%-24s",stat->name); rt_printf("%f\t", sqrtf((float)stat->min)/k); rt_printf("%f\t", sqrtf((float)stat->max)/k); rt_printf("%f\t", sqrtf((float)avg)/k); rt_printf("%-016d%d\r\n",stat->sum,stat->cnt); return; } #endif int sw_ui_printf_e(void) { int i; rt_printf("UI通道:\r\n"); rt_printf("name\t\t\tmin\t\tmax\t\tavg\t\tsum\t\tcnt\r\n"); for(i=0; i