基于单片机的pid算法温度控制技术代码
基于PID算法的89C52单片机温度控制系统

基于PID算法和89C52单片机的温度控制系统基于PID算法和89C52单片机的温度控制系统0 引言温控技术无论是在工业生产,还是日常生活中都起着非常重要的作用。
在冶金、石油、化工、电力和现代农业等行业,温度是极为重要而又普遍的热工参数之一,在普通家庭里热水器、电饭煲、电烤箱等依赖于温控技术的家电设备也是必不可少。
可以说温度控制技术无处不在。
常规的温度控制方法以设定温度为临界点,超出设定允许范围即进行温度调控:低于设定值就加热,反之就停止或降温。
这种方法实现简单、成本低,但控制效果不理想,控制温度精度不高、容易引起震荡,达到稳定点的时间也长,因此,只能用在精度要求不高的场合。
而采用PID算法进行温度控制,它具有控制精度高,能够克服容量滞后的特点,特别适用于负荷变化大、容量滞后较大、控制品质要求又很高的控制系统。
单片机作为控制系统中必不可少的部分,在各个领域得到了广泛的应用,用单片机进行实时系统数据处理和控制,保证系统工作在最佳状态,提高系统的控制精度,有利于提高系统的工作效率。
本系统采用单片机编程实现PID算法进行温度控制。
1 PID控制的原理和特点在工程实际中,应用最为广泛的调节器控制规律为比例、积分、微分控制,简称PID控制,又称PID调节。
PID控制器以其结构简单、稳定性好、工作可靠、调整方便而成为工业控制的主要技术之一。
当被控对象的结构和参数不能完全掌握,或得不到精确的数学模型,控制理论的其他技术也难以采用,系统控制器的结构和参数必须依靠经验和现场调试来确定时,应用PID控制技术最为方便。
PID控制器的参数整定是控制系统设计的核心内容。
它是根据被控过程的特性确定PID 控制器的比例系数、积分时问和微分时间的大小。
PID控制器参数整定的方法概括起来有两大类:一是理论计算整定法。
它主要是依据系统的数学模型,经过理论计算确定控制器参数。
这种方法所得到的计算数据未必可以直接用,还必须通过工程实际进行调整和修改。
一个实用的单片机PID方式控温实例

一个实用的单片机PID方式控温实例§1:基本情况本例中控制对象是一款小型专用工业烘箱要求恒温范围:室温--300℃恒温精度:±1℃(其它指标略)§2:控制器硬件(参考原理图)①.单片机采用(C51系列)TI公司的MCS1210Y4(内部有8通道24位AD转换器)串行口在线编程②.前向通道温度信号(来自烘箱的Pt100电阻信号)经INA118放大送入AD通道CH0③.后向通道 I/O口驱动光耦MOC-3061,再驱动大功率双向可控硅输出④.键盘 up 递增按钮和down 递减按钮,设置目标温度⑤.LED(3位)显示温度值(软件切换显示目标温度或采样温度)⑥.电源 +5V单电源§3:软件介绍(由C语言编写)①.流程采样当前温度--PID运算--PWM(占空比式)输出②.温度采样采样周期是一个很重要的参数其确定取决于烘箱的固有响应特性参数(比如纯滞后时间θ以及响应时间常数τ)一般值在4--20秒之间(例中取16秒)③.PID运算每采样一次之后进行一次PID运算,得到一个输出量,供输出函数调用.为了下面叙述方便先定义几个变量定义: T_target 表示目标温度T_real 表示当前温度T_diff 表示当前温差并且T_diff=T_target-T_realPID运算表达式如下PWM_OUT=P_OUT+I_OUT+D_OUT+P_H;(求代数和)其中 P_OUT=KP*(T_diff)称为比例项,KP是比例系数,比例项的作用是纠正偏差.比例项输出等于比例系数乘当前温差(原理图)I_OUT=KI*∑(diff)称为积分项,KI是积分系数,积分项用于消除系统稳态误差∑(diff)含义是由当前算起前面N次采样温差的和(例中N取20)D-_OUT=KD*Δdiff称为微分项,KD是微分系数,微分项用于减小系统超调量,增加系统稳定性.(Δdiff=当前温差-上次温差)P_H=KC*(T_target)称为维持功率项,达温后(其它项均趋于0)此项起抵消散热维持温度的作用,可增加系统稳定性.KC是维持功率系数如果约定满功率值为100,停止输出功率值为0 那末PWM_OUT的取值范围就确定为0--100主要是为了后面编制输出函数时方便简明,直接调用PWM_OUT作为输出占空比的百分数)后面整定系数时就要兼顾PWM_OUT的取值范围§4.源程序(部分)#define KP 3.0 //比例系数#define KI 0.3 //积分系数#define KD 200.0 //微分系数#define KC 0.1 //维持功率系数#define T_c 16 //采样周期(单位:秒)sbit pid_port=P3^5; //控制输出端口float T_target=0; //目标温度float T_real=0; //当前温度float PWM=0; //输出控制量bit read_AD_enable=0; //PID运算允许标志位//T0定时器初始化void Timer0_Init(){TMOD|=0x01;TF0 =0;TR0 =1;IE |=0x02;}//读取AD 转换值并刻度void read_AD(void){int delta_ad;unsigned char ad[3];ad[0]=ADRESH;ad[1]=ADRESM;ad[2]=ADRESL;delta_ad=ad[0]*0x100+ad[1]-0x23cb;if(delta_ad<=0)delta_ad=0;T_real=(float)delta_ad/70;}//*--------PID运算函数void pid(void){static float diff[20]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; static float sum_diff=0; //∑(diff)static int curr_=0;float p_out,i_out,d_out,temp;float pwm_0;temp=diff[curr_];if(curr_+1>=20)curr_=0;else curr_+=1;sum_diff-=diff[curr_];diff[curr_]=T_target-T_real;sum_diff+=diff[curr_];p_out=KP*diff[curr_]; //比例项输出i_out=KI*sum_diff; //积分项输出d_out=KD*(diff[curr_]-temp); //微分项输出pwm_0=KC*T_target; //维持功率项if(i_out>100)i_out=100; //积分分离if(i_out<-100)i_out=-100;PWM=p_out+i_out+d_out+pwm_0; //总输出量if(PWM<0)PWM=0;else if(PWM>=100)PWM=100;}// 输出函数void PWM_OUT(float PWM){static unsigned char t=1; //t=(1--100)周期为4秒unsigned char limit; //pid_value输出百分比limit=(unsigned char)PWM;if(t<=limit)pid_port=0; //加热else pid_port=1; //停止加热t++;if(t>100)t=1;}/**************************************************///T0中断服务程序void Timer0_ISR() interrupt 1 using 1{static unsigned int x=0;TH0=(28672)>>8; // 11.0592MHz,interval 40mSTL0=(28672+20)&0xff; // +20 compensateTF0=0;if((x++)>(T_c*25)){x=0;read_AD_enable=1;}PWM_OUT(PWM); //可控硅输出}/****************************************************主程序----------------------------------------------------*/void main (void){//-------程序初始化(略)while (1){if(read_AD_enable==1){read_AD_enable=0;read_AD();pid();}}}§5.参数的整定(这大概是最困难而且费时的事)①T_c(采样周期)单从控制精度上考虑,T_c当然是越小越好,但过小占用处理器的运算时间会加长,从而导致系统成本增加,例中主要考虑被控对象的时间常数τ和纯滞后时间θ,下面用扩充响应曲线法求取τ及θ.a. 使系统处于开环,手动直接在被控对象输入端加一个阶跃信号描绘出响应曲线(如图)b. 在响应曲线的最大斜率处作切线即可得到θ和τc. 选择T_c,当θ占主导地位时,应尽量使θ为T_c的整倍数如θ=2T_c 或θ=T_c ,当θ比T_c小得多时,可取T_c= τ/10②KP( 比例系数)先定为1,做一个简单的只有比例调节的函数,使系统工作于闭环,T_target 定在150℃(恒温范围的中间值)纪录响应曲线,如果曲线没有出现振铃则可能是KP偏小,调整KP,使曲线出现轻微振铃.反之振铃幅度过大,则可能是KP偏大.③KC(维持功率系数)借用§5.②中的曲线(如下图)根据图中所示由KC*150=PWM_H 导出KC④KI(积分系数)KI 的选取与T_c和积分时长有关,回过头看源程序PID运算函数中有一个静态数组,记录过去t 时刻到当前的各个温度采样值.每一次采样之后都要更新(淘汰掉最早的采样值,加入当前采样值).积分时长=T_c*采样个数(即数组大小[SIZE])积分时长的选择一般使它大于纯滞后时间θ即可,反过来通过T_c和θ可以确定数组的大小[SIZE],接着套用下式就可以大致确定KI了.KI*SIZE=10%*满功率值⑤KD(微分系数)KD取值大致为纯滞后时间θ(比如θ=200秒,KD先取200,后根据实验在调整)以上的步骤可能要反复进行多次,各个系数也要作相应的调整.这里我介绍一个站长编写的并已成功应用的调试软件HUANENG.EXE专用于串行口数据分析绘图,可同时描绘8条曲线,(VC编写)使用非常简单,只需在上面源程序中pid()函数末尾加上几行数据打印输出的语句比如:printf("CH0=%x\nCH1=%x",T_real,PWM);通过串行口接到计算机,打开该软件即可.界面如下图统调中记住:增大KP,会加快系统响应,减小静差,但超调量增大,稳定性变差.减小KI,削弱积分作用,系统超调量变小,但消除静差的时间长.增大KD,可减小超调量,稳定性好,但系统响应速度变慢.。
基于单片机的PID温度控制

