在正式讲解之前,先来总结一下。该项目是对大学学过的部分知识进行整合,同时这也是我大学的毕业设计,也算是对大学的一个交待。
首先来讲述一下该项目具体实现了哪些功能,方便大家理清思路。该项目拥有四种控制方式,分别是语音识别、触摸屏、小程序、APP,而控制的对象是家用电器(这里利用一个多路继电器来模拟家用电器)。
这四种控制方式还能对采集的数据进行反馈显示:
在语音识别方面,语音模块识别到特定的关键词语后,会将采集到的温湿度数据通过语音播报模块进行播报反馈;
在触摸屏和APP方面,将采集到的温湿度、有害气体浓度、光照强度显示在触摸屏上,还可以设置湿度和有害气体浓度的阈值(湿度阈值的设置是当湿度超过设定阈值时,表明室外下雨了,让窗户自动关闭(这样也是利用一路继电器来模拟窗户的打开与关闭);有害气体浓度阈值的设置是当浓度超过设定阈值时,表明屋内有害气体浓度过高,让语音播报"煤气含量过高,请及时处理"来达到警示的目的),最后还能设置是否开启安防模式,在安防模式下,会通过人体感应模块不断检测周围是否有人,如果有人的话,蜂鸣器就会报警警示,同时在APP和小程序上也会改变相对应的图标。
在小程序方面,除了可以显示采集到的数据和控制用电器之外,这里还可以显示当地的天气状态。
APP的远程控制可参考我之前写的文章:stm32+esp8266+onenet平台
小程序的远程控制可参考我之前写的文章:stm32利用mqtt与小程序通信
语音识别的控制可参考我之前写的文章:stm32利用语音识别与播报智能控制led灯
触摸屏的控制可参考淘晶驰官方文档:USART HMI资料中心
本项目所用到的器件如下:
STM32F103ZET6最小系统板
ESP8266-01S模块(2个,一个用于APP,一个用于小程序)
USB转microUSB数据线
DHT11温湿度
MQ-5模块
光敏电阻模块
HC-SR505人体感应模块
BEEP蜂鸣器
语音识别与播报模块(亚博智能)
串口触摸屏(淘晶驰X3系列 4.3寸)
为了让大家更加深刻的理解器件的摆放位置,这里利用soliwork画了一个三维理想模型,里面清楚表明了器件的具体位置。如下图所示:
由于本项目需要连接的线非常多,如果采用杜邦线连接的话,会非常繁琐,所以为了简化接线,这里画了一块PCB板来代替杜邦线,整体的效果也美观了许多。如下图所示:
本项目的接线定义如下所示:
/* 接线定义
ESP8266(APP) DHT11 MQ-5 光敏电阻 HC-SR505 BEEP(有源,低电平触发)
TX->stm32 RX(PA3) VCC->stm32 3.3V VCC->stm32 5V VCC->stm32 5V VCC->stm32 5V VCC->stm32 3.3V
RX->stm32 TX(PA2) GND->stm32 GND GND->stm32 GND GND->stm32 GND GND->stm32 GND GND->stm32 GND
3.3V->stm32 3.3V DATA->stm32 PF12 AO->stm32 PA1 AO->stm32 PA4 AO->stm32 PF13 AO->stm32 PF14
GND->stm32 GND
语音识别模块 语音合成播报模块 串口屏 ESP8266(小程序)
IIC1 IIC2 TX->stm32 RX(PD9) TX->stm32 RX(PC11)
VCC->单片机5V VCC->单片机5V RX->stm32 TX(PD8) RX->stm32 TX(PC10)
SCL->单片机PB8 SCL->单片机PB10 5V->stm32 5V 3.3V->stm32 3.3V
SDA->单片机PB9 SDA->单片机PB11 GND->stm32 GND GND->stm32 GND
GND->单片机GND GND->单片机GND
*/
再来看看设计的页面效果图:
APP界面设计:
小程序界面设计:
触摸屏界面设计:
接着附上录制的相关视频:
1.小程序登录
2.语音识别(有声)
3.数据采集
4.按键控制
5.安防检测(有声)
最后附上32程序的主代码:
#include "stm32f10x.h"
#include "onenet.h"
#include "esp8266.h"
#include "delay.h"
#include "usart.h"
#include "serial.h"
#include "led.h"
#include "dht11.h"
#include "adc.h"
#include "hc-sr505.h"
#include "beep.h"
#include "bsp_i2c.h"
#include "esp8266_mqtt.h"
#include "onenet_mqtt.h"
//C库
#include
#include
//网络卡导致发送到云平台的速度变慢
/* 接线定义
ESP8266(APP) DHT11 MQ-5 光敏电阻 HC-SR505 BEEP(有源,低电平触发)
TX->stm32 RX(PA3) VCC->stm32 3.3V VCC->stm32 5V VCC->stm32 5V VCC->stm32 5V VCC->stm32 3.3V
RX->stm32 TX(PA2) GND->stm32 GND GND->stm32 GND GND->stm32 GND GND->stm32 GND GND->stm32 GND
3.3V->stm32 3.3V DATA->stm32 PF12 AO->stm32 PA1 AO->stm32 PA4 AO->stm32 PF13 AO->stm32 PF14
GND->stm32 GND
语音识别模块 语音合成播报模块 串口屏 ESP8266(小程序)
IIC1 IIC2 TX->stm32 RX(PD9) TX->stm32 RX(PC11)
VCC->单片机5V VCC->单片机5V RX->stm32 TX(PD8) RX->stm32 TX(PC10)
SCL->单片机PB8 SCL->单片机PB10 5V->stm32 5V 3.3V->stm32 3.3V
SDA->单片机PB9 SDA->单片机PB11 GND->stm32 GND GND->stm32 GND
GND->单片机GND GND->单片机GND
*/
/* 初始化阶段不要说话,防止被语音识别到,导致语音识别卡住 */
/* 发送数据给服务器端,如果没有应答,可能是因为服务器不稳定,过段时间就好了 */
/* 在开发过程中发现,有时候明明只延时了10ms但是实际上延时了足足100ms(多了十倍),
其原因可能是:
1、外部HSE没起震,结果使用的是内部HSI,这种情况下,默认的是没有倍频的。
实际时钟速度就变成了8MHZ,而不是72MHZ,所以时间相差了接近10倍。
解决方法是重新复位,直到他外部晶振起震
2、语音识别模块使用的硬件IIC干扰到晶振的正常运行,可能是硬件设计电路的问题,
如果要想正确延时的话,必须关闭语音识别模块,若想要打开语音识别模块,则会加长延时时间
*/
extern SendData sendata;
extern unsigned short esp8266_cnt;
const char *devSubTopic[] = {"/iot/1009/zsd1"}; //适用EMQX(无需主题前缀)、杰叔叔服务器(需要指定前缀)
const char *devPubTopic = "/iot/1009/zsd2"; //适用EMQX(无需主题前缀)、杰叔叔服务器(需要指定前缀)
void Hardware_Init(void) //各种功能器件的初始化
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置
delay_init(); //systick初始化
Usart1_Init(115200); //串口1,打印信息用
Usart2_Init(115200); //串口2,驱动ESP8266用于APP
Usart3_Init(); //串口3,与串口屏通信进行数据交互
Uart4_Init(115200); //串口4,驱动ESP8266用于小程序
LED_Init(); //LED灯初始化
Device_Init(); //继电器六个IO的初始化
HC_SR505_Init(); //人体感应模块初始化
Beep_Init(); //蜂鸣器初始化
Adc_Init(); //ADC初始化
while(DHT11_Init()) //DHT11初始化
delay_ms(200);
UsartPrintf(USART_DEBUG, " Hardware init OK\r\n");
}
int main(void)
{
char array[256]; //将要发布主题的数据存储区
unsigned char *dataPtr_mqtt = NULL; //接收MQTT数据的数据包指针
unsigned short timeCount = 0; //发送间隔变量
unsigned char *dataPtr = NULL; //存储接收到的数据
u8 i = 0; //LED灯闪烁计数位
u8 j = 0; //ESP8266(APP)复位计数位
bool flag = 0; //LED取反标志位
Hardware_Init(); //初始化外围硬件
ESP8266_Init(); //初始化ESP8266(APP)
ESP8266_Init_MQTT(); //初始化ESP8266(小程序)
while(OneNet_DevLink()) //接入OneNET服务器
delay_ms(500);
while(OneNet_DevLink_MQTT()) //接入EMQX服务器
delay_ms(500);
OneNet_Subscribe(devSubTopic, 1); //MQTT的订阅主题
voice_module(); //语音模块初始化
while (1) {
if (++timeCount > 3) {//下面ESP8266_GetIPD函数执行完需要70-100ms的时间,这里计数30,表示大约3s发送一次数据;如果外部晶振不起作用,这里就设置为3也就是3s
//UsartPrintf(USART_DEBUG, "data:%d\r\n",esp8266_cnt); //判断串口2是否有数据接收到
DHT11_Read_Data(&sendata.temp,&sendata.humi); //读取温湿度值
get_ppm_lx(&sendata.ppm, &sendata.lx); //获取煤气ppm、光强lx,这个函数大概花费50ms
deal_with(); //判断湿度、煤气含量是否超阈值
OneNet_SendData(); //发送数据给云平台
sprintf(array, "{\"temp\":%.1f,\"humi\":%.0f,\"light\":%.1f,\"ppm\":%.0f,\"led1\":%d,\"led2\":%d,\
\"win\":%d,\"cur\":%d,\"fan\":%d,\"cook\":%d,\"sec\":%d,\"sec_image\":%d}", \
sendata.temp, sendata.humi, sendata.lx, sendata.ppm, sendata.light1, sendata.light2, sendata.window\
, sendata.curtain, sendata. fan, sendata.rice_cooker, sendata.security, sendata.detect);
OneNet_Publish(devPubTopic, array); //MQTT的发布主题
memset(array, 0, sizeof(array));
//发送数据给串口屏
Screen_SendData(sendata.temp, sendata.humi, sendata.ppm, sendata.lx);
timeCount = 0;
//ESP8266_Clear(); //清除esp8266_buf中的数据
}
speech_recognition(sendata.temp, sendata.humi); //判断是什么指令并给出相应的回应
data_handle(); //对串口返回的数据进行处理
if (sendata.security == 1) { //安防模式开启
if (HC_SR505 == 1) { //感应到人
sendata.detect = 1;
beep = 0; //蜂鸣器响
} else if (HC_SR505 == 0) { //感应不到人
sendata.detect = 0;
beep = 1; //蜂鸣器不响
}
} else if (sendata.security == 0) sendata.detect = 2; //安防模式关闭
//若延时正常,这里设置等待的时间为10*10ms=100ms,确保进入一次函数后能收到数据,如果返回NULL,表示暂时接收不到数据
//若延时不正常,这里可以设置等待1*10ms,虽然会使得数据在下一次才接受到,不过程序运行很快,这种的话会实时响应其他的程序代码,这里延时大概是50ms
dataPtr = ESP8266_GetIPD(10);
if(dataPtr != NULL){
OneNet_RevPro(dataPtr);
j=0;
}
dataPtr_mqtt = ESP8266_GetIPD_MQTT(1);
if(dataPtr_mqtt != NULL)
OneNet_RevPro_MQTT(dataPtr_mqtt);
i++;
j++;
if (i > 3) { //这里计数10,表示1秒;如果外部晶振不起作用,这里计数1,表示1秒;如果进入此判断LED闪烁一次,表示系统正常运行
i = 0;
flag = !flag;
LED0(flag);
}
if(j > 12){ //这里计数160,表示16秒;如果外部晶振不起作用,这里计数16,表示16秒;如果进入此判断表明设备掉线,需要重新连接
ESP8266_Init(); //这里需要等待几分钟,要等到WIFI模块彻底断开连接后,串口才会接收到WIFI模块的AT指令返回值
OneNet_DevLink();
j = 0;
}
}
}
这里主要给大家列出main程序,几乎每个函数后面都有相应的注释,里面嵌套的函数也有相应的注释,由于函数过多,这里就不一一列举出来。该项目采用BSP工程管理的思想来进行模块化,方便代码的维护。如下图所示:
本项目具体的执行流程如下图所示:
上面只是给大家提供一个大概的思路,希望对大家能有所启发。在制作该项目过程中,考虑到实时性问题,将原来裸机的代码移植到μCOS-III中,从而来提高系统的响应。
附上整个智能家居项目代码链接:智能家居系统设计(stm32/μCOS-III)
代码要的下方留言邮箱我会第一时间发给你们的,有什么问题也可以下面评论!(其中包含裸机stm32和μCOS-III两个版本)