/* Includes ------------------------------------------------------------------*/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #ifdef CFG_DEV_TYPE_LAND_CA /* 标准C库头文件. */ #include #include #include #include #include #include #include #include #include /* 用户代码头文件. */ #include "cmd.h" #include "fifo.h" #include "common.h" #include "ca_cau.h" #include "serial.h" #include "modbus.h" #include "hwgpio.h" #include "ca_main.h" #include "ca_CL106d.h" #include "ca_dbg.h" #include "debug.h" /* Private define ------------------------------------------------------------*/ /* Private macro -------------------------------------------------------------*/ /* Private typedef -----------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ cau_t cau; pwr_t pwr; int cau_collect_flag = 0; /* Private function prototypes -----------------------------------------------*/ int _pwr_read_vout(void); int _pwr_read_vbat(void); int _pwr_read_vsc(void); /* Internal functions --------------------------------------------------------*/ void _cau_get_float_data(unsigned char *hex,float *val) { unsigned int ivar = ((hex[0]&0xff) << 8) |((hex[1]&0xff) << 0) |((hex[2]&0xff) << 24) |((hex[3]&0xff)<<16); //val = (float *)&ivar; memcpy(val, &ivar, sizeof(float)); } /********************************************************************** * 函数名称: _cau_recv * 功能描述: * 输入参数: * * 输出参数: pbuf * 返 回 值: 0:failure 1:success * 其它说明: * 修改日期: 2023/12/08 ***********************************************************************/ int _cau_recv(unsigned char *pkt) { int len; len = serial_read(cau.serial_fd, pkt, MODBUS_DATA_LENGTH); if (len > 0 && _modbus_verify_crc(pkt, len) > 0) { return len; } return 0; } int _cau_set_user_param() { int len; int ch; int loop; int slen; unsigned char *pkt = cau.modbus_send_buf; //LOG("%s:%d\n", __FUNCTION__, __LINE__); // cau1:0-7 use,cau2:8-15 no use,cau3:16-23 no use for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { cau_param_t *pparam = &pparam_config->cauParam[ch]; len = _modbus_write_head(pkt, MB_FUNC_MULIT_WR, MB_USER_PARAM + ch * 0x10, 12); DBG(DBG_M_CA_CAU, "[ch%d]Range=%f,Ratio=%f,ZeroPoint=%f,ChangeThreshold=%f,HighLimit=%f,LowLimit=%f\n", ch, pparam->Range, pparam->Ratio, pparam->ZeroPoint, pparam->ChangeThreshold, pparam->HighLimit, pparam->LowLimit); _modbus_add_float(pkt + len, pparam->Range); len += 4; _modbus_add_float(pkt + len, pparam->Ratio); len += 4; _modbus_add_float(pkt + len, pparam->ZeroPoint); len += 4; _modbus_add_float(pkt + len, pparam->ChangeThreshold); len += 4; _modbus_add_float(pkt + len, pparam->HighLimit); len += 4; _modbus_add_float(pkt + len, pparam->LowLimit); len += 4; _modbus_checksum(pkt, len); len += 2; for (loop = 0; loop < 5; loop++) { serial_write(cau.serial_fd, pkt, len); DBG_ARRAY(DBG_M_CA_CAU, pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { DBG_ARRAY(DBG_M_CA_CAU, rxpkt, slen); if (slen == 8) break; else sleep(1); } } if (slen != 8) { return -1; } } return 0; } int _cau_set_user_param_ratio(Parameters_t *pbuf) { int len; int slen; int ch, loop; unsigned char *pkt = cau.modbus_send_buf; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { if (!pbuf->chClose[ch]) continue; Parameter_t *param = &(pbuf->chNew[ch]); len = _modbus_write_head(pkt, MB_FUNC_MULIT_WR, MB_USER_PARAM + ch * 0x10, 12); _modbus_add_float(pkt + len, param->span); //量程 len += 4; _modbus_add_float(pkt + len, param->ratio); //变比 len += 4; _modbus_add_float(pkt + len, 0); //零点(保留) len += 4; _modbus_add_float(pkt + len, 1000); //突变阈值 每通道独立开 len += 4; _modbus_add_float(pkt + len, 1000); //保留 len += 4; _modbus_add_float(pkt + len, 0); //保留 len += 4; _modbus_checksum(pkt, len); len += 2; DBG(DBG_M_CA_CAU, "CH%d_量程:%.2f 变比:%.2f\r\n",ch,param->span,param->ratio); for (loop = 0; loop < 5; loop++) { serial_write(cau.serial_fd, pkt, len); //print_raw_data(pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; slen = _cau_recv(rxpkt); if (slen != 8) { sleep(1); DBG(DBG_M_CA_CAU, "Send repeatedly in %d times.\r\n", loop+1); continue; } break; } } return 0; } int _cau_get_user_param_ratio(Parameters_t *pbuf) { int len; int slen; int ch, loop; unsigned char *pkt = cau.modbus_send_buf; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { //if (!pbuf->chClose[ch]) // continue; len = _modbus_write_head(pkt, MB_FUNC_MULIT_RD, MB_USER_PARAM + ch * 0x10, 4); _modbus_checksum(pkt, len); len += 2; for (loop = 0; loop < 5; loop++) { serial_write(cau.serial_fd, pkt, len); print_raw_data(pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { print_raw_data(rxpkt, slen); unsigned char *ppkt = rxpkt + 3; Parameter_t *param = &cau.cali_param.chOld[ch]; _cau_get_float_data(ppkt, ¶m->span); _cau_get_float_data(ppkt+4, ¶m->ratio); DBG(DBG_M_CA_CAU, "ch%d span=%f ratio=%f\r\n", ch, param->span, param->ratio); break; } } } return 0; } int _cau_power_on() { GPIO_CAU1_POWER_ON; sleep(5); return 0; } int _cau_power_off() { GPIO_CAU1_POWER_OFF; return 0; } int _cau_parase_real_data(unsigned char *rxpkt) { int ch; if((rxpkt[2] & 0xff) < 0x40) return -1; unsigned char *ppkt = rxpkt + 3 + 0x20; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { cau_real_data_t *preal = &cau.real_data; float val = 0; _cau_get_float_data(ppkt, &val); if(val <10.0 && val > 0.555) val = val + 0.055; preal->tag[ch] = val; ppkt += 4; DBG(DBG_M_CA_CAU, "ch%d:%f\r\n", ch, preal->tag[ch]); } return 0; } int _cau_get_meas_param() { int len, slen, loop; unsigned char *pkt = cau.modbus_send_buf; len = _modbus_write_head(pkt, MB_FUNC_MULIT_RD, MB_MEAS_PARAM, 0x20); _modbus_checksum(pkt, len); len += 2; for (loop = 0; loop < 5; loop++) { serial_write(cau.serial_fd, pkt, len); DBG_ARRAY(DBG_M_CA_CAU, pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { DBG_ARRAY(DBG_M_CA_CAU, rxpkt, slen); if (slen > 68) { _cau_parase_real_data(rxpkt); break; } else { sleep(1); } } if (slen <= 68) { LOG("cau collect error!!!"); } } return 0; } int _cau_get_meas_current_value() { int len; int slen; unsigned char *pkt = cau.modbus_send_buf; len = _modbus_write_head(pkt, MB_FUNC_MULIT_RD, MB_MEAS_VALUE, 0x10); _modbus_checksum(pkt, len); len += 2; serial_write(cau.serial_fd, pkt, len); DBG_ARRAY(DBG_M_CA_CAU, pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { int ch; DBG_ARRAY(DBG_M_CA_CAU, rxpkt, slen); unsigned char *ppkt = rxpkt + 3; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { cau_real_data_t *preal = &cau.real_data; _cau_get_float_data(ppkt, &preal->tag[ch]); ppkt += 4; DBG(DBG_M_CA_CAU, "ch%d:%.3f\r\n", ch, preal->tag[ch]); } } return 0; } /********************************************************************** * 函数名称: _cau_set_channel_segment_param * 功能描述: * 输入参数: * * 输出参数: pbuf * 返 回 值: 0:failure 1:success * 其它说明: * 修改日期: 2023/12/08 ***********************************************************************/ int _cau_set_channel_segment_param(Parameters_t *pbuf) { int ret = 0; int len; int slen; int ch, loop; unsigned char *pkt = cau.modbus_send_buf;; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { int i; if (!pbuf->chClose[ch]) continue; Parameter_t *param = &pbuf->chNew[ch]; len = _modbus_write_head(pkt, MB_FUNC_MULIT_WR, MB_CALI_PARAM + ch *0x20 , 30); DBG(DBG_M_CA_CAU, "[0x%04x]\n", MB_CALI_PARAM + ch *0x20); for (i = 0; i < 15; i++) { DBG(DBG_M_CA_CAU, " %.6f\n", param->param[i]); _modbus_add_float(pkt + len, param->param[i]); len += 4; } _modbus_checksum(pkt, len); len += 2; for (loop = 0; loop < 5; loop++) { usleep(300*1000); serial_write(cau.serial_fd, pkt, len); //print_raw_data(pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; slen = _cau_recv(rxpkt); //print_raw_data(rxpkt, slen); if (slen != 8) { sleep(1); DBG(DBG_M_CA_CAU, "Send repeatedly in %d times.\n", loop+1); continue; } break; } } return ret; } int _cau_get_channel_segment_param(Parameters_t *pbuf) { int len; int slen; int ch, loop; unsigned char *pkt = cau.modbus_send_buf;; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { //if (!pbuf->chClose[ch]) // continue; len = _modbus_write_head(pkt, MB_FUNC_MULIT_RD, MB_CALI_PARAM + ch *0x20, 30); _modbus_checksum(pkt, len); len += 2; for (loop = 0; loop < 5; loop++) { serial_write(cau.serial_fd, pkt, len); print_raw_data(pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { int j; print_raw_data(rxpkt, slen); unsigned char *ppkt = rxpkt + 3; Parameter_t *param = &cau.cali_param.chOld[ch]; DBG(DBG_M_CA_CAU, "ch%d param:\n", ch); for (j = 0; j < 15; j++) { _cau_get_float_data(ppkt + 4 * j, ¶m->param[j]); DBG(DBG_M_CA_CAU, "%f \n", param->param[j]); } break; } } } return 0; } int _cau_save_flash(Parameters_t *pbuf) { int len; int slen; unsigned char *pkt = cau.modbus_send_buf;; len = _modbus_write_head(pkt, MB_FUNC_MULIT_WR, MB_FAC_PARAM , 2); pkt[len++] = 0x12; pkt[len++] = 0x34; pkt[len++] = 0x55; pkt[len++] = 0xAA; _modbus_checksum(pkt, len); len += 2; serial_write(cau.serial_fd, pkt, len); print_raw_data(pkt, len); unsigned char *rxpkt = cau.modbus_recv_buf; if ((slen = _cau_recv(rxpkt)) > 0) { print_raw_data(rxpkt, slen); } return 0; } int _find_peripheral(const char *name) { int idx = -1; int i; for (i = 0; i < pparam_config->devSize; i++) { DevCfg_t *dev = &pparam_config->devs[i]; if (dev == NULL) continue; if (strcmp((char*)dev->devName,name) == 0) { idx = i; break; } } return idx; } int _cau_noraml_work() { unsigned int cur_time, diff_time; int id; id = _find_peripheral("CAU1"); if (id >= 0) { cur_time = time(NULL); diff_time = CPUMS_DIFF(cau.last_collect_time, cur_time); //LOG("diff_time = %d, space=%d\n", diff_time, pparam_config->devs[id].space); if (diff_time >= pparam_config->devs[id].space) { cau.last_collect_time = cur_time; _cau_power_on(); if (_cau_set_user_param() == 0) { //_cau_get_user_param_ratio(NULL); _cau_get_meas_param(); cau_collect_flag = 1; } _cau_power_off(); } } return 0; } int _cau_cali_start(Parameters_t *cali) { int point; for (point = 0; point < CALI_POINT_MAX; point++) { if (cali->isVoltage) { cl106d_setpower(cali->sample[point], 0); sleep(10); } else { cl106d_setpower(57.7, cali->sample[point]); DBG(DBG_M_CA_CAU, "--------电流校准点%d:%.4f __%.4f-------",point,cali->sample[point],cali->sample[point]*cali->turns); sleep(5); } int j; for (j = 0; j < 20; j++) // 1个点20个值 { usleep(20*1000); _cau_get_meas_current_value(); memcpy(&cau.cali_val.cauVal[point*20 + j], &cau.real_data, sizeof(cau_real_data_t)); } } return 0; } float sort(float *a,int len) { int i=0; int j; float t; float ret = 0; for(i=0;ia[j+1]) { t=a[j]; a[j]=a[j+1]; a[j+1]=t; } } } for(i = 5;i<15;i++) { ret += a[i]; } ret = ret*0.1; return ret; } int _cau_cali_calculation(Parameters_t *cali) { int ch; for (ch = 0; ch < MAX_CAU_CHANNEL; ch++) { if (!cali->chClose[ch]) continue; int i,j; for (i = 0; i < CALI_POINT_MAX; i++) { float sum; float temp[20] = {0}; for (j = 0; j < 20; j++) temp[j] = cau.cali_val.cauVal[j+i*20].tag[ch]; sum = sort(temp,20); cau.cali_val.cauAvg[i].tag[ch] = sum / cali->turns; cau.cali_val.cauAvg[i].tag[ch] = ( (float)( (int)( (cau.cali_val.cauAvg[i].tag[ch]+0.0005)*1000 ) ) )/1000; cali->chNew[ch].param[i*2+5] = cali->sample[i]/cau.cali_val.cauAvg[i].tag[ch]; //校准系数a DBG(DBG_M_CA_CAU, "ch[%d]-[%d] avg=%.3f a=%.3f\n", ch,i, cau.cali_val.cauAvg[i].tag[ch],cali->chNew[ch].param[i*2+5]); } } return 0; } int _cau_manual_calibratin(Parameters_t *cali) { int ch; _cau_get_channel_segment_param(cali); _cau_get_user_param_ratio(cali); for (ch = 0; ch < 8; ch++) { memcpy(cali->chNew[ch].param, cali->chOld[ch].param, sizeof(Parameter_t)); } printh("[%s:%d]Result ManualAdjust Status\r\n", __FUNCTION__, __LINE__); cau.send_data(DEBUG_ManualAdjust, (char *)cali, sizeof(Parameters_t)); while (1) { usleep(1000*1000); } return 0; } int _cau_calibration_process(Parameters_t *cali) { if (cali == NULL) { return -1; } if (cali->cauBoard != 1) { return -1; } if (cau.workstat == 1) { return 0; } printh("[%s:%d]\n", __FUNCTION__, __LINE__); char tmp[256] = {0}; sprintf(tmp, "CAU%d", cali->cauBoard); int id = _find_peripheral(tmp); if (id <= 0) goto err; _cau_power_off(); sleep(2); _cau_power_on(); sleep(5); if (cau.ismanual == 1) { _cau_manual_calibratin(cali); } if (cali->inAdjust == 2) goto get; _cau_set_channel_segment_param(cali); _cau_set_user_param_ratio(cali); if (cali->inAdjust == 3) goto init; cl106d_init(); if (!cl106d_connet()) { cali->err = 4; printh("cl106d_connet err.\n"); goto err; } _cau_cali_start(cali); _cau_cali_calculation(cali); // 写参数 _cau_set_channel_segment_param(cali); sleep(2); cau.workstat = 1; init: //保存flash _cau_save_flash(cali); sleep(2); _cau_power_off(); _cau_power_on(); get: _cau_get_channel_segment_param(cali); _cau_get_user_param_ratio(cali); err: // 此处增加回调,返回给管理工具; printh("[%s:%d]rebackAdjustResult\r\n", __FUNCTION__, __LINE__); cau.send_data(DEBUG_ADJUST_RESULT, (char *)cali, sizeof(Parameters_t)); return 0; } /* CAU采集处理函数. */ void *_cau_data_handle(void *arg) { cau.serial_fd = serial_open("/dev/ttymxc1", 921600); if (cau.serial_fd < 0) { log_err(LOG_CAU, "serial_open failed!\n"); return NULL; } sleep(1); //_cau_set_user_param(); while(1) { switch (cau.cali_param.inAdjust) { case 0: _cau_noraml_work(); break; case 4: break; default: _cau_calibration_process(&cau.cali_param); break; } pwr.vbat = _pwr_read_vbat(); pwr.vsc = _pwr_read_vsc(); pwr.vout = _pwr_read_vout(); //LOG("vbat:%d vsc:%d vout:%d", pwr.vbat, pwr.vsc, pwr.vout); usleep(100*1000); } return NULL; } /* CAU采集处理函数. */ void *_cau_recv_handle(void *arg) { while(1) { sleep(1); } return NULL; } int32_t _cau_handle_init_common(void) { struct sched_param param; pthread_attr_t attr; pthread_t pid; int32_t rv = 0; /* 配置线程RR调度, 优先级79 */ pthread_attr_init(&attr); param.sched_priority = 79; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _cau_data_handle, NULL); if (rv != 0) { log_err(LOG_CAU, "PD can't create CAU data pthread %d!", rv); return E_ERROR; } else { thread_m_add("CA_CAU_CAPTURE", pid); } pthread_attr_destroy(&attr); #if 0 /* 初始化 CAU 收包线程. */ /* 配置线程RR调度, 优先级80 */ pthread_attr_init(&attr); param.sched_priority = 80; pthread_attr_setschedpolicy(&attr, SCHED_RR); pthread_attr_setschedparam(&attr, ¶m); pthread_attr_setinheritsched(&attr, PTHREAD_EXPLICIT_SCHED); rv = pthread_create(&pid, &attr, _cau_recv_handle, NULL); if (rv != 0) { log_err(LOG_CAU, "CAU can't create recv pthread %d!", rv); return E_SYS_CALL; } else { thread_m_add("CA_CAU_RECV", pid); } pthread_attr_destroy(&attr); #endif return E_NONE; } /* Interface functions -------------------------------------------------------*/ int32_t cau_handle_init(void) { /* 开启cau电源 */ //GPIO_CAU1_POWER_ON; memset(&cau, 0, sizeof(cau_t)); cau.serial_fd = -1; cau.last_collect_time = time(NULL); cau.send_data = _debug_pkt_send_data; /* 初始化模块. */ LD_E_RETURN(DBG_M_CA_CAU_ERR, _cau_handle_init_common()); //cmd_install_element(CONFIG_NODE, &csg_server_set_cmd); /* 注册配置保存函数 */ return E_NONE; } static int _pwr_read_adc(int fd) { char buffer[16]={0}; int ret, cnt = 2; do{ fsync(fd); lseek(fd,0,SEEK_SET); ret = read(fd,buffer,sizeof(buffer)); if(ret <= 0) usleep(1000); else break; }while(cnt--); if(ret <= 0) return -2; return (atoi(buffer) * 6600 /4096) + 100; } int _pwr_read_vsc(void) { static int fd = 0; const char *path = "/sys/bus/iio/devices/iio:device0/in_voltage1_raw"; if(fd <= 0) { fd = open(path, O_RDONLY); if(fd <= 0) { LOG("读VSC-ADC失败,PATH = %s",path); return -1; } } return _pwr_read_adc(fd); } int _pwr_read_vbat(void) { static int fd = 0; const char *path = "/sys/bus/iio/devices/iio:device0/in_voltage2_raw"; if(fd <= 0) { fd = open(path, O_RDONLY); if(fd <= 0) { LOG("读VBAT-ADC失败,PATH = %s",path); return -1; } } return _pwr_read_adc(fd); } int _pwr_read_vout(void) { static int fd = 0; const char *path = "/sys/bus/iio/devices/iio:device0/in_voltage3_raw"; if(fd <= 0) { fd = open(path, O_RDONLY); if(fd <= 0) { LOG("读VOUT-ADC失败,PATH = %s",path); return -1; } } return _pwr_read_adc(fd); } #endif