pid温度控制c语言程序及仿真,模糊PID控制温控系统仿真设计C程序代码

/********************************************************************

模糊PID控制温控系统仿真设计C程序代码

********************************************************************/

#include

#define uchar unsigned char

#define uint unsigned int

#define PULSE 200

#define number 0.035

sbit SDO = P2^0;

sbit SDI = P2^1;

sbit CS  = P2^2;

sbit CLK = P2^3;

sbit EOC = P2^4;

sbit RS  = P2^5;

sbit RW  = P2^6;

sbit EN  = P2^7;

sbit KEY1= P3^0;

sbit KEY2= P3^1;

sbit KEY3= P3^2;

sbit KEY4= P3^3;

sbit KEY5= P3^4;

sbit IN1 = P3^5;

sbit IN2 = P3^6;

sbit ENA = P3^7;

uchar flag;

uchar flag_start;

float S_temp=60.0;

float P_temp=20.0;

float Kp;

float Ki;

float Kd;

float Err=0.0;

float Last_Err=0.0;

float D_Err=0.0;

float Sum_Err=0.0;

float U=0.0;

/******************************

函数功能:延时

******************************/

void delay_ms(uchar z)

{

uchar i;

uchar j;

for(i=z;i>0;i--)

for(j=360;j>0;j--);

}

void delay_us(uchar z)

{

uchar i;

for(i=z;i>0;i--);

}

void LCD_WriteData(uchar Dat)

{

RS = 1;

P1 = Dat;

delay_us(10);

EN = 1;

delay_us(10);

EN = 0;

}

void LCD_WriteCOM(uchar com)

{

RS = 0;

P1 = com;

delay_us(10);

EN = 1;

delay_us(10);

EN = 0;

}

void Show_Num(uchar x,uchar y,uchar n,float num)

{

uchar a[3];

uchar i;

uint Temp;

Temp=(int)num;

for(i=0;i

{

a[i] = Temp%10;

Temp = Temp/10;

}

if(y%2 == 1)

LCD_WriteCOM(0x80+x);

else

LCD_WriteCOM(0x80+0x40+x);

for(i=n;i>0;i--)

LCD_WriteData(a[i-1]+0x30);

}

void Show_Ki(uchar num_Ki)

{

uchar Temp;

num_Ki=Ki*100;

Temp=(uchar)num_Ki;

Show_Num(10,2,1,Temp%10);

Temp=Temp/10;

Show_Num(9,2,1,Temp%10);

Temp=Temp/10;

Show_Num(7,2,1,Temp);

}

void Show_char(uchar x,uchar y,uchar ch)

{

if(y%2 == 1)

LCD_WriteCOM(0x80+x);

else

LCD_WriteCOM(0x80+0x40+x);

LCD_WriteData(ch);

}

void LCD_Init(void)

{

RW = 0;

EN = 0;

LCD_WriteCOM(0x38);

LCD_WriteCOM(0x0c);

LCD_WriteCOM(0x06);

LCD_WriteCOM(0x01);

}

/***********************************

函数功能:显示函数

*************************************/

void LCD_display(void)

{

Show_char(1,1,'T');

delay_us(10);

Show_char(0,1,'P');

delay_us(10);

Show_char(1,1,'T');

delay_us(10);

Show_char(2,1,':');

delay_us(10);

Show_Num(3,1,3,P_temp);

delay_us(10);

Show_char(10,1,'S');

delay_us(10);

Show_char(11,1,'T');

delay_us(10);

Show_char(12,1,':');

delay_us(10);

Show_Num(13,1,3,S_temp);

delay_us(10);

Show_char(0,2,'P');

delay_us(10);

Show_char(1,2,':');

delay_us(10);

Show_Num(2,2,2,Kp);

delay_us(10);

Show_char(5,2,'I');

delay_us(10);

Show_char(6,2,':');

delay_us(10);

Show_char(8,2,'.');

delay_us(10);

Show_Ki(Ki);

delay_us(10);

Show_char(12,2,'D');

delay_us(10);

Show_char(13,2,':');

delay_us(10);

Show_Num(14,2,2,Kd);

delay_us(10);

}

/************************************

函数功能:定时器2初始化

*************************************/

void Timer2_Init()

{

RCAP2H =(65536-300)/256;

RCAP2L =(65536-300)%256;

TH2 = RCAP2H;

TL2 = RCAP2L;

ET2 = 1;

TR2 = 1;

EA = 1;

}

/*************************************

函数功能:键盘扫描,调整设置温度

****************************************/

void key_scan(void)

{

if(KEY1==0)

{

delay_ms(1);

if(KEY1==0)

{

S_temp=S_temp+1;

if(S_temp>=200)

S_temp=200;

while(!KEY1);

}

}

if(KEY2==0)

{

delay_ms(1);

if(KEY2==0)

{

if(S_temp>0)

S_temp=S_temp-1;

else if(S_temp<=0)

S_temp=0;

while(!KEY2);

}

}

if(KEY3==0)

{

delay_ms(1);

if(KEY3==0)

{

if(S_temp<=190)

S_temp=S_temp+10;

while(!KEY3);

}

}

if(KEY4==0)

{

delay_ms(1);

if(KEY4==0)

{

if(S_temp>=10)

S_temp=S_temp-10;

while(!KEY4);

}

}

if(KEY5==0)

{

delay_ms(1);

if(KEY5==0)

{

flag_start=1;

while(!KEY5);

}

}

}

/************************************

函数功能:PID的计算

**********************************/

void PID_Calculate()

{

Err = S_temp - P_temp;

Sum_Err += Err;

D_Err = Err - Last_Err;

Last_Err = Err;

U=Kp*Err+Ki*Sum_Err+Kd*D_Err;

U=(int)U;

if(U>=0)

{

if(U>=200)

U=200;

flag=1;

}

else

{

U=-U;

if(U>=200)

U=200;

flag=0;

}

}

/***********************************************

函数功能:PID参数Kp的计算

************************************************/

float fuzzy_kp(float e, float ec)                                //e,ec,表示误差,误差变化率

{

float Kp_calcu;

uchar num,pe,pec;

float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};   //误差E的模糊论域

float code ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0}; //误差变化率EC的模糊论域

