智能家居是一种通过物联网将家里的各种电器设备连接在一起,并由中心控制器统一管理的信息系统。系统的核心是各类家居信息的采集与处理。阿里云能够提供云端的数据存储和分析功能,可以作为智能家居中心控制器的重要平台。
本文主要研究了基于阿里云的智能家居信息采集系统,即单片机将传感器检测的家庭环境参数透传到阿里云,用于远程分析和管理,同时提供移动终端的查询与控制功能。
系统硬件基于STM32F103ZET6单片机设计,通过配置多种传感器和WIFI通信等功能模块,实现家庭环境参数的获取与上传功能。软件设计分为两部分实现,一是在MDK5上进行总体程序设计,二是在阿里云的物联网平台上进行网页编程和APP编程,再通过安卓构建的功能将物联网平台上编辑的APP下载到移动用户端。其中,网页和APP的数据通过软件MQTT与阿里云建立连接得到。系统最终实现在LCD和APP上实时显示当前家庭环境的相关情况,可以利用红外遥控器、按键、APP实现对LED灯的开关控制,并实现灯光亮度的自动调节。
关键词
智能家居;阿里云;单片机;透传;MQTT
第1章 概 述
1.1 研究背景
1.2 选题来源
1.3 选题意义
1.4 技术方案的比较和选择
1.5 论文内容及结构安排
第2章 基于阿里云的简易智能家居系统的总体设计
2.1 硬件系统设计方案
2.2 软件系统设计方案
第3章 系统硬件构成
3.1 传感器模块硬件设计
3.2 红外模块硬件设计
3.3 WIFI模块硬件设计
3.4 LCD模块硬件设计
第4章 基于阿里云的简易智能家居系统软件设计
4.1 程序开发总坏境
4.2 哈希算法计算连接服务器的密码
4.3 uCOSII操作系统配置
4.4 FatFs文件操作系统
4.5 MQTT数据透传设置
4.6 阿里云物联网程序设计
4.7 环境参数检测软件设计
4.8 WIFI模块软件设计
4.9 红外模块软件设计
4.10 本章小结
第5章 总结与展望
致 谢
参考文献
附录1:效果展示图
附录2:主程序代码
当前,国家正处于科技创新和产业转型发展的关键阶段,随着5G、物联网、云计算等技术的日渐成熟,在国家政策的支持以及市场的需求下,智能家居和各类物联网类产品的需求量将急剧上升。
据Verified Market Research最近发布了一份报告,2019年全球智能家居市场规模为808.3亿美元,预计到2027年将达到2019年的2.5倍,从2020年到2027年的复合年增长率为13.52%。[1]
互联网快速发展,相关技术日趋成熟,为智能家居系统的设计和完善提供了坚实的基础。正是因为智能家居系统涉及的智能传感器技术、互联网技术、云存储与云计算等技术趋于综合化,所以各方面的提升对智能家居系统的实现与发展具有很大的促进作用。
智能家居的发展符合社会发展潮流,是大势所趋。
由于个人对编程及电子信息技术的兴趣,基于实际工程需求选择了本课题。在大一阶段,我接触到计算机应用基础和C语言程序设计等方面的知识,由此激发了我对计算机编程的兴趣;随后在大二必修了微机原理与接口技术课程,选修了人工智能课程,加深了对编程和人工智能等方面的认识,并通过参加电子设计制作、电子线路CAD课程设计等实践环节,锻炼了动手实践的能力;在大三阶段我又先后接触到智能家居、人脸识别等设计项目,使我对智能家居方面产生了极大的兴趣,于是本次选择此课题进行进一步的研究。
在信息化的时代,智能家居很有可能成为未来居家环境建设模式的主流。
将智能家居融入老年居住公寓的建设中,不仅可以为老年人提供更好的居住体验,还可以随时检测老人的身体状况。当有危险发生时,及时提醒居住者,并且通过互联网功能和报警功能,通知相关人员及时进行处理,保障老人的生命和财产安全。
智能家居系统并不仅仅局限于个人居住环境,还可以延伸至小区的规划与建设之中。将智慧系统运用到小区的访问系统中,可以准确记录小区每天的进出的居民,并且检测进出居民的身体状况。不仅可以更好保障居民的生命和财产安全,还可以减少安保人员的工作量。例如,在后疫情时代,建设小区智慧访问系统,不仅可以减少居民因为相互接触而交叉感染的风险,还可以及时有效的检测居民的体温和相关身体健康指标。
在未来,智能家居会得到广泛的运用,并为提高人们的居住环境贡献自己的一份力量,极大的增强人们的幸福感和获得感。但是,现阶段的智能家居系统还比较零散,建设整体的智能家居环境费用还较高,家庭经济收入一般的家庭还很难接收它。并且该系统还需要有完善的维修团队。它有可能先建设于一线和二线等经济较发达的地区,但还很难下放到三线或者四线城市。
因此,需要更多的研究人员参与到智能家居的开发研究中来,推动智能家居的发展。
所学的主控芯片主要有MCS-51系列、AT89S5x系列和STM32F10x系列三种。
MCS-51系列:由Intel公司推出,具有8位CPU,基本能满足研究开发项目的需求。但是存在运算精度不足(乘除运算)以及I/O口作为输出引脚使用时不具有驱动能力等缺点。另外,它的运行速度较慢。但是MCS-51系列对新手来说,更容易入门。因此,仍然具有很大的教学和使用价值。
AT89S5x系列:由美国Atmel推出,属于8位微控制器,将FLASH ROM技术运用于片内ROM,兼容性广。
STM32F10x系列:由意法半导体集团推出,具有性能高、精度高等特性。
结合实际的学习过程中,个人使用STM32F10x系列单片机解决实际问题较多,对其相对熟悉。因此,本次设计的主控芯片采用STM32F10x系列的STM32F103ZET6。
uCOS-II:具有可固化、可剪切性、多任务、可移植性和可剥夺等等特点。可利用任务的创建和优先级抢占执行函数块,简化编程并在一定程度上增强其可读性。但是由于同一时间只能执行一个任务,所以存在程序执行慢的缺点。
Linux:属于类Unix操作系统,具有多CPU、多任务等特点。与uCOS-II操作系统相比,具有执行速度更快的特点。
由于没有接触过Linux操作系统的使用,结合uCOS-II操作系统的优点。因此,本次设计采用uCOS-II操作系统为主,进行程序的编写。
本文内容主要介绍基于阿里云的简易智能家居系统的设计以及相关内容。
第一章概述主要介绍选题来源、选题背景、设计现状、部分技术方案的比较和选择等。并且简要描述本文的结构安排。
第二章从整体出发,介绍本次设计的总体设计。从全局把握设计的整体思路和技术方案。
第三章介绍系统的硬件构成。
第四章具体介绍本次设计的软件设计。
总结是进步最好的良药之一。第五章从整体出发,对本次设计进行简要的总结。
本次设计需要实现对湿度、温度、光照强度和烟雾浓度的检测及显示,并且利用MQTT模块连接并上传数据至阿里云。本设计采用STM32F103ZET6为核心控制器,配置了温湿度、光照度及烟雾浓度等传感器检测家庭中的相关环境参数,实现信息的采集与显示功能。利用WIFI实现测量数据的无线传输,将相关参数显示到APP上。通过编写阿里云平台的设置软件和APP程序,实现云端及手机移动终端上显示环境参数、家居设备的工作状态的功能,同时可以远程遥控灯具开关。
硬件系统总体框图如图2.1所示。
图2.1 硬件系统总体框图
软件的总开发环境为MDK5,并且主要利用uCOS-II系统编写和调试程序。下载程序到单片机时借助软件FlyMcu。在阿里云的物联网平台上进行网页和APP的编辑及生成。
软件的主要控制逻辑如图2.2所示。首先,对各模块进行初始化(控制模块已经能正常工作),随后各传感器模块开始采集数据,随即通过数模转换处理后将数据传至单片机处理(此时数据已经可以显示在LCD屏上),再通过MQTT连接并将数据上传至阿里云,将数据显示在APP上。手机终端通过阿里云连接,可以实现查看家庭环境测量数据和控制状态的功能。
图2.2 软件总流程图
各模块的主要功能为:
初始化模块:使能配置的资源,使各模块开始工作;
数据采集模块:通过传感器采集当前环境的相关数据;
ADC模块:数模转换;
WIFI模块:连接手机,将数据显示于APP上;
MQTT模块:连接服务器以及订阅阿里云的相关报文,实现数据的上传和下发;
阿里云:在阿里云提供的物联网平台上进行网页和APP的编辑和生成;
控制模块(红外、按键、APP):通过动作实现对设备的控制(例如,LED灯的开和关);
显示模块:在LCD屏和APP上显示当前环境的相关情况。
温湿度测量采用DHT11数字式温湿度传感器。其内部已经完成了数据校准,且输出的是数字信号、通过输出一串0和1组成的数据表示温度和湿度。使用时将VCC(连接电源)、GND(连接地)、DATA(数据引脚)连接到单片机的IO端口PG11,传感器接线电路图如图3.1所示。其数据格式为:
8bit湿整+8bit湿小+8bit温整+8bit温小+8bit校验和。
当数据传送无误时,校验和的数据格式为:
8bit校验和=8bit温整+8bit温小+8bit湿整+8bit湿小。
图3.1 温湿度检测电路
MQ2传感器属于二氧化锡气敏元件,导电率随着烟雾浓度提高而减小,相应的电阻值就越大。另外,气敏器件又是电传感器件,可以将烟雾的浓度转换为相应的电信号。图3.2为测量烟雾浓度的检测电路,测量的电压值接入单片机的端口PC1。
图3.2 烟雾浓度检测电路
光照强度传感器利用了光敏电阻的内光电效应,其阻值随光照强度发生变化。本次设计采用的光敏电阻的阻值随光强增加而增加,图3.3为其电路接线图。光敏电阻上的电压值对应了代表光照强度的电阻值。该电压接入单片机的PA5端口,经ADC处理后转化为光照强度值。
图3.3 光照强度检测电路
(1)红外信号的格式
红外信号本质是38KHZ的载波信号。本文采用的红外信号数据格式为(引导码+数据+结束码):
a.引导码:9毫秒的载波信号+4.5毫秒非载波信号;
b.数据1:0.56毫秒的载波信号+1.69毫秒非载波信号;
c.数据0:0.56毫秒的载波信号+0.56毫秒的非载波信号。
(2)红外信号的接收电路
红外信号接收电路如图3.4所示。HS0038是红外接收探头,用于接收红外脉冲信号,并转换为TTL电平的编码。解调后的红外信号经PA1端口接入单片机。
图3.4 红外接收电路图
图3.5所示为WIFI模块的接线图。图中将WIFI发送和接收管脚分别连接在串口的接收和发送管脚,在串口上发送AT指令,WIFI模块就会执行所发的指令的动作(本次用于设计的WIFI模块仅支持2.4G网络)。该模块通过AT指令完成数据传输的操作。
图3.5 WIFI模块接线图
部分指令见表3.1和表3.2。
表3.1 AT指令
指令 |
AT |
AT+RST |
ATE |
AT+UART |
AT+CWMODE |
描述 |
测试AT启动 |
重启模块 |
开关回显功能 |
UART配置 |
设置WIFI模式 |
表3.2 TCP相关指令
指令 |
AT+CWMODE |
AT+CWJAP |
AT+CIPSTART |
AT+CIPMODE |
描述 |
工作模式 |
连接那个热点 |
连接服务器 |
设置传输模式 |
其中:
AT+CWMODE=x,其中x取值1、2、3(1:Station、2:Ap、3:Station+Ap);
AT+CWJAP=“A”,“B”(A:热点名称、B:热点密码);
AT+CIPSTART=type,remote IP,remote port (type使用TCP);
AT+CIPMODE=x,x取值为1、0(1:透明传输、0:普通传输)。
LCD利用背光板发光显示,可以进行画线、画点、图片和汉字等的显示。本文用于显示测量数据,其连接方式如图3.6所示。
图3.6 LCD模块接线图
软件设计主要分为两部分:一是基于MDK5的程序编写,二是基于阿里云的APP编程。在MDK5上编写程序时主要用uCOS-II操作系统,程序编写中计算连接服务器密码时需要用到哈希算法,文件管理时用到FatFs文件操作系统,连接阿里云时需要用到MQTT。因此本章将主要介绍传感器等硬件部分的软件编写、APP编程和MQTT编程,简要介绍MDK5、哈希算法、uCOS-II系统和FatFs操作系统。
本次设计的程序使用C语言编写,而keil拥有完整的C语言的开发方案,并且具有集成的开发环境,是使用C语言编写调试程序的不二之选。另外,keil发展至今拥有众多版本,但是每个新的版本基本都能兼容之前的旧版本,但是使用旧版本编写的程序不一定能在所有的新版本上使用。因此,本次选用的版本是keil5。
哈希算法实质上是一计算机程序,哈希表则是以“键-值”存储数据的结构。通过不同的构造方法得到不同的哈希函数,从而产生不同的哈希算法,不同的哈希算法一般是指其运算的速度和安全性等。
哈希算法只能加密而不能解密的特点在一定程度上决定了其用途。哈希算法用于区块链中可以提高存取的效率,用于货币加密中可以提高可靠性。
本系统设计软件时,将哈希算法用于计算连接服务器的密码。本次设计编写的哈希算法的函数原型为:
void utils_hmac_sha1(const char *msg, int msg_len, char *digest, const char *key, int key_len);
在程序编写时利用uCOSII操作系统创建任务,再给每一个任务设置不同的优先级,由此简化程序的编写。由于uCOSII操作系统具有可移植的特点,因此使用前首先将其移植到本次设计的工程中。其移植的一般过程为首先在官网下载源码并解压,然后一个新建工程,将源码加入工程文件夹中并在工程中添加头文件路径。最后,修改相关函数以及相关定义。
在本次程序编写时,主要使用的任务相关函数有任务创建函数、任务挂起函数和任务删除函数。这些函数的使用格式分别为:OSTaskCreate(a,b,c,d)、OSTaskSuspend(d)、OSTaskDel(d)。
通常SD卡中需要存放很多文件,且每个文件有一个读取地址和一个写地址。读取文件时一般需要读取其地址和大小,当SD卡中存储文件过多时,读取速度就会很慢。
根据C89编写的FatFs文件操作系统具有独立于平台,小且可移植的特点,这就使得其可以嵌入微控制器和单片机中用于管理文件。即可以将FatFs文件操作系统看作一个文件管理工具。
FatFs文件操作系统的移植过程一般为首先在官网下载并解压源码,然后将解压后的源码文件夹添加至本次设计的工程文件夹中并在工程中添加源码的路径,再将FatFs文件的头文件路径添加至主函数的头文件处,最后修改相关函数和语句。FatFs模块提供的部分API函数如表4.1所示。
表4.1 API函数
函数 |
f_mount |
f_open |
f_close |
f_read |
f_write |
描述 |
注册/注销工作区 |
打开文件 |
关闭文件 |
读取文件 |
写文件 |
MQTT是一个客户服务端架构的发布/订阅模式的消息传输协议。客户端可以利用MQTT进行诸多操作。例如,本次软件设计中利用MQTT连接并上传数据至阿里云。MQTT协议有固定的帧格式:固定报头(固定数字+剩余长度)+可变报头(固定的参数)+有效负载(发送的数据)。其中,剩余字节长度为可变报头的长度和有效负载的长度之和,且剩余长度的所有字节的最高位均不参与计算。剩余字节长度计算举例如下:
0x80 0x01:剩余长度=0+1*128=128
0x81 0x01:剩余长度=1+1*128=129
0x82 0x01:剩余长度=2+1*128=130
MQTT发送消息具有严格的等级划分,一般为Qos0(无论是否成功,消息最多发送一次)、Qos1(消息至少成功发送一次)和 Qos2三个等级。
另外,MQTT使用时,必须借助其各种具体协议连接服务器,收发消息和订阅相关主题。本文主要介绍MQTT的三个协议,分别是CONNECT协议(连接阿里云服务器)、PUBLISH协议(发送数据至阿里云)、SUBCRIBE协议(订阅阿里云的通信主题)。其具体介绍分别见表4.2、表4.3、表4.4、表4.5、表4.6。其中,PUBLISH协议、SUBCRIBE协议和CONNECT协议的有效负载分别为:阿里云的Json数据格式、主题自身加主题长度加一个字节0、ClientID_Len(2byte)+ClientID+DUserNameLen(2byte)+UserName+PassWordLen(2byte)+PassWord。PUBLISH协议的可变报头为:主题自身加主题长度。
表4.2 CONNECT协议固定报头
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte1 |
MQTT报文类型(1) |
保留位 |
||||||
0 |
0 |
0 |
1 |
0 |
0 |
0 |
0 |
|
byte2 |
剩余长度 |
表4.3 CONNECT协议可变报头
Bit |
说明 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte1 |
长度(0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte2 |
长度(4) |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
0 |
byte3 |
‘M’ |
0 |
1 |
0 |
0 |
1 |
1 |
0 |
1 |
byte4 |
‘Q’ |
0 |
1 |
0 |
1 |
0 |
0 |
0 |
1 |
byte5 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
byte6 |
‘T’ |
0 |
1 |
0 |
1 |
0 |
1 |
0 |
0 |
表4.4 PUBLISH协议的固定报头
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte1 |
MQTT控制报文类型 (3) |
DUP |
QoS-H |
QoS-L |
RETAIN |
|||
0 |
0 |
1 |
1 |
X |
X |
X |
X |
|
byte2 |
剩余长度 |
表4.5 SUBCRIBE协议的固定报头
Bit |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
byte1 |
MQTT控制报文类型(8) |
保留位 |
||||||
1 |
0 |
0 |
0 |
0 |
0 |
1 |
0 |
|
byte2 |
剩余长度 |
表4.6 SUBCRIBE协议的可变报头
描述 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
|
报文标识符 |
|||||||||
byte1 |
报文标识符MSB(0) |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
0 |
byte2 |
报文标识符LSB(10) |
0 |
0 |
0 |
0 |
1 |
0 |
1 |
0 |
报文总览为固定报头、可变报头和有效负载三者的十六进制数的组合,利用报文总览可以实现以上三个协议的具体功能。本次设计的实测报文数据如下所示:
连接报文:10 74 00 04 4D 51 54 54 04 C2 00 3C 00 2A 20 48 57 5F 50 34 30 20 7C 73 65 63 75 72 65 6D 6F 64 65 3D 33 2C 73 69 67 6E 6D 65 74 68 6F 64 3D 68 6D 61 63 73 68 61 31 7C 00 12 48 57 5F 50 34 30 26 61 31 48 72 37 4D 69 71 31 4F 37 00 28 34 63 63 34 63 61 38 36 31 31 38 62 33 65 36 38 63 38 31 64 39 38 30 31 30 38 32 61 62 61 62 34 64 61 33 64 65 37 37 34
发布报文:30 DE 01 00 31 2F 73 79 73 2F 61 31 48 72 37 4D 69 71 31 4F 37 2F 48 57 5F 50 34 30 2F 74 68 69 6E 67 2F 65 76 65 6E 74 2F 70 72 6F 70 65 72 74 79 2F 70 6F 73 74 7B 0D 0A 09 22 69 64 22 3A 22 32 33 30 37 38 38 30 32 39 22 2C 0D 0A 09 22 6D 65 74 68 6F 64 22 3A 22 74 68 69 6E 67 2E 65 76 65 6E 74 2E 70 72 6F 70 65 72 74 79 2E 70 6F 73 74 22 2C 22 70 61 72 61 6D 73 22 3A 7B 20 20 0D 0A 09 09 09 22 43 75 72 72 65 6E 74 48 75 6D 69 64 69 74 79 22 3A 32 32 2C 0D 0A 09 09 09 22 43 75 72 72 65 6E 74 54 65 6D 70 65 72 61 74 75 72 65 22 3A 34 39 2C 0D 0A 09 09 09 22 52 65 6C 61 79 22 3A 30 0D 0A 09 09 7D 2C 0D 0A 09 22 76 65 72 73 69 6F 6E 22 3A 22 31 2E 30 22 0D 0A 7D 0D 0A
订阅报文:82 37 00 01 00 32 2F 73 79 73 2F 61 31 48 72 37 4D 69 71 31 4F 37 2F 48 57 5F 50 34 30 2F 74 68 69 6E 67 2F 73 65 72 76 69 63 65 2F 70 72 6F 70 65 72 74 79 2F 73 65 74 00
阿里云专注于通过在线公共服务的方式,提供安全可靠的数据处理和计算能力,其下提供诸多平台供用户使用,例如物联网平台、大数据、云通信等。本次设计利用阿里云的物联网平台提供的Iot Studio接口编辑网页,在可视化应用中编辑并生成APP。
4.6.1 阿里云物联网平台的使用
(1)获得阿里云平台的使用权:实名注册阿里云账号→物联网与云通信→物联网平台→立即开通;
(2)创建产品:产品→创建产品→设置产品信息→保存;
(3)给产品添加功能:产品→功能定义→编辑草稿→添加自定义功能→设置功能信息→保存→发布;
(4)创建设备:设备→添加设备→编辑设备基本信息(选择所属产品、设备名称)→确认(此时的产品处于未激活状态);
(5)利用软件MQTT.fx激活产品
a.MQTT.fx连接设备的凭证(三元组):设备→查看→一键复制;
b.设置软件MQTT.fx的属性:设置属性(Profile Name、Profile Type、MQTT Broker、Broker Adress、Broker Port(1883)、Client ID、User Name、Pass Word)→Apply→Connect;
(6)阿里云与设备通信(通过Topic实现通信):产品的Topic列表下的物模型通信Topic中含有发布消息、回复消息等一系列主题。在MQTT.fx中订阅阿里云的相应主题,实现阿里云数据的上传和下发。
本次设计的三元组、域名、Client ID、User Name、Pass Word、阿里云的数据格式以及订阅主题如下所示:
三元组:
{
"ProductKey": "a1Hr7Miq1O7",
"DeviceName": "HW_P40",
"DeviceSecret": "ea8164d584f924be42c772db214373c4"
}
域名:a1Hr7Miq1O7.iot-as-mqtt.cn-shanghai.aliyuncs.com;
Client ID:HW_P40 |securemode=3,signmethod=hmacsha1|;
User Name:HW_P40&a1Hr7Miq1O7;
Pass Word:4cc4ca86118b3e68c81d9801082abab4da3de774;
发布主题:/sys/a1Hr7Miq1O7/HW_P40/thing/event/property/post;
下发主题
主动:/sys/a1Hr7Miq1O7/HW_P40/thing/service/property/set
被动:/sys/a1Hr7Miq1O7/HW_P40/thing/event/property/post_reply
阿里云的数据格式:
{
"id":"230788029",
"method":"thing.event.property.post","params":{
"CurrentHumidity":22,
"CurrentTemperature":49,
"MQ2":200,
"GM":2000,
"Relay":0
},
"version":"1.0"
}
4.6.2 阿里云网页在线编程
(1)编辑网页基本信息:Iot Studio→项目管理→新建项目→创建空白项目→编辑项目基本信息(项目名称)→Web应用→新建→设置应用基本信息→确定→编辑页面信息(页面名称、背景图片等)→组件→编辑组件的基本信息(大小、名称、背景色、展示格式、透明度等);
(2)首页跳转至属性页面:在首页中放一个图片组件→点击该组件→属性界面→交互→新增交互→设置交互基本信息(事件设置为“点击”、动作设置为“打开链接”、链接打开方式为“当前页面”、目标链接为“属性页面”)→确定;
(3)在页面上显示阿里云数据:组件→图表→仪表盘→设置仪表盘的基本信息(名字,如:温度、湿度、烟雾浓度、光照强度等)→展示数据→配置数据源→选择数据源→选择产品→产品管理→关联物联网平台产品→华为_P40(选中关联产品同时关联其下所有设备)→确定→再次点击配置数据源→选择产品华为_P40→设备→指定设备→HW_P40→属性→选择已经存在的属性(继电器、当前温度、当前湿度、烟雾浓度、光照强度)→确定→保存页面→(此时各项数据与阿里云保持同步,可以用MQTT.fx查验)→应用发布生效。
4.6.3 阿里云APP在线编程
(1)进入移动应用开发页面:Iot Studio→项目管理→点击华为_P40→复制此主页网址中以a123开头的字符串→将字符串替换到移动应用开发的网址中→点击网址跳转到移动应用开发的页面→选择可视化应用→新增可视化应用→编辑APP的基本信息(应用名称、所属项目、选择模板)→完成(自动跳转到编辑页面);
(2)编辑控制页面:UI组件→界面模板→编辑模板基本信息(背景图片、组件名称、背景色、对齐方式等);
(3)使开关与阿里云数据关联:UI组件→点击容器→选择容器方向→在容器中放一个卡片组件和一个开关组件→点击卡片组件→编辑卡片的基本信息(背景、文字、主标题为“继电器”、动态文本等)→点击开关组件→配置数据(选择产品、选择设备、选择属性为“继电器”)→确定(此时开关组件的数据和阿里云数据相关联);
(4)编辑属性页面(温湿度页面、光照强度和烟雾浓度页面),具体操作流程与控制页面一致;
(5)使编辑的APP页面与实际APP关联:点击页面→列表页→新增页面入口(自动跳转到列表页配置页面)→编辑列表页1(标题为“继电器”、描述、图标、跳转链接为“控制页面”)→确定→新增列表页2(标题为“温湿度”、描述、图标、跳转链接为“属性页面”)→新增列表页3(标题为“光强和烟雾浓度”、描述、图标、跳转链接为“属性页面”)→确定→保存;
(6)生成APP:点击账号→设置账号的基本信息(用户别名、用户登录手机、登陆密码)→确定(增加用户成员)→点击编辑→选择右侧Android构建→选择构建用途(选中我只想自己使用)→输入构建信息(点击随机生成)→下一步→构建成功→扫描二维码下载。
环境参数的检测由各类传感器完成。传感器采集的各类电压信号经ADC转换为数字信号(其中,因DHT11是数字传感器,不需要进行模数转换)。
单片机与DTH11的收发数据主要依靠数据引脚。当单片机主动发出请求后,DTH11的数据引脚被拉高或拉低。该数据引脚连接到单片机的PG11引脚,同时需要对该引脚配置两种工作模式,分别是推挽输出和浮空输入,其温湿度测量程序流程如图4.1所示。
图4.1 DHT11程序流程图
温湿度检测主要程序代码:
void DHT11_Task(void * prg)
{
char tmp_buf[32];
while(1)
{
OSTimeDly(2000);
Get_DHT11_Value();
Ali_data.CurrentTemperature=dht11_value_buf[2];
Ali_data.Humidity=dht11_value_buf[0];
}}
当烟雾传感器接触烟雾时,由于导电率变化引起电阻值变化,使电阻R39、R34中间输出值将发生改变。因此将烟雾浓度连接到单片机的PC1引脚,并将该引脚的工作模式配置为模拟输入。将模拟量转化为数字量需要ADC模块的参与,因此配置了ADC2。
类似的,电阻R19和光敏电阻R22串联组成的光照检测电路中,当光照强度改时,两者之间的比值也将发生变化,因此将电路标号为ILLV VAL的端口接至单片机的PA5引脚,并将该引脚配置也为模拟输入。与烟雾浓度传感器一样,需要ADC处理。因此,配置了ADC1。
光强和烟雾浓度检测和显示的程序流程图见图4.2。
图4.2 GM和MQ2程序流程图
光强和烟雾浓度检测主要程序代码如下:
void GM_Task(void *prg)
{
char gm_buf[32];
while(1)
{
OSTimeDly(1000);
ADC_SoftwareStartConvCmd(ADC1,ENABLE);//开启转换
ADC_SoftwareStartConvCmd(ADC2,ENABLE);//开启转换
while(ADC_GetFlagStatus(ADC1,ADC_FLAG_EOC)==0);
while(ADC_GetFlagStatus(ADC2,ADC_FLAG_EOC)==0);
GM_Value = ADC1->DR;
MQ2_Value = ADC2->DR;
Ali_data.GM=GM_Value;
Ali_data.MQ2=MQ2_Value;
}
}
WIFI模块与单片机的串口连接,配合AT指令使用。WIFI模块和串口通信需要连接对应的引脚,要求引脚具有复用功能。单片机的PB10、PB11都可以与USTRT3复用。因此,将PB10和PB11的工作模式分别配置为复用推挽输出和浮空输入。其中,PB10连接串口3的TX引脚和WIFI模块的RXD引脚;PB11连接串口3的PX引脚和WIFI模块的TXD引脚。另外,WIFI模块使用前必须进行使能,将该模块标号为ESP-EN的端口号连接到主控芯片的PE6引脚,并将该引脚的工作模式配置为推挽输出拉高。
WIFI模块程序配置流程见图4.3。
图4.3 WIFI模块程序流程图
WIFI模块设置主要函数为:
a.void UART2_Config(u32 baud_rate); //串口和引脚初始化
b.void USART3_IRQHandler(void); //中断服务函数
c.uint8_t Check_Esp8266(void); //检测WIFI是否正常
d.void Init_Esp8266(void); //初始化WIFI模块
e.uint8_t ConnectServer(char* mode,char* ip,uint16_t port); //连接服务器
红外信号通过定时器捕获,所连接的GPIO口需要具备与定时器的复用功能,A端口的PA1是能与TIM5的通道2复用的GPIO口。因此,将引脚PA1配置为浮空输入以捕获红外信号。另外,红外信号捕获完成后,定时器产生溢出,随即进入中断服务函数,所以还需要将定时器本身的中断打开。其设置流程见图4.4所示。
图4.4 红外模块程序流程图
红外模块主要程序代码:
void Ir_Task(void *prg)
{
while(1)
{
IR_analysis();
if(ir_data[2]==0x45&&ir_data[3]==0xBA)
{
ir_data[2]=0;ir_data[3]=0;
Ali_data.Relay=!Ali_data.Relay;
RELAY(Ali_data.Relay);
LED1(Ali_data.Relay);LED2(Ali_data.Relay);
LED3(Ali_data.Relay);LED4(Ali_data.Relay);
SEN_STATE=1;
}
OSTimeDly(20);
}
}
红外遥控编码:
红外遥控编码(NEC格式):引导码(9ms+4.5ms)+16位客户代码(8位数据代码+8位取反的数据代码)+结束码(0.56ms)。例如,{0x00,0xFF,0x45,0xBA}是遥控上“开”、“关”按键的数据码。转化位二进制形式,如下所示:
0x00: 0000 0000
0xFF: 1111 1111
0x45: 0100 0101
0xBA: 1011 1010
这一组数据再加上引导码和结束码共67个时间,捕获到这67个时间就可以解析出该按键的数据,从而实现红外控制。
到目前为止,硬件和软件部分已经基本完成,网页和APP已经成功发布,如图4.5、图4.6、图4.7、图4.8所示。另外,系统已经够实现检测数据并显示在LCD屏和APP上,具体效果见附录1。
图4.5 网页控制页面
图4.6 网页属性页面
图4.7 创建的设备
图4.8 APP发布图
最终的设计结果基本能满足设计要求,但是也存在不尽人意的地方。例如,用APP控制灯具的开和关,本次设计只能实现用LED灯模拟实际的设备,但是实际的家电工作所需的电压和模拟的存在差异。预计的改进措施是外扩一个继电器,从而实现强电控制家电的效果。另外,本次设计中存在一个光控灯的模块,设计时采用的是通过调节占空比改变灯的亮度,但是实际的光控灯基本是通过调节电压或电流的大小控制灯的亮度。预计的改进措施是,首先外扩一个继电器,使其可以控制实际的灯具,再通过查表法,提前记录不同光照强度时电流或电压的大小,从而使灯光亮度随光照强度变化。最后,由于阿里云升级后,不再免费提供可视化应用的编辑功能,所以已经发布的应用不能再修改,所以本次设计的APP只能按照初次设定的一个开关控制4个LED灯。预计修改的举措为,开通付费功能,再完善相应功能。
本次毕业设计涉及的知识面很广。不仅用到了大一学习的C程序涉及和计算机应用基础,大二学习的微机原理、模拟电路和数字电路,还用到了大三学习的的单片机原理和嵌入式系统的知识。经过大学四年的学习,我才明白当初认为没有什么用处的课程是进一步学习的基础,所学的知识由零散渐渐汇成系统,融为一个整体。
化繁为简是处理问题的有效方法之一。我将本次设计内容大致分为LCD显示模块,阿里云APP设计模块和软件设计模块。将整体划分为诸多小的部分,每个模块分别实现功能,最后再将这些模块整合到一起。
从确定题目、资料收集、方案设计、可执行分析到实物设计和论文书写花费大约3个月时间。本次设计内容偏向于软件设计,而软件设计又主要分为两部分,一是编写各模块的程序,二是基于阿里云的APP编程。在设计时,我首先完成了各模块程序的设计,再进行了APP的在线编程,完成实物设计后开始书写论文,论文书写按照概述、总体介绍、硬件、软件的大致流程书写。
原本想在该系统中增加语音交互功能和报警功能,但是由于现阶段个人时间和能力有限,设计的只是简易的系统。希望有以后机会能完善丰富本次设计的内容,也希望智能家居行业能得到进一步的发展,能更好的为社会服务,增强人们的幸福感和获得感。
※※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
附录1:效果展示图
控制页面图
属性页面图1
首页图
属性页面图2
附录2:主要程序代码
主函数 功能:程序入口、创建任务
int main(void)
{
All_Init(); //各部分初始化
OSInit();
OS_CPU_SysTickInit(); //系统时钟初始化
OSTaskCreate(Key_task,NULL,&KEY_STACK[127],23); //创建按键任务
OSTaskCreate(rgb_task,NULL,&RGB_STACK[127],18); //创建RGB任务
OSTaskCreate(USART_Ctrl_LED_Task,NULL,&USART_STACK[127],14); //创建LED任务
OSTaskCreate(DHT11_Task,NULL,&DHT11_STACK[127],11); //创建温湿度检测任务
OSTaskCreate(GM_Task,NULL,&GM_STACK[127],9); //创建光照强度和烟雾浓度任务
OSTaskCreate(Ir_Task,NULL,&IR_STACK[127],7); //创建红外任务
OSTaskCreate(Ali_Data_Elec_Task,NULL,&Ali_Elec_Task[127],5); //创建阿里云数据回显任务
OSTaskCreate(Ali_Data_Send_Task,NULL,&Ali_Send_Task[127],33); //创建阿里云数据发送任务
OSTaskCreate(Pic_Task,NULL,&PIC_TASK[511],37); //创建图片显示任务
OSStart();
while(1) //任务固定的死循环
{
}
}
显示函数、光控灯函数 功能:显示图片和数据、控制光强
int gm_val=0;
u8 PIC_FLAG=0;
void Pic_Task(void * prg)
{
char tmp_buf[32];
char gm_buf[32];
while(1)
{
if(GM_run[0]2600 && gm_val<2800 )
TIM4->CCR1 = 20;
else if(gm_val>1600&&gm_val<1800)
TIM4->CCR1 = 400;
else if(gm_val<800)
TIM4->CCR1 = 900;
};
}
if(PIC_FLAG == 1)
{
PIC_FLAG = 0;
JPG_ShowFunc("0:2.jpg",0,0);
sprintf(tmp_buf,"T==%dRH==%d",dht11_value_buf[2],dht11_value_buf[0]); //温湿度显示
Show_Sting(0,0,0,0xF800,(u8 *)tmp_buf);
}else if(PIC_FLAG == 2)
{
PIC_FLAG=0;
JPG_ShowFunc("0:2.jpg",0,0);
sprintf(gm_buf,"GM == %d ",GM_Value); //光照强度显示
Show_Sting(0,0,0,0xF800,(u8 *)gm_buf);
}else if(PIC_FLAG == 3)
{
PIC_FLAG=0;
JPG_ShowFunc("0:3.jpg",0,0);
sprintf(gm_buf,"MQ2 == %d ",MQ2_Value); //烟雾浓度显示
Show_Sting(0,0,0,0xF800,(u8 *)gm_buf);
}
OSTimeDly(10);
}
}
阿里云初始化函数 功能:获取用户端信息
void AliIoT_Parameter_Init(void)
{
char temp[128]; //计算加密时临时使用的缓冲区
memset(ClientID,128,0); //客户端ID的缓冲区全部清零
sprintf(ClientID,"%s|securemode=3,signmethod=hmacsha1|",DEVICENAME); //构建客户端ID,并存入缓冲区
ClientID_len = strlen(ClientID); //计算客户端ID的长度
memset(Username,128,0); //用户名的缓冲区全部清零
sprintf(Username,"%s&%s",DEVICENAME,PRODUCTKEY);
//构建用户名,并存入缓冲区
Username_len=strlen(Username); //计算用户名的长度
memset(temp,128,0); //临时缓冲区全部清零
sprintf(temp,"clientId%sdeviceName%sproductKey%s",DEVICENAME,DEVICENAME,PRODUCTKEY); //构建加密时的明文
utils_hmac_sha1(temp,strlen(temp),Passward,DEVICESECRE,DEVICESECRE_LEN); //以DeviceSecret为秘钥对temp中的明文,进行hmacsha1加密,并将结果保存到缓冲区中
Passward_len=strlen(Passward); //计算用户名的长度
memset(ServerIP,128,0);
sprintf(ServerIP,"%s.iot-as-mqtt.cn-shanghai.aliyuncs.com",PRODUCTKEY); //构建服务器域名
ServerPort=1883; //服务器端口号1883
printf("服 务 器:%s:%d\r\n",ServerIP,ServerPort); //串口输出调试信息
printf("客户端ID:%s\r\n",ClientID); //串口输出调试信息
printf("用 户 名:%s\r\n",Username); //串口输出调试信息
printf("密 码:%s\r\n",Passward); //串口输出调试信息
ConnectServer("TCP",ServerIP,ServerPort);
}
连接服务器函数 功能:连接服务器
void MQTT_ConectPack(void)
{
Fixed_len=2; //连接报文中,固定报头长度=2
Variable_len=10; //连接报文中,可变报头长度=10
Payload_len = 2 + ClientID_len + 2 + Username_len + 2 + Passward_len;
//总报文长度
memset(usart2_tx_buff,0,512);
usart2_tx_buff[0]=0x10; //第1个字节 :固定0x01
usart2_tx_buff[1]=Variable_len + Payload_len;
//第2个字节 :可变报头+有效负荷的长度
usart2_tx_buff[2]=0x00; //第3个字节 :固定0x00
usart2_tx_buff[3]=0x04; //第4个字节 :固定0x04
usart2_tx_buff[4]=0x4D; //第5个字节 :固定0x4D
usart2_tx_buff[5]=0x51; //第6个字节 :固定0x51
usart2_tx_buff[6]=0x54; //第7个字节 :固定0x54
usart2_tx_buff[7]=0x54; //第8个字节 :固定0x54
usart2_tx_buff[8]=0x04; //第9个字节 :固定0x04
usart2_tx_buff[9]=0xC2; //第10个字节:使能用户名和密码校验,不使用遗嘱,不保留会话
usart2_tx_buff[10]=0x00; //第11个字节:保活时间高字节 0x00
usart2_tx_buff[11]=0x64; //第12个字节:保活时间高字节 0x64 100s
usart2_tx_buff[12] = ClientID_len/256; //客户端ID长度高字节
usart2_tx_buff[13] = ClientID_len%256; //客户端ID长度低字节
memcpy(&usart2_tx_buff[14],ClientID,ClientID_len); //复制过来客户端ID字串
usart2_tx_buff[14+ClientID_len] = Username_len/256; //用户名长度高字节
usart2_tx_buff[15+ClientID_len] = Username_len%256; //用户名长度低字节
memcpy(&usart2_tx_buff[16+ClientID_len],Username,Username_len); //复制过来用户名字串
usart2_tx_buff[16+ClientID_len+Username_len] = Passward_len/256;
//密码长度高字节
usart2_tx_buff[17+ClientID_len+Username_len] = Passward_len%256; //密码长度低字节
memcpy(&usart2_tx_buff[18+ClientID_len+Username_len],Passward,Passward_len); //复制过来密码字串
Usart2_Send_Buf(usart2_tx_buff, Fixed_len + Variable_len + Payload_len); //加入发送数据缓冲区
}