间延迟的控制系统 [ 1] , 它可以通过模型设定和频率响应设定两种方法设定 PID 控制器的参数 K p 、、Ti 。Td 假设控制系统模型为:
如图.5 在时域内作系统的阶跃响应曲线,根据曲线可以得出特征参数 k , L 和 T 的值, 有了这些参数, 并假设ê = kL/ T , 则 PID 控制器的参数可以由表 1 求出来。如图.6 在频域内作系统的 Nyquist 图, 可以从图形上直接得出系统 的相位穿越频率ω g 和该点处的增益值 K g , 这样就可以得出 Tg = 2 π / ω g , 这时 PID 控制器的参数也可以由表 1 求出来。
2.1 实物展示
图.1
ቤተ መጻሕፍቲ ባይዱ图.2
图.3
图.4
图.1 是用欧姆龙的温控器,已经集成于机箱中,图.2 是单片机模块,图.3 是 实验室实验平台,图.4 是系统集成模块。
3.1 PID 参数自整定思想
本系统的被控对象是某水壶里的温度, 一般温度可近似用一阶惯性纯滞后环 节来表示, 其传递函数 G s
PID 控制指的是通过调整上式的控制器参数 K p 、Ti 、Td , 使整个控制 系统性能满足工作要求。自整定 PID 控制提供了简单的调整参数的方法, 使其 能够达到较好的控制效果 。常用的自整定 PID 设定参数方法有 :Zieg ler -Nichols 方法、改进的 Zieg ler -Nichols 方法、幅值相位裕度设定方法及最 优整定方法等, 下面将分别介绍各种参数设定方法 (1)Ziegler -Nichols 方法。Zieg ler 和 Nichols 提控制策略给出的控制 结构, PID 控制器模型为出的调节 PID 控制器参数的经验公式适用于具有纯时
3.3
基于C51单片机的温度闭环控制实验程序

#include <reg51.h>#include <absacc.h>#include <math.h>void pid(void) //PID算法子程序void init(void) //初始化子程序void display(void) //延时子程序void clear() //清零子程序int mmul(int x,int y) //16位乘法,溢出赋极值int madd(int x,int y) //16位加法,溢出赋极值int change32_16(int x,int t) //32——16char change16_8(int wd) //16——8#define C8255_A XBYTE[0x7F00]#define C8255_B XBYTE[0x7F01]#define C8255_C XBYTE[0x7F02]#define C8255_CON XBYTE[0x7F03]#define AD0809 XBYTE[0xFEFF] //定义AD0809的地址sbit P17=P1^7; //PWM的驱动char TS=0x64; //采样周期int X=0x80;char SPEC=0x28; //给定:要求达到的温度值char IBAND=0x60; //积分分离值:PID算法中积分分离值int KP=12; //比例系数:PID算法中比例项系数char KI=20; //积分系数char KD=32; //微分系数int CK; //控制量:PID算法产生用于控制的量int TC; //采样周期变量char FPWM; //PWM脉冲中间标识位int CK_1; //控制量变量,用于记录上次控制的值int AAAA; // PWM高电平脉冲时间计算int VAA; //AAAA变量int BBB; //PWM低电平脉冲时间计算int VBB; //BBB变量int TKMARK; //采样标志值int ADMARK; //AD转换结束标志位int ADV ALUE; //AD采样后保存int YK; //反馈:测量温度值int EK; //温度误差int EK_1;int AEK;int BEK;unsigned char dis; //BCD码显示unsigned char led[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};unsigned char b[]={0x00,0x00,0x00,0x00}; //位选/********************温度表**************/unsigned char codea[0x100]={0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x14,0x15,0x16,0x17,0x18,0x19, 0x1a,0x1b,0x1c,0x1d,0x1e,0x1e,0x1f,0x20,0x21,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,0x3 c,0x3d,0x3e,0x3f,0x40,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x4 f,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f,0x60,0x61,0x6 2,0x63,0x64,0x64,0x65,0x65,0x66,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6e,0x6f,0 x6f,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,0x8 a,0x8b,0x8c,0x8e,0x8f,0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9b,0 x9c,0x9c,0x9d,0x9d,0x9e,0x9e,0x9f,0x9f,0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf,0 xb0,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,0 xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,}/**************延时子程序*********************/void delay(unsigned int time){unsigned int i;for(i=0;i<time;i++)}/*************主程序*************************/void main(){init();while(1);{while(1){if(TRMARK==0x01)break; //采样周期到否}TRMARK==0x00;while(1){if(ADMARK==0x01)break; //AD转换是否结束}ADMARK=0x00;YK=a[ADV ALUE];dis=(char)YK; //查温度表pid(); //PID算法if(CK<=0x80) //根据CK产生PWMAAAA=0x00;elseAAAA=CK-0x80;BBB=0x7f-AAAA;}}/***********初始化函数*********************/void init(void){YK=0x00; //变量初始化EK=0x00;EK_1=0x00;AEK=0x00;BEK=0x00;CK=0x00;CK_1=0x00;BBB=0x00;VBB=0x00;ADV ALUE=0x00;TKMARK=0x00;ADMARK=0x00;TC=0x00; //采样周期变量FPWM=0x01;AAAA=0x7f;V AA=0x7f;C8255_CON=0x81;display();clear();TMOD=0x11; //T1 ,T0由外部控制中断控制信号,16位定时器,工作在方式一下IP=0x02; //设定T0中断优先级最高IT1=1; //外部中断请求信号方式为脉冲触发方式,外中断1为下降沿有效EX1=1; //允许INT1中断TH0=0xd8;TL0=0xef;TH1=0xd8;TL1=0xef;ET0=ET1=1; //允许T0,T1中断TR0=TR1=1; //启动T0,T1EA=1;AD0809=1; //启动AD转换}void myint3(void) interrupt 3 //定时器1 LED显示{TH1=0xd8;TL1=0xef;ET1=1;display();clear();}void myint1(void) interrupt 2 //外中断1 读AD转换结果{ADV ALUE=AD0809;ADMARK=0x01;}void myint2(void) interrupt 1 //定时器0 启动AD转换{TH0=0xd8;TL0=0xef;ET0=1; //启动定时器0AD0809=1; //启动ADif(TC<TS)TC++; //采样周期变量else{TKMARK=0x01;TC=0x00;}if(FPWM==0x01) //产生PWM ,0x01表示加热模块{if(V A!=0x00){V AA=V AA-1;P17=0; //输出为低加热else{FPWM=0x02;VBB=BBB/2;}}if(FPWM==0x02) //0x02表示停止加热模块{if(VBB!=0x00){VBB=VBB-1;P17=1; //输出为高停止加热}else{FPWM=0x01;V AA=AAAA/2;}}return;}/*****************PID子程序***********/void pid(void){int K,P,I,D;K=P=I=D=0;EK=SPEC-YK;//得到偏差BEK=EK-EK_1-AEK;//12EKAEK=EK-EK_1; //偏差变化量/*********UK=Kp*AEK+Ki*EK+Kd*BEK****/if(abs(EK)>abs(IBAND))I=0; //判积分分离elseI=(EK*TS)/KI; //计算积分项P=AEK;D=((KD/TS)*BEK)/10000; //计算微分项//与书上对照,忽略KP K=madd(I,P);K=madd(D,K);K=mmul(K,KP);CK=K+CK_1;CK=change16_8(CK);CK_1=CK;EK_1=EK;CK=CK+X;}int mmul(int x,int y){int t,z;long s;s=x*y;z=(int)(s&0x0ffff);t=(int)((s>>16)&0x0ffff);s=change32_16(z,t);return(s);}int change32_16(int z,int t) //t=高字节,z=低字节{int s;if(t==0){if((z&0x8000)==0) s=z;else s=0x7fff;}else if((t&0xffff)==0xffff){if((z&0x8000)==0) s=0x8000;else s=z;}else if((t&0x8000)==0) s=0x7fff;else s=0x8000;return(s);}int mmad(int x,int y){int t;t=x+y;if(x>=0&&y>=0) //同号相乘,符号位变反说明溢出{if((t&0x8000)!=0) t=0x7fff;}else if(x<=0&&y<=0){if((t&0x8000)==0) t=0x8000;}return(t);}char change16_8(int wd) //t=高字节,z=低字节{char z,t,s;z=(wd>>8)&0x0ff;if(t==0x00){if((z&0x80)==0) s=z;else s=0x7f;}else if((t&0xff)==0xff){if((z&0x80)==0) s=0x80;else s=z;}else if((t&0x80)==0) s=0x7f;else s=0x80;return(s);}void display() //数码管显示函数{unsigned char i,j=0xf7;b[3]=SPEC/10;b[2]=SPEC%10;b[1]=dis/10;b[0]=dis%10;for(i=0;i<4;i++){C8255_A=j;C8255_B=led[b[i]];delay(0x55);j>>=1;}}void clear(){C8255_B=0x00;}。
基于单片机的软件实现PID温度控制系统

