/****************************************************************************** 版权所有: 文件名称: factor.c 文件版本: 01.01 创建作者: sunxi 创建日期: 2013-05-20 功能说明: 通道参数处理。 其它说明: 修改记录: */ /*------------------------------- 头文件 -------------------------------------- */ #include "head.h" /*------------------------------- 宏定义 -------------------------------------- */ #define FACTOR_P_BASE (-360.0 / 32 / 8) // CT PT标度,1V或1A对应的码值 // = (二次有效值/一次有效值)*(AD码值范围/电压范围(V))*1.4142 // = (7.07/一次有效值)*(65536/20)*1.4142 // = (7.07*65536/20*1.4142)/ 一次有效值. #define SCALE_PT_BIG (32768.0) // 二次有效值为7.07V或3.53V,需对应改变ADC的输入范围 #define SCALE_CT_BIG (32768.0) // 二次有效值为7.07V或3.53V,需对应改变ADC的输入范围 // 使用初级电阻标识 #define SCALE_PT_102K (1.650 * 32768 / 5.0 * 1.4142) // DTU FTU使用电阻配置100V #define SCALE_PT_120K (1.032 * 32768 / 2.5 * 1.4142) // 153K #define SCALE_PT_150K (1.0348 * 32768 / 2.5 * 1.4142) // 开普测试,测量范围264 增加了电阻 #define SCALE_PT_172K (0.916 * 32768 / 2.5 * 1.4142) // 加264V相电压二次用万用表测有效值为0.916v // #define SCALE_PT_204K (0.513*32768/2.5*1.4142) // 次级电阻200k 最终版本 // DTUv5与DTUv4同样硬件,系数一样 #define SCALE_PT_204K (0.1105 * 32768 / 2.5 * 1.4142) // 加264V相电压二次用万用表测有效值为0.063v 初级241KΩ次级100Ω #define SCALE_PT_FUXI (0.1090 * 32768 / 5.0 * 1.4142) // 使用次级电阻标识 #define SCALE_CT_100A_51 (2.526 * 32768 / 5.0 * 1.4142) // 次级电阻51欧,,加5A相电流二次用万用表测有效值为0.127V #define SCALE_CT_10A_51 (0.254 * 32768 / 2.5 * 1.4142) // 次级电阻51欧,加10A相电流二次用万用表测有效值为0.254V #define SCALE_CT_10A_120 (1.27 * 32768 / 2.5 * 1.4142) // 次级电阻249欧,加10A相电流二次用万用表测有效值为0.643V // 零序穿心5倍 最大量程20A #define SCALE_CT_10A_249 (1.265 * 32768 / 5.0 * 1.4142) // 1ACT 量程20A #define SCALE_CT_10A_604 (3.235 * 32768 / 5.0 * 1.4142) // 次级电阻604欧,加10A相电流二次用万用表测有效值为3.235V #define SCALE_CT_FUXI (3.069 * 32768 / 5.0 * 1.4142) #define SCALE_EVT (32768.0) #define SCALE_ECT (32768.0) #define SCALE_PT_DEFAULT SCALE_PT_FUXI #define SCALE_CT_DEFAULT SCALE_CT_FUXI /*------------------------------ 类型结构 ------------------------------------- */ /*------------------------------ 全局变量 ------------------------------------- */ // 比例系数计算方法请参考<电子互感器比例系数计算方法.xlsx> static const float g_e_k[EQU_SCALE_NUM] = { SCALE_PT_BIG / (220 * 1.2), SCALE_PT_DEFAULT / (220 * 1.2), SCALE_EVT / (108.7856586), // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; SCALE_EVT / (31.31), // EQU_SCALE_EVT 最大测到30V #if 1 SCALE_CT_BIG / 54.752, #else SCALE_CT_BIG / 100, #endif SCALE_CT_DEFAULT / 100, SCALE_ECT / (10.60660172), // EQU_SCALE_ECT_1V_1A, 1V=1A SCALE_ECT / (11.73797257), // EQU_SCALE_ECT_0V2_1A,0.2V=1A. SCALE_CT_10A_51 / 10, SCALE_PT_102K / (220 * 1.2), SCALE_PT_120K / (220 * 1.2), SCALE_PT_172K / (220 * 1.2), SCALE_PT_204K / (220 * 1.2), SCALE_CT_10A_604 / 10, SCALE_CT_10A_120 / 10, SCALE_CT_10A_249 / 10, }; // 一次/二次变比 static const float g_e_ps[EQU_SCALE_NUM] = { 10000.0 / 220.0, 10000.0 / 100.0, 10000.0 / 100.0, // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; 5773.502692 / (100.0 / 3), // EQU_SCALE_EVT_6V50_100V, 600.0 / 5.0, 600.0 / 5.0, 600.0 / 1.0, // EQU_SCALE_ECT_1V_1A, 1V=1A 20.0 / 1.0, // EQU_SCALE_ECT_0V2_1A,0.2V=1A. 600.0 / 1.0, 10000.0 / 100.0, 10000.0 / 100.0, 10000.0 / 100.0, 10000.0 / 100.0, 10000.0 / 100.0, 10000.0 / 100.0, 10000.0 / 100.0, }; // 电子互感器和电磁互感器二次值换算的比值 const float g_e_k_ECVT[EQU_SCALE_NUM] = { 1.0, 1.0, 0.0325, // EQU_SCALE_EVT_3V25_100V,10/(3.25*1.414)*100; 0.065, // EQU_SCALE_EVT_6V50_100V, 1.0, 1.0, 1.0, // EQU_SCALE_ECT_1V_1A, 1V=1A 0.2, // EQU_SCALE_ECT_0V2_1A,0.2V=1A. 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, }; struct ac_slot_factor g_ac_factor[EQU_SLOT_AC_NUM]; u32 g_factor_version = ACFACTOR_FILE_VERSION; u16 g_base_v, g_base_i; /*------------------------------ 函数声明 ------------------------------------- */ int factor_read_all(void); int factor_printf_temp(void); /*------------------------------ 外部函数 ------------------------------------- 外部函数供其它实体文件引用,必须仔细检查传入参数的合法性. */ int factor_init(void) { int slot, ret; // 取默认值 g_factor_version = ACFACTOR_FILE_VERSION; for (slot = 0; slot < EQU_SLOT_AC_NUM; slot++) { factor_get_default(&g_ac_factor[slot]); } // 检查装置配置 if (equ_config_null()) { return -1; } // 从文件系统读取系数 ret = factor_read_all(); if (ret != 0) { rt_err_set(ERR_CODE_FACTOR, 0); dp_err_n_c("交流系数文件错误: (ret=%d)", ret); return -2; } return 0; } int factor_exit(void) { return 0; } int factor_read(u32 slot, struct ac_slot_factor *asf) { // 检查参数 slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM || asf == NULL) { return -1; } memcpy((u8 *)asf, &g_ac_factor[slot], sizeof(struct ac_slot_factor)); return 0; } /****************************************************************************** 函数名称: factor_write 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 创建交流系数文件 参数说明: 无 返回值: 成功返回0. 修改记录: */ int factor_write(u32 slot, struct ac_slot_factor *asf) { // 检查参数 slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM || asf == NULL) { return -1; } memcpy(&g_ac_factor[slot], (u8 *)asf, sizeof(struct ac_slot_factor)); return 0; } /****************************************************************************** 函数名称: factor_read 函数版本: 01.01 创建作者: xxxxxx 创建日期: 2015-10-23 函数说明: 读取交流系数文件 参数说明: 无 返回值: 成功返回0. 修改记录: */ int factor_read_all(void) { int len; u16 crc; u8 *buf; off_t pos; struct file *pfile; // int file_size; struct acfactor_file_head_data *brh; // 创建并打开文件 pfile = (struct file *)rt_file_open("/app/data/acfactor.bin", O_RDWR, 0); if (IS_ERR(pfile)) { return -2; } // 得到文件长度 len = rt_file_getfile_size(pfile); if (len <= 0) { rt_file_close(pfile, 0); return -21; } // 分配内存 buf = (u8 *)rt_malloc(len); if ((buf) == NULL) { rt_file_close(pfile, 0); return -3; } // 读出内容 pos = 0; if (rt_file_read(pfile, buf, len, &pos) != len) { rt_file_close(pfile, 0); rt_free(buf); return -4; } // 关闭文件 rt_file_close(pfile, 0); // 检查CRC crc = CrcStr(buf, len - 2); if (crc != *(u16 *)(buf + len - 2)) { rt_free(buf); return -5; } // 检查文件签名 brh = (struct acfactor_file_head_data *)buf; if (brh->cfh.signature != SIG_ACFACTOR_FILE) { rt_free(buf); return -6; } #if 0 // 检查文件版本 if(brh->cfh.version != ACFACTOR_FILE_VERSION) { rt_free(buf); return -66; } #endif // noted by sunxi: 20220413 暂进屏蔽 #if 0 // 检查FLASH唯一ID号 if (memcmp (brh->auth_id, g_auth_id, 8) != 0) { rt_free(buf); return -7; } #endif // 检查板卡数量 if (brh->num != EQU_SLOT_AC_NUM) { rt_free(buf); return -77; } // 检查文件长度 if (len < (int)(sizeof(*brh) + brh->num * sizeof(struct ac_slot_factor) + 2)) { rt_free(buf); return -8; } // 取出文件中存储内容 g_factor_version = brh->cfh.version; g_base_v = brh->base_v; g_base_i = brh->base_i; memcpy((u8 *)g_ac_factor, buf + brh->addr, EQU_SLOT_AC_NUM * sizeof(struct ac_slot_factor)); rt_free(buf); return 0; } int factor_write_all(u16 base_v, u16 base_i) { unsigned int addr, file_length; u16 crc; char *p; off_t pos; int pfile; struct acfactor_file_head_data acfactor_file; // 写文件头 memset(&acfactor_file, 0, sizeof(acfactor_file)); acfactor_file.cfh.signature = SIG_ACFACTOR_FILE; acfactor_file.cfh.version = ACFACTOR_FILE_VERSION; memcpy(&acfactor_file.auth_id, g_auth_id, 8); acfactor_file.base_v = base_v ? base_v : g_base_v; acfactor_file.base_i = base_i ? base_i : g_base_i; g_base_v = acfactor_file.base_v; g_base_i = acfactor_file.base_i; acfactor_file.addr = FILE_ADDR_ALGIN(sizeof(acfactor_file)); acfactor_file.num = EQU_SLOT_AC_NUM; // 得到文件长度 addr = acfactor_file.addr + acfactor_file.num * sizeof(struct ac_slot_factor); file_length = FILE_ADDR_ALGIN(addr); // 分配并初始化空间 p = (u8 *)rt_malloc(file_length + 2); if (!p) { rt_err_set(ERR_CODE_FACTOR, 0); return -2; } memset(p, 0, file_length + 2); // 写入文件头 memcpy(p, (char *)&acfactor_file, sizeof(acfactor_file)); // 写系数 memcpy(p + acfactor_file.addr, g_ac_factor, EQU_SLOT_AC_NUM * sizeof(struct ac_slot_factor)); // 计算CRC crc = CrcStr(p, file_length); memcpy(p + file_length, &crc, 2); // swap16(p+file_length);//added by sunxi: 大小端问题 ----- 维护工具好像没有处理crc的大小端 // 创建数据文件 pfile = rt_file_open("/app/data/acfactor.bin", O_CREAT | O_RDWR | O_TRUNC, 0); if (IS_ERR(pfile)) { rt_err_set(ERR_CODE_FACTOR, 0); rt_free(p); return -3; } pos = 0; rt_file_write(pfile, p, file_length + 2, &pos); rt_file_close(pfile, 0); rt_free(p); system("sync"); // noted by sunxi: 把写好的文件,写到系统中去,不然,断电重启,有机会掉失 // 清除交流告警灯 rt_err_clr(ERR_CODE_FACTOR, 0); return 0; } int factor_write_board(u32 slot, struct ac_slot_factor *asf) { int ret; ret = factor_write(slot, asf); if (ret != 0) { rt_err_set(ERR_CODE_FACTOR, slot); rt_printf("factor_write_board:slot=%lu,ret=%d.\r\n", slot, ret); return -1; } g_base_v = 0; g_base_i = 0; ret = factor_write_all(0, 0); return ret; } int factor_get_default(struct ac_slot_factor *asf) { int i; if (asf == NULL) { return -1; } for (i = 0; i < EQU_SLOT_AC_CHN; i++) { asf->factor_e_c[i] = 1.0; asf->factor_p_c[i] = 0.0; #ifdef PROTECT_AC_ADJUST asf->factor_p_e_c[i] = 1.0; #endif asf->pq_factor[i][0] = 0.0; asf->pq_factor[i][1] = 0.0; } asf->temp = 35.0; return 0; } int factor_restore_default(void) { int slot, ret; // 取默认值 g_factor_version = ACFACTOR_FILE_VERSION; for (slot = 0; slot < EQU_SLOT_AC_NUM; slot++) { factor_get_default(&g_ac_factor[slot]); } // 重新初始化开关 sw_init(); // 保存 g_base_v = 0; g_base_i = 0; ret = factor_write_all(0, 0); rt_printf("factor_restore_default(ret=%d).\r\n", ret); return ret; } int factor_e_c_get(u32 slot, u32 index, float *f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } if (f == NULL) { return -2; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_e_c[index]; return 0; } int factor_e_c_set(u32 slot, u32 index, float f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_e_c[index] = f; return 0; } int factor_p_c_get(u32 slot, u32 index, float *f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } if (f == NULL) { return -2; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_p_c[index]; return 0; } int factor_p_c_set(u32 slot, u32 index, float f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_p_c[index] = f; return 0; } #ifdef PROTECT_AC_ADJUST int factor_p_e_c_get(u32 slot, u32 index, float *f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } if (f == NULL) { return -2; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -3; } *f = g_ac_factor[slot].factor_p_e_c[index]; return 0; } int factor_p_e_c_set(u32 slot, u32 index, float f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -2; } g_ac_factor[slot].factor_p_e_c[index] = f; return 0; } #endif int factor_pq_get(u32 slot, u32 index, float *f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } if (f == NULL) { return -2; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -3; } *f++ = g_ac_factor[slot].pq_factor[index][0]; *f = g_ac_factor[slot].pq_factor[index][1]; return 0; } int factor_pq_set(u32 slot, u32 index, float *f) { // 检查参数 if (index >= (u32)equ_get_ac_num(slot)) { return -1; } if (f == NULL) { return -2; } slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -3; } g_ac_factor[slot].pq_factor[index][0] = *f++; g_ac_factor[slot].pq_factor[index][1] = *f; return 0; } float factor_e_k(u32 index) { if (index >= EQU_SCALE_NUM) { return -1; } return g_e_k[index]; } float factor_e_ps(u32 index) { if (index >= EQU_SCALE_NUM) { return -1; } return g_e_ps[index]; } float factor_p_k(u32 index) { if (index >= CFG_ADC_CHANNEL) { return 0; } // 保持旧版本的兼容性 { u32 us; if (g_factor_version != ACFACTOR_FILE_VERSION) { return (index / 8) * FACTOR_P_BASE; } // 1倍过采样延时1us us = (index % 16) / 2 * CFG_ADC_OS_NUM; return -g_freq * us / 1000000.0 * 360; } return 0; } int factor_temp_get(int slot, float *temp) { // 检查参数 slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -1; } *temp = g_ac_factor[slot].temp; return 0; } int factor_temp_set(int slot, float temp) { // 检查参数 slot -= g_ac_slot_begin; if (slot >= EQU_SLOT_AC_NUM) { return -1; } g_ac_factor[slot].temp = temp; return 0; } /*------------------------------ 内部函数 ------------------------------------- 内部函数以下划线‘_’开头,不需要检查参数的合法性. */ /*------------------------------ 测试函数 ------------------------------------- 一个实体文件必须带一个本模块的测试函数来进行单元测试,如果的确不方便在本模块中 进行单元测试,必须在此注明实际的测试位置(例如在哪个实体文件中使用哪个测试函数). */ int factor_printf(void) { int slot, j; float f; rt_printf("校正系数:\r\n"); rt_printf("版本:0x%08lx.\r\n", g_factor_version); rt_printf("最后校准基准值:电压=%d,电流=%d.\r\n", g_base_v, g_base_i); for (slot = 0; slot < EQU_SLOT_AC_NUM; slot++) { rt_printf("序号:%02d(temp=%f).\r\n", slot, g_ac_factor[slot].temp); for (j = 0; j < EQU_SLOT_AC_CHN; j++) { rt_printf("%02d:\tec=% 9f,\tpc=% 9f,\tpq1=% 9f,\tpq2=% 9f.\r\n", j, g_ac_factor[slot].factor_e_c[j], g_ac_factor[slot].factor_p_c[j], g_ac_factor[slot].pq_factor[j][0], g_ac_factor[slot].pq_factor[j][1]); } } for (j = 0; j < (int)(sizeof(g_e_k) / sizeof(g_e_k[0])); j++) { rt_printf("g_e_k[%d]:%f.\r\n", j, g_e_k[j]); } for (j = 0; j < 16; j++) { f = factor_p_k(j); rt_printf("factor_p_k(%02d):%f.\r\n", j, f); } return 0; } //========================== 本文件结束 =============================