资源描述
指导老师评定成绩:
审定成绩:
重 庆 邮 电 大 学
自 动 化 学 院
综合设计汇报
设计题目:基于单片机光源自适应控制系统设计
单位(二级学院): 自 动 化 学 院
学 生 姓 名:
专 业: 自 动 化
班 级:
学 号:
指 导 教 师: 蒋建春
设计时间: 年 10 月
重庆邮电学院自动化学院制
摘 要
本设计给出了一个基于单片机点光源自动跟踪系统设计方案, 该设计使用TI企业超低功耗AT89C52单片机作为整个系统控制关键,关键由电机驱动模块,点光源检测模块,电源转换模块等模块组成。利用8路光敏电阻来检测点光源位置并将检测到信号经过放大后进行AD转换,将转换结果传给控制器AT89C52单片机,经过过单片机运算和处理来确定点光源运动趋势,并将运算控制信号控制两台步进电机,使其跟随点光源运动。
本设计能够扩展为以后太阳能发电自动跟踪系统。该系统不仅能自动依据太阳光方一直调整太阳能电池板朝向, 结构简单、成本低, 而且在跟踪过程中能自动记忆和更正不一样时间坐标位置, 无须人工干预, 尤其适合天气改变比较复杂和无人值守情况, 有效地提升了太阳能利用率, 有很好推广应用价值。
关键词:AT89C52单片机,光源,自动跟踪,传感器
目 录
摘要 2
目录 3
一 设计题目 4
1.1 基于单片机光源自适应控制系统设计 4
1.2 设计要求 4
二 设计汇报正文 5
2.1 设计方案总体方向选择 5
2.1.1 系统方案确实定 5
2.1.2 方案选择 5
2.2 硬件电路设计 6
2.2.1 A/D转换模块 6
2.2.2 步进电机模块 9
2.2.3 电机驱动模块 11
2.2.4 检测模块 13
2.2.5 单片机模块 14
2.3 系统软件设计 18
三 总体调试 19
3.1 总体调试 19
3.2 问题及处理方案 19
3.2.1 通道比较阀值设置 19
3.2.2 电机防抖 19
四 设计总结 20
五 参考文件 21
六 附录 22
一、 设计题目
1.1基于单片机光源自适应控制系统设计
设计一控制系统,假设有一个太阳能电池板,为了使电池板最大程度接收光照强度,经过控制器调整电池板角度使电池板一直正对光线。采取步进电机作为角度调整装置,使系统能上下和左右旋转。
1.2设计要求
1. 绘出电路原理图;
2. 制作电路图;
3. 编写程序;
4. 调试运行。
二、 设计汇报正文
2.1设计方案选择
2.1.1系统方案确实定
1. 方案一
本方案是由检测电路、AT89C52单片机、时钟电路、A/D转换控制电路等关键模块组成。传感器部分采取光敏二极管,将光信号变换为电信号。经过A/D转换将其转化离散数字信号。控制电路以单片机为关键,能够对采集数字信号进行处理和判定,控制电机运转使太阳能板正对光线。
2. 方案二
本方案用以单片机STC12C5A60S2为关键,光强度检测模块,时钟模块,步进电机控制电路模块和12864液晶显示等关键模块组成。传感器采取光敏电阻,STC12C5A6S2单片机自带10位A/D,能够识别模拟信号。控制电路以单片机为关键,能够对采集模拟信号进行处理和判定对步进电机实现控制。
2.1.2方案选择
比较以上两方案可知,系统工作原理是一致,全部是经过传感器采集太阳光并间接或直接将其转化成单片机能够识别信号,经过单片机处理信号并进行判定,步进电机控制电路依据单片机传出信号转动。所不一样是采取元器件差异,但从单片机方面考虑,方案一所使用传统单片机器件方案二所使用系列成本低。依据实际情况方案一元器件基础全部是简单易上手器件,利用起来比较灵活,原理简单轻易了解方便写程序代码。综合考虑,最终确定选择方案一。
系统组成及工作原理以单片机为控制关键,采取光强度检测电路测量,以光敏电阻传感器作为测量元件,组成光电测量模块。该系统可分为电源模块电路、光电测量电路、时钟电路、步进电机控制电路、单片机、A/D转换电路。选择关键器件有:光敏电阻,时钟芯片74LS74,AT89C52,步进电机和转换芯片ADC0809等。
系统设计框图图2-1所表示。
图2-1 系统设计框图
2.2硬件电路设计
2.2.1 AD转换模块
1.ADC0809内部逻辑结构
ADC0809由一个8路模拟开关、一个地址锁存和译码器、一个A/D转换器和一个三态输出锁存器组成。多路开关可选通8个模拟通道,许可8路模拟量分时输入,共用A/D转换器进行转换。三态输出锁器用于锁存A/D转换完数字量,当OE端为高电平时,才能够从三态输出锁存器取走转换完数据。
2.ADC0809引脚结构
ADC0809各脚功效以下:
D7-D0:8位数字量输出引脚。
IN0-IN7:8位模拟量输入引脚。
VCC:+5V工作电压。
GND:地。
REF(+):参考电压正端。
REF(-):参考电压负端。
START:A/D转换开启信号输入端。
ALE:地址锁存许可信号输入端。
(以上两种信号用于开启A/D转换).
EOC:转换结束信号输出引脚,开始转换时为低电平,当转换结束时为高电平。
OE:输出许可控制端,用以打开三态数据输出锁存器。
CLK:时钟信号输入端(通常为500KHz)。
A、B、C:地址输入线。图2-2所表示
图2-2实物图和管脚图
ADC0809对输入模拟量要求:信号单极性,电压范围是0-5V,若信号太小,必需进行放大;输入模拟量在转换过程中应该保持不变,如若模拟量改变太快,则需在输入前增加采样保持电路。
地址输入和控制线:4条
ALE为地址锁存许可输入线,高电平有效。当ALE线为高电平时,地址锁存和译码器将A,B,C三条地址线地址信号进行锁存,经译码后被选中通道模拟量进入转换器进行转换。A,B和C用于选通IN0-IN7上一路模拟量输入。通道选择表如表2-1所表示。
数字量输出及控制线:11条
ST为转换开启信号。当ST上跳沿时,全部内部寄存器清零;下跳沿时,开始进行A/D转换;在转换期间,ST应保持低电平。EOC为转换结束信号。当EOC为高电平时,表明转换结束;不然,表明正在进行A/D转换。OE为输出许可信号,用于控制三条输出锁存器向单片机输出转换得到数据。OE=1,输出转换得到数据;OE=0,输出数据线呈高阻状态。D7-D0为数字量输出线。
CLK为时钟输入信号线。因ADC0809内部没有时钟电路,所需时钟信号必需由外界提供,通常使用频率为500KHZ,VREF(+),VREF(-)为参考电压输入。
表2-1输入通道
3.ADC0809应用说明
1)ADC0809内部带有输出锁存器,能够和AT89S51单片机直接相连。
2)初始化时,使ST和OE信号全为低电平。
3)要转换哪一通道地址到A,B,C端口上。
4)在ST端给出一个最少有100ns宽正脉冲信号。
5)是否转换完成,我们依据EOC信号来判定。
6)当EOC变为高电平时,这时给OE为高电平,转换数据就输出给单片机了。
图2-3 ADC0809连接图
图2-3所表示,IN0-IN7分别和8个检测单元连接,D0-D7管脚接在单片机1P3口,ST管脚于单片机1P1.2连接,OE、EOC分别和P1.0、P1.1连接,A、B和C和P1.4-P1.6连接,CLK接外部时钟电路,11、12管脚接VCC,13、16管脚接地。
2.2.2 步进电机模块
1. 驱动方法及关键参数如表2-2、表2-3所表示:
表2-2驱动方法(4-1-2相驱动)
导线颜色
1
2
3
4
5
6
7
8
6红
+
+
+
+
+
+
+
+
4橙
-
-
3黄
-
-
-
2粉
-
-
-
1蓝
-
-
-
表2-3关键技术参数
电机型号
电压V
相数
步距角度
减速比
28BYJ-48
5
4
5.625/64
1:64
2.步进电机关键特征:
1) 步进电机必需加驱动才能够运转, 驱动信号必需为脉冲信号,没有脉冲时候,步进电机静止, 假如加入合适脉冲信号, 就会以一定角度(称为步角)转动。转动速度和脉冲频率成正比。
2)28BYJ48是减速步进电机,减速比为1:64,步进角为5.625/64度。假如需要转动1圈,那么需要360/5.625*64=4096个脉冲信号。
3) 步进电机含有瞬间开启和急速停止优越特征。
4)改变脉冲次序, 能够方便改变转动方向。
电机线圈由四相组成,即A、B、C、D四相,电机示意图和各线圈通电次序图2-4和表2-4所表示:
图2-4步进电机原理图
表2-4 各线圈通电次序
相次序
1
2
3
4
5
6
1
0
0
1
1
1
0
2
1
0
0
1
1
1
3
1
1
1
0
1
1
4
1
1
1
1
0
0
相次序从0到1称为一步,电机轴将转过5.625度,四相四拍为0-1-2-3则称为通电一周,若循环进行这种通电一周操作,电机便连续转动起来,而进行相反通电次序如3-2-1-0将使电机同速反转。同理四相八拍通电次序为A-AB-B-BC-C-CD-D-DA-A(本设计用是四相八拍)。通电一周周期越短,即驱动频率越高,则电机转速越快,但步进电机转速也不可能太快,因为它每走一步需要一定时间,若信号频率过高,可能造成电机失步,甚至只在原步颤动。
图2-5 水平方向步进电机电路连接
图2-6 竖直方向步进电机电路连接
2.2.3电机驱动模块
本设计采取51单片机AT89C52(晶振频率为11.0592MHZ)对该四线八相制步进电机进行控制。经过I/O口输出含有时序方波作为步进电机控制信号,信号经过特定芯片驱动步进电机。本文选择ULN组成步进电机驱动电路,下面但见介绍下ULN结构和特点:
ULN 是高耐压、大电流达林顿陈列,由七个硅NPN 达林顿管组成。
该电路特点以下:
ULN 每一对达林顿全部串联一个2.7K 基极电阻,在5V 工作电压下它能和TTL 和CMOS 电路直接相连,能够直接处理原先需要标准逻辑缓冲器来处理数据。ULN 工作电压高,工作电流大,灌电流可达500mA,而且能够在关态时承受50V 电压,输出还能够在高负载电流并行运行。ULN 采取DIP—16 塑料封装。ULN方框图图2-7所表示。ULN和AT89C52组成驱动电路图2-8所表示。
图2-7 ULN内部方框图
图2-8 ULN和AT89C52组成驱动电路
2.2.4检测模块:
光敏电阻分布图2-9所表示:
图2-9 光敏电阻分布图
比较控制式太阳跟踪装置。设置一个直筒形外壳,在直筒外部,东、南、西、北四个方向上分别部署4只光电阻;其中一对光电阻(PI,P3)东西对称安装在直筒两侧,用来粗略检测太阳由东往西运动偏转角度即方位角;另一对光电阻(PZ,P4)南北对称安装在直筒两侧,用来粗略检测太阳视高度即高度角;在直筒内部,东、南、西、北四个方向上也分别部署4只光电阻;其中一对光电阻(PS,P7)东西对称安装在直筒内侧,用来正确检测太阳由东往西运动偏转角度;另一对光电阻(P6,PS)南北对称安装在直筒内侧,用来正确检测太阳视高度。其电路图如如2-10所表示。
图2-10检测电路
2.2.5单片机模块
1.AT89C52内部结构和引脚
AT89C52是一个低功耗高性能单片机,40个引脚,32个外部双向输入/输出(I/O)端口,同时内含2个外部中止口,2个16位可编程定时计数器,2个全双工串行通信口,AT89C52能够根据常规方法进行编程,也能够在线编程。其将通用微处理器和Flash存放器结合在一起,尤其是可反复擦写Flash存放器可有效地降低开发成本。管脚说明以下:
VCC:电源。
GND:地。
P0 口:P0 口是一个8 位漏极开路双向I/O 口。作为输出口,每位能驱动8 个TTL逻辑电平。对P0 端口写“1”时,引脚用做高阻抗输入。当访问外部程序和数据存放器时,P0 口也被作为低8 位地址/数据复用。在这种模式下,P0 含有内部上拉电阻。在Flash编程时,P0 口也用来接收指令字节;在程序校验时,输出指令字节。在程序校验时,需要外部上拉电阻。
P1 口:P1 口是一个含有内部上拉电阻8 位双向I/O 口,P1 输出缓冲器能驱动4 个TT逻辑电平。当对P1 端口写“1”时,内部上拉电阻把端口拉高,此时能够作为输入口使用。看成为输入使用时,被外部拉低引脚因为内部电阻原因,将输出电流(IIL)。另外,P1.0 和P1.2 分别作为定时器/计数器2 外部计数输入(P1.0/T2)和定时器/计数器2触发输入(P1.1/T2EX),在Flash编程和校验时,P1口接收低8 位地址字节。
P2 口:P2 口是一个含有内部上拉电阻8 位双向I/O 口,P2 输出缓冲器能驱动4 个TT逻辑电平。对P2 端口写“1”时,内部上拉电阻把端口拉高,此时能够作为输入口使用。看成为输入使用时,被外部拉低引脚因为内部电阻原因,将输出电流(IIL)。
P3 口:P3 口是一个含有内部上拉电阻8 位双向I/O 口,P2 输出缓冲器能驱动4 个TT逻辑电平。对P3 端口写“1”时,内部上拉电阻把端口拉高,此时能够作为输入口使用。看成为输入使用时,被外部拉低引脚因为内部电阻原因,将输出电流(IIL)。P3口也可作为AT89C52部分特殊功效口,以下所表示:
P3.0 RXD(串行输入口)
P3.1 TXD(串行输出口)
P3.2 /INT0(外部中止0)
P3.3 /INT1(外部中止1)
P3.4 T0(记时器0外部输入)
P3.5 T1(记时器1外部输入)
P3.6 /WR(外部数据存放器写选通)
P3.7 /RD(外部数据存放器读选通)
P3口同时为闪烁编程和编程校验接收部分控制信号。
RST: 复位输入。在晶振工作时,RST脚连续两个机器周期高电平将使单片机复位。看门狗计时完成后,RST脚输出96个晶振周期高电平。特殊寄存器AUXR(地址8EH)上DISRTO 位能够使此功效无效。在DISRTO 默认状态下,复位高电平有效。
ALE/PROG:地址锁存控制信号(ALE)在访问外部程序存放器时,锁存低8 位地址输出脉冲。在Flash编程时,此引脚(PROG)也用做编程输入脉冲。
PSEN:外部程序存放器选通信号(PSEN)是外部程序存放器选通信号。当AT89S52从外部程序存放器实施外部代码时,PSEN 在每个机器周期被激活两次,而在访问外部数据存放器时,PSEN将不被激活。
EA/VPP:访问外部程序存放器控制信号。为使能从0000H 到FFFFH 外部程序存放器读取指令,EA必需接GND。为了实施内部程序指令,EA应该接VCC。在Flash编程期间,EA也接收12伏VPP电压。
XTAL1:振荡器反相放大器和内部时钟发生电路输入端。
XTAL2:振荡器反相放大器输出端。
AT89S52单片机引脚功效介绍(图2-11):
图2-11 AT89S52 DIP封装管脚分布图
2.单片机电路设计
单片机1经过和ADC0809连接,接收ADC0809转换后数据并对其作出判定和比较,在P2口发出信号和单片机2通信。其电路连接图图2-12所表示:
图2-12 单片机1电路图
单片机2经过接收单片机1P2口发出信号作出判定控制水平和竖直方向上电机运作以求太阳能板正对光线。其电路连接图图2-13所表示:
图2-13 单片机2电路图
3. 两片单片机通信
单片机1关键负责接收ADC0809转换后数据,并经过比较产生控制信号并将信号发送给单片机2,而单片机2关键负责接收信号然后经过信号控制两台步进电机运作从而达成试验目标。两片单片机通信接口协议如表2-5所表示:
表2-5单片机通信
接线1
接线2
接线3
单片机1
P2^6
P2^5
P2^4
单片机2
P3^2
P3^3
P3^4
2.3系统软件设计
本设计,程序采取C语言进行设计。程序中关键有以下多个关键子程序:主程序,ADC0809初始化、采集、转换数据程序,电机驱动控制程序。程序源代码见附录。
三、 总体调试
3.1 软硬件调试
硬件焊接及程序编写完成后,在对整个系统调试过程中,出现了电机不运转等问题。关键经过单独调试各个模块及检验相关硬件电路焊接,找出问题所在,然后针对问题逐一击破,最终成功完成本设计。
3.2 关键问题及处理方案
3.2.1 通道比较阀值设置
因为采取ADC0809进行数模转换,而在转换过程中光敏电阻采光是时时改变,所以8个通道数据比较过程会有一定波动,如不加阀值比较则会致使电机不停工作,最终太阳能板无法正确对光。
在阀值选定上,经过实物测试,最终选定在+5(-5)。这个阀值既能数据比较正确性又能确保电机正常运转。
3.2.2电机防抖
在最初程序编写过程,因为没考虑到检测时候延时及数据波动,造成最初太阳能板在最终对光时不停波动。以后经过程序延时加入、数据比较时阀值引入及实物测试最终使此问题得到改善,成功完成太阳能板对光。
四、 设计总结
此次课程设计使我对设计一个完整计算机控制系统有了更全方面体会,经过绘制电路原理图,温故了PROTEL软件,提升了我动手设计能力。电路焊接过程中,经过每个对模块焊接和测试,极大地提升了我动手分析处理问题能力。
本设计经过两片AT89C52分别控制数模转换芯片ADC0809和电机驱动控制芯片组成数据采集转换电路和电机驱动控制电路实现光源自适应控制。同时又利用单片机AT89C52内部计时器,节省了大量资源。不过,因为存在步进电机转角度数精度不高、手工制作试验装置不规整等非线性、ADC0809数据转换不够正确等问题,所以存在误差,所以本设计还有待继续研究和改善。
在此次课程设计中,经过和队员之间合作,使得我们能顺利完成设计任务,体会到了合作力量,增强了我团体合作意识,在方案选择和电路原理图设计过程中,感谢老师悉心指导,才能顺利地完成设计,节省了很多时间来应付更大障碍。特在此忠心感谢我指导老师蒋建春老师!
五、 参考文件
[1] 张毅刚.单片机原理及应用[M].北京:高等教育出版社,.5.
[2] ADC0809汉字资料.
[3] AT89C52 汉字资料.
[4] ULN汉字资料.
六、 附录
1.系统整体电路图
优酷视频地址:
2.源程序1(数据采集)
#include <reg52.h>
#define uint unsigned int
#define uchar unsigned char
uchar code LEDData[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar code pip[8] = {0x0f,0x1f,0x2f,0x3f,0x4f,0x5f,0x6f,0x7f}; //通道选择
uint buffer[8]={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //数据存放
char charset[10] = {'0','1','2','3','4','5','6','7','8','9'};
sbit P25=P2^5;
sbit P26=P2^6;
sbit P24=P2^4;
sbit OE = P1^0;
sbit EOC = P1^1;
sbit ST = P1^2;
sbit CLK = P3^3;
uchar i=0;
uchar s[6] = {'|',' ','=',' ',' ',' '};
void long_char(uchar l,char *s)
{
*(s+3) = charset[l/100];
*(s+4) = charset[l%100/10];
*(s+5) = charset[l%10];
}
void DelayMS(uint i) //延时iMS
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
void SendStr(unsigned char *s);
/*------------------------------------------------
串口初始化
------------------------------------------------*/
void InitUART (void)
{
SCON = 0x50; // SCON: 模式 1, 8-bit UART, 使能接收
TMOD |= 0x20; // TMOD: timer 1, mode 2, 8-bit 重装
TH1 = 0xFD; // TH1: 重装值 9600 波特率 晶振 11.0592MHz
TR1 = 1; // TR1: timer 1 打开
EA = 1; //打开总中止
//ES = 1; //打开串口中止
}
/*------------------------------------------------
发送一个字节
------------------------------------------------*/
void SendByte(char dat)
{
SBUF = dat;
while(!TI);
TI = 0;
}
/*------------------------------------------------
发送一个字符串
------------------------------------------------*/
void SendStr(char *s)
{
while(*s!='\0')// \0 表示字符串结束标志,
//经过检测是否字符串末尾
{
SendByte(*s);
s++;
}
}
void main()
{
InitUART();
i=0;
P1=0x2f;
while(1)
{
ST = 0;
ST = 1;
ST = 0;
while(EOC == 0);
OE = 1;
P1=pip[i];
buffer[i]=P3;
DelayMS(20);
i++;
i = (i>=8)?0:i;
OE = 0;
if(buffer[2]>buffer[3]+10) //通道比较
{
P26=1;
P25=1;
P24=1;
}
else if(buffer[2]<buffer[3]-10)
{
P26=1;
P25=0;
P24=1;
}
else if((buffer[2]>buffer[3]-10)&&(buffer[2]<buffer[3]+10))
{
if(buffer[4]>buffer[1]+10)
{
P26=0;
P25=0;
P24=1;
}
else if(buffer[4]<buffer[1]-10)
{
P26=0;
P25=1;
P24=1;
}
else if((buffer[4]>buffer[1]-10)&&(buffer[4]<buffer[1]+10))
{
P24=0;
}
}
}
}
3.源程序2(电机驱动)
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit Y1 = P3^2; //上接控制线P26
sbit Y2 = P3^3; //上接控制线P25
sbit Y3 = P3^4; //上接控制线P24
uchar code B_Rotation[8]={0x08,0x0c,0x04,0x06,0x02,0x03,0x01,0x09}; //电机1逆时钟旋转相序表
uchar code F_Rotation[8]={0x09,0x01,0x03,0x02,0x06,0x04,0x0c,0x08}; //电机1正时钟旋转相序表
uchar code CCW2[8]={0x80,0xc0,0x40,0x60,0x20,0x30,0x10,0x90};//电机2逆时钟旋转相序表
uchar code CW2[8]={0x90,0x10,0x30,0x20,0x60,0x40,0xc0,0x80};//电机2顺时钟旋转相序表
void Delay(uint i)
{
uchar x,j;
for(j=0;j<i;j++)
for(x=0;x<=148;x++);
}
void main()
{
uchar i=0;
while(Y3==1)
{
if(Y1==1&&Y2==1)
Delay(20);
if(Y1==1&&Y2==1)
{
P2 = B_Rotation[i]; //电机1逆时针转动
i++;
if(i==8) i=0;
}
else if(Y1==1&&Y2==0)
Delay(20) ;
if(Y1==1&&Y2==0)
{
P2 = F_Rotation[i]; //电机1顺时针转动
i++;
if(i==8) i=0;
}
else if(Y1==0&&Y2==0)
Delay(20);
if(Y1==0&&Y2==0)
{
P2 = CW2[i]; //电机2逆时针转动
i++;
if(i==8) i=0;
}
else if(Y1==0&&Y2==1)
Delay(20) ;
if(Y1==0&&Y2==1)
{
P2 = CCW2[i]; //电机2顺时针转动
i++;
if(i==8) i=0;
}
}
}
展开阅读全文