姓名:专业:学号:学科:基于单片机的软件实现PID温度控制系统引言随着控制理论和电子技术的发展,工业控制器的高精度性要求越来越高,其中以单片机为核心实现的数字控制器因其体积小,成本低,功能强,简便易行而得到广泛应用。
温度控制器作为一种重要的控制设备,在化工,食品等诸多工业生产过程和家用电器中得到了广泛的应用,本文主要讨论在家用电器电冰箱中得到广泛应用的数字PID控制,在单片机温度控制系统中的应用。
通过对实验数据的分析表明单片机的温度控制系统设计的合理性和有效性。
1硬件系统设计本文所研究的温度控制系统硬件部分按功能大致可以分为以下几个部分:单片机主控模块,输入通道输出通道等。
硬件总体结构框图如图所示。
图1中,温度控制系统以单片机为核心,并扩展外部存储器,构成主控模块零度保鲜箱的温度由铂Pt100电阻温度传感器检测并转换成微弱的电压信号,再通过位的转换器转换成数字量,此数字量经过数字滤波之后,一方面将零度保鲜箱的温度通过控制面板上的液晶显示器显示出来,另一方面将该温度值与设定的温度值进行比较,根据其偏差值的大小,采用控制算法进行运算,最后通过控制双向可控硅控制周期内的通断占空比,即控制零度保鲜箱制冷平均功率的大小,进而达到对零度保鲜箱温度进行控制的目的。
控制系统电路的核心器件是Atmel公司生产的单片机,图2所示.它是一种低功耗低电压高性能的位单片机片,内带有一个的可编程可擦除只读存储器,它采用的工艺是Atmel公司的高密度非易失存储器技术。
其输出引脚和指令系统都与MCS51兼容且价格低廉,性能可靠,抗干扰能力强,因此广泛应用于工业控制和嵌入式系统中。
为了节省成本和体积采用多路选择开关和AD7705模数转换器协同工作,组成多路数据采集系统.AT24C02是Atmel公司生产的EEPROM器件,存储容量256字节可擦写次数达100万次,主要用来存储设定温度。
2软件实现PID控制PID控制是最早发展起来的控制策略之一,在微机测控系统中,软件与硬件同样重要.硬件是系统的躯体,软件则是灵魂,当系统的硬件电路设计好之后,系统的主要功能还是要靠软件来实现,而且软件的设计在很大程度上决定了测控系统的性能,很多的单片机软件系统都是采用如图2所示的前后台系统也称超循环系统。
pid算法温度控制c语言程序

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温度控制系统设计 -回复

基于单片机的pid温度控制系统设计-回复基于单片机的PID温度控制系统设计摘要:本文将介绍一种基于单片机的PID温度控制系统的设计方法。
该系统利用单片机的强大计算处理能力和易编程特性,通过PID控制算法实现对温度的精确调节和稳定控制。
文章将从系统的硬件设计和软件编程两个方面逐步讲解具体设计步骤和实施方法,旨在帮助读者理解和掌握该技术。
第一节:引言温度控制是很多工程领域中常用的一项自动化控制技术。
在一些需要保持稳定温度或者按设定温度进行自动控制的应用中,如温室、恒温箱、冷藏室等,PID控制算法广泛应用。
而采用基于单片机的PID温度控制系统,无论是从成本、体积还是功能扩展等方面都具有一定优势。
第二节:系统硬件设计PID温度控制系统的硬件设计主要包括传感器模块、智能温控器模块和执行器模块。
1. 传感器模块:选择适合应用场景的温度传感器,如热敏电阻、热电偶等。
将传感器与单片机相连,通过模拟输入口将传感器输出的模拟电压信号转换为数字信号。
2. 智能温控器模块:使用单片机作为智能温控器的核心,通过LCD显示屏和按键,实现温度的设定和显示。
单片机利用PID控制算法对设定温度和实际温度进行比较,并输出控制信号。
3. 执行器模块:执行器模块用于控制温度。
根据具体系统要求,可以选择继电器、加热器、风扇等。
执行器根据控制信号的输入来执行相应的操作,从而实现温度的调节控制。
第三节:软件编程PID温度控制系统的软件编程主要包括单片机的初始化设置和PID控制算法的实现。
1. 单片机的初始化设置:包括系统时钟设置、IO引脚设置、模拟输入口配置、LCD显示配置、按键操作配置等。
这些设置可以利用单片机提供的开发工具或者编程软件完成。
2. PID控制算法的实现:PID控制算法是PID温度控制系统的核心部分。
PID控制器由比例(P)、积分(I)和微分(D)三个部分组成。
通过不断调节三个参数的大小以及权衡不同参数的影响,实现对温度的稳定控制。
基于PID的温度控制系统设计

