You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

882 lines
22 KiB
C

/* Includes ------------------------------------------------------------------*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef CFG_DEV_TYPE_LAND_CA
/* 标准C库头文件. */
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
/* 用户代码头文件. */
#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)
{
DBG(DBG_M_CA_CAU_ERR, "get cau value failed.\n");
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, &param->span);
_cau_get_float_data(ppkt+4, &param->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, &param->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;
}
else
{
_cau_reset_real_data();
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;i<len-1;i++) //len-1
{
for(j=0;j<len-i-1;j++)
{
if(a[j]>a[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, &param);
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, &param);
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);
}
void _cau_reset_real_data()
{
cau_real_data_t *pval = &cau.real_data;
memset(pval, 0, sizeof(cau_real_data_t));
}
int _cau_get_current_values(float *fdestArr)
{
float valist[24] = {0};
int chswitch;
int i;
cau_real_data_t *pval = &cau.real_data;
memcpy(valist, pval->tag, sizeof(pval->tag));
for (i = 0; i < 11; i++)
{
chswitch = pparam_config->cauParam[i].chSwitch;
if (chswitch > 0)
fdestArr[chswitch - 1] = valist[i];
}
return 0;
}
#endif