自动窗帘.docx
《自动窗帘.docx》由会员分享,可在线阅读,更多相关《自动窗帘.docx(18页珍藏版)》请在冰豆网上搜索。
![自动窗帘.docx](https://file1.bdocx.com/fileroot1/2023-7/27/1f44deef-4cbe-4936-9a20-561edbc4b6a0/1f44deef-4cbe-4936-9a20-561edbc4b6a01.gif)
自动窗帘
第2章步进电机原理简介
2.1步进电机
在电气时代的今天,电动机一直在现代化的生产和生活中起着十分重要的作用。
无论是在工农业生产还是在日常生活中的家用电器,都大量地使用着各种各样的电动机。
因此对电动机的控制变得越来越重要了。
。
下图1为本设计所用到的五线式四相步进电机
图1五线式四相步进电机
2.1.1步进电机原理
步进电机是机电控制中一种常用的执行机构,其原理是通过对它每相线圈中的电流和顺序切换来使电机作步进式旋转。
驱动电路由脉冲信号来控制,所以调节脉冲信号的频率便可改变步进电机的转速。
通俗地说:
当步进驱动器接收到一个脉冲信号,它就驱动步进电机按设定的方向转动一个固定的角度(及步进角)。
通过控制脉冲个数即可以控制角位移量,从而达到准确定位的目的。
同时通过控制脉冲频率来控制电机转动的速度和加速度,从而达到调速的目的,现在比较常用的步进电机包括反应式步进电机(VR)、永磁式步进电机(PM),混合式步进电机(HB)和单相式步进电机等。
2.1.2步进电机的一些基本参数
电机固有步距角:
它表示控制系统每发一个步进脉冲信号,电机所转动的角度。
电机出厂时给出了一个步距角的值,如86BYG250A型电机给出的值为0。
90/1。
80(表示半步工作时为0。
90、整步工作时为1。
80),这个步距角可以称之为“电机固有步距角”,它不一定是电机实际工作时的真正步距角,真正的步距角和驱动器有关。
步进电机的相数:
是指电机内部的线圈组数,目前常用的有二相、三相、四相、五相步进电机。
电机相数不同,其步距角也不同,一般二相电机的步距角为0。
90/1。
80、三相的为0。
750/1。
50、五相的为0。
360/0。
720。
在没有细分驱动器时,用户主要靠选择不同相数的步进电机来满足自己步距角的要求。
如果使用细分动器,则“相数”将变得没有意义,用户只需在驱动器上改变细分数,就可以改变步距角。
3.2.3TH12864-15液晶显示
TH12864-15是128(列)×64(行)点阵的液晶显示模块。
当15脚为低且16脚为高时选中TH12864-15的左区(左边的64×64),当15脚为高且16脚为低时选中MG12864的右区(右边的64×64)。
19脚和20脚是为了在光线暗的环境下看到液晶显示器的显示内容而加的背光,即在液晶显示器的背面加一光源。
控制线R/W、CSI、CS2、RS必须在使能线E为低的时候改变。
当使能线E为高时控制线R/W、CSI、CS2、RS不能改变;使能线E为高时TH12864-15从数据线DB0~DB7输出数据。
下图6为TH12864-15的管脚说明。
引脚号符号功能
引脚号符号功能
1GND模块的电源地
7~14DB0~DB7并行数据0~7
2VDD模块的电源正端
15PSB并/串行接口选择
3V0LCD驱动电压输入端
16NC空脚
4RS并行的指令/数据选择信号;串行的片选信号
17RET复位,低电平有效
18NC空脚
5R/W并行的读/写选择信号;串行的数据口
19BLA背光源正极(LED+5V)
6E并行的使能信号;串行的同步时钟
19BLK背光源负极(LED-0V)
图6TH12864-15管脚说明
图612864液晶显示模块
3.3总设计电路图(见报告最后)
3.4软件设计
3.4.1程序流程:
结论
本次课程设计中主体功能采用步进电机实现,显示功能采用液晶12864实现,对于步进电机的驱动采用uln2003芯片,使用方便,简化电路。
对于液晶12864的操作采用串行通信,串行通信操作简单,连线方便。
检测感应模块主要通过检测人体运动产生电平跳变即有人走近窗帘或者离开窗帘,然后将信号发送给lpc2131来控制电机正反转。
对于主程序的设计,先定义一个标志变量flag,当检测到电平上升沿时,控制电机正转,变量flag=1;当检测到下降沿,同时flag=1时即人离开窗帘,控制电机反转,关闭窗帘。
定义两个变量用来计数,在开关窗帘过程中,每当电机转动一圈时,相应变量自动加一,当变量达到设定上限值时,电机停止转动,即窗帘已经完全打开或者完全关闭。
附录
朱闯设计心得
为期两周的课程设计结束了,在没有实际操作以前,我觉得ARM课程设计会比较麻烦,为此我们参考了别人的设计,初步了解总体思路后开始动手实践。
由于有C语言编程经验和51单片机课设的经验,再结合ARM课程的学习,真正设计的过程中并没有想象的那么困难。
只要ARM中的各个寄存器的名称和功能,以及一些常用的指令语句记得清楚,那么同样的用C语言编程是没有什么困难的。
对于这种实践性比较强的课程,一般情况下是少说多动手才有益于我们对这门课程的学习。
对于程序设计来说,各个子程序的设计比较简单,只需按照各个芯片的操作时序编程就可以。
比较困难的是主程序,由于各个模块功能相互穿插,因此要综合考虑。
我们这次课设所做的题目是红外感应自动窗帘控制器设计。
总共能够实现两个功能,第一是控制两个步进电机的同时的正转、反转和停止,也即控制窗帘的开闭和停。
第二是实现了一个显示的功能,显示窗帘的开关以及窗帘的开度。
这次课设中硬件电路比较简单,最重要的是加深了软件的调试方法,先将各个功能模块的子程序设计好,再与主程序连接综合调试,加深了对ARM课程内容的理解。
参考文献:
[1]周立功.编著.ARM微控制器基础与实践[M].北京:
北京航空航天大学出版社.2005.
[2]黄智伟.ARM嵌入式系统应用设计与实践[M].北京:
北京航空航天大学出版社.2011.
[2]沈建华.译.ARM嵌入式系统开发、软件设计与优化[M].北京:
北京航空航天大学出版社.2005.
voltage=AD_data*Vref/1024
voltage为电压值
AD_data为AD芯片的采集离散数值
Vref为你的基准电压
1024为2^10,
设计程序:
#include"config.h"
#include"stdio.h"
#defineKEY11<<17//P0.17
#defineKEY21<<20//P0.20
#defineBEEPCON1<<7//P0.07
#defineKEY31<<21//P0.21
#defineMOTO11<<9//P0.09
#defineMOTO21<<10//P0.10
#defineMOTO31<<12//P0.12
#defineMOTO41<<13//P0.13
#defineMOTOCON0x3c003600//MOTO控制字
#defineGPIOSET(PIN)IO0SET=PIN//方便修改置位端口
#defineGPIOCLR(PIN)IO0CLR=PIN//方便修改清位端口
#defineLCD_CON0x000c0080//液晶显示控制字
#defineE_CLK(1<<18);//clockinput同步时钟输入端
constuint32RW_SID=(1<<19);//datainput/output串行数据输入、输出端
constuint32CS=(1<<7);//P0.7
unsignedcharXX[]="西安科技大学";
unsignedcharTM[]="自5智能窗帘";
unsignedcharXS[]="屈爱刘郭相";
unsignedcharBJ[]="张泽栋任建超"
unsignedcharZZ[]="开窗帘";
//unsignedcharZZ1[]="每步走1.8";
unsignedcharFZ[]="关窗帘";
unsignedcharTZ[]="停止";
//unsignedcharKD[]="开度:
";
uint32zhen;
uint32fan;
uint8tin;
uint8flag;
voidDelayNS(uint32dly);
voidMOTO_Mode1(uint8i);//AB-BC-CD-DA正转
voidMOTO_Mode2(uint8i);//AD-DC-CB-BA反转
voidMOTO_Mode3(uint8i);//电机停止
/***********************************************************
******************以下是显示器的子程序********************/
voiddelay(uint32dly)
{
uint32i;
for(;dly>0;dly--)
for(i=0;i<10;i++);
}
//串行发送一字节数据
voidSendByte(uint8dat)
{
uint8i;
IO0SET=CS;
for(i=0;i<8;i++)
{
IO0CLR=E_CLK;delay(5);
if(dat&0x80)
{
IO0SET=RW_SID;delay(5);
}
elseIO0CLR=RW_SID;
{
IO0SET=E_CLK;delay(5);
}
dat=dat<<1;
}
IO0CLR=CS;
}
//串行接收一字节数据
unsignedcharReceieveByte(void)
{
uint8i,d1,d2;
for(i=0;i<8;i++)
{
IO0CLR=E_CLK;delay(5);
IO0SET=E_CLK;delay(5);
if(RW_SID)d1++;
d1=d1<<1;
}
for(i=0;i<8;i++)
{
IO0CLR=E_CLK;delay(5);
IO0SET=E_CLK;delay(5);
if(RW_SID)d2++;
d2=d2<<1;
}
return(d1&0xF0+d2&0x0F);
}
//写控制命令
voidSendCMD(uint8dat)
{
SendByte(0xF8);
SendByte(dat&0xF0);
SendByte((dat&0x0F)<<4);}
//写显示数据或单字节字符
voidSendDat(uint8dat)
{
SendByte(0xFA);
SendByte(dat&0xF0);
SendByte((dat&0x0F)<<4);}
voiddisplay(uint8x_add,unsignedchar*word)
{
SendCMD(x_add);
while(*word)
{
SendDat(*(word++));
}
}
//初始化LCM
voidinitlcm(void)
{
delay(200);
SendCMD(0x30);//功能设置,一次送8位数据,基本指令集
SendCMD(0x0C);//0000,1100整体显示,游标off,游标位置off
SendCMD(0x01);//0000,0001清DDRAM
SendCMD(0x02);//0000,0010DDRAM地址归位
SendCMD(0x80);//1000,0000设定DDRAM7位地址000,0000到地址计数器AC
}
/****************************************************************************
*名称:
main()
*功能:
根据表DISP_TAB来控制LED显示。
****************************************************************************/
intmain(void)
{
PINSEL0=0x00000000;
PINSEL1=0X00000000;
PINSEL2&=~(0x00000006);//设置所有I/O口为GPIO口
IO0DIR=MOTOCON|BEEPCON|LCD_CON;
initlcm();//12864初始化程序
display(0x80,XX);
delay(100);
display(0x90,TM);
delay(100);
display(0x88,XS);
delay(100);
display(0x98,BJ);
delay(100);
//DelayNS(1000);
//IO0CLR=LCD_CON;
//while
(1);
while
(1)
{
if((KEY1&IO0PIN)==0)
{delay(5);
if((KEY1&IO0PIN)!
=0&&(flag==0))
{MOTO_Mode1(6);
zhen=0x00;
flag=1;
}
}
//if((KEY1&IO0PIN)==0)
//{delay(5);
if((KEY1&IO0PIN)!
=0&&(flag!
=0))
{MOTO_Mode2(6);
fan=0x00;
flag=0;
}
//}
elseif((KEY2&IO0PIN)==0)
{MOTO_Mode2(6);}
//WaitKey3();
if((KEY3&IO0PIN)==0)
{MOTO_Mode3(6);}
}
return0;
}
/****************************************************************************
*名称:
DelayNS()
*功能:
长软件延时
*入口参数:
dly延时参数,值越大,延时越久
*出口参数:
无
****************************************************************************/
voidDelayNS(uint32dly)
{uint32i;
for(;dly>0;dly--)
{
for(i=0;i<4000;i++);
}
}
////////
voidMOTO_Mode2(uint8i)
{
while((fan!
=0x5cf)&&(KEY3&IO0PIN)!
=0)
{
initlcm();
display(0x80,FZ);
delay(100);
//display(0x90,ZZ1);
//delay(100);
/*AB*/
GPIOSET(MOTO1);
GPIOSET(MOTO4);
DelayNS(i);
GPIOCLR(MOTO1);
GPIOCLR(MOTO4);
/*BC*/
GPIOSET(MOTO4);
GPIOSET(MOTO3);
DelayNS(i);
GPIOCLR(MOTO4);
GPIOCLR(MOTO3);
/*CD*/
GPIOSET(MOTO3);
GPIOSET(MOTO2);
DelayNS(i);
GPIOCLR(MOTO3);
GPIOCLR(MOTO2);
/*DA*/
GPIOSET(MOTO2);
GPIOSET(MOTO1);
DelayNS(i);
GPIOCLR(MOTO2);
GPIOCLR(MOTO1);
fan++;
}
if(fan==0x5cf)
{initlcm();
display(0x80,TZ);
delay(100);
}
}
///////
voidMOTO_Mode1(uint8i)
{
if((KEY3&IO0PIN)!
=0)
{
while(zhen!
=0x5cf)
{
initlcm();
display(0x80,ZZ);
//display(0x90,ZZ1);
delay(100);
if(zhen<=1400)
{
//display(0x88,KD);
//delay(100);
SendCMD(0x8B);
SendDat((zhen/14)/10+0x30);
SendCMD(0x8C);
SendDat((zhen/14)%10+0x30);
}
/*AB*/
GPIOSET(MOTO1);
GPIOSET(MOTO2);
DelayNS(i);
GPIOCLR(MOTO1);
GPIOCLR(MOTO2);
/*BC*/
GPIOSET(MOTO2);
GPIOSET(MOTO3);
DelayNS(i);
GPIOCLR(MOTO2);
GPIOCLR(MOTO3);
/*CD*/
GPIOSET(MOTO3);
GPIOSET(MOTO4);
DelayNS(i);
GPIOCLR(MOTO3);
GPIOCLR(MOTO4);
/*DA*/
GPIOSET(MOTO4);
GPIOSET(MOTO1);
DelayNS(i);
GPIOCLR(MOTO4);
GPIOCLR(MOTO1);
zhen++;
if((KEY3&IO0PIN)==0)
{while(tin==0)
{initlcm();
display(0x80,TZ);
delay(100);
GPIOCLR(MOTO1);
GPIOCLR(MOTO2);
GPIOCLR(MOTO3);
GPIOCLR(MOTO4);
DelayNS(10);
}
}
}
if(zhen==0x5cf)
{initlcm();
display(0x80,TZ);
delay(100);}
}
}
///////////
voidMOTO_Mode3(uint8i)
{while((KEY3&IO0PIN)==0)
{
initlcm();
display(0x80,TZ);
delay(100);
GPIOCLR(MOTO1);
GPIOCLR(MOTO2);
GPIOCLR(MOTO3);
GPIOCLR(MOTO4);
DelayNS(i);
}
}