(2014届)毕业设计题目:基于PID的温度控制系统设计学院: ********专业:电气工程及其自动化班级:电气***学号: **********姓名:某某某指导教师:某某某教务处制年月日诚信声明我声明,所呈交的论文是本人在老师指导下进行的研究工作及取得的研究成果。
据我查证,除了文中特别加以标注和致谢的地方外,论文中不包含其他人已经发表或撰写过的研究成果,也不包含为获得______或其他教育机构的学位或证书而使用过的材料。
我承诺,论文中的所有内容均真实、可信。
论文作者签名:签名日期:年月日授权声明学校有权保留送论文交的原件,允许论文被查阅和借阅,学校可以公布论文的全部或部分内容,可以影印、缩印或其他复制手段保存论文,学校必须严格按照授权对论文进行处理,不得超越授权对论文进行任意处置。
论文作者签名:签名日期:年月日基于PID的温度控制系统设计摘要温度是工业上最基本的参数,与人们的生活紧密相关,实时测量温度在工业生产中越来越受到重视,离不开温度测量所带来的好处,因此研究控制和测量温度具有及其重要的意义。
本设计介绍了以AT89C52单片机为主控器件,基于PID的温度控制系统的设计方案和设计的基本原理。
由DS18B20收集温度信号,并以数字信号的方式送给单片机进行处理,从而达到温度控制的目标。
主要包括硬件电路的设计和系统程序的设计。
硬件电路由主控器件、温测电路、温控电路和显示电路等组成。
软件设计部分包括:显示电路、温度信号处理,超温警报、继电器控制、按键处理等程序。
关键词:温度检测,温度控制,PID算法Design of Temperature Control System Based on PIDAbstractTemperature is the most basic parameters of industrial and closely related with people's lives, real-time measurement of temperature in industrial production and more attention, which is inseparable from the benefits of the temperature measurement, temperature control and measurement study therefore has its significance.This design introduces the basic principles to AT89C52 microcontroller-based controller pieces temperature control system design and design. Collected by the DS18B20 temperature signal, and digital signal sent by way of the microcontroller for processing, so as to achieve the target temperature control. Including the design of hardware circuit design and system programs. Hardware circuit includes a master device, the temperature measuring circuit, temperature control circuit and display circuit. Software design, including: display electrical, temperature, signal processing, over-temperature alarm, relay control, key handling procedures.Keywords: temperature detection, temperature control, PID algorithm摘要 (II)Abstract (III)1绪论 01.1课题的来源 01.2课题的意义 01.3课题研究的主要内容 02硬件设计 (2)2.1单片机控制模块的设计 (2)2.1.1 AT89C52单片机简介 (2)2.1.2 单片机的引脚功能 (3)2.1.3 单片机控制模块的电路设计 (4)2.1.4 电源设计 (5)2.2温度采集模块的设计 (6)2.2.1 DS18B20芯片的简介 (6)2.2.2 DS18B20的内部结构 (7)2.2.3 DS18B20的供电方式 (9)2.2.4 DS18B20的引脚功能 (9)2.3温度控制模块的设计 (10)2.4按键及显示模块的设计 (12)2.4.1 LCD1602的参数和引脚功能 (13)2.4.2 LCD1602的特点 (14)2.4.3 按键电路的设计 (14)2.5报警模块的设计 (15)3软件设计 (17)3.1主程序的设计 (17)3.2DS18B20读温度程序的设计 (17)3.3键盘扫描程序的设计 (18)3.4报警处理程序的设计 (19)3.5PID控制算法 (19)4系统仿真 (23)参考文献 (28)致谢 (29)附录 (30)1.1课题的来源在食品加工、化工、冶炼等工业控制和生产中,在工业生产和日常生活中经常要用到温度检测和控制。
基于51单片机和PID算法的温度控制系统核心算法

#include <reg52.h>#include <stdio.h>#include "1602.h"#include "delay.h"float SetTemp=50;sbit Key_Add=P3^1;sbit Hot=P3^2;float Temperature=0;bit ReadTempFlag;//定义读时间标志char displaytemp[16];//定义显示区域临时存储数组float Error=0,PreError=0,SumError=0,Cout=0;void Init_Timer0(void);//定时器初始化/*------------------------------------------------主函数------------------------------------------------*/void main(){unsigned char key_press_num;Init_Timer0();Key_Add=1;LCD_Init(); //初始化液晶DelayMs(20); //延时有助于稳定LCD_Clear(); //清屏Lcd_User_Chr();sprintf(displaytemp,"Set%5.1f",SetTemp);//显示设定温度LCD_Write_String(0,1,displaytemp);LCD_Write_Char(9,0,0x01);//写入温度右上角点LCD_Write_Char(10,0,'C'); //写入字符Cwhile(1){if(!Key_Add) //如果检测到低电平,说明按键按下{DelayMs(10); //延时去抖,一般10-20msif(!Key_Add) //再次确认按键是否按下,没有按下则退出{while(!Key_Add){key_press_num++;DelayMs(10); //10x200=2000ms=2sif(key_press_num==200) //大约2s{key_press_num=0; //如果达到长按键标准//则进入长按键动作while(!Key_Add) //这里用于识别是否按//键还在按下,如果按//下执行相关动作,否则退出{if(Temperature<51) //加操作Temperature++;DelayMs(500);if(Temperature=51)Temperature=0;sprintf(displaytemp,"Temp%5.1f",Temperature);LCD_Write_String(0,0,displaytemp);}}}key_press_num=0;//防止累加造成错误识别if(Temperature<51) //加操作Temperature++;if(Temperature==51)Temperature=0;}}if(ReadTempFlag==1){ReadTempFlag=0;Error=SetTemp-Temperature;PreError=Error;SumError=SumError+Error;Cout=2*Error+0*SumError+(Error-PreError);if(Cout<0)Cout=0;else if(Cout>100)Cout=100;}sprintf(displaytemp,"Temp%5.1f",Temperature);//显示当前温度LCD_Write_String(0,0,displaytemp);// LCD_Write_String(0,1,"gao jie");sprintf(displaytemp,"%5.1f%%",Cout);//显示占空比LCD_Write_String(10,1,displaytemp);}}/*------------------------------------------------定时器初始化子程序------------------------------------------------*/void Init_Timer0(void){TMOD |= 0x01; //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响//TH0=0x00; //给定初值//TL0=0x00;EA=1; //总中断打开ET0=1; //定时器中断打开TR0=1; //定时器开关打开}/*------------------------------------------------定时器中断子程序------------------------------------------------*/void Timer0_isr(void) interrupt 1{static unsigned int num=0;TH0=(65536-5000)/256; //重新赋值2msTL0=(65536-5000)%256;num++;if(num==400) //{num=0;ReadTempFlag=1;}if(0<num&&num<(4*Cout))elseHot=1; }。
基于PID控制算法的电阻炉温度控制单片机C语言程序

