表8 牡丹江师范学院社会实践学期优秀实践成果申报书选题方向: 电气控制 指导教师: 白 龙 单 位: 工学院 联系: 15845304801 牡丹江师范学院教务处 一、项目组基本情况教师情况姓 名白龙专 业电气工程及其自动化职 称讲师学 历 硕士研究生联系15845304801电子邮箱long_mdj@学生成员情况序号姓 名专业年级序号姓名专业年级1肖川10工业电气10级9冉泽亮10工业电气10级2吴柳俊10工业电气10级10杜艳伟10工业电气10级3胡超10工业电气10级11沈柱添10工业电气10级4刘爱阳10工业电气10级12梁浩10工业电气10级5田万里10工业电气10级13王颖10工业电气10级6李航10工业电气10级14王敏10工业电气10级7董强10工业电气10级15吴勇锋10工业电气10级8高鹤铭10工业电气10级16陈志成10工业电气10级注:序号第1位的学生为该项目组学生负责人。
二、实践内容实践的目的和意义:目的:作一个以单片机为控制核心,以超声波做水位测量的一个自动上水控制系统,以解决农村上水系统的控制问题意义:进一步掌握单片机运用技能,巩固学习数电模电知识,提高动手操作能力为以后工作设计打下一定实践基础实践方法及创新之处: 实践方法:本设计主要是完成硬件电路设计,以及软件编程工作,并完成整个控制系统的模拟调试使系统按设计类容正确运行,完成水位检查与自动控制上水过程创新之处:水位控制在日常生活中应用也相当广泛,比如水塔、地下水、水电站等情况下的水位控制而水位检测可以有多种实现方法,如机械控制、逻辑电路控制、机电控制等本设计主要基于单片机的水塔自动上水系统的控制,其主要包括了系统电路的设计,控制电路的设计而目前,国内外用于水塔自动上水控制装置主要有浮球升降式,程开关式,弹簧管开关磁浮式,水压仪表电接点式,电极传导式等本设计是基于超声波测距的水深测量,并且通过单片机对水塔的水位进行智能的实时的控制其中主要包括以下几大主要部分微机控制供水部分,电驱动部分液晶显示部分本文主要对单片机的水塔自动上水控制系统进行了硬件的电路设计和软件的设计本设计也可以当作水位报警电路,用在与防患自然灾害水灾,本设计制造成本低,容易使用。
安装该电路,水泵就会在水塔没水的时候自动给水塔灌水,当灌满之后又会自动切断水泵电源停止灌水,取代了人类的复杂劳动三、实践成果1.实践过程:在小组成员讨论后对整个系统一些功能进行了选定,于2013 年1月3日正式开始了设计的工作1).首先是对真个程序的大概流程在草纸上进行设计具体工作便是将各功能模块需要设计的函数以空函数形式嵌在在程序流程中,并将各功能模块资料发给小组成员,并分配程序编写任务,在后续更具电路完成后再整体完成程序编写 (2).电路设计本设计调试电路使用一块锐志学习板已有电路,只是在次电路板基础上,自画了protel原理图,并设计了一块印刷电路板PCB图,可做为成品电路板由于成本原因,未做成品仅以学习板做了模拟演示3).整体程序的完成和部分电路的焊接这段时间是在一家电子设备维修部完成,在这里能够获焊接得所需工具,并且可以学习一些基本硬件知识4).对真个系统的调试,当然刚开始时并没有成功,于是对程序反复的修改和硬件的检查,发现超声测距模块极不稳定各种软件滤波后能正确测量距离,但是实时性变得极差于是重购一款差距模块后问题解决在经过一系列优化调试后是效果趋于最佳2.实践成果:设计于2013年1月20日基本功能与附加功能便全面完成,并测试运行成功。
下面列出功能项基本功能: 超声测水位并控制继电器自动上水附加功能: (1).显示水位高度百分比2).环境温度测量显示(为测距提供温度补偿) (3).时钟显示(提供夜间省电时间参照) (4).显示器背光定时关闭 (5).提供按键操作设定各种参数 (6).使用E2PROM对设定参数断电保护3.实践总结报告:本次设计完成制作过程中学习了很多知识,其中学习了很多的焊接知识,以前终觉得焊接就是简单的将元件焊在电路板上,在观看专业人士焊接过程后,发现其中有很多技巧比如阻焊剂和助焊剂的使用,焊接点的好坏分辨,还用热缩管的使用等等这些都是在学校理论学习中无法学到的经验在设计过程送也遇见了很多困难问题,比如第一次程序完成编译后,下载到单片机运行时毫无反应进过一步步修改后一些功能实现,但还有一些功能没有实现,多次修改程序也不能实现例如在超声测距功能上,始终不能得到稳定的测量数据于是查了很多资料并做了各种软件滤波,最终得出了较为正确的数据,但由此导致了测量时间的加长,灵敏度极度下降于是有对超声测距模块,做了一些改变测试结果是模块抗干扰太差,重买了一块超声测距模块后调试成功。
当然在整个过程中还有很多问题,在一个个问题解决的同时,查阅了很多相关资料,丰富了自己的知识储存总的来说,本次设计实践活动无论对现在的学习还是以后的工作都有极大的帮助作用最后,感谢学校提供了这次实践活动机会,感谢白龙老师的精心指导4.其他佐证材料目录:佐证材料均见 附录一:系统原理图 附录二:PCB图附录三:材料清单附录四:系统源程序附录五:系统实物图及设计过程照片附录六:系统运行录像(刻录光盘) (不足部分可附页)附录一原理图附录二 PCB图附录三数量参数元件编号封装21KR1R10RES-20034.7KR2 R3 R4RES-200110R25RES-200610KR5 R6 R7 R8 R9 R20RES-200110UF/16VEC2EC-100110kPR1SIP9112MHZX1XTAL-200124C08U4DIP8430PFC1 C2 C3 C4CAP-100132.768MHZX2XTAL-2001100UF/16VEC1EC-1006104C6 C7 C8 C9 C10 C11CAP-1001CAOSHENGJ1SIP42CAPC5 C12CAP-1001CON2S2BT21CON6S1USB1CON11S3DB91DS18B20U1TO-92EBC1DS1302U3DIP82IN4007D1 D2DIODE-3001K-6SW1SW-65KEY-4KEY1 KEY2 KEY3 KEY4 KEY6KEY-41LCD1602J2SIP161LEDLED1LED-1001MAX232U5DIP161NPNQ2TO-92EBC1PNPQ1TO-92EBC1RELAY-SPDT-5KEY5JDQ51STC89S52U2DIP40附录四#include#include #define uint unsigned int#define uchar unsigned charuint TT0=0,Tt1=6000,distance[6];bit Nightmode=0,succeed_flag=0 ,Nightfuzhu=0; uchar timeH,timeL,key=0,TD=0,TN=0; //自定义寄存器 sbit Jdq= P3^7;sbit Tx = P3^1; //产生脉冲引脚 sbit Rx = P3^2; //回波引脚 /****************************显示字符串定义******************************/char code Welc_1[]=" welcome to use"; //启动第一排显示字符串char code Welc_2[]="x water raising"; // 启动第二排显示字符串char code Use_auto[]="use automesure ?";// 字符串显示char code YN[]=" Y/N ? ";char code B_deep[]=" Barrel Deep";char code Chang_T[]=" cheange time";char code Water[]=" W:";char code Usse_night[]="use Night mode ?";char code Time[]=" TIME:";char code Set_t[]="*set time ";char code Set_m[]="*Nightmode";char code On[]="(on) ";char code Off[]="(off) ";char code Rais_water[]="*raising water ";char code Temper[]="T:"; //温度unsigned char Temper_c[]={0x10,0x06,0x09,0x08,0x08,0x09,0x06,0x00};// 自定义字符℃ /*************************LCD1602专区************************/sbit Bg = P1^3; //背光控制位sbit RS=P2^0; //寄存器选择位,将RS位定义为P2.0引脚 sbit RW=P2^1; //读写选择位,将RW位定义为P2.1引脚 sbit E0=P2^2; //使能信号位,将E位定义为P2.2引脚 sbit BF=P0^7;void INIT_1602();bit busyTest(); //测忙 。
void writeData(uchar); //写数据 void write_com(uchar ); //写指令void addrset(uchar,uchar); //坐标设置void Print(uchar p[]); //输出流void display_2(uchar); // 显示两位整数void display_time_temper(); // 工作状态时间、温度显示void display_d(uchar); // 设置时桶深显示void clear_p(); // 清屏void biao_on(); // 关光标void biao_off(); // 开光标void splash_p();void move_pr();void move_pl();/**********************************DS1302专区*****************************/void INIT_1302(); // sbit SCLK=P1^0; //位定义1302芯片的接口,时钟输出端口定义在P1.0引脚sbit DATA=P1^1; //位定义1302芯片的接口,数据输出端定义在P1.1引脚sbit RST=P1^2; //位定义1302芯片的接口,复位端口定义在P1.2引脚unsigned char ReadSet1302(unsigned char Cmd);// 根据命令字,从1302读取一个字节数据unsigned char Read1302(void); // 从1302读一个字节数据void WriteSet1302(unsigned char Cmd,unsigned char dat); //向1302写一个字节数据void Write1302(unsigned char dat); // 向1302写一个字节数据void delaynus(unsigned char n); // 延时若干微秒void set_time(); // 设置时间/**********************************AT24c08专区*************************/sbit SCL=P3^4; //将串行时钟总线SCL位定义在为P3.4引脚sbit SDA=P3^5; //将串行数据总线SDA位定义在为P3.5引脚#define OP_READ 0xa1 // 器件地址以及读取操作,0xa1即为1010 0001B#define OP_WRITE 0xa0 // 器件地址以及写入操作,0xa1即为1010 0000Bvoid start(); void stop();void Ask();unsigned char ReadData24c08();void WriteCurrent24c08(unsigned char y);void WriteSet(unsigned char add, unsigned char dat);unsigned char ReadCurrent();unsigned char ReadSet(unsigned char set_addr);void INIT_24c08(); //初始化24c08 void push24c08_d(uchar); //桶深数据写入24c08uchar pop24c08_d(); //读出24c08桶深数据void push24c08_N(bit); //模式数据写入24c08uchar pop24c08_N(); //读出24c08模式数据 /*************************18b20专区**********************************/sbit DQ=P3^3; void ReadyReadTemp();void WriteOneChar(unsigned char dat);unsigned char ReadOneChar();bit Init_DS18B20();/*************************************************************************/void getkey(); // 扫描键盘uint test_deep(); // 超声测桶深void set_deep(uchar temp); // 手动设置桶深void menu_mode(); //菜单模式void delay_30us(); //延时120微秒void delay_ms(uint); // 延时若干毫秒void INIT_test();/******************************* **主函数*****************************/ void main(){ uchar deep=0,temp=0,j=0,i=0; uint temp_test; INIT_1602(); INIT_24c08(); INIT_1302(); INIT_test(); addrset(16,0); Print(Welc_1);// addrset(16,1); Print(Welc_2);// move_pl(); splash_p(); //闪屏调用 delay_ms(1500); move_pr(); while(1) { addrset(16,0); Print(Use_auto); addrset(16,1); Print(YN); move_pl(); TT0=0; key=0; while(key==0) //等待选择按键 { getkey(); if(TT0==4000) //一分钟无操作默认按下按键一 key=1; } move_pr(); if(key==2) //如按果按下按键二自动测量桶深 { key=0;// clear_p(); move_pl(); addrset(0,0); Print(B_deep); move_pr(); while((temp/2)!=((uchar)test_deep()/2)) //连续两次测量相等表示测量准确 temp=(uchar)test_deep()+2; display_d(temp); //显示测得桶深 TT0=0; while((key!=1)&&(key!=4)) //等待按下按键 { getkey(); if(TT0==6000) //一分钟后默认按一键 key=1; } if(key==1) push24c08_d(temp); } if(key==3) //如果按下按键三则手动设置桶深 { key=0;// clear_p(); move_pl(); addrset(0,0); Print(B_deep); move_pr(); temp=pop24c08_d(); //从E2PROM中取出上次存入的桶深 display_d(temp); set_deep(temp); //设置桶深函数调用。
} // if(key==4) //如按下按键四键值清零视为无操作 { key=0; clear_p(); } if(key==1) //当按下按键一则进入工状态 { key=0; deep=pop24c08_d(); //从E2PROM中取出上次存入的桶深给deep以作比较 delay_ms(5); Nightmode=(bit)pop24c08_N(); clear_p(); addrset(0,0); Print(Time); //在0,0处显示 Time addrset(0,1); Print(Water); // 在0,1处显示 addrset(5,1); writeData('%'); // 在5,1处显示 addrset(8,1); Print(Temper); // 在8,1处显示 addrset(3,1); //在3,1处显示百分比整数值 temp_test=test_deep(); temp=100-temp_test*100/deep; display_2(temp); while(1) { display_time_temper(); getkey(); if(key==1) { key=0; menu_mode(); addrset(3,1); //在3,1处显示百分比整数值 temp_test=test_deep(); temp=100-temp_test*100/deep; display_2(temp); } temp_test=test_deep(); temp_test=100-temp_test*100/deep; //得出现在水深与桶深百分比 if(temp==temp_test) i=0; if(temp!=temp_test) i++; if(i==2) { i=0; temp=temp_test; addrset(3,1); //在3,1处显示百分比整数值 display_2(temp); } getkey(); if(temp<10) { Jdq=0; Jdq=0; } if(temp>90) { Jdq=1; Jdq=1; if(Nightfuzhu==1) { Nightmode=1; Nightfuzhu=0;} } } } }}/******************** 延时毫秒函数****** ********************/void delay_ms(uint t) { uint i,j; for(i=0;i>4)*10 + (ReadValue&0x0F); //将读出数据转化 hour=ReadValue; display_2(ReadValue); writeData(':'); ReadValue = ReadSet1302(0x83); //从分寄存器读 ReadValue =((ReadValue&0x70)>>4)*10 + (ReadValue&0x0F); //将读出数据转化 display_2(ReadValue); getkey();/**********************温度显示**************************/ addrset(10,1); ReadyReadTemp(); //读温度准备 getkey(); TL=ReadOneChar(); //先读的是温度值低位 TH=ReadOneChar(); //接着读的是温度值高位 getkey(); if((TH&0xf8)!=0x00)//判断高五位 得到温度正负标志 { writeData('-'); TL=~TL; //取反 TH=~TH; //取反 TL=TL+1; //低位加1 if(TL>255) TH++; //如果低8位大于255,向高8位进1 TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16 //这样得出的是温度的整数部分,小数部分被丢弃了 TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整, } //这样得到的是温度小数部分的第一位数字(保留1位小数) else { writeData(' '); TN=TH*16+TL/16; //实际温度值=(TH*256+TL)/16,即:TH*16+TL/16 //这样得出的是温度的整数部分,小数部分被丢弃了 TD=(TL%16)*10/16; //计算温度的小数部分,将余数乘以10再除以16取整, //这样得到的是温度小数部分的第一位数字(保留1位小数) } temp_T=TN; display_2(TN); writeData('.'); TD=TD+'0'; writeData(TD); delay_ms(1); writeData(0); //显示字符℃ } while((key!=1)&&Nightmode&&(hour>22||hour<6));}void display_2(uchar temp) // 显示两位数函数{ uchar a,b; a=temp%100/10+'0'; b=temp%10+'0'; writeData(a); delay_ms(1); writeData(b); delay_ms(1);} /********************DS1302时钟专区**************************//***************延时微秒函数*******************/ void delaynus(unsigned char n){ unsigned char i; for(i=0;i>=1; //将dat的各数据位右移1位,准备写入下一个数据位 } }/*************函数功能:根据命令字,向1302写一个字节数据************************/ void WriteSet1302(unsigned char Cmd,unsigned。