全国大赛帆板控制系统.docx
《全国大赛帆板控制系统.docx》由会员分享,可在线阅读,更多相关《全国大赛帆板控制系统.docx(51页珍藏版)》请在冰豆网上搜索。
全国大赛帆板控制系统
帆板控制系统
摘要:
报告介绍基于STC89C52单片机的帆板角度控制系统,系统可以利用风扇控制装置对帆板角度进行控制,并通过LCD12864实时显示角度变化。
还可依据设定的帆板角度信息智能控制风扇转速,在很短时间内(5秒以内)动态调整帆板摆角,同时实时显示帆板角度等信息。
系统包括:
单片机主控模块、角度信号采集模块、键盘输入模块、显示模块、电源模块、风扇电机驱动模块。
系统主控模块采用性价比高的单片机最小系统;选用ADXL345加速度传感器完成系统角度信号采集功能;利用LCD12864实时显示角度变化的信息,5*6矩阵键盘完成风力等级和角度设定的输入;系统电源模块采用两路稳压输出电路(5v、15v),提供控制系统与风扇电机的工作电源;风扇电机采用L298N模块驱动。
本系统制作成本较低、工作性能控制稳定,能很好达到设计要求。
关键词:
STC89C52;加速度传感器;LCD12864;L298N
一、引言
单片机又称单片微控制器,单片机具有体积小、功耗低、控制功能强、扩展灵活、微型化和使用方便等优点,广泛应用于仪器仪表中,结合不同类型的传感器,可实现诸如电压、功率、频率、湿度、温度、流量、速度、厚度、角度、长度、硬度等物理量的测量。
本系统就是以单片机为核心建立起来的,要实现对帆板转角大小的控制,其归根就是对风扇的控制,帆板的转角随着风扇风力的变化而变化,角度传感器给单片机不同的角度检测信号,经单片机处理后在LCD液晶上显示,同时给出声光提示。
系统体现了模块化的设计理念,将单片机和各个器件结合在一起,完成系统化的设计,充分发挥了单片机的可靠性、可操作性和强大处理功能。
二、系统方案
(一)方案论证与比较
1、主控电路
【方案一】采用可编程逻辑器件FPGA作为控制器。
FPGA可以实现各种复杂的逻辑功能,IO资源丰富,易于进行功能扩展。
但本系统不需要复杂的逻辑功能,且从使用、功耗及经济的角度考虑我们放弃了此方案。
【方案二】STC89C52单片机采用STC89C52单片机作为主控器,其算术功能强,软件编程简洁灵活、自由度大,可用软件编程实现各种逻辑控制功能,且其功耗低、技术成熟,成本低廉。
本系统主要是进行信号的处理以及风扇电机的控制。
综合考虑,本系统设计的功能依靠51单片机均可实现,故采用方案二。
2、角度传感器的选用
【方案一】用UZZ9001Y与KMZ41连接构成一个角度测量系统。
电路组成繁琐,制作较困难,稳定性较差。
【方案二】倾角传感器。
该集成芯片为专用的水平倾角测量芯片,具有体积小、灵敏度高等优点,但是输出为模拟信号,需要用到DA转换,操作间为复杂,且占用I/O口较多,不利于本统功能模块的操作。
【方案三】用ADXL345数字加速度传感器。
ADXL345是一款小而薄的超低功耗的3轴加速度计,可测量帆板在斜面所受重力加速度在斜面上的分量,进而转换成倾斜角,测量精度较高。
ADXL345输出信号为数字信号,避免了A/D转换,操作简单;此外ADXL345只需用到两个I/O口,占用资源少,能满足本设计的要求。
本系统选择了第三种方案。
3、按键选用
【方案一】采用独立键盘。
多个使用时,线路连接不便,操作繁琐。
【方案二】采用5*6的距阵键盘,可输入的值比较多,可设定的功能也多。
在本系统中需要多个键,系统选择了第二种方案。
4、显示
【方案一】使用数码管显示。
要完成功能电路的显示需要多个数码管,此方案占用I/O口多,连接不便,显示效果差,功耗大。
【方案二】用LCD1602液晶显示。
1602是一种专门用于显示字母、数字、符号等点阵式,1602分为上下2行,每行显示16个字符。
驱动简单,但不能显示汉字。
【方案三】用LCD12864液晶显示。
LCD12864功能强大,不仅能显示字母、数字、符号,还可以显示汉字和图形,最多可显示4行,每一行最多显示8个中文,16个半宽字体。
(最好选用带字库的,方便编写程序。
)LCD12864和LCD1602使用方法类似,驱动简单,耗电量小,无辐射危险,显示直观、抗干扰能力强,但体积较大。
本系统选择了第三种方案。
5、电机的驱动
【方案一】用分立w元件构成的H桥电路利用分立三极管元件构成的H桥电路结构简单,但驱动能力有限,所带负载不可过大。
【方案二】采用L298N集成H桥芯片。
在L298N集成芯处中集成了两套H桥电路,可直接驱动两路直流电机,利用单片机产生的PWM信号,可方便地进行电机调速。
【方案三】用ULN2003功率放大器件。
ULN2003是高耐压、大电流达林顿陈列,由七个硅NPN达林顿管w组成。
通过使用不同的放大电路和不同参数的器件,可达到不同的放大的要求,放大后能得到较大的功率。
本系统设计采用方案二。
6、风扇
【方案一】用普通的散热风扇。
风力小,风力流失大,很难达到系统要求。
【方案二】用带通风通道的风扇。
风力集中,流失小,能很好的吹动帆板。
本系统设计采用方案二。
7、电源
【方案一】自制稳压电源。
采用变压器与三端稳压器相结合,使220V电压经变压器变压,降为系统所需电压,过整流桥并利用两个大的电容滤波,从而得到较为稳定的直流电压。
自制电源体积大,需接入220V电压,电压不稳定,使用不方便。
【方案二】三块6V蓄电池串联供电。
直接选用所需型号蓄电池,能量足,供电稳定,高低温适应性强。
本系统选用第二种方案。
(二)总体设计方案
系统功能的实现,以STC89C52单片机为核心,在单片机系统实现的输入输出和显示功能的基础上,由单片机的内置逻辑和运算功能,加上外围电路得以实现。
根据设计任务要求,该电路的总体框图可分为几个基本的模块,总体框图如下图2—1所示:
图2—1总体框图
三、理论分析与计算
(一)距离计算
帆板尺寸:
长15cm,宽10cm。
风扇到帆板的距离:
7~15cm。
本系统帆板转轴直径0.5cm
(二)角度计算
帆板转角:
0~60度。
帆板转角测量原理:
风扇吹动帆板转动,产生帆板角度变化,利用ADXL345数字加速度传感器测出三维坐标x、y、z的变化,将加速度传感器固定在帆板上,从而通过固定y,利用x、z的关系求出角度。
角度θ=(180*atan(tempz/tempx))/3.14。
角度的测量范围是0—90°,可以满足系统要求。
(三)控制算法
首先利用键盘控制风扇的转速,使帆板能够偏转一定的角度,再利用加速度传感器测出帆板的角度,送显示电路显示。
具体控制算法采用C语言编程实现,具体程序代码见附录2。
四、电路与程序设计
(一)硬件设计
1、总体电路图(见附录1)
2、主控电路
系统采用STC89C52单片机构成主控制电路,电路如图4—1所示:
图4—1主控电路
3、风扇控制
风扇电机选用L298N模块驱动,并由4*4按键矩阵控制PWM,改变电机速度,达到控制风扇风力大小的目标。
L298N驱动模块如下图4—2所示:
图4—2风扇控制
4、显示模块
使用LCD12864显示,如下图4—3所示:
图4—3显示模块
5、声光提示模块
图4—4声光提示模块
6、传感器模块
图4—5传感器模块
(二)软件设计
1、风扇控制算法设计
风扇控制算法如下图4—6所示:
图4—6风扇控制算法
2、声光提示算法设计
声光提示算法如下图4—7所示:
图4—7声光提示算法
3、系统流程图
整个系统程序流程图如图4—8所示:
图4—8系统流程图
五、系统测试
(一)测试方法与仪器
利用四位半数字万用表、秒表、量角器等设备通电对系统进行测试。
(二)测试结果
1、功能要求测试
序号
指标(目标值)
实测值
1
显示范围为0-60°,实时显示。
0-66°
2
分辨力为2°,绝对误差≤5°。
分辨1°误差3°
3
使帆板转角θ稳定在45°±5°范围内,制过程在10秒内完成,实时显示θ,并由声光提示
5秒
4
θ在5秒内达到设定值
5秒
表1
2、按键控制风力等级测试
风力等级
角度W
角度W
角度W
0
0°
0°
0°
5
1°
1°
1°
10
9°
10°
11°
15
23°
22°
23°
20
25°
29°
31°
25
37°
37°
39°
30
40°
39°
40°
35
47°
46°
43°
40
49°
49°
51°
45
51°
52°
53°
50
55°
56°
52°
55
55°
57°
54°
60
58°
59°
57°
65
57°
60°
58°
70
60°
62°
59°
75
61°
63°
60°
80
64°
63°
64°
85
65°
64°
65°
90
65°
65°
65°
95
65°
65°
65°
99
66°
66°
66°
表2
(三)测试结果分析
本系统总体性能良好。
但是也有不足的地方,由于帆板摆动大的问题,当系统工作时,影响到转角实际测量的精确性。
这个地方有待改进。
六、设计总结
本方案的系统设计基本符合2011年全国大学生电子设计竞赛试题(F题)的要求。
通过本次设计,深深感到理论与实践之间的差距。
很多知识点在理论上完全理解了,但到具体的电路设计与实现中,会出现很多一时无法理解的问题,要通过不断测试修改软硬件,才能用理论来指导实践,进一步深入理解理论。
参考文献
[1]郭天祥.51单片机C语言教程.北京:
电子工业出版社,2009年.
[2]阎石.数字电子技术基础(第四版).北京:
高等教育出版社,1997年.
[3]李建忠.单片机原理及应用.西安:
西安电子科技大学出版社,2002年.
附录1硬件原理图
附录2程序代码
主函数
/***************************************************************/
#include
#include"control.h"
#include"12864.h"
#include"ADXL.H"
#defineucharunsignedchar
#defineuintunsignedint
sbitkey=P2^7;
voidtimer_init()
{
TMOD=0X10;
TH1=(65535-100)/256;
TL1=(65535-100)%256;
EA=1;
ET1=1;
TR1=1;
}
voidmain()
{
chardevid;
timer_init();
lcd_12864_init();
Init_ADXL345();//初始化ADXL345
devid=Single_Read_ADXL345(0X00);//读出的数据为0XE5,表示正确
while
(1)
{
adxl345();
if(key==0)
keyscan_1();
else
keyscan();
}
}
/***************************************************************/
Controh.H文件
#ifndef__contral_h_
#define__contral_h_
externsignedcharpwm;
externvoiddelayms(unsignedintxms);
externvoidkeyscan();
externvoidkeyscan_1();
#endif
/***************************************************************/
Control.C文件
#include
#include"control.h"
#include"12864.h"
#defineucharunsignedchar
#defineuintunsignedint
#definekeydataP0
sbitA1=P2^4;
sbitA2=P2^5;
sbitENA=P2^6;
signedintcount=0;
signedcharpwm=0;
signedcharanjian=0;
ucharnumshi=0;
ucharnumge=0;
voiddelayms(unsignedintxms)
{
unsignedinti,j;
for(i=0;ifor(j=0;j<110;j++);
}
voidpwm_dis()
{
numshi=pwm/10;
numge=pwm%10;
write_12864_data(0x30+numshi);
write_12864_data(0x30+numge);
}
voidanjian_dis()
{
numshi=anjian/10;
numge=anjian%10;
write_12864_data(0x30+numshi);
write_12864_data(0x30+numge);
}
voidkeyscan()
{
unsignedchardat=0;
unsignedcharnum=0;
keydata=0xfe;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xee:
num=1;
break;
case0xde:
num=2;
break;
case0xbe:
num=3;
break;
case0x7e:
num=4;
break;
}
while(dat!
=0xf0)
{
dat=keydata;
dat=dat&0xf0;
}
}
}
keydata=0xfd;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xed:
num=5;
break;
case0xdd:
num=6;
break;
case0xbd:
num=7;
break;
case0x7d:
num=8;
break;
}
while(dat!
=0xf0)
{
dat=keydata;
dat=dat&0xf0;
}
}
}
keydata=0xfb;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xeb:
num=9;
break;
case0xdb:
num=10;
break;
case0xbb:
num=11;
break;
case0x7b:
num=12;
break;
}
while(dat!
=0xf0)
{
dat=keydata;
dat=dat&0xf0;
}
}
}
keydata=0xf7;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xe7:
num=13;
break;
case0xd7:
num=14;
break;
case0xb7:
num=15;
break;
case0x77:
num=16;
break;
}
while(dat!
=0xf0)
{
dat=keydata;
dat=dat&0xf0;
}
}
}
switch(num)
{
case1:
write_12864_addr(1,3);
pwm=0;
pwm_dis();
break;
case2:
write_12864_addr(1,3);
pwm=10;
pwm_dis();
break;
case3:
write_12864_addr(1,3);
pwm=20;
pwm_dis();
break;
case4:
write_12864_addr(1,3);
pwm=30;
pwm_dis();
break;
case5:
write_12864_addr(1,3);
pwm=40;
pwm_dis();
break;
case6:
write_12864_addr(1,3);
pwm=50;
pwm_dis();
break;
case7:
write_12864_addr(1,3);
pwm=60;
pwm_dis();
break;
case8:
write_12864_addr(1,3);
pwm=70;
pwm_dis();
break;
case9:
write_12864_addr(1,3);
pwm=80;
pwm_dis();
break;
case10:
write_12864_addr(1,3);
pwm=90;
pwm_dis();
break;
case11:
write_12864_addr(1,3);
pwm=99;
pwm_dis();
break;
case12:
write_12864_addr(1,3);
pwm=35;
pwm_dis();
break;
case13:
write_12864_addr(1,3);
pwm=pwm+5;
pwm_dis();
break;
case14:
write_12864_addr(1,3);
pwm=pwm-5;
pwm_dis();
break;
case15:
write_12864_addr(1,3);
pwm=pwm+1;
pwm_dis();
break;
case16:
write_12864_addr(1,3);
pwm=pwm-1;
pwm_dis();
break;
}
}
voidkeyscan_1()
{
unsignedchardat=0;
unsignedcharnum=0;
keydata=0xfe;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xee:
num=1;
break;
case0xde:
num=2;
break;
case0xbe:
num=3;
break;
case0x7e:
num=4;
break;
}
while(dat!
=0xf0)
{
dat=keydata;
dat=dat&0xf0;
}
}
}
keydata=0xfd;
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
delayms(5);
dat=keydata;
dat=dat&0xf0;
while(dat!
=0xf0)
{
dat=keydata;
switch(dat)
{
case0xed:
num=5;
break;
case0xdd:
num=6;
break;
case0xbd:
num=7;