基于PID控制算法的电阻炉温度控制单片机C语言程序#include //函数申明、参数定义#include#include#include#define uchar unsigned char#define uint unsigned intsbit DQ=P2^7; //DS18B20的数据DQ脚sbit BEEP=P2^6; //蜂鸣器控制脚sbit PWM=P2^5; //继电器与单片机的连接sbit lcden=P2^0; //LCD1602的使能端sbit lcdrw=P2^1; //LCD1602的读/写sbit lcdrs=P2^2; //LCD1602的数据/指令uchar dis_buf,temp,key;float kp; // 比例常数uint set_temp; //设定温度uint now_temp; //当前温度float prev_prev_error=0,prev_error=0,error=0;//e(k-2),e(k-1),e(k)float dp; //p(k)-p(k-1)uchar high_pulse,low_pulse; //PWM波形占空比uchar low_time=0,high_time=0; //每个周期里低电平次数,高电平次数uchar code table3[]="0123456789";void delayms(int z); //延时void write_com(uchar com); //向LCD1602写指令void write_dat(uchar dat); //向LCD1602写数据void LCD_init(); //LCD1602初始化void LCD_disp_char(uchar x,uchar y,uchar dat);//在某个屏幕位置上显示一个字符,X (0-15),y(0-1)void LCD_disp_str(uchar x,uchar y,uchar *str); //LCD1602显示字符串函数void DS18B20_init(); //DS18B20初始化uchar tempreadbyte(); //按字节读uint tempread(); //读取温度void tempwritebyte(uchar dat); //按字节写uchar tempreadbit(); //按位写void temp_start(); //温度转化void DS18B20_wait(); //等待void displaylcd(uint now_temp,uint set_temp); //LCD1602显示void keyscan(); //按键扫描void keydown(); //判断按键是否按下uint key_input(); //按键输入void pid(float kp); //PID控制void InitTimer2(void); //T2定时器初始化void delayms(int z) //ms延时函数{int x,y;for(x=z;x>0;x--)for(y=110;y>0;y--);}void LCD_Init(void) //LCD1602初始化{write_com(0x38); //显示模式设置delayms(1);write_com(0x06); //显示光标移到设置delayms(5);write_com(0x01); //显示清屏delayms(1);write_com(0x0C); //显示开及光标设置delayms(5);}void write_com(uchar com) //向LCD1602写指令rs低,rw低{lcdrs=0;lcden=1;lcdrw=0;P0=com;delayms(1);lcden=0;delayms(1);}void write_dat(uchar dat) //向LCD1602写数据rs高,rw低{ lcdrs=1;lcden=1;lcdrw=0;P0=dat;delayms(1);lcden=0;delayms(1);}void displaylcd(uint now_temp,uint set_temp) //LCD1602显示{uint k=0;//第一行显示当前温度k=now_temp/1000;if(k!=0){LCD_disp_char(9,0,table3[k]); //百位k=now_temp%1000/100; //十位k=now_temp%100/10; //个位LCD_disp_char(11,0,table3[k]); LCD_disp_str(12,0,".");k=now_temp%10; //小数LCD_disp_char(13,0,table3[k]); LCD_disp_char(14,0,0xdf);LCD_disp_str(15,0,"C"); //显示℃delayms(5);}else{LCD_disp_char(9,0,' ');k=now_temp%1000/100; //十位LCD_disp_char(10,0,table3[k]);k=now_temp%100/10; //个位LCD_disp_char(11,0,table3[k]); LCD_disp_str(12,0,".");k=now_temp%10; //小数LCD_disp_char(13,0,table3[k]); LCD_disp_char(14,0,0xdf);LCD_disp_str(15,0,"C"); //显示℃delayms(5);}//第二行显示设定温度k=0;k=set_temp/100;if(k!=0){LCD_disp_char(9,1,table3[k]); //百位k=set_temp%100/10; //十位LCD_disp_char(10,1,table3[k]);k=set_temp%10; //个位LCD_disp_char(11,1,table3[k]);LCD_disp_char(12,1,0xdf);LCD_disp_str(13,1,"C"); //显示℃LCD_disp_char(14,1,' ');LCD_disp_char(15,1,' ');delayms(5);}else{LCD_disp_char(9,1,' ');k=set_temp%100/10; //十位k=set_temp%10; //个位LCD_disp_char(11,1,table3[k]);LCD_disp_char(12,1,0xdf);LCD_disp_str(13,1,"C"); //显示℃LCD_disp_char(14,1,' ');LCD_disp_char(15,1,' ');delayms(5);}}void LCD_disp_char(uchar x,uchar y,uchar dat) //显示字符{uchar address;if(y==0)address=0x80+x;elseaddress=0xc0+x;write_com(address);write_dat(dat);}void LCD_disp_str(uchar x,uchar y,uchar *str) //显示字符串{uchar address;if(y==0)address=0x80+x;elseaddress=0xc0+x;write_com(address);while(*str!='\0'){write_dat(*str);str++;}}void DS18B20_init() //DS18B20初始化{//对于11.0592MHz时钟, uint型的i, 作一个i++操作的时间大于8usuint i=0;DQ=0;i=100; //拉低约800us, 符合协议要求的480us以上while(i>0)i--;DQ=1; //产生一个上升沿, 进入等待应答状态while(i>0)i--;}void DS18B20_wait() //等待{uint i;while(DQ);while(~DQ); //检测到应答脉冲i=4;while(i>0)i--;}uchar tempreadbit() //读取一位{uint i=0;bit b;DQ=0;i++; //延时约8us, 符合协议要求至少保持1usDQ=1;i++;i++; //延时约16us, 符合协议要求的至少延时15us以上b=DQ; i=8;while(i>0)i--; //延时约64us, 符合读时隙不低于60us要求return b;}uchar tempreadbyte() //读取一个字节{uint i;uchar j, dat=0;for(i=0; i<8; i++){j = tempreadbit();//最先读出的是最低位数据dat = (j << 7) | (dat >> 1);}return dat;}void tempwritebyte(uchar dat) //写字节{uint i;uchar j;for(j=0; j<8; j++){b=dat&0x01;dat>>=1;//写"1", 将DQ拉低15us后, 在15us~60us内将DQ拉高, 即完成写1if(b){DQ=0;i++;i++; //拉低约16us, 符号要求15~60us内DQ=1;i=8;while(i>0)i--; //延时约64us, 符合写时隙不低于60us要求}else //写"0", 将DQ拉低60us~120us{DQ=0;i=8;while(i>0)i--; //拉低约64us, 符号要求DQ=1;i++;i++; //整个写0时隙过程已经超过60us, 这里就不用像写1那样, 再延时64us了}}}void temp_start() //开始温度转换{DS18B20_init(); //初始化DS18B20, 无论什么命令, 首先都要发起初始化DS18B20_wait(); //等待DS18B20应答delayms(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us 作为应答信号tempwritebyte(0xCC); // 发Skip ROM命令tempwritebyte(0x44); // 发转换命令}uint tempread() //读温度{uint a,b;temp_start();DS18B20_init(); //初始化DS18B20DS18B20_wait(); //等待DS18B20应答delayms(1); //延时1ms, 因为DS18B20会拉低DQ 60~240us 作为应答信号tempwritebyte(0xCC); //发Skip ROM命令tempwritebyte(0xBE); //发read命令a=tempreadbyte(); //低8位b=tempreadbyte(); //高8位b=b<<8;now_temp=((a|b))*0.0625*10.0+0.5;return(now_temp);}void keyscan() //按键扫描{P1=0x0F; //低四位输入delayms(1);temp=P1; //读P1口temp=temp&0x0F;temp=~(temp|0xF0);if(temp==1)key=0;else if(temp==2)key=1;else if(temp==4)key=2;else if(temp==8)key=3;elsekey=0;P1=0xF0; //高四位输入delayms(1);temp=P1; //读P1口temp=temp&0xF0;temp=~((temp>>4)|0xF0); if(temp==1)key=key+0;else if(temp==2)key=key+4;else if(temp==4)key=key+8;else if(temp==8)key=key+12;elsekey=0;dis_buf=key; //键值入显示缓存dis_buf=dis_buf&0x0f;if(dis_buf>11) //转换为ASCII码dis_buf=0x30;else if(dis_buf<10)dis_buf=dis_buf+0x30;elsedis_buf=dis_buf+0x37;}void keydown() //判断按键是否按下{P1=0xF0;while(1){if(P1!=0xF0){keyscan();break;}}}void pid(float kp) //增量型PID算法归一化参数{error=now_temp*1.0-set_temp*10.0; // 偏差u(k) dp=kp*1.0*(2.45*error-3.5*prev_error+1.25*prev_prev_error);//p(k)-p(k-1)=kp*[2.45e(k)-3.5e(k-1)+1.25e(k-2)]prev_prev_error=prev_error;prev_error=error;if(dp<-20.0){high_pulse=1;low_pulse=4;}else if(dp<-15.0){high_pulse=2;low_pulse=3;}else{high_pulse=4;low_pulse=1;}}void InitTimer2() //T2定时器初始化{RCAP2H=(65536-50000)/256; //定时50ms初值RCAP2L=(65536-50000)%256;ET2=1;EA=1;TR2=1;}uint key_input() //按键输入{uint m=0,n=0;do{keydown(); //读取按键值}while(dis_buf<0x30||dis_buf>0x39);m=dis_buf-0x30;LCD_disp_char(0,1,dis_buf); //显示第一个输入delayms(500);do{keydown(); //读取按键值}while(dis_buf<0x30||dis_buf>0x39);n=dis_buf-0x30;LCD_disp_char(1,1,dis_buf); //显示第二个输入set_temp=m*10+n; //设定温度值delayms(500);return set_temp;}void main() //主函数{uint s=0,r=1;LCD_init();delayms(100);LCD_disp_str(0,0," INPUT SET TEMP "); //第一行显示INPUT SET TEMP delayms(500);while(r){key_input(); //输入设定温度keydown(); //确认键和取消键s=dis_buf;if(s==0x41) //A确认键,B取消键{r=0; //确认键按下标志位delayms(500);LCD_disp_str(0,0,"NOW TEMP:"); //显示NOW TEMP:delayms(10);LCD_disp_str(0,1,"SET TEMP:"); //显示SET TEMP:delayms(10);displaylcd(0,set_temp); //显示当前温度0和设定温度}else{write_com(0x01); //清屏delayms(1000);LCD_disp_str(0,0," INPUT SET TEMP "); //第一行显示INPUT SET TEMPr=1;}}BEEP=1; //蜂鸣器默认不响PWM=0; //继电器默认导通while(1){now_temp=tempread();displaylcd(now_temp,set_temp); //显示当前温度和设定温度if(now_temp>10*set_temp) //当前温度大于设定温度的时,给继电器持续的高电平,停止加热{TR2=0; //关闭定时器T2PWM=1; //继电器高电平关断BEEP=0; //蜂鸣器响}else if(now_temp>9*set_temp) //当前温度大于设定温度的90%时,进行PID 控制{BEEP=1;InitTimer2();pid(2.72); //调用增量型PID算法}else{BEEP=1;PWM=0;}}delayms(10);}void Timer2() interrupt 5 //T2定时器中断服务程序{TF2=0;PWM=0;switch(PWM==1){case 0:if(++low_time==low_pulse) //达到低电平脉宽设定值{PWM=1; //输出PWM高电平,继电器断开low_time=0;break;}case 1:if(++high_time==high_pulse) //达到高电平脉宽设定值{PWM=0; //输出PWM低电平,继电器导通high_time=0;break;} } }。
基于PLC的PID温度控制系统设计(附程序代码)

