【图】温度PID控制接线与编程实例
来源:电工天下时间:2015-10-26 11:55:59 作者:老电工手机版>>
温度PID控制接线与编程实例
一、温度PID控制接线
A、硬件接线(如图1);
由于固态继电器输出是采用脉冲开关形式,因此采用plc的晶体管输出,型号为CPU224 DC/DC/DC。对于扩展模块EM231 4TC的另外3个端口,采取短接的形式,以防止不必要的干扰。
图1 温度PID控制的硬件接线
B、PID编程
PID编程包括主程序、子程序和中断程序三部分组成。主程序主要完成上电初始化调用子程序,并以两秒为周期(定时器T32)控制固态继电器Q0.0的输出。主程序中的变量M20.0为两秒脉冲;VW200为PID的输出实际值。
二、PID温度控制实验程序
按照时间的顺序:
0:初始化过程
在这个阶段 设置但是中断10ms,设置DOUT0 = 0;烤箱最初从加温模式开始(因为(FPWM==0x01; VAA=0x7f),以及其它初始化设置
1: 定时器每隔10ms中断一次,在中断了TK(100)次之后,也就是1s之后,进行AD值采样和转换,转换完以后把采样值输入PID控制器
进行PID算法控制,输出控制变量UK
2:PID处理过以后,紧接着就改变输出脉宽的控制变量,但是,但是。。。注意,这有一个亮点,就是此时(也就是紧随1000ms之后)
改变的还仅仅是变量,而非实际的温度控制输出,实际的温度控制输出在中断中控制
3:在时间达到0x7f=1270ms后,DOUT0 = 0使温度升高的现象得以改变,FPWM==0x02,DOUT0 = 1;使温度下降,下降持续的时间取决于
我们在1000ms时经过PID的手法处理后的输出变量uk,
4:这就是在系统启动开始1~2s内发生的事,接下来,系统会自己进行采集调节,重复上述步骤
初始化参数由硬件决定,PID子函数中的 参数应该同样如此。
程序实例:
#include <reg51.h>
#include <absacc.h>
#include <math.h>
#define uchar unsigned char
#define uint unsigned int
#define ADC_0 XBYTE[0x0600] //定义模数转换IO地址
#define DAC_1 XBYTE[0x0640] //定义D/A第一路的IO地址
#define DAC_2 XBYTE[0x0641] //定义D/A第二路的IO地址
void pid(void);
sbit str = P1^7;
sbit DOUT0 = P1^4; //PWM输出
uint data time; //声明变量,用于定时
uchar data t0_h,t0_l; //用于存储定时器0的初值
char TK=100; //声明采样周期变量,//采样周期=TK*10ms=1s
char TC=0; //TK的变量
char SPEC=50; //温度给定值
char IBAND=20; //积分分离值
float kp=6.8; //比例系数
float ti=600; //积分系数
float td=50; //微分系数
int FPWM,TKMARK; //PWM标志
int AAA1,VAA; //PWM高电平变量
int BBB,VBB; //PWM低电平变量
int ADMARK,ADVALUE; //温度计算标志和温度累加变量
int YK; //温度值
char EK,EK_1; //当前采样的偏差值
float ZEK; //上一次采样的偏差值
char AEK,AEK_1; //偏差的变化量
int UK; //当前时刻的D/A输出
char code a[0x1ff]={0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,
0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1e,0x1f,0x20,0x21,
0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f,
0x31,0x32,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,
0x3e,0x3f,0x40,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,
0x4d,0x4e,0x4f,0x50,0x4f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,
0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x62,0x63,0x64,0x64,0x65,
0x65,0x66,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6e,0x6f,0x6f,
0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,
0x7e,0x7f,0x80,0x81,0x82,0x83,0x84,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,
0x8b,0x8c,0x8d,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,
0x99,0x9a,0x9b,0x9b,0x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9f,0x9f,0xa0,0xa1,
0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,
0xb0,0xb0,0xb1,0xb2,0xb3,0xb4,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,
0xbd,0xbe,0xbe,0xc1,0xc2,0xc3,0xc4,0xc5,0xc6,0xc8,0xca,0xcc,0xce,0xcf,
0xd0,0xd1,0xd2,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,
0xe3,0xe6,0xe9,0xec,0xf0,0xf2,0xf6,0xfa,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
void main(void)
{
TMOD = 0x01; //工作在定时方式,计数容器0的工作模式为1(16位计数容器)
time = 10; //定时10ms
t0_h = (65536-1000*time)/256; //计算定时器0初值
t0_l = (65536-1000*time)%6;
t0_l = t0_l+20; //修正因初值重装而引起的定时误差
TH0 = t0_h;
TL0 = t0_l;
IT1 = 1; //边沿触发中断
EX1 = 1; //开外部中断1
ET0 = 1; //开定时中断0
TR0 = 1; //启动定时器
DAC_1= 0x80; //D/A清零
DAC_2= 0x80;
ADVALUE=YK=EK=EK_1=AEK=ZEK=0; //变量清零
UK=TKMARK=BBB=VBB=ADMARK=TC=0;
FPWM=0x01; //变量赋初值
AAA1=VAA=0x7f;
str =0;
EA = 1; //开总中断
while(1)
{
for(;;) if(TKMARK==0x01) break; //判采样周期到否,次数不到等待,到后向下执行 (定时中断)
TKMARK=0x00;
for(;;) if(ADMARK==0x01) break; //判A/D采样完成否,采样没完则等待,完成向下执行 (外部中断)
ADMARK=0x00;
//如果采样周期(1s)到了,而且AD转换完成了,向下执行
YK=a[ADVALUE]; //查表读出温度参考值
pid(); //调用PID程序计算控制量
//PID之后,输出量Uk影响的是下一次脉宽比例
// PID的作用就是根据采样值控制下一周期的输出,预见性有没有?
if( UK <= 128) AAA1=0x10; //如果控制量太小,赋极值,此值能使温度启动
else AAA1=UK-128;
BBB=0x7f-AAA1;
DAC_1=SPEC+128; //给定值送D/A第一路输出
DAC_2=YK+128; //温度值送D/A第二路输出
}
}
void pid(void)
{ float K,P,I,D;
EK=SPEC-YK; //计算偏差_____SPEC(温度给定值)____YK(采样查表值)___EK(当前采样偏差值)
AEK=EK-EK_1; //____AEK(偏差的变化量)____EK_1(上次采样偏差值)
if ( (abs(EK)>IBAND) || ti==0) I=0;//判积分分离值 如果偏差值过大或者积分系数为0,I=0
else
{
ZEK=ZEK+EK; //计算积分项 ZEK(上次采样的偏差值)
if(ZEK>127) ZEK=127;
if(ZEK<-128) ZEK=-128;
I=ZEK*TK; //TK(采样周期变量)
I=I/ti;
}
P=EK; //比例项
D=td*AEK; //计算微分项
D=D/TK;
K=kp*(P+I+D); //计算比例项
if(K>127) K=127; //判控制量是否溢出,溢出赋极值
if(K<-128) K=-128;
UK = K;
EK_1=EK; //更新保存采样偏差
UK=UK+128; //经过PID之后,当前DA输出
}
void int1() interrupt 2 using 2
{
ADVALUE=ADC_0; //读取A/D转换结果,并置标志
ADMARK=0x01;
}
void Timer0() interrupt 1 using 1
{
str = 1; //输出高电平
TH0 = t0_h; //重新装入初值
TL0 = t0_l;
if(TC<TK) TC++; //采样周期变量累加
else {TKMARK=0x01; //如果定时次数达到TK,则MARK
TC=0x00;
}
if (FPWM==0x01)
if(VAA!=0x00) //初始化时VAA=0x7f,所以在前0x7f*10ms=1270ms 内可保证DOUT0 = 0;温度升高
{ VAA=VAA-1; //当再一次VAA!=0时,VAA的大小取决于VAA=AAA1/2;VAA值的大小影响的是升高温度的时间
DOUT0 = 0; //P1.4清零,温度开始升高
}
else //注意:else总是与它上边的最近的未配对的if配对 ——(谭浩强C程序设计)第三版99页末
{ FPWM=0x02; //1270ms过后,改变标志和参变量
VBB=BBB/2; //
}
if(FPWM==0x02) //当1270ms后,首次执行此if下语句
if(VBB!=0x00) //VBB的大小取决于VBB=BBB/2;VBB值的大小影响的是降低温度的时间
{ VBB=VBB-1;
DOUT0 = 1; //P1.4置一,温度开始降低
}
else
{ FPWM=0X01;
VAA=AAA1/2;
}
str = 0;
}
相关文章
plc与变频器如何接线(附接线图)
有关plc与变频器的接线图,学习下plc连接变频器的接线方法,感兴趣的朋友参考下。
时间:2022-09-18 13:08:17
学习PLC需要先学习继电器控制吗?
在学习PLC基础知识之前,是否需要先学习继电器控制,能够问出这个问题的人,在学习下算是比较用的了,答案是肯定的,最好先学习下继电器控制方面的知识,下面具体来了解下。
时间:2022-07-17 05:26:08
将继电器控制电路转换为plc梯形图的方法
继电器控制电路转换为plc梯形图的方法,需要用plc的外部接线图和梯形图来等效继电器电路图,根据继电器电路图设计梯形图,将继电器电路图转换为具有相同功能的plc外部硬件接线图和梯形图。
时间:2022-07-11 08:50:25
plc梯形图实现路灯延时触模开关控制
分享一个路灯延时触模开关控制的plc梯形图程序,plc梯形图实现路灯的延时开关,这在很多路灯控制场合经常会用到,配有实例图,供大家学习参考。
时间:2022-07-10 07:15:52
电工必备电气原理图14:PLC正反转控制原理
以下是PLC正反转控制的工作原理图,通过PLC编程实现电动机的正向启动、反向启动和停止,以下是简单而实用的电气原理图,有需要的朋友参考下。
时间:2022-03-28 09:17:14
电工必备电气原理图1:自动往返控制工作原理图
电工必备电气原理图1:自动往返控制工作原理图,完整动画演示,从原理上了解自动往返控制的工作过程,有需要的朋友参考下。
时间:2022-03-11 15:35:32
plc自锁控制梯形图与指令表程序的二种方式
plc自锁控制梯形图与指令表程序的二种方式,包括启动按钮、停止按钮、热保护、运行继电器等,学习下plc自锁控制梯形图与指令表程序的编写方法。
时间:2021-11-22 09:20:06
plc自锁控制原理图(FX2N-32MR)
有关plc自锁控制的原理图,型号为FX2N-32MR,分享给大家,做个参考。
时间:2021-11-22 09:20:05