作者:曹洋 邱邦彦 姚磊 刘童 靳晨曦
单位:泰州学院
指导老师:宋向前 李杨
1. 场景调研
随着科技的进步,我国经济水平也有了快速的发展,智能门窗的发展与我国建筑行业的发展有着密切的关系。近些年来我国房地产行业的持续升温、基础设施建设投入力度的不断加大,使得我国建筑业每年以20%以上的速度递增,全行业进入了一个高速发展的黄金时期。我国每年约有21亿平方米的房屋建筑工程,相当于欧洲和美国的总和。通常在房屋总建筑面积中,门与窗的建设面积约占25%-30%,也就是说,我国每年约有6亿多平方米的门窗建设任务。现阶段,我国门窗需求量现已达到每年2.5亿套,成为全球范围内最主要的门窗消费市场之一,智能门窗行业面临着巨大的市场发展空间。
随着人民生活水平的不断提高以及智能门窗宣传推广力度的加大,未来这种智能化、自动化的智能门窗将得到越来越多消费者的认可。预计未来5年内,我国智能门窗将凭借其极良好的性能,逐步扩大市场份额,成为未来门窗行业发展的趋势之一,占据着市场的重要地位。所以在这个背景下设计一款智能窗户是十分具有意义的。目前我们平时使用的窗户在特殊环境(如阳光、下雨、烟雾等)下是不可以智能主动地作出应对的,这给我们的生活带来了许多不便利,当然有时会给我们带来健康、经济上的损失。在这种背景下选择一款智能窗在很大程度上就会让我们不再让这些问题成为困扰我们生活上的烦恼。同时随着社会进步和发展,智能窗户取代现在日常家庭中的普通窗户将会成为一种不可阻挡的趋势。
2. 技术路线说明
2.1 窗帘模拟结构说明
窗帘运行结构由一个电动机和一条履带组成,负责控制窗帘的开关与停止功能,如下图所示:
通过霍尔传感器对窗帘位置进行定位,达到指定位置时发送信号停止,如下图所示:
2.2 窗户结构说明
窗户的结构由两个舵机连接两扇窗框组成,通过舵机的转动角度实现窗户的开关(0°、90°)和半开(45°),如下图所示:
2.3 系统设计
本设计采用光敏传感器、近红外传感器、触碰传感器、雨滴传感器、烟雾传感器、蓝牙传感器、霍尔传感器结合Arduino单片机开发板实现对外界光强、红外线、雨滴、烟雾数据的监测,通过编程设定对环境感知还有认为蓝牙远程链接完成对窗户的关闭或打开。如下图所示为整体结构图:
2.4 硬件设计
使用的Basra是一款基于Arduino开源方案设计的一款开发板。微控制器可以在 Arduino、eclipse、VisualStudio等IDE中通过c/c++语言来编写程序,编译成二进制文件,烧录进微控制器。Basra是一款核心板,大部分时间需要配合外围电路使用。同时装载了BigFish扩展板为核心板提供外围电路,可连接传感器、电机、输出模块、通信模块等,可靠稳定。如下图所示为单片机及扩展板实物图:
2.4.1 光强传感器模块
光强传感器(如下图所示)实质是利用光强元件将光信号转换为电信号的器件,敏感波长在可见光波长附近。通过光敏三极管在采集外界环境的光照强度,然后将采集光信号转换为电信号,进而通过LM385芯片对所信号进行放大处理,当光照强度达到所设定的阈值时,光照传感器输出端将输出一个低电平,代表传感器已经被触发。主要用于检测环境的光强进而控制窗户和窗帘的开和关。在本设计中自动模式下当光照增强时,窗户打开、窗帘打开,移走光源窗户重新关闭。
2.4.2 近红外传感器模块
近红外传感器(如下图所示)是一种开关量传感器,它可以检测到前方是否有物体存在,当检测到有物体存在时,传感器输出口会输出低电平;相反在未检测到前方有物体时,传感器输出口会输出一个高电平。主控芯片可根据传感器采集的电平高低做出相应的动作指令。
2.4.3 雨滴传感器模块
如下图所示,雨滴传感器是一个模拟(数字)输入模块,也叫雨水、雨量传感器。可用于各种天气状况的监测,检测是否下雨及雨量的大小,转成数字信号(DO)和模拟信号(AO)输出,并广泛应用于Arduino 机器人套件,雨滴,下雨传感器,可用于各种天气状况的监测,并转成数定信号和 AO 输出。本设计中在自动模式下,滴上雨滴时,输出低电平,窗帘不动,步进电机旋转90°完成关窗动作,无雨滴时,再次根据其他条件判断是否打开窗户。
2.4.4 烟雾传感器模块
MQ-2型烟雾传感器(如下所示)属于二氧化锡半导体气敏材料,属于表面离子式N型半导体。当与烟雾接触时,如果晶粒间界处的势垒收到烟雾的调至面变化,就会引起表面导电率的变化。利用这一点就可以获得这种烟雾存在的信息烟雾浓度越大导电率越大,输出电阻越低,则输出的模拟信号就越大。本设计中在自动模式下,当有烟雾或者有害气体时,窗户打开、窗帘打开。
2.4.5触碰传感器模块
触碰传感器(如下图所示)是一种开关量传感器,它的检测元件是一个微动开关(小行程限位开关),可以检测物体对开关的有效触碰,开关行程距离约2mm,接触式触发。触发触碰传感器后,该传感器会在其输出端输出数字量0,即低电平信号,未触发时输出数字量1,即高电平信号。本设计中主要利用其作为开关触碰切换“自动、语音、蓝牙”三种模式。
2.4.6 霍尔传感器模块
霍尔传感器(如下图所示)主要利用霍尔效应。磁场中有一个霍尔半导体片,恒定电流 I 从 A 到 B 通过该片。在洛仑兹力的作用下,I 的电子流在通过霍尔半导体时向一侧偏移,使该片在 CD 方向上产生电位差,这就是所谓的霍尔电压。
当磁性物件移近霍尔开关时,开关检测面上的霍尔元件因产生霍尔效应而使开关内部电路状态发生变化,由此识别附近有磁性物体存在,进而控制开关的通或断。本设计中主要利用其作为限位开关,用来控制窗帘停止的位置。
2.4.7 语音模块
语音识别模块及语音输出模块如上图9所示,该模块采用了基于helios-adsp新一代中大词汇语音识别协处理方案的语音识别专用芯片HBR640,非特定人语音识别技术可对用户的语音进行识别,支持中文音素识别,可任意指定中文识别词条(小于8个汉字),单次识别可支持1000 条以上的语音命令,安静环境下,标准普通话,识别率大于95%,可自动检测环境噪声,噪声环境下也能保证较好的识别率。语音输出模块它的功能是播放声音,我们需要通过软件把自己想要播放的文字转成16进制,然后添加到代码里就好。SYN6288这个模块可以播报中英文,它和单片机的连接走的是串口通信,串口发送包含声音内容的GB2312编码,模块播放声音。
在语音模式下,可用普通话进行开关窗、开关窗帘等操作。同时切换三种模式时,喇叭会发出提示音,在语音模式下,开关窗户、窗帘时会有相应提示音。
2.4.8 蓝牙传感器模块
蓝牙串口模块(如下图所示)具有两种工作模式:命令响应工作模式和自动连接工作模式,在自动连接工作模式下模块又可分为主(Master)、从(Slave)和回环(Loopback)三种工作角色。
当模块处于自动连接工作模式时,将自动根据事先设定的方式连接的数据传输;当模块处于命令响应工作模式时能执行下述所有AT命令,用户可向模块发送各种AT指令,为模块设定控制参数或发布控制命令。通过控制模块外部引脚(PIO11)输入电平,可以实现模块工作状态的动态转换。当模块处于自动连接工作模式时,将自动根据事先设定的方式连接的数据传输;当模块处于命令响应工作模式时能执行下述所有AT命令,用户可向模块发送各种AT指令,为模块设定控制参数或发布控制命令。蓝牙模式下,可以用手机app控制系统的动作和状态。
2.5 软件设计
主要采用Arduino ide环境进行相应功能编程,主要功能如下:
在自动模式下:
① 当光强高于某一值时(白天),打开窗户、窗帘;当光强低于某个值(即夜晚),关闭窗户、窗帘。
② 当检测到外面下雨时,立即关闭窗户,如果雨停了,打开窗户。
③ 当家里检测到烟雾时,打开窗户、窗帘。
在语音模式下:
语音模式下,可用普通话进行开关窗、开关窗帘等操作。同时切换三种模式时,喇叭会发出提示音,在语音模式下,开关窗户、窗帘时会有相应提示音。
在蓝牙模式下:
可以用手机app远程遥控窗户和窗帘的开关,还可实现窗户的半开、窗帘拉动时随时停止等功能。
3. 示例程序
① shiyan10_voice.ino
#include <Servo.h>
byte value;
int left_angle=160;
int right_angle=20;
#define la left_angle
#define ra right_angle
int i;
#define Left_Pos A0
#define Right_Pos A1
#define Light A2
#define Raindrop A3
#define Smoke A4
#define Choise A5
#define Humen 13
boolean pattern;
boolean flag1=0;
boolean flag2=0;
boolean flag3=0;
boolean flag4=0;
boolean flag5=0;
boolean flag6=0;
boolean flag7=0;
boolean flag8=0;
boolean flag9=0;
int pin[4]={Smoke,Raindrop,Light,Humen};
int voice[3]={12,8,3};
int voice1;
char buttonState;
Servo Left_Window;
Servo Right_Window;
void setup()
{
Serial.begin(9600);
Left_Window.attach(4);
Right_Window.attach(7);
Left_Window.write( left_angle );
Right_Window.write( right_angle );
pinMode( 5 , OUTPUT);
pinMode( 6 , OUTPUT);
pinMode( 11 , INPUT);
pinMode( 3 , INPUT);
pinMode( 8 , INPUT);
pinMode( 12 , INPUT);
pinMode( 9 , OUTPUT);
pinMode( 10 , OUTPUT);
pinMode( 13 , INPUT);
}
void loop()
{
if(digitalRead(Humen)==0)
close_window();
if(digitalRead(Choise)==0)
{
delay(50);
while(digitalRead(Choise)==0);
delay(50);
if(digitalRead(Choise)==1)
{
pattern=pattern+1;
if(pattern>=3)
pattern=0;
flag1=1;
flag2=1;
flag7=1;
}
}
if(pattern==0)
{
//Serial.println("automatic control");
digitalWrite(9, HIGH);
digitalWrite(10, LOW);//绿灯自动控制
if(flag1==1)
{
speech5();flag1=0;
}
}
else if(pattern==1)
{
//Serial.println("voice control");
digitalWrite(10, HIGH);
digitalWrite(9, LOW);//红灯语音控制
if(flag2==1)
{
speech6();flag2=0;
}
}
else
{
digitalWrite(10, 0);
digitalWrite(9, 0);//APP控制
if(flag7==1)
{
speech7();flag7=0;
}
}
if(pattern==0)
{
digitalWrite(11,0);
delay(50);
digitalWrite(11,1);
value=0;
for(int j=0;j<=3;j++)
value|=(digitalRead(pin[j])<<j);
Serial.println(value);
switch (value)
{
case 0: close_window();open_curtain();break;
case 1: close_window();close_curtain();break;
case 2: close_window();open_curtain();break;
case 3: close_window();close_curtain();break;
case 4: close_window();open_curtain();break;
case 5: close_window();open_curtain();break;
case 6: close_window();open_curtain();break;
case 7: close_window();open_curtain();break;
case 8: open_window();open_curtain();break;
case 9: close_window();close_curtain();break;
case 10: open_window();open_curtain();break;
case 11: close_window();close_curtain();break;
case 12: open_window();open_curtain();break;
case 13: close_window();open_curtain();break;
case 14: open_window();open_curtain();break;
case 15: open_window();open_curtain();break;
default:break;
}
}
if(pattern==1)
{
value=0;
for(int j=0;j<=2;j++)
value|=(digitalRead(voice[j])<<j);
if(value==voice1)
{
flag3=0;
flag4=0;
flag5=0;
flag6=0;
}
else
{
flag3=1;
flag4=1;
flag5=1;
flag6=1;
}
voice1=value;
// Serial.println(value);
switch (value)
{
case 0:
{close_window();
if(flag3==1)
{
speech2();flag3=0;
}
digitalWrite(11,0);
delay(50);
digitalWrite(11,1);
break;}
case 1:
{open_window();
if(flag4==1)
{
speech1();flag4=0;
}
digitalWrite(11,0);
delay(50);
digitalWrite(11,1);
break;}
case 2:
{close_curtain();
if(flag5==1)
{
speech4();flag5=0;
}
digitalWrite(11,0);
delay(50);
digitalWrite(11,1);
break;}
case 3:
{open_curtain();
if(flag6==1)
{
speech3();flag6=0;
}
digitalWrite(11,0);
delay(50);
digitalWrite(11,1);
break;}
default:break;
}
}
if(pattern==2)
{
if(Serial.available()>0)//串口接受到的数据个数
buttonState = Serial.read();
switch (buttonState)
{
case '1': open_window();buttonState='0'; break;
case '2': close_window();buttonState='0';break;
case '3': open_curtain();buttonState='0';break;
case '4': close_curtain();buttonState='0';break;
case '5': Stop();buttonState='0';break;
case '6': half_open_window();buttonState='0';break;
default:break;
}
}
if(digitalRead(Right_Pos)==0&&flag8==1)
{Stop( );flag8=0;}
if(digitalRead(Left_Pos)==0&&flag9==1)
{Stop( );flag9=0;}
}
void Stop()
{
digitalWrite( 5 , LOW );
digitalWrite( 6 , LOW );
}
void Open()
{
analogWrite( 5 , 150 );
digitalWrite( 6 , LOW );
}
void Close()
{
digitalWrite( 5 , LOW );
analogWrite( 6 , 150 );
}
void close_curtain()
{
if(digitalRead(Right_Pos)==1)
{Close( );flag8=1;}
else
{Stop( );flag8=0;}
}
void open_curtain()
{
if(digitalRead(Left_Pos)==1)
{Open( );flag9=1;}
else
{Stop( );flag9=0;}
}
void close_window()
{
for(la,ra;la<=160,ra>=20;la++,ra--)
{
Left_Window.write(la);delay(5);
Right_Window.write(ra);delay(5);
}
}
void open_window()
{
for(la,ra;la>=70,ra<=110;la--,ra++)
{
Left_Window.write(la);delay(5);
Right_Window.write(ra);delay(5);
}
}
void half_open_window()
{
if (la>=65&&la<=75)
{
for(la,ra;la<=115,ra>=65;la++,ra--)
{
Left_Window.write(la);delay(5);
Right_Window.write(ra);delay(5);
}
}
if (la>=155&&la<=165)
{
for(la,ra;la>=115,ra<=65;la--,ra++)
{
Left_Window.write(la);delay(5);
Right_Window.write(ra);delay(5);
}
}
}
//好的,窗户已打开
void speech1(){
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xBA;
head[6] = 0xC3;
head[7] = 0xB5;
head[8] = 0xC4;
head[9] = 0xA3;
head[10] = 0xAC;
head[11] = 0xB4;
head[12] = 0xB0;
head[13] = 0xBB;
head[14] = 0xA7;
head[15] = 0xD2;
head[16] = 0xD1;
head[17] = 0xB4;
head[18] = 0xF2;
head[19] = 0xBF;
head[20] = 0xAA;
head[21] = 0xA0;
for(i=0; i<22; i++){
Serial.write(head[i]);
}
}
//好的,窗户已关闭
void speech2(){
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xBA;
head[6] = 0xC3;
head[7] = 0xB5;
head[8] = 0xC4;
head[9] = 0xA3;
head[10] = 0xAC;
head[11] = 0xB4;
head[12] = 0xB0;
head[13] = 0xBB;
head[14] = 0xA7;
head[15] = 0xD2;
head[16] = 0xD1;
head[17] = 0xB9;
head[18] = 0xD8;
head[19] = 0xB1;
head[20] = 0xD5;
head[21] = 0xF6;
for(i=0; i<22; i++){
Serial.write(head[i]);
}
}
//好的,窗帘已打开
void speech3()
{
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xBA;
head[6] = 0xC3;
head[7] = 0xB5;
head[8] = 0xC4;
head[9] = 0xA3;
head[10] = 0xAC;
head[11] = 0xB4;
head[12] = 0xB0;
head[13] = 0xC1;
head[14] = 0xB1;
head[15] = 0xD2;
head[16] = 0xD1;
head[17] = 0xB4;
head[18] = 0xF2;
head[19] = 0xBF;
head[20] = 0xAA;
head[21] = 0xCC;
for(i=0; i<22; i++){
Serial.write(head[i]);
}
}
//好的,窗帘已关闭
void speech4()
{
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xBA;
head[6] = 0xC3;
head[7] = 0xB5;
head[8] = 0xC4;
head[9] = 0xA3;
head[10] = 0xAC;
head[11] = 0xB4;
head[12] = 0xB0;
head[13] = 0xC1;
head[14] = 0xB1;
head[15] = 0xD2;
head[16] = 0xD1;
head[17] = 0xB9;
head[18] = 0xD8;
head[19] = 0xB1;
head[20] = 0xD5;
head[21] = 0x9A;
for(i=0; i<22; i++)
{
Serial.write(head[i]);
}
}
//已切换到自动模式
void speech5()
{
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xD2;
head[6] = 0xD1;
head[7] = 0xC7;
head[8] = 0xD0;
head[9] = 0xBB;
head[10] = 0xBB;
head[11] = 0xB5;
head[12] = 0xBD;
head[13] = 0xD7;
head[14] = 0xD4;
head[15] = 0xB6;
head[16] = 0xAF;
head[17] = 0xC4;
head[18] = 0xA3;
head[19] = 0xCA;
head[20] = 0xBD;
head[21] = 0xF9;
for(i=0; i<22; i++){
Serial.write(head[i]);
}
}
//已切换到语音模式
void speech6()
{
unsigned char i = 0;
unsigned char head[22];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x13;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xD2;
head[6] = 0xD1;
head[7] = 0xC7;
head[8] = 0xD0;
head[9] = 0xBB;
head[10] = 0xBB;
head[11] = 0xB5;
head[12] = 0xBD;
head[13] = 0xD3;
head[14] = 0xEF;
head[15] = 0xD2;
head[16] = 0xF4;
head[17] = 0xC4;
head[18] = 0xA3;
head[19] = 0xCA;
head[20] = 0xBD;
head[21] = 0xF9;
for(i=0; i<22; i++){
Serial.write(head[i]);
}
}
//已切换到APP模式
void speech7(){
unsigned char i = 0;
unsigned char head[21];
head[0] = 0xFD;
head[1] = 0x00;
head[2] = 0x12;
head[3] = 0x01;
head[4] = 0x00;
head[5] = 0xD2;
head[6] = 0xD1;
head[7] = 0xC7;
head[8] = 0xD0;
head[9] = 0xBB;
head[10] = 0xBB;
head[11] = 0xB5;
head[12] = 0xBD;
head[13] = 0x41;
head[14] = 0x50;
head[15] = 0x50;
head[16] = 0xC4;
head[17] = 0xA3;
head[18] = 0xCA;
head[19] = 0xBD;
head[20] = 0xA3;
for(i=0; i<21; i++){
Serial.write(head[i]);
}
}
② voice.ino
#include "HBR740.h"
boolean flag=0;
HBR740 hbr740; //实例化一个语音识别模块
void setup()
{
hbr740.open(); //开始进行语音识别
pinMode( 3 , OUTPUT);
pinMode( 8 , OUTPUT);
pinMode( 11 , INPUT);
pinMode( 12 , OUTPUT);
}
void loop()
{
while(flag==0)
{
initial();
flag=1;
}
if(digitalRead(11)==0)
initial();
if(hbr740.isHeard()) //如果监测到识别语句
{
int value = hbr740.getSentence(); //获得识别语句的序号
switch (value)
{
case 0: close_window();break;
case 1: open_window();break;
case 2: close_curtain();break;
case 3: open_curtain();break;
default:;break;
}
}
}
void serialEvent()
{
hbr740.lisen(); //在串口接收事件中调用语音识别的监听指令
}
void initial()
{
digitalWrite(3,1);digitalWrite(8,1);digitalWrite(12,1);
}
void close_window()
{
digitalWrite(3,0);digitalWrite(8,0);digitalWrite(12,0);
}
void open_window()
{
digitalWrite(3,0);digitalWrite(8,0);digitalWrite(12,1);
}
void close_curtain()
{
digitalWrite(3,0);digitalWrite(8,1);digitalWrite(12,0);
}
void open_curtain()
{
digitalWrite(3,0);digitalWrite(8,1);digitalWrite(12,1);
}
4. 作品创新点
红外扫描模块--防止小孩坠落:采用的红外传感器凭借高可靠性,高性能,低功耗,价格便宜而广受欢迎,应用非常普遍。它是通过接收到人体发出的红外线而引起的电荷失常来工作的,当有人在红外传感器的检测范围时,红外传感器会将检测到的信号转换成电信号,传输给单片机,从而控制舵机实现窗户的关闭。
手机APP控制模块:利用蓝牙连接实现远程对窗户进行控制,当连接时,可进入远程控制操作模式,当人为观察到需要特殊开合窗户的情况时,通过手机与APP的连接,可使用手机软件,然后便可以进行远程控制。
5. 作品难点及解决方案
5.1难点
① 如何实现各个模块之间在互不干扰情况下的合成以及各个模块之间的优先级问题。
② 蓝牙模块调试及手机APP设计问题。
5.2解决方案
① 增加一个按钮用于切换三种模式 设置好各个模块的优先级后接下来用switch函数设置不同情况下的动作。
② 利用蓝牙串口助手逐步运行调试蓝牙模块,向其发送信号后能得到接收回应,之后将程序烧录主板,发送信号测试舵机、发动机的运行状态并调试。接着登陆APP INVENTOR设计手机APP,完成组件设计和逻辑设计后打包apk,下载到手机调试几次,最后成功。
* 更多详情请查看 【S027】智能家居窗户机器人