基于PLC的PID温度控制系统设计(附程序代码)摘要自动控制系统在各个领域尤其是工业领域中有着及其广泛的应用,温度控制是控制系统中最为常见的控制类型之一。
随着PLC技术的飞速发展,通过PLC对被控对象进行控制日益成为今后自动控制领域的一个重要发展方向。
温度控制系统广泛应用于工业控制领域,如钢铁厂、化工厂、火电厂等锅炉的温度控制系统。
而温度控制在许多领域中也有广泛的应用。
这方面的应用大多是基于单片机进行PID 控制, 然而单片机控制的DDC 系统软硬件设计较为复杂, 特别是涉及到逻辑控制方面更不是其长处, 然而PLC 在这方面却是公认的最佳选择。
根据大滞后、大惯性、时变性的特点,一般采用PID调节进行控制。
随着PLC功能的扩充,在许多PLC 控制器中都扩充了PID 控制功能, 因此在逻辑控制与PID控制混合的应用场所中采用PLC控制是较为合理的。
本设计是利用西门子S7-200PLC来控制温度系统。
首先研究了温度的PID调节控制,提出了PID的模糊自整定的设计方案,结合MCGS监控软件控制得以实现控制温度目的。
关键词:PLC;PID;温度控制沈阳理工大学课程设计论文目录1 引言...................................................................... (1)1.1 温度控制系统的意义...................................................................... .. (1)1.2 温度控制系统背景...................................................................... .................. 1 1.3 研究技术介绍...................................................................... .. (1)1.3.1 传感技术...................................................................... (1)1.3.2PLC .................................................................... . (2)上位机...................................................................... ............................1.3.3 31.3.4 组态软件...................................................................... ........................ 3 1.4 本文研究对象...................................................................... .. (4)2 温度PID控制硬件设计...................................................................... (5)2.1 控制要求...................................................................... .................................. 5 2.2 系统整体设计方案...................................................................... .................. 5 2.3 硬件配置...................................................................... . (6)2.3.1 西门子S7-200CUP224 ................................................................. .. (6)2.3.2 传感器...................................................................... . (6)2.3.3 EM235模拟量输入模块.....................................................................72.3.4 温度检测和控制模块...................................................................... .... 8 2.4 I/O分配表 ..................................................................... ................................ 8 2.5 I/O接线图 ..................................................................... .. (8)3 控制算法设计...................................................................... .. (9)3.1 P-I-D控制...................................................................... .............................. 9 3.2 PID回路指令 ..................................................................... .. (11)3.2.1 PID算法 ..................................................................... .. (11)3.2.2 PID回路指令 ..................................................................... (14)3.2.3 回路输入输出变量的数值转换 (16)3.2.4 PID参数整定 ..................................................................... (17)4 程序设计...................................................................... .. (19)4.1 程序流程图...................................................................... .............................. 19 4.2 梯形图...................................................................... .. (19)I沈阳理工大学课程设计论文5 调试...................................................................... . (23)5.1 程序调试...................................................................... .. (23)5.2 硬件调试...................................................................... .. (23)结束语...................................................................... .................................................... 24 附录程序代码...................................................................... ........................................ 25 参考文献...................................................................... (27)II沈阳理工大学课程设计论文1引言1.1 温度控制系统的意义温度及湿度的测量和控制对人类日常生活、工业生产、气象预报、物资仓储等都起着极其重要的作用。
温度控制的PID算法的C语言程序

基于PID算法的温度控制系统89C51单片机,通过键盘输入预设值,与DS18B20测得的实际值做比较,然后驱动制冷或加热电路。
用keil C语言来实现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 按键功能按键键名功能AN1 复位键使系统复位AN2 运行键使系统开始数据采集AN3??? 功能转换键按键按下(D1亮)时,显示温度设定值;按键升起(D1不亮)时,显示前温度值AN4 加一键设定温度渐次加一AN5 减一键设定温度渐次减一??? 显示采用3位共阳LED静态显示方式,显示内容有温度值的十位、个位及小数点后一位,这样可以只用(RXD)口来输出显示数据,从而节省了单片机端口资源,在口和(TXD)的控制下通过74LS164来实现3位静态显示。
基于51单片机的PID调温(热得快)资料

