1、1基于 51 单片机的蓝牙智能光控窗帘1、设计思路系统选用 STC12C5A60S2 作为主控芯片,用以完成对系统执行机构的控制、信息处理和液晶显示。 单片机控制直流减速电机实现窗帘、窗户的控制。 光照强度、温湿度信号均通过无线蓝牙模块传输至单片机,经处理后实现电机对窗户、窗帘的自动控制。根据设计方案和要求,可将电路分为 5 部分,分别为无线蓝牙遥控,传感器数据采集,电机驱动控制,单片机主控和电源部分。2、 系统结构此方案控制采用51单片机的最小系统来驱动步进电动机控制窗户和窗帘的拉开和关闭。家居推拉窗及窗帘控制系统可以利用蓝牙无线模块根据室外环境亮度实现环境亮度光控。以及光控状态下环境亮度的
2、控制参数的调整等等。该控制设计可谓是一款多功能的推拉窗及窗帘控制系统设计方案。系统软件设计框图如下:51单片机光电传感器温湿度传感器蓝牙模块A/D转换器电源模块电机驱动21. 光强度传感器 BH1750FVI不区分光源数字型环境光强度传感器 BH1750FVI是日本 株式会社近些年推出的一种两线式串行总线接口的集成电路,可以根据收集的光线强度数据来进行环境监测,其具有 165535的高分辨率,可支持较大范围的光照强度变化。BH1750FVI 结构框图如图所示。 图 1 BH1750FVI结构框图从结构框图可容易看出,外部光照被接近人眼反应的 高精度光敏二极管探测到后,通过集成运算放大器将 电流
3、转换为 电压,由模数转换器获取 位数字数 据,然后被逻辑和界面进行数据处理与存储。为 内部的振荡器提供内部逻辑时钟,通过相应的指令操作即 可读取出内部存储的光照数据。数据传输使用标准的 总线,按照时序要求操作起来也非常方便。2. 温湿传感器:传感器控制单片机中央控制程序电机驱动3DHT11数字温湿度传感器是一款含有已校准数字信号输出的温湿度复合传感器。它应用专用的数字模块采集技术和温湿度传感技术,确保产品具有极高的可靠性与卓越的长期稳定性。传感器包括一个电阻式感湿元件和一个NTC测温元件,并与一个高性能8位单片机相连接。因此该产品具有品质卓越、超快响应、抗干扰能力强、性价比极高等优点。每个DH
4、T11传感器都在极为精确的湿度校验室中进行校准。校准系数以程序的形式储存在OTP内存中,传感器内部在检测信号的处理过程中要调用这些校准系数。单线制串行接口,使系统集成变得简易快捷。超小的体积、极低的功耗,信号传输距离可达20米以上,使其成为各类应用甚至最为苛刻的应用场合的最佳选则。产品为 4 针单排引脚封装。连接方便,特殊封装形式可根据用户需求而提供。3. 电机驱动L298N 的说明及应用恒压恒流桥式2A 驱动芯片L298NL298 是SGS 公司的产品,比较常见的是15 脚Multiwatt 封装的 L298N,内部同样包含4 通道逻辑驱动电路。可以方便的驱动两个直流电机,或一个两相步进电机
5、。L298N 芯片可以驱动两个二相电机,也可以驱动一个四相电机,输出电压最高可达50V,可以直接通过电源来调节输出电压;可以直接用单片机的IO 口提供信号;而且电路简单,使用比较方便。L298N 可接受标准TTL 逻辑电平信号VSS,VSS 可接457 V 电压。4 脚VS 接电源电压,VS 电压范围VIH 为2546 V。输出电流可达 2 A,可驱动电感性负载。1 脚和15 脚下管的发射极分别单独引出以便接入电流采样电阻,形成电流传感信号。L298 可驱动2 个电动机,OUT1,OUT2 和OUT3,OUT4 之间可分别接电动机,本实验装置我们选用驱动一台电动机。5,7,10,12 脚接输入
6、控制电平,控制电机的正反转。EnA,EnB 接控制使能端,控制电机的停转。表1 是L298N 功能逻辑图。4L298N 驱动模块的应用In3,In4 的逻辑图与表1 相同。由表1 可知EnA 为低电平时,输入电平对电机控制起作用,当EnA 为高电平,输入电平为一高一低,电机正或反转。同为低电平电机停止,同为高电平电机刹停。L298N 控制器原理如下:3、 控制软件流程图(多个)1. 传感器控制程序凡是利用一定的物性(物理、化学、生物)法则、定理、定律、效应等进行能量转换与信息转换,并且输出与输入严格一一对应的器件和装置均可称为传感器;传感器又被称为变换器、转换器、检测器、敏感元件、换能器和一次
7、仪表等。传感器一般由敏感元件、转换元件和测量电路三部分组成,有时还加上辅助电源。系统中的传感器是感受被测量的大小并输出相对应的可用输出信号的器件或装置。数 据传输环节用来传输数据。当检测系统的几个功能环节独立地分隔开的时候,则必须由一 个地方向另一个地方传输数据,数据传输环节就是完成这种传输功能。52. 中断控制程序当传感器模块传来的数据并判断正确时,则中断程序对T1口进行初始化,进而接收来自两个模块的新数据,比较判断后传到命令地址进而对电机进行驱动和通过显示器显示出来。开 始串 口 中 断初 始 化 T 1数 据 传 送 到 命 令置 回 归 标 志 位中 断 返 回是否有数据NY中断控制程
8、序3. 电机驱动程序6步进电机执行来自控制器的命令,判断其命令是否正确,若不正确则返回,若正确则继续执行命令,比较做出相应的动作,当窗帘及推拉窗到达指定的位置时停止,器流程图如下。开 始 接 入是 否 正 确命 令 执 行窗 帘 推 拉 窗停 止 返 回比 较 判 断NYNY比 较 判 断比 较 判 断正 转 反 转 正 转 反 转YNYN4、 主要程序的指令:附录一:蓝牙无线模块附录二:DHT11 数字温湿度传感器附录三:光强度传感器 BH17507附录一:蓝牙无线模块:修改 at:#include / 引用程式庫SoftwareSerial BT(8, 9); / 接收腳, 傳送腳char
9、 val; / 儲存接收資料的變數void setup() Serial.begin(9600); / 與電腦序列埠連線Serial.println(“BT is ready!“);/ 設定藍牙模組的連線速率BT.begin(9600);void loop() / 若收到序列埠監控視窗的資料,則送到藍牙模組if (Serial.available() val = Serial.read();BT.print(val);/ 若收到藍牙模組的資料,則送到序列埠監控視窗if (BT.available() val = BT.read();Serial.print(val);8从机:void setu
10、p()Serial.begin(9600);void loop()while(Serial.available()char c=Serial.read();if(c=A)Serial.println(“Hello I am amarino“);主机:void setup()Serial.begin(9600);void loop()Serial.println(A); / 发送 A while(1); 9附录二:DHT11 数字温湿度传感器:U8 code table2=“ wendu shidu “;U8 code table3=“ . . “;sbit RS=P26;sbit RW=P25
11、;sbit E=P27;void write_com(U8 com)E=0;RS=0;RW=0;Delay(5);E=1;P0=com;E=0;void write_date(U8 date)E=0;RS=1;RW=0;Delay(5);E=1;P0=date;E=0;P0=0;void init()U8 num;Delay(15);write_com(0x38);write_com(0x38);write_com(0x38);write_com(0x0c);write_com(0x06);write_com(0x01);for(num=0;num0;x-)for(y=110;y0;y-);v
12、oid delay_10us() 11U8 i; i-; i-; i-; i-; i-; i-; void COM(void) /数据 0 1确认 U8 i; for(i=0;i #include 13U16 a,b,t;U8 flag,i;void main() RW=1;t=0;flag=0;TMOD=0x01;TH0=(65536-50000)/256;TL0=(65536-50000)%256;EA=1;ET0=1;TR0=1;init();P1_0=1;P2=0xff;Delay(40);while(1) RH();write_dht11(0,U8T_data_H);write_dh
13、t11(3,U8T_data_L);write_dht11(9,U8RH_data_H);write_dht11(12,U8RH_data_L);if(flag=2)/100后 flag 为 2,进行比较if(a=U8T_data_Hwhile(a=U8T_data_Hflag=0;test();void timer0() interrupt 1TH0=(65536-50000)/256;TL0=(65536-50000)%256;t+;if(t=2000)/100秒检测一次t=0;14flag=2;/100秒后 flag 为 2if(flag=0)/最开始 flag 为 0 赋值a=U8T_
14、data_H;b=U8RH_data_H;flag=1;/flag 变化15附录三:光强度传感器 BH1750:/使用时,用户只需更改 GPIO_Pin_14、GPIO_Pin_15 这两个引脚,并在主函数里面调用此函数即可。void BH1750_Get_Guang( float *Zhaodu)#include “stm32f10x_lib.h“#define uchar unsigned char#define uint unsigned int#define DataPort P0 /LCD1602 数据端口#define SlaveAddress 0x46 /定义器件在 IIC 总线
15、中的从地址,根据 ALT ADDRESS地址引脚不同修改/ALT ADDRESS引脚接地时地址为 0x46,接电源时地址为 0xB8#define BH1750_SCL GPIO_Pin_14 #define BH1750_SDA GPIO_Pin_15 /#define GPIO_I2C GPIOB#define BH1750_SCL_0() GPIOF-BRR=BH1750_SCL#define BH1750_SCL_1() GPIOF-BSRR=BH1750_SCL#define BH1750_SDA_0() GPIOF-BRR=BH1750_SDA#define BH1750_SDA_
16、1() GPIOF-BSRR=BH1750_SDA#define BH1750_SDA_STATE() (GPIOF-IDR typedef unsigned char BYTE;typedef unsigned short WORD;BYTE BUF8; /接收数 据缓存区 uchar ge,shi,bai,qian,wan; /显示变量int dis_data; /变量16void Init_BH1750(void);void conversion(uint temp_data);void Single_Write_BH1750(uchar REG_Address); /单个写入数据uch
17、ar Single_Read_BH1750(uchar REG_Address); /单个读取内部寄存器数据void Multiple_Read_BH1750(void); /连续的读取内部寄存器数据/-u8 BH1750_Start(void); void BH1750_Stop(void); u8 BH1750_SendByte(u8 Data); u8 BH1750_ReceiveByte(void); void BH1750_SendACK(void); void BH1750_SendNACK(void);void BH1750_Nop(void );void BH1750_Dela
18、y(unsigned int k) ;/-u8 BH1750_ACK =0; u8 BH1750_READY =0; u8 BH1750_NACK =1; u8 BH1750_BUS_BUSY =2; u8 BH1750_BUS_ERROR =3; u8 BH1750_RETRY_COUNT = 3; /重试次数 void BH1750_Nop(void) u8 i=50; 17while(i) i-; void BH1750_Delay(unsigned int k)unsigned int i,j;for(i=0;ik;i+)for(j=0;j121;j+);/* * 函数名称:IIC_S
19、TART * 描 述:发送启动 * * 输 入:无 * 输 出:无 * 返 回:无 * 作 者: * 修改日期:2010 年 6月 8日 */ u8 BH1750_Start(void) BH1750_SDA_1(); BH1750_Nop(); BH1750_SCL_1(); BH1750_Nop(); if(!BH1750_SDA_STATE() /DebugPrint(“TWI_START:BUSYn“); return BH1750_BUS_BUSY; BH1750_SDA_0(); 18BH1750_Nop();BH1750_SCL_0(); BH1750_Nop(); if(BH1
20、750_SDA_STATE() /DebugPrint(“TWI_START:BUS ERRORn“); return BH1750_BUS_ERROR; return BH1750_READY; /* -*/ /* * Brief: IIC_STOP */ /* -*/ void BH1750_Stop(void) BH1750_SDA_0(); BH1750_Nop(); BH1750_SCL_1(); BH1750_Nop(); BH1750_SDA_1(); BH1750_Nop(); /DebugPrint(“TWI_STOPn“); /* -*/ /* * Brief: IIC_S
21、endACK */ /* -*/ 19void BH1750_SendACK(void) BH1750_SDA_0(); BH1750_Nop(); BH1750_SCL_1(); BH1750_Nop(); BH1750_SCL_0(); BH1750_Nop(); BH1750_SDA_1(); /DebugPrint(“TWI_SendACKn“); /* -*/ /* * Brief: IIC_SendNACK */ /* -*/ void BH1750_SendNACK(void) BH1750_SDA_1(); BH1750_Nop(); BH1750_SCL_1(); BH175
22、0_Nop(); BH1750_SCL_0(); BH1750_Nop(); /DebugPrint(“TWI_SendNACKn“); /* -*/ /* * Brief: TWI_SendByte * * Param: Data * * Returns: */ /* -*/ u8 BH1750_SendByte(u8 Data) u8 i; 20BH1750_SCL_0(); for(i=0;i8;i+) /-数据建立- if(Data else BH1750_SDA_0(); Data=1; BH1750_Nop(); /-数据建立保持一定延时- /-产生一个上升沿正脉冲 BH1750_
23、SCL_1(); BH1750_Nop(); BH1750_SCL_0(); BH1750_Nop();/延时,防止 SCL 还没变成低时改变 SDA,从而产生 START/STOP信号 /- /接收从机的应答 BH1750_SDA_1(); BH1750_Nop(); BH1750_SCL_1(); BH1750_Nop(); if(BH1750_SDA_STATE() BH1750_SCL_0(); BH1750_SDA_1(); /DebugPrint(“TWI_NACK!n“); return BH1750_NACK; else BH1750_SCL_0(); BH1750_SDA_1
24、(); /DebugPrint(“TWI_ACK!n“); return BH1750_ACK; 21/* -*/ /* * Brief: IIC_ReceiveByte * * Returns: */ /* -*/ u8 BH1750_ReceiveByte(void) u8 i,Dat; BH1750_SDA_1(); BH1750_SCL_0(); Dat=0; for(i=0;i8;i+) BH1750_SCL_1();/产生时钟上升沿正脉冲,让从机准 备好数据 BH1750_Nop(); Dat=1; if(BH1750_SDA_STATE() /读引脚状态 Dat|=0x01; B
25、H1750_SCL_0();/准备好再次接收数据 BH1750_Nop();/等待数据准备好 /DebugPrint(“TWI_Dat:%xn“,Dat); return Dat; /*/void conversion(uint temp_data) / 数据转换出 个 ,十,百,千,万/ / wan=temp_data/10000+0x30 ;/ temp_data=temp_data%10000; /取余运算/ qian=temp_data/1000+0x30 ;/ temp_data=temp_data%1000; /取余运算/ bai=temp_data/100+0x30 ;/ tem
26、p_data=temp_data%100; /取余运算22/ shi=temp_data/10+0x30 ;/ temp_data=temp_data%10; /取余运算/ ge=temp_data+0x30; /*void Single_Write_BH1750(uchar REG_Address)BH1750_Start(); /起始信号BH1750_SendByte(SlaveAddress); /发送设备 地址+ 写信号BH1750_SendByte(REG_Address); /内部寄存器地址,/ BH1750_SendByte(REG_data); /内部寄存器数据,BH1750_
27、Stop(); /发送停止信号/*单字节读取*/*uchar Single_Read_BH1750(uchar REG_Address) uchar REG_data;BH1750_Start(); /起始信号BH1750_SendByte(SlaveAddress); /发送设备地址+ 写信号BH1750_SendByte(REG_Address); /发送存储单元地址,从0 开 始BH1750_Start(); /起始信号BH1750_SendByte(SlaveAddress+1); /发送设备地址+读信号REG_data=BH1750_RecvByte(); /读出寄存器数据BH175
28、0_SendACK(1); BH1750_Stop(); /停止信号return REG_data; */*/连续读出 BH1750 内部数据/*void Multiple_Read_BH1750(void) uchar i;BH1750_Start(); /起始信号23BH1750_SendByte(SlaveAddress+1); /发送设备地址+读信号for (i=0; i3; i+) /连续读取 2 个地址数据,存储中 BUFBUFi = BH1750_ReceiveByte(); /BUF0存储 0x32地址中的数据if (i = 3)BH1750_SendNACK(); /最后一个
29、数据需要回 NOACKelseBH1750_SendACK(); /回应 ACKBH1750_Stop(); /停止信号/Delay5ms();BH1750_Delay(500) ;/初始化 BH1750,根据需要请参考 pdf 进行修改*void Init_BH1750()Single_Write_BH1750(0x01); /*/在主程序内调用本函数*/*void BH1750_Get_Guang( float *Zhaodu) BH1750_Delay(100) ; /延时 100msInit_BH1750(); /初始化 BH1750Single_Write_BH1750(0x01); / power onSingle_Write_BH1750(0x10); / H- resolution mode24BH1750_Delay(200) ; /延时 180msMultiple_Read_BH1750(); /连续读出数据,存储在 BUF中dis_data=BUF0;dis_data=(dis_data8)+BUF1;/合成数据,即光照数据*Zhaodu=(float)dis_data/1.2;