基于PID算法的恒温控制系统设计.docx
- 文档编号:27702220
- 上传时间:2023-07-04
- 格式:DOCX
- 页数:22
- 大小:56.99KB
基于PID算法的恒温控制系统设计.docx
《基于PID算法的恒温控制系统设计.docx》由会员分享,可在线阅读,更多相关《基于PID算法的恒温控制系统设计.docx(22页珍藏版)》请在冰豆网上搜索。
基于PID算法的恒温控制系统设计
课程设计说明书
题目:
基于PID算法的
恒温控制系统设计
学号:
姓名:
指导教师:
日期:
一、设计题目
基于PID算法的恒温控制系统设计
二、设计要求
1.利用DS18B20采集温度并显示;
2.利用单片机I/O管角输出PWM控制功率电阻发热;
3.基于PID算法实现恒温控制。
三、设计思路
本设计要求实时采集温度并实现恒温控制,根据设计要求,本次设计拟采用AT89C52单片机作为控制芯片,采集部分使用DS18B20温度传感器,显示部分采用数码管显示实时温度,功率电阻作为控制对象。
在PID算法的基础上完成恒温控制系统的设计。
四、实验设备
单片机开发试验仪1台
AT89C52单片机芯片1个
DS18B20温度传感器1个
C9013三极管1个
1W功率二极管1个
五、硬件介绍
DS18B20:
DS18B20是常用的温度传感器,具有体积小,硬件开销低,抗干扰能力强,精度高的特点。
DS18B20的主要特征:
全数字温度转换及输出。
先进的单总线数据通信。
最高12位分辨率,精度可达土0.5摄氏度。
12位分辨率时的最大工作周期为750毫秒。
可选择寄生工作方式。
检测温度范围为–55°C~+125°C(–67°F~+257°F)
内置EEPROM,限温报警功能。
64位光刻ROM,内置产品序列号,方便多机挂接。
多样封装形式,适应不同硬件系统。
DS18B20数据采集过程
⑴GND地信号
⑵DQ数据输入/输出引脚。
开漏单总线接口引脚。
当被用着在寄生电源下,也可以向器件提供电源。
⑶VDD可选择的VDD引脚。
当工作于寄生电源时,此引脚必须接地。
由于DS18B20采用的是1-Wire总线协议方式,即在一根数据线实现数据的双向传输,而对AT89S51单片机来说,硬件上并不支持单总线协议,因此,我们必须采用软件的方法来模拟单总线的协议时序来完成对DS18B20芯片的访问。
由于DS18B20是在一根I/O线上读写数据,因此,对读写的数据位有着严格的时序要求。
DS18B20有严格的通信协议来保证各位数据传输的正确性和完整性。
该协议定义了几种信号的时序:
初始化时序、读时序、写时序。
所有时序都是将主机作为主设备,单总线器件作为从设备。
而每一次命令和数据的传输都是从主机主动启动写时序开始,如果要求单总线器件回送数据,在进行写命令后,主机需启动读时序完成数据接收。
数据和命令的传输都是低位在先。
六、硬件接线图
AT89C52
恒温控制系统硬件连接图
八位七段码显示
P0
P1
P2.0
P3.7
1W
C9013
DS18B20
硬件部分分别也P0口和P1口作为八位七段码的段选和位选的控制端口,DS18B20连接至P3.1口作为控制线,P2.0口作为PWM波输出口,经过C9013信号放大后接功率电阻作为被控对象。
通过温度传感器采集电阻上的温度反馈给系统,构成闭环调节系统,构成恒温控制系统。
七、软件流程图、
A/D
D/A
被
控
对
象
开始
计算采样初值
设初值e(k-1)=e(k-2)=0
本次采样输入c(k)
计算偏差量e(k)=r(k)-c(k)
计算控制增量Δu(k)
Δu(k)=q0e(k)-q1e(k-1)+q2e(k-2)
输出Δu(k)
为下一时刻做准备
e(k)=e(k-1),e(k-1)=e(k-2)
采样时刻到否
PID算法流程图
软件部分采用PID算法,其中数据采集与显示部分不属于本设计的主要部分在此不再赘述。
PID算法的参数有实验确定,遵循先比例,后积分,再微分的原则,从最小看是逐步调试,最终取得最佳的PID参数。
八、PID参数确定
PID算法运用比例、积分、微分算法,来对回路中的偏差进行修正,通过执行器调节参数,使测量值稳定在设定值附近,,达到控制某一参数的目的。
必须先明白P,I,D各自的含义及控制规律
比例P:
比例项部分其实就是对预设值和反馈值差值的发大倍数。
积分I:
顾名思义,积分项部分其实就是对预设值和反馈值之间的差值在时间上进行累加。
当差值不是很大时,为了不引起振荡。
可以先让电机按原转速继续运行。
当时要将这个差值用积分项累加。
当这个和累加到一定值时,再一次性进行处理。
从而避免了振荡现象的发生。
可见,积分项的调节存在明显的滞后。
而且I值越大,滞后效果越明显。
微分D:
微分项部分其实就是求电机转速的变化率。
也就是前后两次差值的差而已。
也就是说,微分项是根据差值变化的速率,提前给出一个相应的调节动作。
可见微分项的调节是超前的。
并且D值越大,超前作用越明显。
可以在一定程度上缓冲振荡。
比例项的作用仅是放大误差的幅值,而目前需要增加的是“微分项”,它能预测误差变化的趋势,这样,具有比例+微分的控制器,就能够提前使抑制误差的控制作用等于零,甚至为负值,从而避免了被控量的严重超调
其次进行参数调整
a.确定比例增益P
确定比例增益P时,首先去掉PID的积分项和微分项,一般是令Ti=0、Td=0,PID为纯比例调节。
输入设定为系统允许的最大值的60%~70%,由0逐渐加大比例增益P,直至系统出现振荡;再反过来,从此时的比例增益P逐渐减小,直至系统振荡消失,记录此时的比例增益P,设定PID的比例增益P为当前值的60%~70%。
比例增益P调试完成。
b.确定积分时间常数Ti
比例增益P确定后,设定一个较大的积分时间常数Ti的初值,然后逐渐减小Ti,直至系统出现振荡,之后在反过来,逐渐加大Ti,直至系统振荡消失。
记录此时的Ti,设定PID的积分时间常数Ti为当前值的150%~180%。
积分时间常数Ti调试完成。
c.确定积分时间常数Td
积分时间常数Td一般不用设定,为0即可。
若要设定,与确定P和Ti的方法相同,取不振荡时的30%。
九、实验总结
本次课程设计的题目为基于PID算法的恒温控制系统。
在接到这个题目的同时,我们就开始思考如何去设计这个系统。
首先是硬件电路的设计与器件的选择。
其中温度采集与显示部分的设计,我们在单片机课程上已经有所涉及,在这里我们就可以直接拿来用了。
硬件部分需要我们设计的就是被控对象。
为了试验方便我们选择了1W的功率电阻作为被控对象,然后通过DS18B20温度传感器去测量电阻附近的温度变化。
从而实现系统的控制与反馈。
考虑到单片机I/O口的驱动能力不足,不足以驱动功率二极管,我们在I/O口与功率二极管之间串入一个C9013最为驱动与开关器件,用以对二极管的驱动和控制。
软件部分采用了PID控制算法,其中最重要的环节为PID控制参数的确定,一开始我们准备利用计算法来确定,可是在实施的过程终发现,计算法所需要的原始数据难以确定,而且在实际测量中也有很大的不确定性。
最终,经过我们的分析研究,得出实验法确定参数是一个比较切实可行的办法。
然后就通过实验一步一步测试出所需要的参数,经过我们几天的而艰苦奋战,终于测试好了参数。
最后在进行系统的整体调试,最终完成这次课程设计,并顺利通过老师的验收。
这次的课程设计,让我有了很多的收获和感受。
首先,让我认识到了,在学习的过程中仅仅有理论知识是不足的,必须要理论与实践相结合起来。
有的东西看起来非常简单,可是到了实现环节,就会变得异常困难。
在实现的过程中可能会出现各种各样的状况,需要在现场分析解决。
在最任何事情的时候都必须认真细致,有时一个小小的环节出现问题,都会导致结果出现巨大的差异。
在最任何是的过程中遇到困难都是正常的,我们需要做的就是去面对它,通过自己的分析理解,最终找到解决方法,克服困难。
附件:
实验程序
/*******************************************************************************
*
*微机控制课程设计
--------------------------------------------------------------------------------
*实验名:
基于PID算法的恒温控制系统设计
*实验说明:
通过DS18B20采集温度,反馈给系统,构成闭环调节系统
*连接方式:
见连接图
*注意:
*******************************************************************************/
#include
#include"temp.h"
//--定义使用的IO--//
#defineGPIO_DIGP0
#defineGPIO_PLACEP1
sbitPWM=P2^0;
//--定义全局变量
unsignedcharcodeDIG_PLACE[8]={
0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//位选控制查表的方法控制
unsignedcharcodeDIG_CODE[17]={
0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
//0、1、2、3、4、5、6、7、8、9、A、b、C、d、E、F的显示码
unsignedcharDisplayData[8];
unsignedchartimer1;
unsignedintcount=0;
//用来存放要显示的8位数的值
//定义PID参数
floatuk,uk1,uk2;
floatek,ek1,ek2;
floatx;
floatt,Auk;
floatKp,Ki,Kd;
//--声明全局函数--//
floatLcdDisplay(int);
voidDigDisplay();
voidTime1Config();
floatAD_init(void);
voidPID_init(void);
voidDA_init(void);
//voiddelay();
unsignedintj,m;
unsignedintd;
/*******************************************************************************
*函数名:
main
*函数功能:
主函数
*输入:
无
*输出:
无
*******************************************************************************/
main()
{intm;
m=Auk/10;
Time1Config();
Ds18b20Init();
uk=0,uk1=0,uk2=0;
ek=0,ek1=0;ek2=0;
x=40;
Kp=2.83,Ki=0.59,Kd=5.41;
while
(1)
{
AD_init();
PID_init();
DA_init();
LcdDisplay(Ds18b20ReadTemp());
//delay();
}
}
floatAD_init()
{
floattemp;
temp=LcdDisplay(Ds18b20ReadTemp());
return(temp);
}
voidPID_init()
{
t=AD_init();
ek=x-t;
Auk=Kp*(ek-ek1);
if(x>=35&x<=45)
{
Auk=Auk+Ki*ek;
}
Auk=Auk+Kd*(ek-2*ek1+ek2);
uk=Auk+uk;
ek2=ek1;
ek1=ek;
}
voidDA_init()
{
if(Auk>=0)
count++;
if(Auk<0)
PWM=0;
if(count==0|count==99)
count=count;
if(Auk>=5)
count=count+5;
if(Auk<5)
switch(m%10)
{
case0:
count=count;break;
case1:
count++;break;
case2:
count=count+2;break;
case3:
count=count+3;break;
case4:
count=count+4;break;
default:
break;
}
count--;
if(timer1>100)//PWM周期为100*0.5ms
{
timer1=0;
}
if(timer1 { PWM=1; } else { PWM=0; } } /******************************************************************************* *函数名: LcdDisplay() *函数功能: LCD显示读取到的温度 *输入: v *输出: 无 *******************************************************************************/ /*voiddelay() { { for(j=0;j<1000;j++) { for(m=0;m<100;m++) { ; } } } } */ floatLcdDisplay(inttemp)//lcd显示 { floattp; if(temp<0)//当温度值为负数 { DisplayData[0]=0x40; //因为读取的温度是实际温度的补码,所以减1,再取反求出原码 temp=temp-1; temp=~temp; tp=temp; temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算由? .5,还是在小数点后面。 } else { DisplayData[0]=0x00; tp=temp;//因为数据处理有小数点所以将温度赋给一个浮点型变量 //如果温度是正的那么,那么正数的原码就是补码它本身 temp=tp*0.0625*100+0.5; //留两个小数点就*100,+0.5是四舍五入,因为C语言浮点数转换为整型的时候把小数点 //后面的数自动去掉,不管是否大于0.5,而+0.5之后大于0.5的就是进1了,小于0.5的就 //算加上0.5,还是在小数点后面。 } DisplayData[1]=DIG_CODE[temp/10000]; DisplayData[2]=DIG_CODE[temp%10000/1000]; DisplayData[3]=DIG_CODE[temp%1000/100]|0x80; DisplayData[4]=DIG_CODE[temp%100/10]; DisplayData[5]=DIG_CODE[temp%10]; DigDisplay(); return(temp);//扫描显示 } /******************************************************************************* *函数名: DigDisplay *函数功能: 使用数码管显示 *输入: 无 *输出: 无 *******************************************************************************/ voidDigDisplay() { unsignedchari; unsignedintj; for(i=0;i<8;i++) { GPIO_PLACE=DIG_PLACE[i];//发送位选 GPIO_DIG=DisplayData[i];//发送段码 j=10;//扫描间隔时间设定 while(j--); GPIO_DIG=0x00;//消隐 } } voidTime1Config() { TMOD|=0x10;//设置定时计数器工作方式1为定时器 //--定时器赋初始值,12MHZ下定时0.5ms--// TH1=0xFE; TL1=0x0C; ET1=1;//开启定时器1中断 EA=1; TR1=1;//开启定时器 } /******************************************************************************* *函数名: Time1 *函数功能: 定时器1的中断函数 *输入: 无 *输出: 无 *******************************************************************************/ voidTime1(void)interrupt3//3为定时器1的中断号1定时器0的中断号0外部中断12外部中断24串口中断 { TH1=0xFE;//重新赋初值 TL1=0x0C; timer1++; } temp.c #include"temp.h" /******************************************************************************* *函数名: Delay1ms *函数功能: 延时函数 *输入: 无 *输出: 无 *******************************************************************************/ voidDelay1ms(uinty) { uintx; for(;y>0;y--) { for(x=110;x>0;x--); } } /******************************************************************************* *函数名: Ds18b20Init *函数功能: 初始化 *输入: 无 *输出: 初始化成功返回1,失败返回0 *******************************************************************************/ ucharDs18b20Init() { uchari; DSPORT=0;//将总线拉低480us~960us i=70; while(i--);//延时642us DSPORT=1;//然后拉高总线,如果DS18B20做出反应会将在15us~60us后总线拉低 i=0; while(DSPORT)//等待DS18B20拉低总线 { Delay1ms (1); i++; if(i>5)//等待>5MS { return0;//初始化失败 } } return1;//初始化成功 } /******************************************************************************* *函数名: Ds18b20WriteByte *函数功能: 向18B20写入一个字节 *输入: com *输出: 无 *******************************************************************************/ voidDs18b20WriteByte(uchardat) { uinti,j; for(j=0;j<8;j++) { DSPORT=0;//每写入一位数据之前先把总线拉低1us i++; DSPORT=dat&0x01;//然后写入一个数据,从最低位开始 i=6; while(i--);//延时68us,持续时间最少60us DSPORT=1;//然后释放总线,至少1us给总线恢复时间才能接着写入第二个数值 dat>>=1; } } /******************************************************************************* *函数名: Ds18b20ReadByte *函数功能: 读取一个字节 *输入: com *输出: 无 *******************************************************************************/ ucharDs18b20ReadByte() { ucharbyte,bi; uinti,j; for(j=8;j>0;j--) { DSPORT=0;//先将总线拉低1us i++; DSPORT=1;//然后释放总线 i++; i++;//延时6us等待数据稳定 bi=DSPORT;//读取数据,从最低位开始读取 /*将byte左移一位,然后与上右移7位后的bi,注意移动之后移掉那位补0。 */ byte=(byte>>1)|(bi<<7); i=4;//读取完之后等待48us再接着读取下一个数 while(i--); } returnbyte; } /******************************************************************************* *函
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 PID 算法 恒温 控制系统 设计
![提示](https://static.bdocx.com/images/bang_tan.gif)