《自动控制原理》课程设计指导老师:邹恩年级专业:13 自动化 4 班姓名学号(分工) 韩锦澎 201330280107(电路设计) 韦伊玲 201330280219 (程序编写) 徐敏芳 201330280723 (焊接调试) 王可欣 201330280102 (论文)2015年1月7 日1目录1. 系统设计方案......................................................3 1.1 方案一........................................................3 1.2 方案二 .......................................................3 1.3 方案三........................................................3 1.4 方案的比较和确定..............................................3 2.系统硬件部分设计...................................................3 2.1 系统硬件电路图 ...............................................3 2.1.1 单片机 AT89C52 ..........................................4 2.1.2 单片机与 LCD 通信连接 ....................................4 2.1.3 其他电路模块及总电路 .......................................5 3 系统软件部分 .......................................................5 3.1 系统的主流程图如下............................................5 4.温度控制系统 PID 调节...............................................6 4.1 PID 控制传递函数..............................................6 4.2 PID 参数调节方法..............................................6 4.3 PID 参数设定..................................................6 5.实验与调试.........................................................7 6.总论...............................................................8 附 录.............................................................8参 考 文 献.........................................................2421. 系统设计方案1.1 方案一 选用铂电阻温度传感器。
基于PID控制算法的温度控制系统的设计与仿真

摘要本设计是一种温度控制系统,温度控制在工业生产和科学研究中具有重要意义。
其控制系统属于一阶纯滞后环节,具有大惯性、纯滞后、非线性等特点,导致传统控制方式超调大、调节时间长、控制精度低。
采用单片机进行炉温控制,具有电路设计简单、精度高、控制效果好等优点,对提高生产效率、促进科技进步等具有重要的现实意义。
PID控制法最为常见,控制输出采用PWM波触发可控硅来控制加热通断。
使系统具有较高的测量精度和控制精度。
单片机控制部分采用AT89S51单片机为核心,采用Keil 软件进行编程,同时采用分块的模式,对整个系统的硬件设计进行分析,分别给出了系统的总体框图、温度检测调理电路、A/D转换接口电路,按键输入电路以及显示电路,并对相应电路进行相关的阐述软件采用PID算法进行了建模和编程,在Proteus环境中进行了仿真。
关键词:PID;单片机;温度控制;Keil;ProteusAbstractThis design is a kind of temperature control system,The temperature control in industrial production and scientific research is of great significance.Belongs to pure first-order lag link, the control system has the characteristics of big inertia, pure lag and nonlinear, the traditional control overshoot and adjustment time is long, low control precision.By single chip microcomputer temperature control, has simple circuit design, high accuracy and good control effect, to improve the production efficiency, promote the progress of science and technology has important practical significance.PID control is the most common, the control output PWM wave triggering thyristor is used to control the heating on and off.Make the system has high accuracy of measurement and control precision.Single-chip microcomputer control part adopts single chip microcomputer A T89S51 as the core,Using Keil software programming,Using block pattern at the same time, analyzes the hardware design of the whole system, respectively, of the overall system block diagram is given, the temperature detection circuit, A/D conversion interface circuit, key input circuit and display circuit, and the corresponding circuit are related in this paper, the software, the PID algorithm is used for modeling and programming in the Proteus simulation environment.Key words:PID;Single chip microcomputer;The temperature control;Keil;Proteus目录1绪论 (1)2设计方案 (2)3系统硬件仿真电路 (3)3.1 温度测量调理电路 (3)3.2 A/D转换电路 (4)3.3 按键输入电路 (5)3.4 数码管显示电路 (6)3.5 温度控制电路 (7)4程序设计 (9)4.1 程序整体设计 (9)4.2 子程序设计 (1111)4.3源程序设计 (119)5软件调试与运行结果 (41)结论 (42)致谢 (43)参考文献 (44)1绪论现代工业生产过程中,用于热处理的加热炉,需要消耗大量的电能,而且温度控制是纯滞后的一阶大惯性环节。
温度控制的PID算法的C语言程序

基于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算法是本程序中的核心部分。
单片机PID水温控制程序

#include<reg52.h>#include<intrins.h>#include<pid.h>#include<04.h>#define Z 55sbit P27=P2^7;sbit temp=P2^0;sbit P21=P2^1;sbit P22=P2^2;uint nnn;uchar t_min,t_minf,t_sec,t_ge,shii,gee,shiff;uchar uk_qian,uk_bai,uk_shi,uk_ge;//uk显示位uint time;uint z_uk;uchar w_shi,w_ge,w_shif,w_baif; //实际温度数字显示;uchar q_ge,q_shif,q_baif; //占空比显示位uchar idata bai,shi,ge; //预设温度数字显示;bit w_fh;//实际值符号位;uint tvalue; //10倍实际温度。
uint p=20000;uint f,g;//float idata bfb;//占空比设定。
uchar set_temp=60;float idata temperature;uchar idata count=1;uchar idata cont=500;uchar idata xx;void rst18b20(){temp=1;delay10us(1);temp=0;delay10us(70);//延时916us。
temp=1;delay10us(20);//延时266us。
}void writedata(uchar dat)//向ds18b20写数据。
{uchar i;for(i=0;i<8;i++){temp=0;temp=dat&0x01;delay10us(10);temp=1;dat>>=1; //先写低位。
}}uchar readdata()//从ds18b20读数据。
基于stc单片机温度控制的程序

