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.

651 lines
15 KiB
C

/*
* ctrl_process.c
*
* Created on: May 4, 2015
* Author: root
*/
#include "common.h"
#include <stdlib.h>
#include "thread.h"
#include <pthread.h>
#include "msq.h"
#include "serial.h"
#include "ysp_debug.h"
#include <time.h>
#define MAX_SEND_TIME_CURVE 5
#define MAX_SAVE_TEMP 256
mqd_t ctrl_tx_mq;//
extern int ctrl_fd;//控制信号发送串口句柄
COM_HEADER ctrl_tx_header;
COM_HEADER ctrl_rx_header;
OUTPUT_TYPE_DEF ctrl_tx_data;
unsigned char ctrl_tx_buf[128];//串口发送缓冲区
unsigned char ctrl_rx_buf[128];//
unsigned char ctrl_tx_mq_buf[CTRL_TX_MESSAGE_SIZE];//消息队列接收缓冲区
static const unsigned int timeout_curve[MAX_SEND_TIME_CURVE]={
200000,300000,500000,1000000,2000000
};//发送间隔
float latest_spz_temp[MAX_SAVE_TEMP];
unsigned char spz_save_index=0;
/*
static const char *relay_name[]={
"LJ_FAN",
"SAMPLE_FAN",
"YV6",
"YV4",
"no_use",
"no_use",
"YV7",
"YV14",
"YV13",
"YV10",
"YV11",
"YV12",
"no",
"no",
"no",
"YV16",
"YV17",
"YV18",
"YV19",
"YV20",
"YV21",
"NO",
"NO",
"NO",
"NO",
"NO",
"NO",
"NO",
"NO",
"NO",
"NO",
};*/
void arm_var_f32(float *pSrc,unsigned int blockSize,float *pResult)
{
float sum = (float) 0.0;
float meanOfSquares, mean, in, squareOfMean;
unsigned int blkCnt;
float *pIn;
pIn = pSrc;
blkCnt = blockSize>>2u;
while(blkCnt>0u)
{
in = *pSrc++;
sum += in * in;
in = *pSrc++;
sum += in * in;
in = *pSrc++;
sum += in * in;
in = *pSrc++;
sum += in * in;
blkCnt--;
}
blkCnt = blockSize % 0x4u;
while(blkCnt>0u)
{
in = *pSrc++;
sum += in * in;
blkCnt--;
}
meanOfSquares = sum/((float) blockSize-1.0f);
sum = 0.0f;
blkCnt = blockSize>>2u;
pSrc = pIn;
while(blkCnt>0u)
{
sum += *pSrc++;
sum += *pSrc++;
sum += *pSrc++;
sum += *pSrc++;
blkCnt--;
}
blkCnt = blockSize%0x4u;
while(blkCnt>0u)
{
sum += *pSrc++;
blkCnt--;
}
mean = sum/(float)blockSize;
squareOfMean = (mean * mean) *(((float)blockSize)/((float)blockSize-1.0f));
*pResult = meanOfSquares - squareOfMean;
}
void save_spz_temp(float *temp)
{
latest_spz_temp[spz_save_index++]=*temp;
}
int get_spz_stable(float *delt)
{
lock_input_data();
arm_var_f32(latest_spz_temp,sizeof(latest_spz_temp)/sizeof(float),delt);
unlock_input_data();
/*if(*delt<SPZ_TEMP_DELT)
return 0;
return 1; */
return 0;
}
int set_gpio_output(int index,int val)
{
static int iofd[4]={-1,-1,-1,-1};
char c;
if(iofd[index]<0)
{
if((iofd[index]=open("/sys/class/leds/mcu_intr/brightness",O_WRONLY))==-1)//打开设备
{
#ifdef DEBUG
printf("open %s failed \n",io_dev_name[index]);
#endif
return -1;
}
}
c = val?'1':'0';
return write(iofd[index],&c,1);//写数据到设备
}
int send_ctrl_frame(int dev_fd,COM_HEADER *head,void *data,unsigned int data_length)
{
unsigned int data_bytes;
int ret;
data_bytes=sizeof(COM_HEADER)+data_length;
ctrl_tx_buf[0]=0xAA;
ctrl_tx_buf[1]=0x1;//address
ctrl_tx_buf[2]=(unsigned char)data_bytes;
ctrl_tx_buf[3]=(unsigned char)(data_bytes>>8);
ctrl_tx_buf[4]=0x01;//cmd
memcpy(&ctrl_tx_buf[5],head,sizeof(COM_HEADER));//拷贝信息头
memcpy(&ctrl_tx_buf[5+sizeof(COM_HEADER)],data,data_length);//拷贝数据
ctrl_tx_buf[5+data_bytes]=cal_sum(ctrl_tx_buf,5+data_bytes);
ctrl_tx_buf[6+data_bytes]=0x55;
set_gpio_output(0,1);
ret=SerialWrite(dev_fd,ctrl_tx_buf,7+data_bytes);
//usleep(10000);
set_gpio_output(0,0);
return ret;
}
//控制数据重发
int ctrl_data_retrans(void)
{
static mqd_t ctrl_tx_slave_mq=(mqd_t)-1;
unsigned char dumy_msg[16];
if(ctrl_tx_slave_mq==-1)
{
if((ctrl_tx_slave_mq= open_mq(CTRL_TX_MQ))==((mqd_t)-1))
return -1;
}
if(mq_send(ctrl_tx_slave_mq,(const char *)dumy_msg,sizeof(dumy_msg),CTRL_MQ_PRIO)==-1)
return -2;
return 0;
}
void show_hex(unsigned char *buf,unsigned int len)
{
unsigned int i;
for(i=0;i<len;i++)
{
printf("0x%2x ",*buf++);
if((i+1)%16==0)
{
printf("\r\n");
}
}
printf("\r\n\r\n");
}
//获取IO输入状态
unsigned int io_get(unsigned int i)
{
unsigned int val;
lock_input_data();
memcpy(&val,&my_input_data.io_input,sizeof(val));
unlock_input_data();
if((val&(1<<i))!=0)
return ON;
return OFF;
}
int get_pres_vol(unsigned int ch,float *fval)
{
lock_input_data();
*fval=my_input_data.PresVolt[ch%5];
unlock_input_data();
return 0;
}
//获取通道温度
int get_temperature(unsigned int ch,float *fval)
{
if(ch>=5)
return -1;
if((my_input_data.work_state&(1<<ch))!=0)
return -2;
lock_input_data();
*fval=my_input_data.temperature[ch%5];
unlock_input_data();
return 0;
}
/*
//电流转换成压力
void CurrCnvToPres(float *raw_data,float *fval)
{
float temp;
temp=(0.82846*(*raw_data))/3000;
*fval=(0.2*temp-0.1);
}
//获取电流通道压力
void CurrCnvToPresEx(unsigned int ch,float *fval)
{
float temp;
get_curr(ch,&temp);
CurrCnvToPres(&temp,fval);
}*/
//电压转换成压力
/*/void VoltCnvToPres(unsigned int ch,float *fval)
{
if(fval!=NULL)
*fval=(0.4*(*fval));
}*/
//获取通道压力
int VoltCnvToPresEx(unsigned int ch,float *fval)
{
float temp;
get_pres_vol(ch,&temp);
//VoltCnvToPres(&temp);
if(fval!=NULL)
*fval=(my_para_data.mach_run_para.pres_fac[ch].a)*temp+(my_para_data.mach_run_para.pres_fac[ch].b);
//*fval=temp;
return 0;
}
//获取通道压力
int get_presure(unsigned int ch,float *fval)
{
if(ch>=5)
return -1;
//if((my_input_data.work_state&(1<<ch))!=0)
// return -2;
//lock_input_data();
VoltCnvToPresEx(ch,fval);
//unlock_input_data();
return 0;
}
void relay_clr(unsigned int mask)
{
lock_output_data();
my_output_data.relay_ctrl&=mask;
unlock_output_data();
ctrl_data_retrans();
}
void set_man_out(unsigned int ch,unsigned int val)
{
lock_output_data();
my_output_data.man_output[ch]=val;
unlock_output_data();
//ctrl_data_retrans();
}
void set_pid_ch(unsigned int ch,unsigned int en_dis,unsigned int mode)
{
//unsigned int val;
lock_output_data();
ch=ch%4;
if(my_output_data.pid_en[ch]!=en_dis)
{
if(mode)
ctrl_data_retrans();
}
my_output_data.pid_en[ch]=en_dis;
unlock_output_data();
}
//设置目标温度
void set_pid_temp(unsigned int ch,float *temp,unsigned int mode)
{
lock_output_data();
ch&=3;
my_output_data.temperature[ch]=*temp;
if(mode)
{
ctrl_data_retrans();
}
unlock_output_data();
}
void relay_set(unsigned int i,unsigned char val,unsigned int mode)
{
unsigned int tmp;
unsigned int pos=(1<<i);
int retrans_flg=0;
if(i>31)
return;
lock_output_data();
tmp=my_output_data.relay_ctrl;
if(val!=OFF)//=ON
{
tmp|=pos;
}
else//=OFF
{
tmp&=(~pos);
}
if(tmp!=my_output_data.relay_ctrl)
{
my_output_data.relay_ctrl=tmp;
retrans_flg=1;
}
unlock_output_data();
if(retrans_flg)
{
//printf("relay=%x %x %x %x\n",my_output_data.relay_ctrl[0],my_output_data.relay_ctrl[1],my_output_data.relay_ctrl[2],my_output_data.relay_ctrl[3]);
if(mode)
ctrl_data_retrans();
}
//show_hex(my_output_data.relay_ctrl,8);
}
void relay_set_all(unsigned int val,unsigned int mode)
{
unsigned int tmp;
int retrans_flg=0;
lock_output_data();
tmp=my_output_data.relay_ctrl;
if(tmp!=val)
{
my_output_data.relay_ctrl=val;
retrans_flg=1;
}
unlock_output_data();
if(retrans_flg)
{
if(mode)
ctrl_data_retrans();
}
}
unsigned int relay_get(unsigned int i,unsigned char *val)
{
unsigned int pos=(1<<i);
unsigned int ret;
lock_input_data();
if((my_input_data.relay_state&pos)!=0)
{
ret=ON;
}
else
{
ret=OFF;
}
if(val!=NULL)
*val=ret;
unlock_input_data();
return ret;
}
unsigned int relay_get_all(unsigned int *val)
{
unsigned int ret;
lock_input_data();
ret=my_input_data.relay_state;
if(val!=NULL)
*val=ret;
unlock_input_data();
return ret;
}
void ctrl_tx_routine(void *arg)
{
unsigned int send_index=0;
unsigned int curr_timeout;
if((ctrl_tx_mq=create_mq(CTRL_TX_MQ,CTRL_TX_MAX_MESSAGE,CTRL_TX_MESSAGE_SIZE))<0)
{
printf("create ctrl tx message queue failed\n");
exit(1);
}
ctrl_tx_header.stNum=0;
ctrl_tx_header.sqNum=0;
while(1)
{
curr_timeout=timeout_curve[send_index%MAX_SEND_TIME_CURVE];
if(recv_mq_wait(ctrl_tx_mq,(void *)ctrl_tx_mq_buf,sizeof(ctrl_tx_mq_buf),curr_timeout)>0)
{
//清空消息队列?
++ctrl_tx_header.stNum;
if(ctrl_tx_header.stNum==0)
++ctrl_tx_header.stNum; //skip over 0
ctrl_tx_header.sqNum = 0; //reset sqNum to 0 on each state change
send_index=0;
//show_time("tx");
//printf("state change:stNum=%d sqNum=%d\r\n",ctrl_tx_header.stNum,ctrl_tx_header.sqNum);
//LOG_DEBUG(COMUNICATION_TRACE_DEBUG,"state change:stNum=%d sqNum=%d\n",ctrl_tx_header.stNum,ctrl_tx_header.sqNum);
usleep(10000);
}
else
{
if(send_index<(MAX_SEND_TIME_CURVE-1))
{
send_index++;
}
++ctrl_tx_header.sqNum;
//printf("stNum=%d sqNum=%d\n",ctrl_tx_head.stNum,ctrl_tx_head.sqNum);
}
//发送数据
lock_output_data();
memcpy(&my_output_data.pid_para[0],&my_para_data.mach_run_para.pid_type_def[PID_SPZ],sizeof(PID_TYPE_DEF));
memcpy(&my_output_data.pid_para[1],&my_para_data.mach_run_para.pid_type_def[PID_LJ],sizeof(PID_TYPE_DEF));
memcpy(&my_output_data.pid_para[2],&my_para_data.mach_run_para.pid_type_def[PID_SAMPLE],sizeof(PID_TYPE_DEF));
my_output_data.temperature[TEMP_SPZ]=my_para_data.mach_run_para.temperature[TEMP_SPZ];
my_output_data.temperature[TEMP_LJ]=my_para_data.mach_run_para.temperature[TEMP_LJ];
my_output_data.temperature[TEMP_SAM]=my_para_data.mach_run_para.temperature[TEMP_SAM];
//memcpy(my_output_data.pid_en,my_para_data.mach_run_para.pid_en,sizeof(my_output_data.pid_en));
my_output_data.man_output[0]=(unsigned short)my_para_data.mach_run_para.volt_output[0];
my_output_data.man_output[2]=0;
my_output_data.man_output[3]=0;
unlock_output_data();
if(send_ctrl_frame(ctrl_fd,&ctrl_tx_header,&my_output_data,sizeof(my_output_data))<(sizeof(my_output_data)+7))
{
LOG_DEBUG(COMUNICATION_EEROR_DEBUG,"send data failed\n");
}
}
}
int process_message(unsigned char *msg_buf,unsigned int msg_length)
{
static unsigned int spz_index=0;
//unsigned int i=0;
unsigned int length;
COM_HEADER received_header;
if(msg_length<(7+sizeof(COM_HEADER)))
return -1;
if(msg_buf[0]!=0xAA)
return -2;
if(msg_buf[msg_length-1]!=0x55)
return -3;
length=(unsigned int)256*msg_buf[3]+msg_buf[2];
if(length!=(msg_length-7))
return -4;
if(chk_sum(msg_buf,msg_length-2,msg_buf[msg_length-2])!=0)
return -5;
memcpy(&received_header,msg_buf+5,sizeof(COM_HEADER));
if(received_header.stNum!=ctrl_rx_header.stNum)
{
//数据有变化
//printf("state change stNum=%d sqNum=%d\n",received_header.stNum,received_header.sqNum);
}
else if(received_header.sqNum!=(ctrl_rx_header.sqNum+1))
{
//丢帧了
printf("lost frame old_sq=%d new_sq=%d\n",ctrl_rx_header.sqNum,received_header.sqNum);
}
memcpy(&ctrl_rx_header,&received_header,sizeof(COM_HEADER));
//获取信号量
lock_input_data();
//拷贝数据到全局缓冲
memcpy(&my_input_data,&msg_buf[5+sizeof(COM_HEADER)],sizeof(my_input_data));
//保存最近的色谱柱温度,用于分析温度是否稳定
spz_index++;
if((spz_index&3)==0)
{
save_spz_temp(&my_input_data.temperature[TEMP_SPZ]);
}
//printf("temp=%f %f %f %f pres=%f %f\n",my_input_data.temperature[0],my_input_data.temperature[1],my_input_data.temperature[2],my_input_data.temperature[3],my_input_data.PresVolt[6],my_input_data.Current[0]);
//释放信号量
unlock_input_data();
//printf("io_input=0x%2x 0x%2x\n",my_input_data.io_input[0],my_input_data.io_input[1]);
return 0;
}
//接收控制MCU发送的信息,并存入共享内存
void ctrl_rx_routine(void *arg)
{
int curr_length,last_length,rx_length;
int recv_error_tick=0;
pthread_t ctrl_tx_thread;
rx_length=0; //本次接收的字节长度
last_length=0;//上一次接收的字节长度
//打开全局设备
if((ctrl_fd=SerialOpen(CTRL_SERIAL_DEV,CTRL_SERIAL_SPEED))==-1)
{
LOG_DEBUG(COMUNICATION_EEROR_DEBUG,"open ctrl serial device failed\n");
pthread_exit(1);
}
if((ctrl_tx_thread=task_create(ctrl_tx_routine,NULL,0,0))==-1)
{
LOG_DEBUG(COMUNICATION_EEROR_DEBUG,"create ctrl_tx_routine failed\n");
close(ctrl_fd);
pthread_exit(2);
}
my_input_data.com_flg=1;
while(1)
{
usleep(30000);//wait 30ms
curr_length=read(ctrl_fd,ctrl_rx_buf+rx_length,sizeof(ctrl_rx_buf)-rx_length);
if(curr_length>0)
{
//存入缓冲区
rx_length+=curr_length;
last_length=curr_length;
if(rx_length>=sizeof(ctrl_rx_buf))
{
//printf("code1=%d rx_length=%d\n",process_message(ctrl_rx_buf,rx_length),rx_length);//处理消息
if(process_message(ctrl_rx_buf,rx_length)==0)
{
if(recv_error_tick>200)
{
LOG_DEBUG(ERROR_DEBUG,"ctrl mcu recovery\n");
}
recv_error_tick=0;
if(comunication_flg==0)
{
ysp_glb_data.MoDevConf.v.stVal=0;
ysp_glb_data.MoDevConf.q=0;
ysp_glb_data.MoDevConf.t.secs=(unsigned int)time(NULL);
}
comunication_flg=1;
}
rx_length=0;
memset(ctrl_rx_buf,0,sizeof(ctrl_rx_buf));
}
}
else
{
if(last_length>0)
{
//printf("code2=%d rx_length=%d\n",process_message(ctrl_rx_buf,rx_length),rx_length);//处理消息
if(process_message(ctrl_rx_buf,rx_length)==0)
{
if(recv_error_tick>200)
{
LOG_DEBUG(ERROR_DEBUG,"ctrl mcu recovery\n");
}
recv_error_tick=0;
if(comunication_flg==0)
{
ysp_glb_data.MoDevConf.v.stVal=0;
ysp_glb_data.MoDevConf.q=0;
ysp_glb_data.MoDevConf.t.secs=time(NULL);
}
comunication_flg=1;
}
memset(ctrl_rx_buf,0,sizeof(ctrl_rx_buf));
}
else
{
//出错处理
recv_error_tick++;
if(recv_error_tick>256)
{
comunication_flg=0;
if(recv_error_tick==257)
{
ysp_glb_data.MoDevConf.v.stVal=1;
ysp_glb_data.MoDevConf.q=0;
ysp_glb_data.MoDevConf.t.secs=(unsigned int)time(NULL);
LOG_DEBUG(ERROR_DEBUG,"ctrl mcu lost\n");
}
}
}
last_length=0;
rx_length=0;
}
}
//wait ctrl_tx_thread exit
close(ctrl_fd);
}
int ctrl_init(void)
{
pthread_t ctrl_rx_thread;
if((ctrl_rx_thread=task_create(ctrl_rx_routine,NULL,0,0))==-1)
{
LOG_DEBUG(COMUNICATION_EEROR_DEBUG,"create ctrl_tx_routine failed\n");
return 1;
}
return 0;
}