《电子技术综合设计》
设计报告
设计题目:水温自动控制系统 组长姓名:学 号:
专业与班级: 工业自动化14-16班 姓 名:学 号:
专业与班级:工业自动化14-16班 姓 名:学 号:
专业与班级:工业自动化14-16班
时 间: 2016~ 2017学年第(1)学期 指导教师:陈烨成 绩:评阅日期:
1 / 33
一、 课题任务
设计并制作一个水温自动控制系统,对1.5L净水进行加。水温保持在一定范围内且由人工设定。
细节要求如下:
1.温度设定范围为40℃~90℃,最小分辨率为0.1℃,误差≤1℃。 2.可通过LCD显示屏显示温度目标值与实时温度。 3.可以通过键盘调整目标温度的数值。 二、 方案比较
1. 系统模块设计
为完成任务目标,可以将系统分为如下几个部分:5V直流电供电模块、测温模块、80C52单片机控制系统、键盘控制电路、温度显示模块、继电器控制模块、强电加热电路。通过各模块之间的相互配合,可以完成水温检测、液晶显示、目标值设置、水温控制等功能。
系统方框图如下:
2 / 33
2. 5V直流电供电模块
方案一:直接用GP品牌的9v电池,然后接通过三端稳压芯片7805稳压成5伏直流电源提供给单片机系统使用,接两个5伏电源的滤波电容后输出。
方案二:通过变压器,将220v的市电转换成9v左右的交流电,变压器输出端的9V电压经桥式整流并电容滤波。要得到一个比较稳定的5v电压,在这里接一个三端稳压器的元件7805。
由于需要给继电器提供稳定的5V电压,而方案一中导致电池的过度损耗,无法稳定带动继电器持续工作,所以我们选用能够提供更加稳定5v电源的方案二。
3. 测温模块
经查阅资料,IC式感温器在市场上应用比较广泛的有以下几种: AD590:电流输出型的测温组件,温度每升高1 摄氏度,电流增加1μA,温度测量范围在-55℃~150℃之间。其所采集到的数据需经A/D 转换,才能得到实际的温度值。
DS18B20:内含AD转换器,所以除了测量温度外,它还可以把温度值以数字的方式(9 B i t ) 送出,因此线路连接十分简单,它无需其他外加电路,直接输出数字量,可直接与单片机通信,读取测温数据。它能够达到0.5℃的固有分辨率,使用读取温度暂存寄存器的方法还能达到0.0625℃以上精度,温度测量范围在-55℃~125℃之间,应用方便。
SMARTEC感温组件:这是一只3个管脚感温IC,温度测量范围在-45℃~ 13℃,误差可以保持在0.7℃以内。
max6225/6626:最大测温范围也是-55~+125℃,带有串行总线接口,测量温度在可测范围内的的误差在4℃以内,较大,故舍弃该方案。
本设计选用DS18B20感温IC,这是因其性能参数符合设计要求,接口简单,内部集成了A/D 转换,测温更简便,精度较高,反应速度快,且经过市场考察,该芯片易购买,使用方便。
下面是DS18B20感温IC的实物和接口图片
3 / 33
4. 80C52单片机控制系统
ATC52是一个低电压,高性能CMOS 8位单片机,片内含8k bytes的可反复擦写的Flash只读程序存储器和256 bytes的随机存取数据存储器
(RAM),器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位处理器和Flash存储单元,ATC52单片机在电子行业中有着广泛的应用。
5. 键盘控制电路 方案一:四键设定,一个十位控制键,一个个位控制键,一个位控制键,一个确认键,通过四键的配合设定为度,该方案接线和程序简单,但实际操作不太便捷。
方案二:矩阵键盘设定,通过按键输入不同数字实现温度的设定,电路连接比较简单,程序较方案一复杂,但已经在学习过程中接触过矩阵键盘的编程技巧,有一定的可行性,且操作起来更加符合我们的日常习惯。
本次设计暂定采用矩阵键盘来作为温度设定电路的输入。 6. 温度显示模块
方案一:使用数码管显示,通过数码管显示被测温度和设定温度。该方案程序简单,且已学习过其编程技巧,但硬件占用单片机I/O口较多,对于尽量节约端口,让线路简单来说不是好方法,而且显示也不够直观灵活,只能显示数字,。
方案二:使用液晶屏1602显示。1602可显示两行字符及数字,可以用来显示设定温度及测量温度,较之数码管显示更加清晰直观,虽然此前没有接触过相关知识,但该器件上手比较容易,可以在短期内学会其使用方法。
1602较之数码管更加符合本次设计要求,因此使用1602作为显示器件。 7. 继电器控制模块
方案一:采用普通的控制方法,即水温温度到达临界温度时,控制继电器开闭。但由于水温变化快,且惯性大,不易控制精度。
方案二:采用PWM控制加PID算法,通过采用PWM可以产生一个PWM波形,而PWM波形的占空比是通过PID算法调节,这样就可以通过控制加热电路的开、断时间比来控制加热器功率进而控制温度的变化,从而使精度提高。此方法中硬件上可以使用固态继电器或晶闸管控制加热器工作。
我们选择方案二。
三、 电路设计
1. 电源电路
整个系统需要使用5V直流电和220V交流电。电源电路采用变压器与稳压模块,将工频电压降为5V直流电,为系统供电。首先用变压器模块20V交流电降为9V交流电,接入整流电桥,变为直流电输出,再使用三端稳压芯片7805稳压为5V。L7805输出端要联上电解电容,滤除交流电干扰,防止损坏单片机系统。
4 / 33
LM7805最大可以输出1A的电流,内部有限流式短路保护,短时间内,例如几秒钟的时间,输出端对地(2脚)短路并不会使7805烧坏。
2. 温度传感器
DS18B20温度传感器只有三根外引线:单线数据传输总线端口DQ ,外供电源线VDD,共用地线GND。外部供电方式(VDD接+5V,且数据传输总线接4.7k的上拉电阻,其接口电路如下图(外接电源工作方式)所示。
3. 单片机最小系统
单片机最小系统,或者称为最小应用系统,是指用最少的元件组成的单片机可以工作的系统.对51系列单片机来说,最小系统一般应该包括:单片机、晶振电路、复位电路
5 / 33
4. 按键、显示电路
这部分实际上是一个单片机最小系统的基本电路,键盘选用矩阵键盘可满足要求,通过按键输入不同数字实现温度的设定。 在显示方面选用常用的1602液晶显示模块。通过相应的程序,可以实现温度的实时显示,电路连接也比较简单,只需连接数据总线,和三根控制线即可实现数据控制,实现显示功能。
6 / 33
1602显示电路 5. 继电器温控
单片机驱动继电器的通断,从而比较容易的实现对小功率电热棒的加热。本系统利用继电器的吸合与否来实现水温的自动化控制。本次设计采用型号为JRC-21F的继电器。其特点有:
(1).超小型,低功耗;
(2).触点型式:1H,1Z(1A.AC); (3).触点负载:2A,120VAC; (4).外型尺寸:15.7X10.4X11.4
如图是驱动较大功率继电器的接口,当p1.1(连接单片机的输出口)输出低电平时,Q1导通,继电器吸合;当p1.1输出高电平时,Q1截止,继电器断开。由于继电器吸合时电流比较大,所以在单片机与继电器之间增加了光电耦合器件作为隔离电路。R3是光电耦合输出管的限流电阻,R4是驱动管Q1基极泄放电阻。
7 / 33
整体硬件电路见附录
四、 程序设计
程序结构包括:主程序、传感器测温程序、lcd1602显示程序、键盘扫描程序、 PID计算程序、PWM波形发生程序。
主程序流程图如下所示:
8 / 33
传感器测温程序流程图:
9 / 33
lcd1602显示程序流程图:
键盘扫描程序流程图:
10 / 33
温度比较与PID计算程序流程图:
PWM波形发生程序(定时器中断)流程图:
11 / 33
五、 测试方案
1.静态测试:
室温状态下,分别用温度计与18B20传感器检测水温,观察两者是否有误差。
2.动态测试:
用继电器控制“热得快”对1升水加热,用键盘设定需加热温度值,观察、记录1602显示屏上实时水温值的变化过程和每次改变温度设定值后PID调节的超调量。多次调试并和修改PID参数来完善该系统。检验水温的稳定值是否满足设计目标的要求。
六、 系统调试
1.加热水量与加热器的功率确定 加热器水量与功率应当构成匹配,加热水量过多或功率过小会导致加热时间过长,而加热水量过少或功率过大会使超调增大,不利于控制。我们选择1L的容器作为测试对象,预计将20摄氏度的水加热到100摄氏度需要5分钟。经过计算这样的加热器功率至少为1120w,因此选择1000w的加热管。满足1L的容器很多,但是广口的盆水位较低,不利于加热管的安放。经过努力,找到了合适的容器(实物见附件),恰能使得加热棒处于最为合适的水位深度。
2.上下层温差的优化和电动机电源的选择
电动机本不在设计的范围里面,但是随着系统调试的进行,发现容器中的的水很难实现热均匀。容器中上下层温差过大,导致温度传感器所测数据极不准确,滞后过大,非常不利于控制。所以又添加一个直流减速电机带动桨叶加速冷热水对流,从而让容器里面的水受热均匀,方便测温模块对系统水温的实时监测。这一额外的电动机没有在事先考虑的器件电气匹配范围内,所以当它与加热模块一同共用5v的直流电源时,已超出了整流模块所能提供的最大电流,于是又添加了一个电源给电动机供电。
3. PID程序的修改调试
当实际水温与目标值差距过大时,加热器只需满功率工作(或完全停止工作)即可满足要求。此时采用PID控制意义不大,且PID控制范围很大,参数很难整定,而微分环节也容易受到干扰导致加热器无法满功率运行。因此,在满足控制精度的前提下,可将PID控制的范围缩小到设定温度的±1℃之内。范围缩小后,PID参数容易调整,控制效果明显增强。经过调试后PID参数分别为Proportion = 10,Integral = 8,Derivative =6。
4.PWM波周期的调试
PWM波的周期越短,控制的精度越高。但PWM波形的输出需要单片机中断程序进行控制,中断频率过高会干扰单片机中主程序的运行。测温模块18B50对时间的要求非常严格,因此测温模块读取数据期间会与中断程序冲突。若18B20读数期间允许中断中断会导致其温度输出出现大量错误;若不允许中断会导致PWM波周期频繁变化。经过调试,将PWM波周期设为5s。 七、 数据测试与处理
1.静态温度的测试
室温状态下,分别用温度计与18B20传感器检测水温,得到结果分别为。温度计显示17.5℃,18B20传感器显示温度17.9℃,在误差允许的范围内,满足要求。
12 / 33
2.动态温度的测试:
令测温系统工作,对1.5L净水加热,设定温度分别为50℃,60℃,80℃,每10s记录一次显示屏幕上的数据,绘制其温度变化曲线,并计算温度控制的超调量,稳态误差。
温度数据及曲线如下:
(1) 目标温度50度: 时间0 1 2 3 4 5 6 (10s) 温度30.30.31.32.30 30 32 (℃) 1 5 1 7 时间8 9 10 11 12 15 17 (10s) 温度34.35.36.37.38.40.42.(℃) 5 3 1 1 1 6 3 时间19 20 21 23 24 25 26 (10s) 温度44.45.47.48.49.49.45 (℃) 1 8 6 4 1 7 时间28 29 30 31 32 33 34 (10s) 温度51.51.51.51.51.51.51.(℃) 2 6 8 8 8 8 8 时间36 39 40 43 46 51 54 (10s) 温度51.51.51.50.50.50.50.(℃) 6 3 1 8 6 5 3 时间60 63 66 68 69 70 (10s) 温度49.49.50.50.50.50.50 (℃) 8 9 1 5 7 7 时间75 78 81 84 87 88 90 (10s) 温度50.50.50.50.49.49.50 (℃) 5 4 2 1 9 8 时间92 (10s) 温度50 (℃) 7 33.5 18 43.2 27 50.8 35 51.7 57 50.1 72 50.7 91 50 13 / 33
超调量为3.6%
(2) 目标温度60度: 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 0 50 8 55.8 16 61.5 30 60.4 42 60.3 56 60.4 1 50.5 9 56.6 17 61.6 32 60.2 45 60.2 57 60.3 2 51.1 10 57.5 18 61.6 33 60.1 47 60 3 51.8 11 58.3 19 61.6 34 60 48 60 4 52.6 12 58.9 20 61.5 36 59.8 50 59.8 5 53.5 13 59.8 21 61.4 37 60 52 59.9 6 54.1 14 60.3 24 61.1 40 60.2 53 60.1 7 55 15 61.2 27 60.8 41 60.3 54 60.3 14 / 33
超调量为2.5%
(3) 目标温度80度: 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 时间(10s) 温度
0 60 8 66.1 18 73.5 27 79.5 35 79.8 43 79.1 60.8 9 66.8 19 74.3 28 80.1 36 79.6 44 79.2 61.4 10 67.6 21 75.6 29 80.3 37 79.4 45 79.15 / 33
3 62.1 11 68.3 22 76.4 30 80.5 38.5 79.3 46 79.4 62.8 12 69.1 23 77 31 80.5 39 79.3 47 79.5 63.7 13 70.3 24 77.7 32 80.3 40 79.3 48 80 6 .5 15 71.3 25 78.4 33 80.2 41 79.4 49 80 7 65.3 16.5 72.4 26 78.9 34 80.1 42 79.4 50 79.(℃) 时间(10s) 温度(℃) 时间(10s) 温度(℃) 5 51 79.7 59 80.1 6 52 79.6 60 80 7 53 79.6 61 80 8 54 79.6 62 80 9 55 79.7 63 80 56 79.7 57 79.8 9 58 80 超调量为0.6%
由以上温度曲线可以看出,水温能够保持在设定温度上下,控制过程中超调量<4%,且稳态时的误差在为±0.3℃,满足系统设计要求。
八、 设计总结
通过本次应用系统设计,在很大程度上提高了我们的思考、分析判断以及动手实践能力,也对系统设计过程以及设计过程中应注意的问题有了初步的认识,加深了我们对所学知识的理解。
出于对自身知识及可获取的学习资源的考虑,我组本次电子综合设计的选题最终定为水温自动控制系统的设计,该题目为往年电设题目,参考资料较易获取且基本未超出我们现掌握的知识水平。
在参考了书本及网络上的设计思想之后,我们确定了该系统的设计方案初稿,并讨论了设计方案的可行性。讨论确定出实验所需器材以及组员的分工,由一名组员进行程序的编写,另外两名组员进行硬件电路的焊接及调试。
经过几次检查、调试以及修改之后,基本实现了本次设计的部分预期目标:可通过LCD显示屏显示温度目标值与实时温度,可以通过键盘调整目标温度的
16 / 33
数值等功能。
在系统调试过程中,遇到一些问题:
1.由于一开始没有估计好器件占用的空间,所购万用板太小,无法满足实验要求,之后又换用了一个较大的万用板。在最小系统焊接完成后,由于没有搞清楚按键的内部接线,使单片机一直处于复位状态,无法正常工作,后用万用表排查出该错误。
2.在加热控制器件的选择上花费了较多精力,开始的设计方案是用光电耦合器配合双向晶闸管利用PWM波控制加热功率来实现温度的稳定,但在硬件实验时发现控制导通无法实现,且电压、电流余量有限,不能满足设计要求。便换用了固态继电器配合三极管来实现功率控制。
3.在完成基本功能后,发现由于水温分布不均匀,温度传感器无法及时检测到水温变化以改变加热功率,减小超调量,又在原系统中增加了电机搅拌器以使水温分布均匀。
4.在PID参数整定中,发现初始的PID算法过于简单,造成被控变量误差与稳定性均较差。普通的位置PID算法很难满足水温控制系统的要求。查阅资料后,缩小了PID控制的范围,在满足控制精度的前提下,温控范围缩小到设定温度的±1℃之内。范围缩小后,PID参数容易调整,控制效果明显增强。
这些问题的解决帮助我们融合所学的知识,极大提高了我们动手能力。通过对本设计的反思总结,加深了对机械,单片机,自动控制等多方面知识的理解,也激发了我们对电子设计的极大兴趣,这对我们以后的学习生活有着十分重要的作用。
九、 参考文献
1. 刘海成.《AVR单片机原理及测控工程应用》 .北京航空航天大学出版社 2. 周润景刘晓霞.《单片机实用系统设计与仿真经典实例》.电子工业出版社 3. 谢维成杨加国.《单片机原理与应用及C51程序设计》.清华大学出版社
4. 大学生电子设计竞赛组委会.《第五届全国电子设计竞赛获奖作品选编》.北京理工大学出版社
5. 黄志伟《全国大学生电子设计竞赛系统设计》。北京航空航天出版社
6. 51黑电子论坛http://www.51hei.com/bbs/
17 / 33
十、
附录
18 / 33
1. 电路原理图
2.程序
#include #define uchar unsigned char #define uint unsigned int sbit DQ =P2^7; //定义端口 19 / 33 sbit RS=P2^5; sbit RW=P2^4; sbit EN=P2^3; sbit output=P2^0; sbit P0_0=P0^0; sbit P0_1=P0^1; sbit P0_2=P0^2; sbit P0_3=P0^3; uchar flag;//flag为温度值的正负号标志单元 uchar c[2];//18b20的直接输出量 uint cc,cc2;//变量cc为18b20输出量的直接计算值,cc2为放大100倍温度值 float cc1;//cc1为温度值 uchar buff1[10]={\"Set temp: \屏显示 uchar buff2[10]={\"Cur temp: \屏显示 ucharset_c[2]={'5','0'}; //用于温度设置及1602屏显示 uchar buff3[6]={\"+00.0 \ //1602屏显示 uchartemper,set_temper=50;//temper用于PID的测量值(整数),set_temper用于PID参考值 uint s; //PID的测量值(小数) struct PID { unsigned intSetPoint; // 设定目标 unsigned int Proportion; // 比例常数 unsigned int Integral; // 积分常数 unsigned int Derivative; // 微分常数 unsignedintLastError; // Error[-1] unsignedintPrevError; // Error[-2] unsignedintSumError; // Sums of Errors }; struct PID spid; // 创建PID结构 uint rout; // PID Output uintrin; // PID Input unsigned char high_time,low_time,count=0;//占空比调节参数 void delay(uintuseconds) //延时程序 20 / 33 { for(;useconds>0;useconds--); } ucharow_reset(void) //复位(18B20) { uchar presence; DQ = 0; // DQ 低电平 delay(50); DQ = 1; delay(3); presence = DQ; delay(25); return(presence); } ucharread_byte(void) { uchari; uchar value = 0; for (i=8;i>0;i--) { value>>=1; DQ = 0; DQ = 1; delay(1); if(DQ)value|=0x80; delay(6); } return(value); } void write_byte(ucharval) 18B20) { uchari; for (i=8; i>0; i--) { DQ = 0; DQ = val&0x01; delay(5); DQ = 1; val=val/2; } delay(5); // 480ms // DQ 高电平 // 等待 // presence 信号 // 0允许, 1禁止 //从单总线上读取一个字节(18B20) //向单总线上写一个字节 // 一次写一位 21 / 33 ( } void Read_Temperature(void) //读取温度(18B20) { ow_reset(); write_byte(0xCC); // 跳过 ROM write_byte(0xBE); // 读 c[1]=read_byte(); //低字节 c[0]=read_byte(); //高字节 ow_reset(); write_byte(0xCC); write_byte(0x44); // 再次开始 cc=c[0]*256.0+c[1]; // 18b20输出量的直接计算值 if (c[0]>0xf8) {flag=1;cc=~cc+1;}else flag=0; cc1=cc*0.0625; //计算出温度值 cc2=cc1*100; //温度值放大100倍,放在整型变量中便于取数字 c[0]=(c[0]<<4)&0x7f; s=(unsigned int)(c[1]&0x0f); s=(s*100)/16; //温度值小数部分 c[1]=c[1]>>4; temper=c[0]|c[1]; //温度值整数部分 delay(1000); //用于PID的测量温度值 return; } void fbusy() //检查忙函数(1602) { P1 = 0xff; RS = 0; RW = 1; EN = 1; EN = 0; while((P1 & 0x80)) { EN = 0; EN = 1; } } void wc51r(uchar j) //写命令函数(1602) { fbusy(); 22 / 33 EN = 0; RS = 0; RW = 0; EN = 1; P1 = j; EN = 0; } void wc51ddr(uchar j) //写数据函数(1602) { fbusy(); //读状态; EN = 0; RS = 1; RW = 0; EN = 1; P1 = j; EN = 0; } void init() //1602初始化 { wc51r(0x01); //清屏 wc51r(0x38); //使用8位数据,显示两行,使用5*7的字型 wc51r(0x0c); //显示器开,光标开,字符不闪烁 wc51r(0x06); //字符不动,光标自动右移一格 } void display(void) //1602显示程序1(初始化显示) { uchar k; delay(10); init(); wc51r(0x80); //写入显示缓冲区起始地址为第1行第1列 for (k=0;k<10;k++) //第一行显示提示信息\"Set temp:\" { wc51ddr(buff1[k]);} for (k=0;k<2;k++) { wc51ddr(set_c[k]);} //显示设定的温度 wc51r(0xc0); //写入显示缓冲区起始地址为第2行第1列 for (k=0;k<10;k++) //第二行显示提示信息\"Cur temp:\" { wc51ddr(buff2[k]);} buff3[1]=cc2/1000+0x30; if ( buff3[1]==0x30) buff3[1]=0x20;//取出十位,转换成字符,如果十位是0不显示。 buff3[2]=cc2/100%10+0x30;//取出个位,转换成字符 23 / 33 buff3[4]=cc2/10%10+0x30;//取出小数点后一位,转换成字符 if (flag==1) buff3[0]='-';else buff3[0]='+'; for (k=0;k<6;k++) //第二行显示温度 { wc51ddr(buff3[k]);} } void display2(void) //1602显示程序2(循环显示) { uchar k; delay(10); wc51r(0xca); buff3[1]=cc2/1000+0x30; if ( buff3[1]==0x30) buff3[1]=0x20;//取出十位,转换成字符,如果十位是0不显示。 buff3[2]=cc2/100%10+0x30;//取出个位,转换成字符 buff3[4]=cc2/10%10+0x30;//取出小数点后一位,转换成字符 if (flag==1) buff3[0]='-';else buff3[0]='+'; for (k=0;k<6;k++) //第二行显示温度 { wc51ddr(buff3[k]);} } ucharscan_key()//键盘检测程序,16个按键输出序号1~16 { ucharset_num=0; uchar dushu,dushu1; P0=0xff; P0_0=0; //扫描第一行 dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { delay(900); dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { dushu1=dushu; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } delay(900); dushu=P0; 24 / 33 dushu=dushu&0xf0; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } if(dushu1==0xe0) set_num=1; else if(dushu1==0xd0) set_num=2; else if(dushu1==0xb0) set_num=3; else if(dushu1==0x70) set_num=4; } } P0_0=1; delay(900); P0_1=0; //扫描第二行 dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { delay(900); dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { dushu1=dushu; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } delay(900); dushu=P0; dushu=dushu&0xf0; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } 25 / 33 if(dushu1==0xe0) set_num=5; else if(dushu1==0xd0) set_num=6; else if(dushu1==0xb0) set_num=7; else if(dushu1==0x70) set_num=8; } } P0_1=1; P0_2=0; //扫描第三行 dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { delay(900); dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { dushu1=dushu; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } delay(900); dushu=P0; dushu=dushu&0xf0; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } if(dushu1==0xe0) set_num=9; else if(dushu1==0xd0) set_num=10; else if(dushu1==0xb0) set_num=11; else if(dushu1==0x70) 26 / 33 set_num=12; } } P0_2=1; delay(900); P0_3=0; //扫描第四行 dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { delay(900); dushu=P0; dushu=dushu&0xf0; if(dushu!=0xf0) { dushu1=dushu; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } delay(900); dushu=P0; dushu=dushu&0xf0; while(dushu!=0xf0) { dushu=P0; dushu=dushu&0xf0; } if(dushu1==0xe0) set_num=13; else if(dushu1==0xd0) set_num=14; else if(dushu1==0xb0) set_num=15; else if(dushu1==0x70) set_num=16; } } P0_3=1; delay(900); returnset_num; 27 / 33 配 } void PIDInit (struct PID *pp) //PID结构体空间分 序 { memset ( pp,0,sizeof(struct PID)); } unsigned intPIDCalc( struct PID *pp, unsigned intNextPoint ) //PID计算部分 { unsignedintdError,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++) { Read_Temperature(); rin = s; // Read Input rout = PIDCalc ( &spid,rin ); // Perform PID Interation } if (high_time<=100) 28 / 33 high_time=(unsigned char)(rout/800); else high_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++) { Read_Temperature(); rin = s; // Read Input rout = PIDCalc ( &spid,rin ); // Perform PID Interation } if (high_time<100) high_time=(unsigned char)(rout/10000); else high_time=0; low_time= (100-high_time); } } } void set_temp(void) interrupt 0//中断程序,用于设定温度 { ucharss,k=0,ddr16=0x8a; //变量k用于设定温度的的个位、十位切换,ddr16为1602屏幕上显示位置的设定 wc51r(ddr16+k); wc51r(0x0e); while(1) { ss=scan_key(); if(ss!=0) { if(ss<10) { wc51r(ddr16+k); 29 / 33 set_c[k]=ss+0x30; wc51ddr(set_c[k]); wc51r(ddr16+k); } else if(ss==10) { wc51r(ddr16+k); set_c[k]=0x30; wc51ddr(set_c[k]); wc51r(ddr16+k); } else if(ss==11) { k=!k; wc51r(ddr16+k); } else if(ss==12) break; } } wc51r(0x0c); set_temper=(set_c[0]-0x30)*10+set_c[1]-0x30; } void serve_T0() interrupt 1 //T0中断服务子程序,用于控制电平的翻转 { if(++count<=(high_time)) output=0; else if(count<=100) { output=1; } else count=0; TH0 = 0x3C; TL0 = 0x0B0; } void main(void) //主函数 { unsigned char a,b,flag_2=1,count1=0; 30 / 33 IE=0; IP=0x01; TH0 = 0x3C; TL0 = 0x0B0; TR0=1; EA=1; ET0=1; EX0=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 display(); while(1) { Read_Temperature(); b=temper; if(flag_2==1) a=b; if((abs(a-b))>5) temper=a; else temper=b; a=temper; flag_2=0; if(++count1>30) { display2(); count1=0; } compare_temper(); } } 3.作品相关图片 31 / 33 整体图 控制部分 32 / 33 加热部分 33 / 33
因篇幅问题不能全部显示,请点此查看更多更全内容
Copyright © 2019- aiwanbo.com 版权所有 赣ICP备2024042808号-3
违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com
本站由北京市万商天勤律师事务所王兴未律师提供法律服务