#include <reg52.H>#include <stdlib.h>#include <math.h>#include <intrins.h>unsigned int pp1;unsigned int j=0;unsigned int ReceiveData; //计算机向单片机发送的数据unsigned int ADdat2;unsigned char cH;unsigned char cL;unsigned char INPUT_ZH;unsigned char INPUT_X;unsigned int GivenTemper,measure,Error;float pp;sbit DS=P2^4;sbit ss1=P2^0;sbit ss2=P2^1;#define uchar unsigned char#define uint unsigned intuchar Temp_Value[]={0x00,0x00};void delay(unsigned int i);uchar a,b,c;float tt;unsigned int temp;/*************************此部分为18B20的驱动程序*************************************/bit ds18b20isok=1;//===============================================void Delay(uint x) //延时程序{unsigned i;x=x*5/4;for(i=0;i<x;i++);}//===============================================uchar InitDS18B20() //初始化{uchar status;DS=1;Delay(8);DS=0;Delay(500);DS=1;Delay(100);status=DS;Delay(100);DS=1;return status;}//================================================= void WriteByte (uint dat) //单字节写入{uchar i;for (i=0;i<8;i++){DS=0;_nop_();Delay(10);DS=dat&0x01;Delay(40); //delay 45 uS //5DS=1;dat >>= 1;}}//================================================== uchar ReadByte (void) //读取单字节{uchar dat=0,i;DS=1;_nop_();for(i=0;i<8;i++){DS = 0;_nop_();dat >>= 1;DS = 1;_nop_();_nop_();if(DS) dat |= 0x80;Delay (45);DS=1;}return dat;}uchar readtemperature(){if (InitDS18B20()==1)ds18b20isok=0;else{WriteByte(0xCC);WriteByte(0x44);InitDS18B20();WriteByte(0xCC);WriteByte(0xBE);Temp_Value[0]=ReadByte();Temp_Value[1]=ReadByte();a =Temp_Value[0] ; //读取到的第一个字节为温度LSBb = Temp_Value[1];ds18b20isok=1;}}/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/void delay1ms(){unsigned int i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}/*****************************************************函数功能:延时若干毫秒入口参数:n***************************************************/void delaynms(unsigned int n){unsigned int i;for(i=0;i<n;i++)delay1ms();}/********************************************************* 函数功能:单片机向计算机发送数据*********************************************************/ void send(unsigned int send_data){SBUF=send_data;while(TI==0);TI=0;}/********************************************************函数功能:串口中断函数单片机通过中断接收计算机发送数据********************************************************/void UART_SER (void) interrupt 4 //串行中断服务程序{if(RI) //判断是接收中断产生{RI=0; //标志位清零ReceiveData=SBUF; //读入缓冲区的值}}void main(void){IE = 0x90; //Enable ADC interrupt and Open master interrupt switch,允许T1,T0中断TMOD=0x22; //定时器T1工作于方式2,带自动重装功能的8位计数器,最大计数值为256SCON=0x50; //SCON=0101 0000B,串口工作方式1,允许接收(REN=1)PCON=0x00; //PCON=0000 0000B,波特率9600TH1=0xfa; //根据规定给定时器T1赋初值TL1=0xfa; //根据规定给定时器T1赋初值TR1=1; //启动定时器T1TH0=0xF5; //根据规定给定时器T1赋初值TL0=0x78; //根据规定给定时器T1赋初值TR0=1; //启动定时器T0readtemperature();//Delay (9000);while(1){//unsigned char i;readtemperature();//得到AD的输入温度值//ADget_Z=ADget/10;十位//ADget_X=ADget%10;个位//ADget_Z=ADget_Z*1000;//if ( ds18b20isok )//pp=100;//else//{//pp=200;//};temp = b; //先把高八位有效数据赋于temptemp <<= 8; //把以上8位数据从temp低八位移到高八位temp = temp|a; //两字节合成一个整型变量tt = temp*0.0625; //得到真实十进制温度值//因为DS18B20可以精确到0.0625度//所以读回数据的最低位代表的是0.0625度temp = tt*10+0.5; //放大十倍pp=temp*10;pp1=floor(pp);cH=(pp1- pp1%256)/256;cL=pp1%256;send(cH);send(cL);// if (j==1)// {// INPUT_ZH=ReceiveData;//}// else if (j==2)//{//INPUT_X=ReceiveData;// j=0;// }//GivenTemper=(INPUT_ZH*256+INPUT_X)/100;//温度扩大10,给定温度GivenTemper=ReceiveData*100;//Temperature;//pp1=floor(pp*100);//cH=(pp1- pp1%256)/256;//cL=pp1%256;//send(cH);//send(cL);//delaynms(1000);measure=pp;//ss1=0;// ss2=1;// ss1=0;// ss2=1;//GivenTemper=(INPUT_ZH*256+INPUT_X)/100;//温度扩大10,给定温度//给定值大于测量值时if(GivenTemper>measure) //给定值高ccap0加热{Error=GivenTemper-measure;// CCAP1L=0;//CCAP1H=0;//if (Error >0)if(Error >300){ss1=1;ss2=0;}else if (Error>100&&Error<=300){ss1=1;ss2=0;Delay (3000);ss1=0;ss2=0;Delay (2000);}else if (Error>50&&Error<=100){ss1=1;ss2=0;Delay (1000);ss1=0;ss2=0;Delay (100);}else if(Error>10&&Error<=50){ss1=1;ss2=0;Delay (500);ss1=0;ss2=0;Delay (500);}else if(Error>5&&Error<=10){ss1=1;ss2=0;Delay (100);ss1=0;ss2=0;Delay (100);}else{ ss1=0;ss2=0; }}else if(GivenTemper<measure) //给定值低ccap1制冷{ Error=measure-GivenTemper;//if (Error >0)if(Error >300){ss1=0;ss2=1;}else if (Error>100&&Error<=300){ss1=0;ss2=0;Delay (50);ss1=0;ss2=1;Delay (100);}else if (Error>50&&Error<=100){ss1=0;ss2=0;Delay (100);ss1=0;ss2=1;Delay (100);}else if(Error>10&&Error<=50){ss1=0;ss2=0;Delay (100);ss1=0;ss2=1;Delay (1000);}else if(Error>5&&Error<=10){ss1=0;ss2=1;Delay (1000);ss1=0;ss2=0;Delay (10);}else{ss1=0;ss2=0;}}} }/*measure=pp1;//测量温度// Error=GivenTemper-measure;//给定值大于测量值时if(GivenTemper>measure) //给定值高ccap0加热{Error=GivenTemper-measure;}// 给定值小于测量值时else if(GivenTemper<measure) //给定值低ccap1制冷{Error=measure-GivenTemper;delaynms(10000);}}}//增量式PID算法(需要控制的不是控制量的绝对值,而是控制量的增量)/*********************************************************函数功能:AD采样/*********************************************************///unsigned int ADCRESULT()//{//ADC_RES=500;// ADdat2=(ADC_RES<<2)+ADC_RESL;//10位转换结果// pp=(ADdat2/1024)*5; // pp1=((long)ADdat2*1500)/358; //得到温度// ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;// return pp;//}/********************************************************函数功能:完成函数的初始化功能(A/D采样会用到)********************************************************///void InitADC()//{// P1ASF = 0xf7;//Set all P1 as analog input port将所有的P1口定义为模拟输入端口// ADC_RES = 0;//Clear previous result清除上一个结果. ADC_RES 为A/D转换结果寄存器// ADC_CONTR = ADC_POWER | ADC_SPEEDLL | ADC_START;//}//PWM初始化//void InitPWM()//{//CMOD=0x84 ;//CPS1 CPS0=00,FOSC/12是PCA/PWM CLOCK 94//CCON=0x00;//CL=0x00; //PCA计数器//CH=0x00; //PCA计数器//CCAP0L=0x80; //Set the initial value same as CCAPOH 预置初值加热//CCAP0H=0x80; //50%的占空比//CCAPM0=0x42; //01000010 Setup PCA module 0 in 8bit pwm, P1.3输出///////////////另一路pwm//CCAP1L=0x80; //Set the initial value same as CCAPOH 预置初值制冷//CCAP1H=0x80; //50%的占空比//CCAPM1=0x42; //p1.4输出///////////////////CR=1;//启动PCA/PWM 定时器//}。
基于单片机的PID控制算法

基于单片机的PID控制算法基于单片机的PID控制算法实现摘要:温度是工业控制对象主要被控参数之一,在温度控制中,由于受到温度被控对象特性(如惯性大、滞后大、非线性等)的影响,使得控制性能难以提高,有些工艺过程其温度控制的好坏直接影响着产品的质量,因而设计一种较为理想的温度控制系统是非常有价值的。
为了实现高精度的水温测量和控制,本文介绍了一种以At-mel公司的低功耗高性能CMOS单片机为核心,以PID算法控制来实现的温度控制系统,其硬件电路还包括温度采集、温度控制、温度显示、键盘输入以及RS232接口等电路。
该系统可实现对温度的测量,并能根据设定值对温度进行调节,实现控温的目的。
关键词:单片机AT89C51;温度控制;温度传感器PT1000;PID调节算法1 前言1.1课题背景与意义在现代化的工业生产中,电流、电压、温度、压力、流量、流速和开关量都是常用的主要被控参数。
例如:在冶金工业、化工生产、电力工程、造纸行业、机械制造和食品加工等诸多领域中,人们都需要对各类加热炉、热处理炉、反应炉和锅炉中的温度进行检测和控制。
采用AT89C51单片机来对温度进行控制,不仅具有控制方便、组态简单和灵活性大等优点,而且可以大幅度提高被控温度的技术指标,从而能够大大提高产品的质量和数量。
目前,温度控制系统在国内各行各业的应用虽然已经十分广泛,但从国内生产的温度控制器来讲,总体发展水平仍然不高,同国外的日本、美国、德国等先进国家相比,仍然有着较大的差距。
现在,我国在这方面总体技术水平处于20世纪80年代中后期水平。
成熟产品主要以“点位”控制及常规的PID控制器为主,它只能适应一般温度系统控制,难于控制滞后复杂时变温度系统控制,而且适应于较高控制场合的智能化、自适应控制仪表国内技术还不十分成熟,形成商品化并广泛应用的控制仪表较少。
随着嵌入式系统开发技术的快速发展及其在各个领域的广泛应用,人们对电子产品的小型化和智能化要求越来越高,作为高新技术之一的单片机以其体积小、价格低、可靠性高、适用范围大以及本身的指令系统等诸多优势,在各个领域、各个行业应用广泛。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
//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;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 code number[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6}; unsigned char disp_num[6];unsigned int k,k1;k=high_time;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 Structurespid.Proportion = 10; // Set PID Coefficientsspid.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); //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;。