模糊PID的c语言算法
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
#include <cvirte.h>
#include <userint.h>
#include "succus.h"
#include <rs232.h>
#include <ansi_c.h>
#include <formatio.h>
#include <math.h>
#include <string.h>
#define parameterPID 0.1 //PID常数
#define maxcontroldata 10 //最大控制量
#define parameterfuzzy 12 //模糊控制常数
#define Pe1 4 //隶属度范围
#define Pe2 8
#define Psess1 2
#define Psess2 4
#define parainput 100 //输入常数
static int panelHandle;
static int L_PIDstart; //运行标签
static int L_fuzzystart;
static float P_control; //获得参数
static float I_control;
static float D_control;
static int whatmode;
static float model_K; //模型参数
static float model_T;
static float model_t;
static float cycle; //设定周期
static float savedata[3]; //储存偏差量
static float savecontrol[20]; //存储控制量
static float result[2]; //存储仿真结果
static float getsum;
static char senddata[22]; //通信协议
static char recievedata[18];
static char nak[6];
static char ack[6];
int main (int argc, char *argv[])
{
if (InitCVIRTE (0, argv, 0) == 0)
return -1; /* out of memory */
if ((panelHandle = LoadPanel (0, "succus.uir", PANEL)) < 0)
return -1;
OpenComConfig (2, "", 9600, 0, 8, 1, 512, 512); //打开串口
senddata[0] = 5; //构造协议senddata[1] = '0';
senddata[2] = 'A';
senddata[3] = 'F';
senddata[4] = 'F';
senddata[5] = 'W';
senddata[6] = 'W';
senddata[7] = '0';
senddata[8] = 'D';
senddata[9] = '5';
senddata[10] = '0';
senddata[11] = '6';
senddata[12] = '4';
senddata[13] = '0';
senddata[14] = '1';
senddata[21] = 0;
recievedata[0] = 5;
recievedata[1] = '0';
recievedata[2] = 'A';
recievedata[3] = 'F';
recievedata[4] = 'F';
recievedata[5] = 'W';
recievedata[6] = 'R';
recievedata[7] = '0';
recievedata[8] = 'D';
recievedata[9] = '5';
recievedata[10] = '0';
recievedata[11] = '0';
recievedata[12] = '0';
recievedata[13] = '0';
recievedata[14] = '1';
recievedata[15] = '4';
recievedata[16] = '0';
recievedata[17] = 0;
nak[0] = 21;
nak[1] = '0';
nak[2] = 'A';
nak[3] = 'F';
nak[4] = 'F';
nak[5] = 0;
ack[0] = 6;
ack[1] = '0';
ack[2] = 'A';
ack[3] = 'F';
ack[4] = 'F';
ack[5] = 0;
FlushInQ (2);
FlushOutQ (2);
DisplayPanel (panelHandle);
RunUserInterface ();
CloseCom (2);
DiscardPanel (panelHandle);
return 0;
}
int CVICALLBACK autosetPIDCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
SetCtrlVal (panelHandle, PANEL_PARAMETER_P, 20.0);
SetCtrlVal (panelHandle, PANEL_PARAMETER_I, 0.0);
SetCtrlVal (panelHandle, PANEL_PARAMETER_D, 0.0);
break;
}
return 0;
}
int CVICALLBACK fuzzycontrolCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
L_fuzzystart = 1;
GetCtrlVal (panelHandle, PANEL_WORKMODE, &whatmode); //获得工作状态
if(whatmode == 0)
{
GetCtrlVal (panelHandle, PANEL_EMLUATOR_K, &model_K); //模型
GetCtrlVal (panelHandle, PANEL_EMLUATOR_T, &model_T);
GetCtrlVal (panelHandle, PANEL_EMLUATOR_t, &model_t);
}
GetCtrlVal (panelHandle, PANEL_SAMPLINGTIME, &cycle);
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_INTERVAL, cycle);
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_ENABLED, 1); //获得抽样时间。
并开始运行
ClearStripChart (panelHandle, PANEL_STRIPCHART); //版面清空
SetCtrlAttribute (panelHandle, PANEL_FUZZYCONTROL, ATTR_DIMMED, 1); //按键关闭
SetCtrlAttribute (panelHandle, PANEL_STARTPID, ATTR_DIMMED, 1);
SetCtrlAttribute (panelHandle, PANEL_AUTOSETPID, ATTR_DIMMED, 1);
break;
}
return 0;
}
int CVICALLBACK endopjCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
QuitUserInterface (0);
break;
}
return 0;
}
int CVICALLBACK stopCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
int i;
switch (event)
{
case EVENT_COMMIT:
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_ENABLED, 0); //关闭Timer
L_PIDstart = 0; //清标签
L_fuzzystart = 0;
SetCtrlAttribute (panelHandle, PANEL_FUZZYCONTROL, ATTR_DIMMED, 0); //按键开启
SetCtrlAttribute (panelHandle, PANEL_STARTPID, ATTR_DIMMED, 0);
SetCtrlAttribute (panelHandle, PANEL_AUTOSETPID, ATTR_DIMMED, 0);
//数据清空
for(i = 0; i<3; i++)
savedata[i] = 0;
for(i = 0; i<20; i++)
savecontrol[i] = 0;
for(i = 0; i<2; i++)
result[i] = 0;
getsum = 0;
break;
}
return 0;
}
int CVICALLBACK TimerCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
float givedata; //目标量
int i,j; //循环量
int num; //滞后数
float draw[3]; //画点
float getoutput; //输出量
float ADdata;
int setsenddata; //输出控制量
int efficacy; //和效验
int strLen; //发送数据长度
char responsion[5];
char getADdata[10];
float ess[5]; //记录隶属度
float dess[5];
float outcontrol[4];
float makematrix[5][5];
switch (event)
{
case EVENT_TIMER_TICK:
GetCtrlVal (panelHandle, PANEL_SETGIVE, &givedata);
if(whatmode == 0)
getoutput = result[1];
else
{
FlushInQ (2);
ComWrt (2, recievedata, strlen(recievedata));
strLen = 10;
ComRd (2, getADdata, strLen);
for(i = 5; i < 9; i++)
if(getADdata[i] >= '0' && getADdata[i] <= '9')
getADdata[i] = getADdata[i] - '0';
else
getADdata[i] = getADdata[i] - 'A' + 10;
ADdata = (float)(getADdata[5] * 4096 + getADdata[6] * 256 + getADdata[7] * 16 + getADdata[8]);
getoutput = ((ADdata - 678) / 2722.0) * parainput;
if(getoutput < 0) //678 3400
getoutput = 0;
FlushInQ (2);
ComWrt (2, ack, strlen(ack));
}
if(L_PIDstart == 1)
{
savedata[0] = savedata[1]; //控制算法实现
savedata[1] = savedata[2];
savedata[2] = givedata - getoutput;
if(savedata[2] < 10 && savedata[2] > -10)
getsum = getsum + savedata[2];
for(i = 0; i < 19; i ++)
savecontrol[i] = savecontrol[i+1];
savecontrol[19] = P_control * savedata[2] + D_control * (savedata[2] - savedata[1]) + I_control * getsum;
savecontrol[19] = savecontrol[19] * parameterPID; //使用位置试PID
//savecontrol[19] = savecontrol[19] + savecontrol[18];
if(savecontrol[19] < 0)
savecontrol[19] = 0; //控制信号最少为零if(savecontrol[19] > maxcontroldata)
savecontrol[19] = maxcontroldata; //控制信号饱和
SetCtrlVal (panelHandle, PANEL_DISPLAY_CONTROL, (savecontrol[19] * 10));
}
else if(L_fuzzystart == 1)
{
for(i = 0; i < 5; i ++)
ess[i] = 0;
for(i = 0; i < 5; i ++)
dess[i] = 0;
for(i = 0; i < 4; i ++)
outcontrol[i] = 0;
savedata[1] = savedata[2]; //记录偏差;savedata[0]为偏差变化
savedata[2] = givedata - getoutput;
savedata[0] = savedata[2] - savedata[1];
if(savedata[2] < -Pe2) //开始计算隶属度
ess[0] = 1;
else if(savedata[2] >= -Pe2 && savedata[2] < -Pe1)
{
ess[0] = (savedata[2] + Pe2) / (Pe2 - Pe1);
ess[1] = (Pe1 - savedata[2]) / (Pe2 - Pe1);
}
else if(savedata[2] >= -Pe1 && savedata[2] < 0)
{
ess[1] = (savedata[2] + Pe1) / (Pe2 - Pe1);
ess[2] = ( - savedata[2]) / (Pe2 - Pe1);
}
else if(savedata[2] >= 0 && savedata[2] < Pe1)
{
ess[2] = savedata[2] / (Pe2 - Pe1);
ess[3] = (Pe1 - savedata[2]) / (Pe2 - Pe1);
}
else if(savedata[2] >= Pe1 && savedata[2] < Pe2)
{
ess[3] = (savedata[2] - Pe1) / (Pe2 - Pe1);
ess[4] = (Pe2 - savedata[2]) / (Pe2 - Pe1);
}
else if(savedata[2] >= Pe2)
{
ess[4] = 1;
}
else;
if(savedata[0] < -Psess2) //开始计算偏差变化的隶属度dess[0] = 1;
else if(savedata[0] >= -Psess2 && savedata[0] < -Psess1)
{
dess[0] = (savedata[0] + Psess2) / (Psess2 - Psess1);
dess[1] = (Psess1 - savedata[0]) / (Psess2 - Psess1);
}
else if(savedata[0] >= -Psess1 && savedata[0] < 0)
{
dess[1] = (savedata[0] + Psess1) / (Psess2 - Psess1);
dess[2] = ( - savedata[0]) / (Psess2 - Psess1);
}
else if(savedata[0] >= 0 && savedata[0] < Psess1)
{
dess[2] = savedata[0] / (Psess2 - Psess1);
dess[3] = (Psess1 - savedata[0]) / (Psess2 - Psess1);
}
else if(savedata[0] >= Psess1 && savedata[0] < Psess2)
{
dess[3] = (savedata[0] - Psess1) / (Psess2 - Psess1);
dess[4] = (Psess2 - savedata[0]) / (Psess2 - Psess1);
}
else if(savedata[0] >= Psess2)
{
dess[4] = 1;
}
else;
for(i = 0; i < 5; i++)
for(j = 0; j < 5; j++)
makematrix[i][j] = ess[i] > dess[j] ? dess[j] : ess[i];
if(makematrix[4][4] > 0)
{
outcontrol[3] = makematrix[4][4];
}
if(makematrix[4][2] > 0 || makematrix[4][3] > 0)
{
outcontrol[2] = makematrix[4][2] > makematrix[4][3] ? makematrix[4][2] : makematrix[4][3];
}
if(makematrix[2][4] > 0 || makematrix[4][1] > 0 || makematrix[3][2] > 0 || makematrix[3][3] > 0 ||
makematrix[3][4])
{
outcontrol[1] = makematrix[2][4] > makematrix[4][1] ? makematrix[2][4] : makematrix[4][1];
outcontrol[1] = makematrix[3][2] > outcontrol[1] ? makematrix[3][2] : outcontrol[1];
outcontrol[1] = makematrix[3][3] > outcontrol[1] ? makematrix[3][3] : outcontrol[1];
outcontrol[1] = makematrix[3][4] > outcontrol[1] ? makematrix[3][4] : outcontrol[1];
}
if(makematrix[1][4] > 0 || makematrix[1][3] > 0 || makematrix[2][3] > 0 || makematrix[2][2] > 0 ||
makematrix[2][1] > 0 || makematrix[3][1] > 0 || makematrix[3][0] > 0 || makematrix[4][0] > 0)
{
outcontrol[0] = makematrix[1][4] > makematrix[1][3] ? makematrix[1][4] : makematrix[1][3];
outcontrol[0] = makematrix[2][3] > outcontrol[0] ? makematrix[2][3] : outcontrol[0];
outcontrol[0] = makematrix[2][2] > outcontrol[0] ? makematrix[2][2] : outcontrol[0];
outcontrol[0] = makematrix[2][1] > outcontrol[0] ? makematrix[2][1] : outcontrol[0];
outcontrol[0] = makematrix[3][1] > outcontrol[0] ? makematrix[3][1] : outcontrol[0];
outcontrol[0] = makematrix[3][0] > outcontrol[0] ? makematrix[3][0] : outcontrol[0];
outcontrol[0] = makematrix[4][0] > outcontrol[0] ? makematrix[4][0] : outcontrol[0];
}
for(i = 0; i < 19; i ++)
savecontrol[i] = savecontrol[i+1];
if(outcontrol[0] == 0 && outcontrol[1] == 0 && outcontrol[2] == 0 && outcontrol[3] == 0)
savecontrol[19] == 0;
else
savecontrol[19] = parameterfuzzy * (outcontrol[1] + outcontrol[2] * 2 + outcontrol[3] * 3) / (outcontrol[0] + outcontrol[1] + outcontrol[2] + outcontrol[3]);
if(savecontrol[19] < 0)
savecontrol[19] = 0; //控制信号最少为零
if(savecontrol[19] > maxcontroldata)
savecontrol[19] = maxcontroldata; //控制信号饱和
SetCtrlVal (panelHandle, PANEL_DISPLAY_CONTROL, (savecontrol[19] * 10));
}
else;
if(whatmode == 0)
{
num = model_t/cycle;
if(num > 19) //计算滞后时间
num = 19;
result[0] = result[1]; //模拟过程
result[1] = exp(-cycle / model_T) * result[0] + savecontrol[19 - num];
draw[0] = givedata;
draw[1] = savecontrol[19] * 10;
draw[2] = result[1];
SetCtrlVal (panelHandle, PANEL_DISPLAY_REAL, result[1]);
PlotStripChart (panelHandle, PANEL_STRIPCHART, draw, 3, 0, 0, VAL_FLOAT);
}
else
{
//savecontrol[19] = 5;
setsenddata = (int)((savecontrol[19] / maxcontroldata) * 2743 + 683);
//setsenddata = 3426; //683 3426
senddata[15] = (char)(setsenddata / 4096);
senddata[16] = (char)((setsenddata % 4096) / 256);
senddata[17] = (char)((setsenddata % 256)/ 16);
senddata[18] = (char)(setsenddata % 16);
for(i = 15; i < 19; i++)
if(senddata[i] >= 0 && senddata[i] <= 9)
senddata[i] = senddata[i] + '0';
else
senddata[i] = senddata[i] + 'A' - 10;
efficacy = 0; //和效验
for(i = 1; i < 19; i++)
efficacy = efficacy + senddata[i];
senddata[19] = (efficacy / 16) % 16;
senddata[20] = efficacy % 16;
for(i = 19; i < 21; i++)
if(senddata[i] >= 0 && senddata[i] < 10)
senddata[i] = '0' +senddata[i];
else
senddata[i] = 'A' + senddata[i] - 10;
FlushInQ (2); //发送数据
ComWrt (2, senddata, strlen(senddata));
ComRd (2, responsion, 5);
if(responsion[0] =! ('0' + 6))
MessagePopup ("传输错误", "与PLC通讯失败");
draw[0] = givedata;
draw[1] = savecontrol[19] * 10;
draw[2] = getoutput;
SetCtrlVal (panelHandle, PANEL_DISPLAY_REAL, getoutput);
PlotStripChart (panelHandle, PANEL_STRIPCHART, draw, 3, 0, 0, VAL_FLOAT);
}
break;
}
return 0;
}
int CVICALLBACK startPIDCallback (int panel, int control, int event,
void *callbackData, int eventData1, int eventData2)
{
switch (event)
{
case EVENT_COMMIT:
L_PIDstart = 1; //开始标签
GetCtrlVal (panelHandle, PANEL_PARAMETER_P, &P_control); //获得PID参数
GetCtrlVal (panelHandle, PANEL_PARAMETER_I, &I_control);
GetCtrlVal (panelHandle, PANEL_PARAMETER_D, &D_control);
GetCtrlVal (panelHandle, PANEL_WORKMODE, &whatmode); //获得工作状态
if(whatmode == 0)
{
GetCtrlVal (panelHandle, PANEL_EMLUATOR_K, &model_K); //模型
GetCtrlVal (panelHandle, PANEL_EMLUATOR_T, &model_T);
GetCtrlVal (panelHandle, PANEL_EMLUATOR_t, &model_t);
}
GetCtrlVal (panelHandle, PANEL_SAMPLINGTIME, &cycle);
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_INTERVAL, cycle);
SetCtrlAttribute (panelHandle, PANEL_TIMER, ATTR_ENABLED, 1); //获得抽样时间。
并开始运行
ClearStripChart (panelHandle, PANEL_STRIPCHART); //版面清空
SetCtrlAttribute (panelHandle, PANEL_FUZZYCONTROL, ATTR_DIMMED, 1); //按键关闭
SetCtrlAttribute (panelHandle, PANEL_STARTPID, ATTR_DIMMED, 1);
SetCtrlAttribute (panelHandle, PANEL_AUTOSETPID, ATTR_DIMMED, 1);
getsum = 0;
break;
}
return 0;
}
void CVICALLBACK saveCallback (int menuBar, int menuItem, void *callbackData,
int panel)
{
}
void CVICALLBACK exitCallback (int menuBar, int menuItem, void *callbackData,
int panel)
{
QuitUserInterface (0);
}
void CVICALLBACK editionCallback (int menuBar, int menuItem, void *callbackData, int panel)
{
MessagePopup ("Edition", "HUST AC0201 1.0");
}。