float eFuzzy[2]={0.0,0.0};                                    //隶属于误差E的隶属程度

float ecFuzzy[2]={0.0,0.0};            //隶属于误差变化率EC的隶属程度

float code kpRule[4]={0.0,8.0,16.0,24.0};                        //Kp的模糊子集

float KpFuzzy[4]={0.0,0.0,0.0,0.0};                                //隶属于Kp的隶属程度

int code KpRule[7][7]=                                                          //Kp的模糊控制表

{

3,3,3,3,3,3,3,

2,2,2,2,1,2,2,

1,1,1,1,1,1,1,

1,1,0,1,0,1,1,

0,0,1,0,0,1,0,

0,1,0,1,0,0,2,

3,3,3,3,3,3,3

};

/*****误差E隶属函数描述*****/

if(e

{

eFuzzy[0] =1.0;

pe = 0;

}

else if(eRule[0]<=e && e

{

eFuzzy[0] = (eRule[1]-e)/(eRule[1]-eRule[0]);

pe = 0;

}

else if(eRule[1]<=e && e

{

eFuzzy[0] = (eRule[2] -e)/(eRule[2]-eRule[1]);

pe = 1;

}

else if(eRule[2]<=e && e

{

eFuzzy[0] = (eRule[3] -e)/(eRule[3]-eRule[2]);

pe = 2;

}

else if(eRule[3]<=e && e

{   eFuzzy[0] = (eRule[4]-e)/(eRule[4]-eRule[3]);

pe = 3;

}

else if(eRule[4]<=e && e

{

eFuzzy[0] = (eRule[5]-e)/(eRule[5]-eRule[4]);

pe = 4;

}

else if(eRule[5]<=e && e

{

eFuzzy[0] = (eRule[6]-e)/(eRule[6]-eRule[5]);

pe = 5;

}

else

{

eFuzzy[0] =0.0;

pe =5;

}

eFuzzy[1] =1.0 - eFuzzy[0];

/*****误差变化率EC隶属函数描述*****/

if(ec

{

ecFuzzy[0] =1.0;

pec = 0;

}

else if(ecRule[0]<=ec && ec

{

ecFuzzy[0] = (ecRule[1] - ec)/(ecRule[1]-ecRule[0]);

pec = 0 ;

}

else if(ecRule[1]<=ec && ec

{

ecFuzzy[0] = (ecRule[2] - ec)/(ecRule[2]-ecRule[1]);

pec = 1;

}

else if(ecRule[2]<=ec && ec

{

ecFuzzy[0] = (ecRule[3] - ec)/(ecRule[3]-ecRule[2]);

pec = 2 ;

}

else if(ecRule[3]<=ec && ec

{   ecFuzzy[0] = (ecRule[4]-ec)/(ecRule[4]-ecRule[3]);

pec=3;

}

else if(ecRule[4]<=ec && ec

{   ecFuzzy[0] = (ecRule[5]-ec)/(ecRule[5]-ecRule[4]);

pec=4;

}

else if(ecRule[5]<=ec && ec

{   ecFuzzy[0] = (ecRule[6]-ec)/(ecRule[6]-ecRule[5]);

pec=5;

}

else

{

ecFuzzy[0] =0.0;

pec = 5;

}

ecFuzzy[1] = 1.0 - ecFuzzy[0];

/*********查询模糊规则表*********/

num =KpRule[pe][pec];

KpFuzzy[num] += eFuzzy[0]*ecFuzzy[0];

num =KpRule[pe][pec+1];

KpFuzzy[num] += eFuzzy[0]*ecFuzzy[1];

num =KpRule[pe+1][pec];

KpFuzzy[num] += eFuzzy[1]*ecFuzzy[0];

num =KpRule[pe+1][pec+1];

KpFuzzy[num] += eFuzzy[1]*ecFuzzy[1];

/*********加权平均法解模糊*********/           Kp_calcu=KpFuzzy[0]*kpRule[0]+KpFuzzy[1]*kpRule[1]+KpFuzzy[2]*kpRule[2]

+KpFuzzy[3]*kpRule[3];

return(Kp_calcu);

}

/***********************************************

函数功能:PID参数Ki的计算

************************************************/

float fuzzy_ki(float e, float ec)

{

float Ki_calcu;

uchar num,pe,pec;

float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};

float code ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};

float eFuzzy[2]={0.0,0.0};

float ecFuzzy[2]={0.0,0.0};

float code kiRule[4]={0.00,0.01,0.02,0.03};

float KiFuzzy[4]={0.0,0.0,0.0,0.0};

int code KiRule[7][7]=

{

0,0,0,0,0,0,0,

0,0,0,0,0,0,0,

0,0,0,0,0,0,0,

0,0,0,0,0,0,0,

0,0,0,0,0,0,0,

2,0,0,0,0,0,1,

3,3,3,3,3,3,3

};

/*****误差隶属函数描述*****/

if(e

{

eFuzzy[0] =1.0;

pe = 0;

}

else if(eRule[0]<=e && e

{

eFuzzy[0] = (eRule[1]-e)/(eRule[1]-eRule[0]);

pe = 0;

}

else if(eRule[1]<=e && e

{

eFuzzy[0] = (eRule[2] -e)/(eRule[2]-eRule[1]);

pe = 1;

}

else if(eRule[2]<=e && e

{

eFuzzy[0] = (eRule[3] -e)/(eRule[3]-eRule[2]);

pe = 2;

}

else if(eRule[3]<=e && e

{   eFuzzy[0] = (eRule[4]-e)/(eRule[4]-eRule[3]);

pe = 3;

}

else if(eRule[4]<=e && e

{

eFuzzy[0] = (eRule[5]-e)/(eRule[5]-eRule[4]);

pe = 4;

}

else if(eRule[5]<=e && e

{

eFuzzy[0] = (eRule[6]-e)/(eRule[6]-eRule[5]);

pe = 5;

}

else

{

eFuzzy[0] =0.0;

pe =5;

}

eFuzzy[1] =1.0 - eFuzzy[0];

/*****误差变化隶属函数描述*****/

if(ec

{

ecFuzzy[0] =1.0;

pec = 0;

}

else if(ecRule[0]<=ec && ec

{

ecFuzzy[0] = (ecRule[1] - ec)/(ecRule[1]-ecRule[0]);

pec = 0 ;

}

else if(ecRule[1]<=ec && ec

{

ecFuzzy[0] = (ecRule[2] - ec)/(ecRule[2]-ecRule[1]);

pec = 1;

}

else if(ecRule[2]<=ec && ec

{

ecFuzzy[0] = (ecRule[3] - ec)/(ecRule[3]-ecRule[2]);

pec = 2 ;

}

else if(ecRule[3]<=ec && ec

{   ecFuzzy[0] = (ecRule[4]-ec)/(ecRule[4]-ecRule[3]);

pec=3;

}

else if(ecRule[4]<=ec && ec

{   ecFuzzy[0] = (ecRule[5]-ec)/(ecRule[5]-ecRule[4]);

pec=4;

}

else if(ecRule[5]<=ec && ec

{   ecFuzzy[0] = (ecRule[6]-ec)/(ecRule[6]-ecRule[5]);

pec=5;

}

else

{

ecFuzzy[0] =0.0;

pec = 5;

}

ecFuzzy[1] = 1.0 - ecFuzzy[0];

/***********查询模糊规则表***************/

num =KiRule[pe][pec];

KiFuzzy[num] += eFuzzy[0]*ecFuzzy[0];

num =KiRule[pe][pec+1];

KiFuzzy[num] += eFuzzy[0]*ecFuzzy[1];

num =KiRule[pe+1][pec];

KiFuzzy[num] += eFuzzy[1]*ecFuzzy[0];

num =KiRule[pe+1][pec+1];

KiFuzzy[num] += eFuzzy[1]*ecFuzzy[1];

/********加权平均法解模糊********/           Ki_calcu=KiFuzzy[0]*kiRule[0]+KiFuzzy[1]*kiRule[1]+KiFuzzy[2]*kiRule[2]

+KiFuzzy[3]*kiRule[3];

return(Ki_calcu);

}

/***********************************************

函数功能:PID参数Kd的计算

************************************************/

float fuzzy_kd(float e, float ec)

{

float Kd_calcu;

uchar num,pe,pec;

float code eRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};

float code ecRule[7]={-3.0,-2.0,-1.0,0.0,1.0,2.0,3.0};

float eFuzzy[2]={0.0,0.0};

float ecFuzzy[2]={0.0,0.0};

float code kdRule[4]={0.0,1.0,2.0,3.0};

float KdFuzzy[4]={0.0,0.0,0.0,0.0};

int code KdRule[7][7]=

{

3,3,3,2,2,2,2,

2,2,2,1,1,1,1,

1,1,2,1,1,2,1,

1,1,0,1,0,1,1,

1,1,0,0,0,1,1,

2,2,1,0 ,1,1,1,

3,3,3,3,2,3,2

};

/*****误差隶属函数描述*****/

if(e

{

eFuzzy[0] =1.0;

pe = 0;

}

else if(eRule[0]<=e && e

{

eFuzzy[0] = (eRule[1]-e)/(eRule[1]-eRule[0]);

pe = 0;

}

else if(eRule[1]<=e && e

{

eFuzzy[0] = (eRule[2] -e)/(eRule[2]-eRule[1]);

pe = 1;

}

else if(eRule[2]<=e && e

{

eFuzzy[0] = (eRule[3] -e)/(eRule[3]-eRule[2]);

pe = 2;

}

else if(eRule[3]<=e && e

{   eFuzzy[0] = (eRule[4]-e)/(eRule[4]-eRule[3]);

pe = 3;

}

else if(eRule[4]<=e && e

{

eFuzzy[0] = (eRule[5]-e)/(eRule[5]-eRule[4]);

pe = 4;

}

else if(eRule[5]<=e && e

{

eFuzzy[0] = (eRule[6]-e)/(eRule[6]-eRule[5]);

pe = 5;

}

else

{

eFuzzy[0] =0.0;

pe =5;

}

eFuzzy[1] =1.0 - eFuzzy[0];

/*****误差变化隶属函数描述*****/

if(ec

{

ecFuzzy[0] =1.0;

pec = 0;

}

else if(ecRule[0]<=ec && ec

{

ecFuzzy[0] = (ecRule[1] - ec)/(ecRule[1]-ecRule[0]);

pec = 0 ;

}

else if(ecRule[1]<=ec && ec

{

ecFuzzy[0] = (ecRule[2] - ec)/(ecRule[2]-ecRule[1]);

pec = 1;

}

else if(ecRule[2]<=ec && ec

{

ecFuzzy[0] = (ecRule[3] - ec)/(ecRule[3]-ecRule[2]);

pec = 2 ;

}

else if(ecRule[3]<=ec && ec

{   ecFuzzy[0] = (ecRule[4]-ec)/(ecRule[4]-ecRule[3]);

pec=3;

}

else if(ecRule[4]<=ec && ec

{   ecFuzzy[0] = (ecRule[5]-ec)/(ecRule[5]-ecRule[4]);

pec=4;

}

else if(ecRule[5]<=ec && ec

{   ecFuzzy[0] = (ecRule[6]-ec)/(ecRule[6]-ecRule[5]);

pec=5;

}

else

{

ecFuzzy[0] =0.0;

pec = 5;

}

ecFuzzy[1] = 1.0 - ecFuzzy[0];

/***********查询模糊规则表*************/

num =KdRule[pe][pec];

KdFuzzy[num] += eFuzzy[0]*ecFuzzy[0];

num =KdRule[pe][pec+1];

KdFuzzy[num] += eFuzzy[0]*ecFuzzy[1];

num =KdRule[pe+1][pec];

KdFuzzy[num] += eFuzzy[1]*ecFuzzy[0];

num =KdRule[pe+1][pec+1];

KdFuzzy[num] += eFuzzy[1]*ecFuzzy[1];

/********加权平均法解模糊********/

Kd_calcu=KdFuzzy[0]*kdRule[0]+KdFuzzy[1]*kdRule[1]+KdFuzzy[2]*kdRule[2]

+KdFuzzy[3]*kdRule[3];

return(Kd_calcu);

}

/*****************************************

函数功能:AD将采集到的温度进行转化

********************************************/

uint read_tlc2543(uchar port)

{

static uchar PORT = 0;

uchar Temp,i,k=0;

uint AD_value=0;

Temp = port;

CS = 1;

CLK = 0;

Temp<<=4;

CS = 0;

while(1)

{

for(i=0;i<8;i++)

{

CLK = 0;

if(Temp&0x80)

SDI = 1;

else

SDI = 0;

AD_value<<=1;

if(SDO)

AD_value |= 0x01;

CLK = 1;

Temp<<=1;

}

for(i=8;i<12;i++)

{

CLK = 0;

AD_value<<=1;

if(SDO)

AD_value |= 0x01;

delay_us(10);

CLK = 1;

}

CLK = 0;

CS = 1;

if(PORT == port)

break;

else

{

Temp = port;

Temp<<=4;

delay_us(10);

CS = 0;

AD_value = 0;

}

k++;

if(k>2)

{

PORT = port;

}

}

return AD_value;

}

float AD_deal(void)

{

uint AD_value;

float temp;

AD_value = read_tlc2543(0x00);

temp = AD_value*number;

return temp;

}

/*********主函数**********/

void main(void)

{

uchar AD_value=0;

flag=0;

flag_start=0;

ENA=1;

IN1=0;

IN2=0;

LCD_Init();

LCD_display();

Timer2_Init();

while(1)

{

if(flag_start==0)

{

key_scan();

Show_Num(13,1,3,S_temp);

Show_Num(3,1,3,P_temp);

}

else if(flag_start==1)

{

P_temp=AD_deal();

Show_Num(3,1,3,P_temp);

PID_Calculate();

Kp=fuzzy_kp(Err/5,D_Err);                            //E量化因子5

Ki=fuzzy_ki(Err/5,D_Err);

Kd=fuzzy_kd(Err/5,D_Err);

Show_Num(2,2,2,Kp);

Show_Ki(Ki);

Show_Num(14,2,2,Kd);

key_scan();

Show_Num(13,1,3,S_temp);

}

}

}

/***************定时器2中断**************/

void timer2() interrupt 5

{

static uchar num1=0;

TF2 = 0;

num1++;

if(num1<=U)

{

if(flag==1)

{

IN1 = 0;

IN2 = 1;

}

else

{

IN1 = 1;

IN2 = 0;

}

}

else

ENA=0;

if(num1>PULSE)

{num1=0;ENA=1;}

}

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值