温度的PID控制及程序示例
- 格式:doc
- 大小:74.00 KB
- 文档页数:9
温度的PID 控制一.温度检测部分首先要OK. 二、PID 调节作用 PID 控制时域的公式))()(1)(()(⎰++=dtt de Td t e Ti t e Kp t y 分解开来:(1) 比例调节器y(t) = Kp * e(t)e(k) 为当前的温差(设定值与检测值的插值) y(k) 为当前输出的控制信号(需要转化为PWM 形式)# 输出与输入偏差成正比。
只要偏差出现,就能及时地产生与之成比例的调节作用,使被控量朝着减小偏差的方向变化,具有调节及时的特点。
但是, Kp 过大会导致动态品质变坏,甚至使系统不稳定。
比例调节器的特性曲线. (2) 积分调节器y(t) = Ki * ∫(e(t))dt Ki = Kp/Ti Ti 为积分时间#TI 是积分时间常数,它表示积分速度的大小,Ti 越大,积分速度越慢,积分作用越弱。
只要偏差不为零就会产生对应的控制量并依此影响被控量。
增大Ti 会减小积分作用,即减慢消除静差的过程,减小超调,提高稳定性。
(3) 微分调节器y(t) = Kd*d(e(t))/dt Kd = Kp*Td Td 为微分时间#微分分量对偏差的任何变化都会产生控制作用,以调整系统输出,阻止偏差变化。
偏差变化越快,则产生的阻止作用越大。
从分析看出,微分作用的特点是:加入微分调节将有助于减小超调量,克服震荡,使系统趋于稳定。
他加快了系统的动作速度,减小调整的时间,从而改善了系统的动态性能。
三.PID 算法:由时域的公式离散化后可得如下公式:y(k) = y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp +2*Kd)*e(k-1) + Kd*e(k-2)y(k) 为当前输出的控制信号(需要转化为PWM形式)y(k-1)为前一次输出的控制信号e(k) 为当前的温差(设定值与检测值的插值)e(k-1) 为一次前的温差e(k-2) 为二次前的温差Kp 为比例系数Ki = Kp*T/Ti T为采样周期Kd = Kp*Td/T四.PID参数整定(确定Kp,Ts,Ti,Td):温度控制适合衰减曲线法,需要根据多次采样的数据画出响应曲线。
基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。
用keil C语言来实现PID的控制。
//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标Desired Valueunsigned int Proportion; // 比例常数Proportional Constunsigned int Integral; // 积分常数Integral Constunsigned int Derivative; // 微分常数Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/***********************************************************延时子程序,延时时间以12M晶振为准,延时时间为30us×time***********************************************************/void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/*********************************************************** 写一位数据子程序***********************************************************/ void write_bit(unsigned char bitval){EA=0;DQ=0; /*拉低DQ以开始一个写时序*/if(bitval==1){_nop_();DQ=1; /*如要写1,则将总线置高*/}delay(5); /*延时90us供DA18B20采样*/DQ=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/*********************************************************** 写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/*********************************************************** 读一位数据子程序***********************************************************/ unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,开始读时序*/_nop_();_nop_();DQ=1; /*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/*********************************************************** 读一字节数据子程序***********************************************************/ unsigned char read_byte(){unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/*********************************************************** 复位子程序***********************************************************/ unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/}/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/i=0xcc; /*发送设备定位命令*/write_byte(i);i=0x44; /*发送开始转换命令*/write_byte(i);delay(180); /*延时*/do{i=reset(); /*复位*/}while(i!=0);i=0xcc; /*设备定位*/write_byte(i);i=0xbe; /*读出缓冲区容*/write_byte(i);j=read_byte();i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*============================================================================= =======================Initialize PID Structure=============================================================================== ======================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*============================================================================= =======================PID计算部分=============================================================================== ======================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差pp->SumError += Error; // 积分dError = pp->LastError - pp->PrevError; // 当前微分pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error//比例+ pp->Integral * pp->SumError //积分项+ pp->Derivative * dError); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/pare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800);elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}/***************************************************** T0中断服务子程序,用于控制电平的翻转,40us*100=4ms周期******************************************************/ void serve_T0() interrupt 1 using 1{if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/ void serve_sio() interrupt 4 using 2{/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]){unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;else_nop_();clk=1;_nop_();}}}/*****************************************************显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/void display(){unsigned char code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/***********************************************************主程序***********************************************************/main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; // Set PID Setpoint while(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){}if(plus==0){set_temper++;flag=0;}}else if(subs==0){for(a=0;a<5;a++)for(b=0;a<102;b++){}if(subs==0){set_temper--;flag=0;}}else if(stop==0) {for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5) temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30) {display();count1=0;}pare_temper();}TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1;}}//DS18b20 子程序#include <REG52.H>sbit DQ=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480usDQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;for (i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节void write_byte(char val){byte i;for (i=8;i>0;i--) //一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void){union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte();temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了PID算法PID算法是本程序中的核心部分。
温度控制的P I D算法的C语言程序Document number:WTWYT-WYWY-BTGTT-YTTYU-2018GT基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。
用keilC语言来实现PID的控制。
超低温漂移高精度运算放大器0P07将温度一电压信号进行放大,便于A/D进行转换,以提高温度采集电路的可靠性。
模拟电路硬件部分见图2。
图2温度电压转换电路电控制执行电路的设计由输出来控制电炉,电炉可以近似建立为具有滞后性质的一阶惯性环节数学模型。
其传递函数形式为:可控硅可以认为是线形环节实现对水温的控制。
单片机输出与电炉功率分别属于弱电与强电部分,需要进行隔离处理,这里采用光耦元件TLP521在控制部分进行光电隔离,此外采用变压器隔离实现弱强电的电源隔离。
单片机PWM输出电平为0时,光耦元件导通,从而使三极管形成有效偏置而导通,通过整流桥的电压经过集电极电阻以及射集反向偏压,有7V左右的电压加在双向可控硅控制端,从而使可控硅导通,交流通路形成,电阻炉工作;反之单片机输出电平为0时,光耦元件不能导通,三极管不能形成有效偏置而截止,可控硅控制端电压几乎为零,可控硅截止从而截断交流通路,电炉停止工作。
此外,还有越限报警,当温度低于下限时发光二极管亮;高上限时蜂鸣器叫。
控制执行部分的硬件电路如下:图3控制执行部分电路3键盘及显示的设计键盘采用软件查询和外部中断相结合的方法来,低电平有效。
图3中按键AN1,AN2,AN3,AN4,AN5的功能定义如表1所示。
按键AN3与相连,采用外部中断方式,并且优先级定为最高;按键AN5和AN4分别与和相连,采用软件查询的方式;AN1则为硬件复位键,与R、C构成复位电路。
表1按键功能按键键名功能显示采用3位共阳LED静态显示方式,显示内容有温度值的十位、个位及小数点后一位,这样可以只用(RXD)口来输出显示数据,从而节省了单片机端口资源,在口和(TXD)的控制下通过74LS164来实现3位静态显示。
以下为PID温控程序,没有采用SFB41是因为些模块比较大,影响系统反应速度。
些温度控制系统不用微分(D)控制,只用PI控制Kc 为回路的增Ts 为采样的时间间隔Ti 为积分时间MDSPn 为采样时刻n的设定值PVn 为采样时刻n的过程变量值MX 为采样时刻n-1的积分项(又称为积分前项)PID运算公式1:MPN=KC*(SPN-PVN)PID运算公式2;MIN=KC*TS/TI*(SPN-PVN)+MXPID运算公式3:MN=MPN+MIN不用微分(D)控制,原工式为:MN=MPN+MIN+MDNPI运算程序对应的DB1:主程序对应的DB2:模拟输入量:IW2模拟输出量:PQDOKc 为回路的增Ts 为采样的时间间隔Ti 为积分时间MDSPn 为采样时刻n的设定值PVn 为采样时刻n的过程变量值MX 为采样时刻n-1的积分项(又称为积分前项)对应地址:网络1和 2 是模拟采集的“模拟输入量:IW2”和组态画面上Kc Ts Ti SPn PVn 的设定值。
实际操作中不需要。
改变模拟输入量:IW2观察模拟输出量变化:PQDO观察模拟输出量变化:PQDO观察模拟输出量变化:PQDO观察模拟输出量变化:PQDOOK!其他变量改变后一样能回到平衡:如改以下值:Kc 为回路的增Ts 为采样的时间间隔Ti 为积分时间MDSPn 为采样时刻n的设定值以下为PID运算温控程序,没有采用SFB41是因为些模块比较大,影响系统反应速度。
些温度控制系统不用微分(D)控制,只用PI控制下面是主程序:FB2下面是各电机启动程序模拟量输入,数据格式转换模拟量输出,数据格式转换限制输出范围:0~32767停止后全部清零,为组态画面变量编写的程序以下为模拟给PN当前值,SP设定值,TI积分时间,TS采样时间,KC增益量,结果:FB2我们看一下温度显示:Kc DB2。
DBD 66 为回路的增Ts DB2。
DBD74 为采样的时间间隔Ti DB2。
温度控制与PID算法温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。
1.温度控制的框图这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。
系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。
例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。
其调节过程如下:温度控制的功率输出采用脉宽调制的方法。
固态继电器SSR的输出端为脉宽可调的电压U OUT 。
当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。
因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。
一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。
下面将要描述的PID 调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。
2.温度控制的两个阶段温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。
另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。
这给温度的控制带来了困难。
因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。
PID调节温度控制实例(西门⼦S7-300)控制要求
1.⽔罐⽔温设置在50℃
2.误差值在±1℃
硬件配置
设计⽅案
1.采样:使⽤ PT100 热电阻经过变送器把⽔缸温度传送给S7-300 PLC。
2. 数据的处理:在 S7-300 PLC 中经过 PID 调节运算输出模拟量信号到功率调节器中。
3.温度调节:在功率调节器中把对应的模拟量转化为对应的功率来驱动热得快;
程序编写
1. 创建名称为PID调节的⼯程,添加CPU314C-2DP.西门⼦CPU314C-2DP,⾃带有模
拟量输⼊输出通道,⽆需扩展模块,在这⾥我们要注意他们的地址,以及输⼊输出的测量类型与测量范围。
这次试验⽤的是4-20mA的变送器,输出我们采⽤0-10V电压输出,这些参数需要在硬件组态时进⾏设置,设置好以后注意编译保存下载。
2.程序的编写
3.PID 调节
⾸先在开始菜单中打开PID 调节⾯板,如下图所⽰:。
实验十七 直流电机控制实验一、 实验目的1. 学习数字控制器的模拟化设计方法;2. 学习数字PID 控制器的设计方法;3. 学习PWM 控制理论;4. 学习数字PID 控制器在DSP 上的实现方法。
二、实验设备 计算机,CCS 2.0版软件,实验箱、DSP 仿真器、导线。
三、基础理论 PID 控制器(按闭环系统误差的比例、积分和微分进行控制的调节器)自30年代末图1 模拟PID 控制期出现以来,在工业控制领域得到了很大的发展和广泛的应用。
它的结构简单,参数易于调整,在长期应用中已积累了丰富的经验。
特别是在工业过程控制中,由于被控制对象的精确的数学模型难以建立,系统的参数经常发生变化,运用控制理论分析综合不仅要耗费很大代价,而且难以得到预期的控制效果。
在应用计算机实现控制的系统中,PID 很容易通过编制计算机语言实现。
由于软件系统的灵活性,PID 算法可以得到修正和完善,从而使数字PID 具有很大的灵活性和适用性。
实现PID 控制的计算机控制系统如图1所示,其中数字PID 控制器是由软件编程在计算机内部实现的。
1、PID 控制规律的离散化PID 控制器是一种线性调节器,这种调节器是将系统的给定值r 与实际输出值y 构成的控制偏差y r c -=的比例(P )、积分(I )、微分(D ),通过线性组合构成控制量,所以简称PID 控制器。
连续控制系统中的模拟PID 控制规律为:])()(1)([)(0dtt de T dt t e T t e K t u D t I p ++=⎰ (式1)式中)(t u 是控制器的输出,)(t e 是系统给定量与输出量的偏差,P K 是比例系数,I T 是积分时间常数,D T 是微分时间常数。
其相应传递函数为:)11()(s T sT K s G D I p ++= (式2) 比例调节器、积分调节器和微分调节器的作用:(1)比例调节器:比例调节器对偏差是即时反应的,偏差一旦出现,调节器立即产生控制作用,使输出量朝着减小偏差的方向变化,控制作用的强弱取决于比例系数P K 。
温度控制与PID算法温度控制与PID算法j较为复杂,下面结合实际浅显易懂的阐述一下PID控制理论,将温度控制及PID算法作一个简单的描述。
1.温度控制的框图这是一个典型的闭环控制系统,用于控制加热温区的温度(PV)保持在恒定的温度设定值(SV)。
系统通过温度采集单元反馈回来的实时温度信号(PV)获取偏差值(EV),偏差值经过PID调节器运算输出,控制发热管的发热功率,以克服偏差,促使偏差趋近于零。
例如,当某一时刻炉内过PCB板较多,带走的热量较多时,即导致温区温度下降,这时,通过反馈的调节作用,将使温度迅速回升。
其调节过程如下:温度控制的功率输出采用脉宽调制的方法。
固态继电器SSR的输出端为脉宽可调的电压U OUT 。
当SSR的触发角触发时,电源电压U AN通过SSR的输出端加到发热管的两端;当SSR的触发角没有触发信号时,SSR关断。
因此,发热管两端的平均电压为U d=(t/T)* U AN=K* U AN其中K=t/T,为一个周期T中,SSR触发导通的比率,称为负载电压系数或是占空比,K 的变化率在0-1之间。
一般是周期T固定不便,调节t, 当t在0-T的范围内变化时,发热管的电压即在0-U AN之间变化,这种调节方法称为定频调宽法。
下面将要描述的PID 调节器的算式在这里的实质即是运算求出一个实时变化的,能够保证加热温区在外界干扰的情况下仍能保持温度在一个较小的范围内变化的合理的负载电压系数K。
2.温度控制的两个阶段温度控制系统是一个惯性较大的系统,也就是说,当给温区开始加热之后,并不能立即观察得到温区温度的明显上升;同样的,当关闭加热之后,温区的温度仍然有一定程度的上升。
另外,热电偶对温度的检测,与实际的温区温度相比较,也存在一定的滞后效应。
这给温度的控制带来了困难。
因此,如果在温度检测值(PV)到达设定值时才关断输出,可能因温度的滞后效应而长时间超出设定值,需要较长时间才能回到设定值;如果在温度检测值(PV)未到设定值时即关断输出,则可能因关断较早而导致温度难以达到设定值。
我的题目是:基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。
用keil C语言来实现PID的控制。
最佳答案//PID算法温控C语言2008-08-17 18:58#include<reg51.h>#include<intrins.h>#include<math.h>#include<string.h>struct PID {unsigned int SetPoint; // 设定目标 Desired Valueunsigned int Proportion; // 比例常数 Proportional Constunsigned int Integral; // 积分常数 Integral Constunsigned int Derivative; // 微分常数 Derivative Constunsigned int LastError; // Error[-1]unsigned int PrevError; // Error[-2]unsigned int SumError; // Sums of Errors};struct PID spid; // PID Control Structureunsigned int rout; // PID Response (Output)unsigned int rin; // PID Feedback (Input)sbit data1=P1^0;sbit clk=P1^1;sbit plus=P2^0;sbit subs=P2^1;sbit stop=P2^2;sbit output=P3^4;sbit DQ=P3^3;unsigned char flag,flag_1=0;unsigned char high_time,low_time,count=0;//占空比调节参数unsigned char set_temper=35;unsigned char temper;unsigned char i;unsigned char j=0;unsigned int s;/*********************************************************** 延时子程序,延时时间以12M晶振为准,延时时间为30us×time***********************************************************/ void delay(unsigned char time){unsigned char m,n;for(n=0;n<time;n++)for(m=0;m<2;m++){}}/*********************************************************** 写一位数据子程序***********************************************************/ void write_bit(unsigned char bitval){EA=0;DQ=0; /*拉低DQ以开始一个写时序*/if(bitval==1){_nop_();DQ=1; /*如要写1,则将总线置高*/}delay(5); /*延时90us供DA18B20采样*/DQ=1; /*释放DQ总线*/_nop_();_nop_();EA=1;}/*********************************************************** 写一字节数据子程序***********************************************************/ void write_byte(unsigned char val){unsigned char i;unsigned char temp;EA=0; /*关中断*/TR0=0;for(i=0;i<8;i++) /*写一字节数据,一次写一位*/{temp=val>>i; /*移位操作,将本次要写的位移到最低位*/temp=temp&1;write_bit(temp); /*向总线写该位*/}delay(7); /*延时120us后*/// TR0=1;EA=1; /*开中断*/}/*********************************************************** 读一位数据子程序***********************************************************/ unsigned char read_bit(){unsigned char i,value_bit;EA=0;DQ=0; /*拉低DQ,开始读时序*/_nop_();_nop_();DQ=1; /*释放总线*/for(i=0;i<2;i++){}value_bit=DQ;EA=1;return(value_bit);}/*********************************************************** 读一字节数据子程序***********************************************************/ unsigned char read_byte(){unsigned char i,value=0;EA=0;for(i=0;i<8;i++){if(read_bit()) /*读一字节数据,一个时序中读一次,并作移位处理*/ value|=0x01<<i;delay(4); /*延时80us以完成此次都时序,之后再读下一数据*/}EA=1;return(value);}/***********************************************************复位子程序***********************************************************/ unsigned char reset(){unsigned char presence;EA=0;DQ=0; /*拉低DQ总线开始复位*/delay(30); /*保持低电平480us*/DQ=1; /*释放总线*/delay(3);presence=DQ; /*获取应答信号*/delay(28); /*延时以完成整个时序*/EA=1;return(presence); /*返回应答信号,有芯片应答返回0,无芯片则返回1*/ }/***********************************************************获取温度子程序***********************************************************/void get_temper(){unsigned char i,j;do{i=reset(); /*复位*/}while(i!=0); /*1为无反馈信号*/ i=0xcc; /*发送设备定位命令*/ write_byte(i);i=0x44; /*发送开始转换命令*/ write_byte(i);delay(180); /*延时*/do{i=reset(); /*复位*/}while(i!=0);i=0xcc; /*设备定位*/write_byte(i);i=0xbe; /*读出缓冲区内容*/write_byte(i);j=read_byte();i=read_byte();i=(i<<4)&0x7f;s=(unsigned int)(j&0x0f);s=(s*100)/16;j=j>>4;temper=i|j; /*获取的温度放在temper中*/}/*================================================================= ===================================Initialize PID Structure=================================================================== ==================================*/void PIDInit (struct PID *pp){memset ( pp,0,sizeof(struct PID));}/*================================================================= ===================================PID计算部分=================================================================== ==================================*/unsigned int PIDCalc( struct PID *pp, unsigned int NextPoint ){unsigned int dError,Error;Error = pp->SetPoint - NextPoint; // 偏差pp->SumError += Error; // 积分dError = pp->LastError - pp->PrevError; // 当前微分pp->PrevError = pp->LastError;pp->LastError = Error;return (pp->Proportion * Error//比例+ pp->Integral * pp->SumError //积分项+ pp->Derivative * dError); // 微分项}/***********************************************************温度比较处理子程序***********************************************************/ compare_temper(){unsigned char i;if(set_temper>temper){if(set_temper-temper>1){high_time=100;low_time=0;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation}if (high_time<=100)high_time=(unsigned char)(rout/800); elsehigh_time=100;low_time= (100-high_time);}}else if(set_temper<=temper){if(temper-set_temper>0){high_time=0;low_time=100;}else{for(i=0;i<10;i++){ get_temper();rin = s; // Read Inputrout = PIDCalc ( &spid,rin ); // Perform PID Interation }if (high_time<100)high_time=(unsigned char)(rout/10000);elsehigh_time=0;low_time= (100-high_time);}}// else// {}}/***************************************************** T0中断服务子程序,用于控制电平的翻转 ,40us*100=4ms周期******************************************************/ void serve_T0() interrupt 1 using 1{if(++count<=(high_time))output=1;else if(count<=100){output=0;}elsecount=0;TH0=0x2f;TL0=0xe0;}/***************************************************** 串行口中断服务程序,用于上位机通讯******************************************************/void serve_sio() interrupt 4 using 2 {/* EA=0;RI=0;i=SBUF;if(i==2){while(RI==0){}RI=0;set_temper=SBUF;SBUF=0x02;while(TI==0){}TI=0;}else if(i==3){TI=0;SBUF=temper;while(TI==0){}TI=0;}EA=1; */}void disp_1(unsigned char disp_num1[6]) {unsigned char n,a,m;for(n=0;n<6;n++){// k=disp_num1[n];for(a=0;a<8;a++){clk=0;m=(disp_num1[n]&1);disp_num1[n]=disp_num1[n]>>1;if(m==1)data1=1;elsedata1=0;_nop_();clk=1;_nop_();}}}/***************************************************** 显示子程序功能:将占空比温度转化为单个字符,显示占空比和测得到的温度******************************************************/ void display(){unsigned char codenumber[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6};unsigned char disp_num[6];unsigned int k,k1;k=high_time;k=k%1000;k1=k/100;if(k1==0)disp_num[0]=0;elsedisp_num[0]=0x60;k=k%100;disp_num[1]=number[k/10];disp_num[2]=number[k%10];k=temper;k=k%100;disp_num[3]=number[k/10];disp_num[4]=number[k%10]+1;disp_num[5]=number[s/10];disp_1(disp_num);}/*********************************************************** 主程序***********************************************************/ main(){unsigned char z;unsigned char a,b,flag_2=1,count1=0;unsigned char phil[]={2,0xce,0x6e,0x60,0x1c,2};TMOD=0x21;TH0=0x2f;TL0=0x40;SCON=0x50;PCON=0x00;TH1=0xfd;TL1=0xfd;PS=1;EA=1;EX1=0;ET0=1;ES=1;TR0=1;TR1=1;high_time=50;low_time=50;PIDInit ( &spid ); // Initialize Structure spid.Proportion = 10; // Set PID Coefficients spid.Integral = 8;spid.Derivative =6;spid.SetPoint = 100; // Set PID Setpoint while(1){if(plus==0){EA=0;for(a=0;a<5;a++)for(b=0;b<102;b++){} if(plus==0){set_temper++;flag=0;}}else if(subs==0) {for(a=0;a<5;a++)for(b=0;a<102;b++){} if(subs==0){set_temper--;flag=0;}}else if(stop==0) {for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0){flag=0;break;}EA=1;}get_temper();b=temper;if(flag_2==1)a=b;if((abs(a-b))>5) temper=a;elsetemper=b;a=temper;flag_2=0;if(++count1>30) {display();count1=0;}compare_temper(); }TR0=0;z=1;while(1){EA=0;if(stop==0){for(a=0;a<5;a++)for(b=0;b<102;b++){} if(stop==0)disp_1(phil);// break;}EA=1;}}//DS18b20 子程序#include <REG52.H>sbit DQ=P2^1; //定义端口typedef unsigned char byte;typedef unsigned int word;//延时void delay(word useconds){for(;useconds>0;useconds--);}//复位byte ow_reset(void){byte presence;DQ=0; //DQ低电平delay(29); //480us DQ=1; //DQ高电平delay(3); //等待presence=DQ; //presence信号delay(25);return(presence);} //0允许,1禁止//从1-wire 总线上读取一个字节byte read_byte(viod){byte i;byte value=0;for (i=8;i>0;i--){value>>=1;DQ=0;DQ=1;delay(1);if(DQ)value|=0x80;delay(6);}return(value);}//向1-wire总线上写一个字节void write_byte(char val){byte i;for (i=8;i>0;i--) //一次写一个字节{DQ=0;DQ=val&0x01;delay(5);DQ=1;val=val/2;}delay(5);}//读取温度char Read_Temperature(void) {union{byte c[2];int x;}temp;ow_reset();write_byte(0xcc);write_byte(0xBE);temp.c[1]=read_byte(); temp.c[0]=read_byte();ow_reset();write_byte(0xCC);write_byte(0x44);return temp.x/2;}参考资料:你把这两个程序组合就可以了图1 模拟PID 控制系统原理图PID 控制器的控制规律可以描述为:(1)比例(P)控制能迅速反应误差,从而减小稳态误差。
pid算法温度控制c语言程序PID算法是一种常用的温度控制算法,广泛应用于各种温度控制系统中。
在C语言中,我们可以通过编写程序来实现PID算法的温度控制功能。
我们需要了解PID算法的基本原理。
PID算法是通过对系统的反馈信号进行不断调整,使得系统的输出达到期望值。
PID算法由三个部分组成:比例控制、积分控制和微分控制。
比例控制根据反馈信号与期望值的差异来调整输出;积分控制根据反馈信号与期望值的累积差异来调整输出;微分控制根据反馈信号的变化率来调整输出。
在C语言中,我们可以使用变量来表示系统的输入、输出和期望值。
以下是一个简单的示例代码:```c#include <stdio.h>// 定义PID参数float Kp = 1.0; // 比例系数float Ki = 0.5; // 积分系数float Kd = 0.2; // 微分系数// 定义系统变量float setpoint = 25.0; // 期望值float input = 0.0; // 输入值float output = 0.0; // 输出值// 定义误差变量float error = 0.0; // 当前误差float last_error = 0.0; // 上一次误差float integral = 0.0; // 累积误差// PID算法函数float pid_algorithm(float setpoint, float input) {// 计算误差error = setpoint - input;// 计算比例控制float proportional = Kp * error;// 计算积分控制integral += error;float integral_control = Ki * integral;// 计算微分控制float derivative = Kd * (error - last_error); // 计算输出output = proportional + integral_control + derivative;// 更新误差last_error = error;return output;}int main(){// 模拟温度传感器的输入input = 23.5;// 调用PID算法函数output = pid_algorithm(setpoint, input);// 打印输出结果printf("Output: %.2f\n", output);return 0;}```在上述代码中,我们首先定义了PID算法的参数和系统变量。
温度的PID 控制一.温度检测部分首先要OK.二、PID 调节作用PID 控制时域的公式1 de(t)y(t) Kp(e(t) e(t) Td )Ti dt分解开来:(1) 比例调节器y(t) = Kp * e(t)e(k) 为当前的温差(设定值与检测值的插值)y(k) 为当前输出的控制信号(需要转化为PWM 形式)# 输出与输入偏差成正比。
只要偏差出现,就能及时地产生与之成比例的调节作用,使被控量朝着减小偏差的方向变化,具有调节及时的特点。
但是,Kp 过大会导致动态品质变坏,甚至使系统不稳定。
比例调节器的特性曲线.(2) 积分调节器y(t) = Ki * ∫(e(t))dt Ki = Kp/Ti Ti为积分时间#TI 是积分时间常数,它表示积分速度的大小,Ti 越大,积分速度越慢,积分作用越弱。
只要偏差不为零就会产生对应的控制量并依此影响被控量。
增大Ti 会减小积分作用,即减慢消除静差的过程,减小超调,提高稳定性。
(3) 微分调节器y(t) = Kd*d(e(t))/dt Kd = Kp*Td Td 为微分时间#微分分量对偏差的任何变化都会产生控制作用,以调整系统输出,阻止偏差变化。
偏差变化越快,则产生的阻止作用越大。
从分析看出,微分作用的特点是:加入微分调节将有助于减小超调量,克服震荡,使系统趋于稳定。
他加快了系统的动作速度,减小调整的时间,从而改善了系统的动态性能。
三.PID 算法:由时域的公式离散化后可得如下公式:y(k) = y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp +2*Kd)*e(k-1) + Kd*e(k-2)y(k) 为当前输出的控制信号(需要转化为PWM 形式) y(k-1)为前一次输出的控制信号e(k) 为当前的温差(设定值与检测值的插值) e(k-1) 为一次前的温差e(k-2) 为二次前的温差Kp 为比例系数Ki = Kp*T/Ti T 为采样周期Kd = Kp*Td/T四.PID 参数整定(确定Kp,Ts,Ti,Td ):温度控制适合衰减曲线法,需要根据多次采样的数据画出响应曲线。
pid控制应用实例PID (Proportional Integral Derivative)控制是一种常用的控制算法,被广泛应用于工业自动化和过程控制领域。
PID控制是一种反馈控制方法,通过对系统的输出进行实时监测,并根据误差的大小调整系统的输入,以使系统的输出尽量接近期望值。
在实际应用中,PID控制常被用于控制温度、压力、流量等物理量。
下面以一个温度控制的实例来说明PID控制的应用。
假设我们有一个加热系统,需要将系统的温度维持在一个特定的设定值。
该系统由一个加热器和一个温度传感器组成。
加热器通过调节电流的大小来控制加热功率,而温度传感器则测量系统的温度。
我们需要确定一个目标温度,即设定值。
假设我们的目标温度是60摄氏度。
接下来,我们需要将目标温度与当前温度进行比较,以确定误差。
当前温度可以通过温度传感器获取。
如果当前温度与目标温度相差较大,说明系统需要进行调整。
PID控制算法根据误差的大小来调整加热功率。
具体来说,PID控制算法由三个部分组成:比例控制、积分控制和微分控制。
比例控制是根据误差的大小来调整控制量的大小。
误差越大,控制量的调整幅度越大。
比例控制可以快速地将系统的温度接近设定值,但可能会导致系统的超调。
积分控制是根据误差的积分来调整控制量的大小。
如果系统的温度一直与设定值有偏差,积分控制将持续地增加控制量,以减小偏差。
积分控制可以消除系统的静态误差,但可能会导致系统的超调和震荡。
微分控制是根据误差的变化率来调整控制量的大小。
如果系统的温度变化较快,微分控制将增加控制量以抑制温度的快速变化。
微分控制可以提高系统的稳定性,但可能会导致控制量的突变。
将比例控制、积分控制和微分控制结合起来,就形成了PID控制算法。
通过不断地调整加热功率,系统的温度将逐渐接近目标温度,并在一定的范围内保持稳定。
在实际应用中,PID控制算法的参数需要经过调试和优化。
比例系数、积分系数和微分系数的选择将影响系统的响应速度、稳定性和抗干扰性能。
(* init program *)PIDpara.enable = 1 ;使能端PIDpara.enter = 1 ;当enter为1时,检查参数并转换为内部显示。
;当enter为0时,忽略输入参数的改变并存储计算时间。
PIDpara.Y_max = 32767 ;PID输出最大值(0~~32767)PIDpara.Y_min = 0 ;PID输出最小值(0~~32767)PIDpara.dY_max = 10.0 ;输出最大容许变化量,操作变量斜坡最大值。
为0时ramp不起作用,不需计算时间PIDpara.Kp = 1.0 ;比例PIDpara.Tn = 10.0 ;积分(越小作用越大),为0时第I part和jolt-free切换不起作用且不需要任何计算时间。
= 1 ;微分PIDpara.Tf = 1 ;微分滤波时间。
若Tv不为0必须输入(初值为Tv/10),不应少于(1.4*任务的扫描时间).PIDpara.Kw = 1 ;比例项衰减系数。
Kw为1时设定值不变进行比例项计算,为小于1时,设定值乘Kw后进行比例项计算(此项不能为零)PIDpara.Kfbk = 1 ;抗积分饱和,终结阻尼值。
Kfbk为0时终结保护无效,不需要计算时间PIDpara.fbk_mode = LCPID_FBK_MODE_INTERN ;操作变量的反馈模式:内部模式(一般为内部模式)PIDpara.d_mode = LCPID_D_MODE_E ;微分模式:对偏差值进行微分计算(标准PID控制);X模式:对实际值进行微分计算(一般选次方式)PIDpara.calc_mode= LCPID_CALC_MODE_EXACT ;计算模式:精确(所有计算为双精度浮点型, 如无舍入错误和CPU计算次数过长)(一般选次方式)PIDpara FUB LCPIDpara() ;调用PID参数功能块循环程序中程序如下,此程序只对P、I、D三个参数由变量进行输值,变量可在pid程序运行中实时修改,如果大家还需要某些参数实时修改,方法相同:(* cyclic program *)PIDpara.enable = PIDpara.enablePIDpara FUB LCPIDpara() = D_Ctrl ;积分(越小作用越大),为0时第I part和jolt-free 切换不起作用且不需要任何计算时间。
PID温度控制的PLC程序设计PID温度控制的PLC程序设计温度控制是许多机器的重要的构成部分。
它的功能是将温度控制在所需要的温度范围内,然后进行工件的加工与处理。
PID控制系统是得到广泛应用的控制方法之一。
在本文中,将详细讲叙本套系统。
l 系统组成本套系统采用Omron的PLC与其温控单元以及Pro-face的触摸屏所组成。
系统包括CQM1H-51、扩展单元TC-101、GP577R以及探温器、加热/制冷单元。
l 触摸屏画面部分(见图1-a)1-a如图所见,数据监控栏内所显示的002代表现在的温度,而102表示输出的温度。
如按下开始设置就可设置参数。
需要设置的参数有六个,分别是比例带、积分时间、微分时间、滞后值、控制周期、偏移量。
它们在PLC的地址与一些开关的地址如下所列。
比例带: DM51积分时间: DM52微分时间: DM53滞后值: DM54控制周期: DM55偏移量: DM56数据刷新: 22905l PLC程序部分002:PID的输入字102:PID的输出字[NETWORK]Name="Action Check" //常规检查[STATEMENTLIST]LD 253.13 //常ONOUT TR0CMP 002 #FFFF //确定温控单元是否完成初始化AND NOT 255.06 //等于OUT 041.15 //初始化完成LD TR0AND 041.15OUT TR1AND NOT 040.10 //不在参数设置状态MOV DM0050 102 //将设置温度DM50传送给PID输出字LD TR1MOV 002 DM0057 //将002传送到DM57[NETWORK]Name="Setting Start"//设置开始[STATEMENTLIST]LD 253.13AND 229.05 //触摸屏上的开始设置开关DIFU 080.05 //设置微分LD TR0AND 041.15AND 080.05SET 040.01 //开始设置标志位1SET 040.10 //开始设置标志位2[NETWORK]Name="Poportion"//比例带设置[STATEMENTLIST]LD 040.01OUT TR0AND NOT 042.01MOV #C110 102 //读输出边与输入边的比例带CMP 002 #C110 //比较输入字是否变成C110AND 255.06 //等于SET 042.01 //设置比例带标志LD TR0AND 042.01MOV DM0051 102 //将比例带的设定值写入输出字CMP 002 DM0051 //是否写入AND 255.06RSET 040.01 //复位标志1RSET 042.01 //复位比例带标志SET 040.02 //向下继续设置标志[NETWORK]Name="Integral"//积分时间设置[STATEMENTLIST]LD 040.02OUT TR0AND NOT 042.02MOV #C220 102 //读输出边与输入边的积分CMP 002 #C220 //比较输入字是否变成C220AND 255.06SET 042.02 //设置积分标志LD TR0AND 042.02MOV DM0052 102 //将积分的设定值写入输出字CMP 002 DM0052 //是否写入AND 255.06RSET 040.02SET 040.03 //向下继续设置标志[NETWORK]Name="differential"//微分时间设置[STATEMENTLIST]LD 040.03OUT TR0AND NOT 042.03MOV #C330 102 //读输出边与输入边的微分CMP 002 #C330 //比较输入字是否变成C330AND 255.06SET 042.03 //设置微分标志LD TR0AND 042.03MOV DM0053 102 /将微分的设定值写入输出字CMP 002 DM0053 //是否写入AND 255.06RSET 040.03RSET 042.03SET 040.04 //向下继续设置标志[NETWORK]Name="Hysteresis"//滞后值设置[STATEMENTLIST]LD 040.04OUT TR0AND NOT 042.04MOV #C440 102 //读输出边与输入边的滞后值CMP 002 #C440 //比较输入字是否变成C440 AND 255.06SET 042.04 设置滞后值标志LD TR0AND 042.04MOV DM0054 102 /将滞后值的设定值写入输出字 CMP 002 DM0054 //是否写入AND 255.06RSET 040.04RSET 042.04SET 040.05 //向下继续设置标志[NETWORK]Name="Period"//控制周期设置[STATEMENTLIST]OUT TR0AND NOT 042.05MOV #C550 102 //读输出边与输入边的控制周期 CMP 002 #C550 //比较输入字是否变成C550AND 255.06SET 042.05 //设置控制周期标志LD TR0AND 042.05MOV DM0055 102 将控制周期的设定值写入输出字 CMP 002 DM0055 是否写入AND 255.06RSET 040.05RSET 042.05SET 040.06 //向下继续设置标志[NETWORK]Name="Shift"//偏移量设置[STATEMENTLIST]LD 040.06OUT TR0AND NOT 042.06MOV #C660 102 //读输出边与输入边的偏移量CMP 002 #C660 //比较输入字是否变成C660AND 255.06SET 042.06 //设置偏移量标志LD TR0AND 042.06MOV DM0056 102 //将偏移量的设定值写入输出字 CMP 002 DM0056 //是否写入AND 255.06RSET 040.06RSET 042.06SET 040.00[NETWORK]Name="Return"//返回[STATEMENTLIST]LD 040.00OUT TR0AND NOT 042.00MOV #C070 102 //读输入边的处理值CMP 002 #C070 比较输入字变成C070AND 255.06SET 042.00 //返回标志LD TR0AND 042.00MOV DM0050 102 将设定温度值写入输出字RSET 040.00RSET 042.00RSET 040.10以上是本套系统的全部内容,经过反复试验,此系统可以维持温度在1°C 之间变化。
温度控制的PID算法与C程序实现PID (Proportional-Integral-Derivative) 是一种经典的反馈控制算法,被广泛应用于温度控制中。
在温度控制中,PID算法可以根据实际温度与设定温度之间的差异来调整控制器的输出,以达到稳定的温度控制。
下面将介绍PID算法的原理及其在C程序中的实现。
PID算法是通过对三个控制参数的不同组合调整,来实现对控制系统的精确控制。
这三个参数分别是比例项(P),积分项(I)和微分项(D)。
比例项(P)是根据实际温度与设定温度的差异计算出来的,并且与这个差异成比例。
比例项主要用于对系统的快速响应进行调整。
如果比例项过大,可能会导致系统产生震荡,如果比例项过小,则可能导致控制系统响应迟缓。
积分项(I)用于校正持续的误差,通过对误差的积分来进行控制系统的调整。
积分项主要用于对系统的稳定性进行调整。
如果积分项过大,可能会导致系统产生超调和振荡,如果积分项过小,则可能导致系统无法快速地消除误差。
微分项(D)用于预测系统未来变化的趋势,并根据这个趋势来进行控制系统的调整。
微分项主要用于对系统的响应速度进行调整。
如果微分项过大,可能会导致系统产生过度的抖动,如果微分项过小,则可能导致系统响应迟缓。
PID算法的输出是三个控制参数的加权和,即 control = P * error + I * integral + D * derivative。
其中,error为实际温度与设定温度的差异,integral为误差的累积和,derivative为误差的变化率。
下面是一个使用PID算法实现温度控制的C程序的示例:```c#include <stdio.h>//PID参数float Kp = 0.5;float Ki = 0.2;float Kd = 0.1;//温度设定值float setpoint = 50.0;//初始化float errorSum = 0;float lastError = 0;//计算PID控制量float calculateOutput(float currentTemperature) float error = setpoint - currentTemperature; errorSum += error;//计算PID控制量float proportional = Kp * error;float integral = Ki * errorSum;float derivative = Kd * (error - lastError);float output = proportional + integral + derivative; lastError = error;return output;int mai//模拟当前温度float currentTemperature = 40.0;//模拟控制循环while (1)//获取温度传感器读数// float currentTemperature = readTemperature(;//计算PID控制量float controlOutput = calculateOutput(currentTemperature); //执行控制动作,例如根据控制量控制加热器或冷却器// executeControlAction(controlOutput);//模拟温度变化currentTemperature += 0.5;//输出当前温度和控制量printf("Current temperature: %.2f, Control output: %.2f\n", currentTemperature, controlOutput);}return 0;```上述C程序中,首先定义了PID参数Kp、Ki和Kd,以及温度设定值setpoint。
pid控制温度实例 c语言以下是一个简单的PID温度控制器的C语言实现示例:```c#include <stdio.h>// PID参数结构体typedef struct {double Kp; // 比例系数double Ki; // 积分系数double Kd; // 微分系数double integral; // 积分项double pre_error; // 上一次误差} PID_t;// PID温度控制器函数double pid_temperature_control(PID_t *pid, double setpoint, double actual_temperature) {double error = setpoint - actual_temperature; // 计算误差pid->integral += error; // 计算积分项double derivative = error - pid->pre_error; // 计算微分项double output = pid->Kp * error + pid->Ki * pid->integral + pid->Kd * derivative; // 计算输出值pid->pre_error = error; // 保存上一次误差值return output;}int main() {PID_t pid = {1.0, 0.5, 0.1, 0.0, 0.0}; // PID参数初始化 double setpoint = 100.0; // 设定温度值double actual_temperature = 0.0; // 实际温度值double output = 0.0; // 输出值int i;for (i = 0; i < 100; i++) { // 模拟控制过程,迭代100次 output = pid_temperature_control(&pid, setpoint, actual_temperature); // 计算输出值printf("Time: %d, Setpoint: %f, ActualTemperature: %f, Output: %f\n", i, setpoint,actual_temperature, output); // 输出结果actual_temperature += output * 0.1; // 根据输出值调整实际温度值,模拟控制过程}return 0;}```在上面的示例中,我们首先定义了一个PID参数结构体,其中包含了比例系数、积分系数、微分系数、积分项和上一次误差等参数。
PID温度控制的PLC程序设计(梯形图语言)PID温度控制的PLC程序设计温度控制是许多机器的重要的构成部分。
它的功能是将温度控制在所需要的温度范围内,然后进行工件的加工与处理。
PID控制系统是得到广泛应用的控制方法之一。
在本文中,将详细讲叙本套系统。
l 系统组成本套系统采用Omron的PLC与其温控单元以及Pro-face的触摸屏所组成。
系统包括CQM1H-51、扩展单元TC-101、GP577R以及探温器、加热/制冷单元。
l 触摸屏画面部分(见图1-a)1-a如图所见,数据监控栏内所显示的002代表现在的温度,而102表示输出的温度。
如按下开始设置就可设置参数。
需要设置的参数有六个,分别是比例带、积分时间、微分时间、滞后值、控制周期、偏移量。
它们在PLC的地址与一些开关的地址如下所列。
比例带: DM51积分时间: DM52微分时间: DM53滞后值: DM54控制周期: DM55偏移量: DM56数据刷新: 22905l PLC程序部分002:PID的输入字102:PID的输出字[NETWORK]Name="Action Check" //常规检查[STATEMENTLIST]LD 253.13 //常ONOUT TR0CMP 002 #FFFF //确定温控单元是否完成初始化字串1AND NOT 255.06 //等于OUT 041.15 //初始化完成LD TR0AND 041.15OUT TR1AND NOT 040.10 //不在参数设置状态MOV DM0050 102 //将设置温度DM50传送给PID输出字LD TR1MOV 002 DM0057 //将002传送到DM57[NETWORK]Name="Setting Start"//设置开始[STATEMENTLIST]LD 253.13OUT TR0AND 229.05 //触摸屏上的开始设置开关DIFU 080.05 //设置微分LD TR0AND 041.15AND 080.05SET 040.01 //开始设置标志位1SET 040.10 //开始设置标志位2[NETWORK]Name="Poportion"//比例带设置[STATEMENTLIST]LD 040.01OUT TR0AND NOT 042.01MOV #C110 102 //读输出边与输入边的比例带CMP 002 #C110 //比较输入字是否变成C110AND 255.06 //等于SET 042.01 //设置比例带标志LD TR0AND 042.01MOV DM0051 102 //将比例带的设定值写入输出字CMP 002 DM0051 //是否写入AND 255.06 字串4RSET 040.01 //复位标志1RSET 042.01 //复位比例带标志SET 040.02 //向下继续设置标志[NETWORK]Name="Integral"//积分时间设置[STATEMENTLIST]LD 040.02OUT TR0AND NOT 042.02MOV #C220 102 //读输出边与输入边的积分CMP 002 #C220 //比较输入字是否变成C220AND 255.06SET 042.02 //设置积分标志LD TR0AND 042.02MOV DM0052 102 //将积分的设定值写入输出字CMP 002 DM0052 //是否写入AND 255.06RSET 040.02RSET 042.02SET 040.03 //向下继续设置标志[NETWORK]Name="differential"//微分时间设置[STATEMENTLIST]LD 040.03OUT TR0AND NOT 042.03MOV #C330 102 //读输出边与输入边的微分CMP 002 #C330 //比较输入字是否变成C330 AND 255.06SET 042.03 //设置微分标志LD TR0AND 042.03MOV DM0053 102 /将微分的设定值写入输出字CMP 002 DM0053 //是否写入字串3AND 255.06RSET 040.03RSET 042.03SET 040.04 //向下继续设置标志[NETWORK]Name="Hysteresis"//滞后值设置[STATEMENTLIST]LD 040.04OUT TR0AND NOT 042.04MOV #C440 102 //读输出边与输入边的滞后值CMP 002 #C440 //比较输入字是否变成C440 AND 255.06SET 042.04 设置滞后值标志LD TR0AND 042.04MOV DM0054 102 /将滞后值的设定值写入输出字CMP 002 DM0054 //是否写入AND 255.06RSET 040.04RSET 042.04SET 040.05 //向下继续设置标志[NETWORK]Name="Period"//控制周期设置[STATEMENTLIST]LD 040.05OUT TR0AND NOT 042.05MOV #C550 102 //读输出边与输入边的控制周期CMP 002 #C550 //比较输入字是否变成C550AND 255.06SET 042.05 //设置控制周期标志LD TR0AND 042.05MOV DM0055 102 将控制周期的设定值写入输出字CMP 002 DM0055 是否写入AND 255.06RSET 040.05RSET 042.05SET 040.06 //向下继续设置标志[NETWORK]Name="Shift"//偏移量设置[STATEMENTLIST]LD 040.06OUT TR0AND NOT 042.06MOV #C660 102 //读输出边与输入边的偏移量CMP 002 #C660 //比较输入字是否变成C660AND 255.06SET 042.06 //设置偏移量标志LD TR0AND 042.06MOV DM0056 102 //将偏移量的设定值写入输出字CMP 002 DM0056 //是否写入AND 255.06RSET 040.06RSET 042.06SET 040.00[NETWORK]Name="Return"//返回[STATEMENTLIST]LD 040.00OUT TR0AND NOT 042.00MOV #C070 102 //读输入边的处理值CMP 002 #C070 比较输入字变成C070AND 255.06SET 042.00 //返回标志LD TR0AND 042.00MOV DM0050 102 将设定温度值写入输出字RSET 040.00RSET 042.00RSET 040.10以上是本套系统的全部内容,经过反复试验,此系统可以维持温度在1°C之间变化。
温度的PID 控制一.温度检测部分首先要OK. 二、PID 调节作用 PID 控制时域的公式))()(1)(()(⎰++=dtt de Td t e Ti t e Kp t y 分解开来:(1) 比例调节器y(t) = Kp * e(t)e(k) 为当前的温差(设定值与检测值的插值) y(k) 为当前输出的控制信号(需要转化为PWM 形式)# 输出与输入偏差成正比。
只要偏差出现,就能及时地产生与之成比例的调节作用,使被控量朝着减小偏差的方向变化,具有调节及时的特点。
但是, Kp 过大会导致动态品质变坏,甚至使系统不稳定。
比例调节器的特性曲线. (2) 积分调节器y(t) = Ki * ∫(e(t))dt Ki = Kp/Ti Ti 为积分时间#TI 是积分时间常数,它表示积分速度的大小,Ti 越大,积分速度越慢,积分作用越弱。
只要偏差不为零就会产生对应的控制量并依此影响被控量。
增大Ti 会减小积分作用,即减慢消除静差的过程,减小超调,提高稳定性。
(3) 微分调节器y(t) = Kd*d(e(t))/dt Kd = Kp*Td Td 为微分时间#微分分量对偏差的任何变化都会产生控制作用,以调整系统输出,阻止偏差变化。
偏差变化越快,则产生的阻止作用越大。
从分析看出,微分作用的特点是:加入微分调节将有助于减小超调量,克服震荡,使系统趋于稳定。
他加快了系统的动作速度,减小调整的时间,从而改善了系统的动态性能。
三.PID 算法:由时域的公式离散化后可得如下公式:y(k) = y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp +2*Kd)*e(k-1) + Kd*e(k-2)y(k) 为当前输出的控制信号(需要转化为PWM形式)y(k-1)为前一次输出的控制信号e(k) 为当前的温差(设定值与检测值的插值)e(k-1) 为一次前的温差e(k-2) 为二次前的温差Kp 为比例系数Ki = Kp*T/Ti T为采样周期Kd = Kp*Td/T四.PID参数整定(确定Kp,Ts,Ti,Td):温度控制适合衰减曲线法,需要根据多次采样的数据画出响应曲线。
所以需要通过串口将采样时间t, 输出y(t)记录下来,方便分析。
1)、不加入算法,系统全速加热,从常温加热到较高的温度的时间为Tk, 则采样时间一般设为 T = Tk/10。
2)、置调节器积分时间TI=∞,微分时间TD=0,即只加比例算法:y(k) = y(k-1)+Kp*e(k)比例带δ置于较大的值。
将系统投入运行。
(δ = 1/Kp)3)、待系统工作稳定后,对设定值作阶跃扰动,然后观察系统的响应。
若响应振荡衰减太快,就减小比例带;反之,则增大比例带。
如此反复,直到出现如图所示的衰减比为4:1的振荡过程时,记录此时的δ值(设为δS),以及TS 的值(如图中所示)。
当采用衰减比为10:1振荡过程时,应用上升时间Tr替代振荡周期TS计算。
系统衰减振荡曲线图中,TS为衰减振荡周期,Tr为响应上升时间。
据表中所给的经验公式计算δ、TI及TD的参数。
大致计算出Kp,Ti,Td后代入公式,然后完善算法。
让系统运作多测试几次。
直到满意为止。
以下是网上找的一个示例程序#include<reg51.h>#include<intrins.h>#define N0 40536#define nop() _nop_()#define uchar unsigned char#define uint unsigned int/*程序中变量数组定义*/uchar idata table[]={"Real-time Temp:"};//第一行显示"Real-time Temp:"uchar idata table1[5];uchar data1,kp,ki,kd;uint t,hightime,count; //占空比调节参数uint rltemp,settemp=350;int e1,e2,e3,duk,uk;/*引脚定义*/sbit EOC=P2^6;sbit OE=P2^5;sbit START=P2^7;sbit lcden=P3^2;sbit lcdrw=P3^1;sbit lcdrs=P3^0;sbit pwm=P3^3;/******************************延时子程序*******************************/void delay(uint z){uint x,y;for(x=z;x>0;x--)for(y=29;y>0;y--);}/******************************LCD忙检测*******************************/ bit lcd_busy(){bit result;lcdrw = 1;lcdrs = 0;lcden = 1;nop();nop();nop();nop();result = (bit)(P0&0x80);lcden = 0;return(result);}/****************************** LCD写命令子程序*******************************/ void write_com(uchar com){while(lcd_busy());//忙等待lcdrs = 0;lcdrw = 0;P1 = com;delay(5);lcden = 1;delay(5);lcden = 0;}/****************************** LCD写数据子程序*******************************/ void write_data(uchar date){while(lcd_busy()); //忙等待lcdrs = 1;lcdrw = 0;P1=date;delay(5);lcden = 1;delay(5);lcden = 0;}/******************************LCD初始化*******************************/ void lcd_init(){lcden = 0;write_com(0x38);delay(5);write_com(0x0f);delay(5);write_com(0x06);delay(5);write_com(0x01);delay(5);write_com(0x80);delay(5);write_com(0x01);}/****************************** 定时器初始化*******************************/ void time_init(){EA = 1;ET0 = 1;ET1 = 1;TR0 = 1;TR1 = 1;TMOD = 0x11;TH0 = N0/256;TL0 = N0%256;TH1 = 0X3C;TL1 = 0XB0;}/****************************** PID算法系数装载*******************************/ void Pid_init(){hightime= 0; //输出的占空比e1 = 0; //本次的温度差e2 = 0; //前一次的温度差e3 = 0; //两次前的温度差kp = 10; //需要根据试验确定参数ki = 5; //需要根据试验确定参数kd = 5; //需要根据试验确定参数}/******************************温度比较PID算法*******************************/void pid_ys(){if(rltemp<settemp) // 如果实际温度小于设定温度值{if(settemp-rltemp>20) // 如果相差20度(根据实际情况确定是多少){hightime=100; //全速加热}else //否则运行PID算法进行平滑加热{e1 = settemp-rltemp;duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3))/10; // 式(1)因为Kp是10,输入放大了10倍,所以duk的输出结果需要除以10uk = uk+duk;/*****************************式(1)与上面提到的公式类似y(k) = y(k-1)+(Kp+Ki+Kd)*e(k)-(Kp +2*Kd)*e(k-1) + Kd*e(k-2) 可以写成y(k)-y(k-1)=(kp*(e(k)-e(k))+ki*e(k)+kd*(e(k)-e(k-1)*2+e(k-2)) 式(1)中duk 相当于y(k)-(k-1)*****************************/if(uk>100)uk = 100; //设置饱和控制,else if(uk<-100)uk = -100;if(uk<0){hightime=-uk;}else{hightime=uk;}e3 = e2;e2 = e1;}}if(rltemp>=settemp) // 如果实际温度大于设定值{if(rltemp-settemp >0) //只要实际温度与设定值不相等{hightime=0; //停止加热}else /{e1 = rltemp-settemp;duk=(kp*(e1-e2)+ki*e1+kd*(e1-e2*2+e3));uk = uk+duk;if(uk>100)uk = 100;else if(uk<-100)uk = -100;e3 = e2;e2 = e1;}}}/******************************主函数*******************************/void main(){uint i;time_init();//定时器初始化Pid_init(); // PID初始化lcd_init();// LCD初始化table1[5]=0x43;table1[4]=0xdf;table1[2]=0x2e; //小数点摄氏度符号ASCII码for(i=0;i<15;i++) //带循环第一行显示"Real-time Temp:"{write_data(table[i]);delay(20);}while(1){t=data1*196/100;table1[3]=(t%100)%10+0x30;table1[1]=(t%100)/10+0x30;table1[0]=t/100+0x30; //以上温度数据转化rltemp = t; //给PID算法装载实际值write_com(0x80+0x45);//写LCD第二行的初地址for(i=0;i<5;i++) //该循环显示温度值{write_data(table1[i]);delay(20);}pid_ys();//运行温度比较PID算法}}/******************************温度采集转换的定时中断0.5s刷新一次数据*******************************/void timer0() interrupt 1{uint j;j++;if(j==20){OE = 0;START = 0;_nop_();START = 1;_nop_();START = 0;while(EOC==0);OE = 1;_nop_();data1 = P0;_nop_();OE = 0;j = 0;}TH0=N0/256;TL0=N0%256;}/****************************** PWM波输出的定时中断*******************************/ void timer1() interrupt 3{if(++count<=(hightime))pwm=0;else if(count<=100){pwm=1;}elsecount=0;TH1=0x3c;TL1=0xb0;}。