智能家居系统设计(裸机stm32/μCOS-III)

news/2024/7/20 3:30:03 标签: stm32, μCOS-III, 小程序, APP, 语音识别

智能家居系统设计[裸机stm32/μCOS-III]

​  在正式讲解之前,先来总结一下。该项目是对大学学过的部分知识进行整合,同时这也是我大学的毕业设计,也算是对大学的一个交待。
​  首先来讲述一下该项目具体实现了哪些功能,方便大家理清思路。该项目拥有四种控制方式,分别是语音识别、触摸屏、小程序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 <string.h>
#include <stdio.h>

//网络卡导致发送到云平台的速度变慢

/*	接线定义
 	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两个版本)


http://www.niftyadmin.cn/n/1322161.html

相关文章

android学习第一天

android之View 1.继承关系 android.view.ViewGroup 继承自android.view.View , android.view.View 继承自java.lang.Object 2.布局层次 ViewGroup 内部可嵌套view 和ViewGroup ,View 内部不可嵌套. 3.View 的基本属性 android:layout.width" "//控件的宽度 andr…

Android之双击Home退出应用

private boolean homeBackfalse;//标志 private Timer timer new Timer();//定时 /* *onKeyDown() */ Override public boolean onKeyDown(int keyCode,keyEvent event){ if(keyCodeKeyEvent.KEYCODE_BACK){ if(!homeBack){ homeBacktrue;//准备退出 Toast.makeText…

Android之垂直跑马灯

此程序为电商类app中垂直轮播的广告&#xff0c; 主要借助于github 的现有封装程序 下载地址&#xff1a;https://github.com/Neilsgithub/MarqueeView 在此感谢github 感谢大神 开发工具&#xff1a;android studio 下载程序并解压后&#xff0c;可将文件夹下的DisplayUti…

Android之定时刷新数据

近期项目,要求定时刷新访问服务器获取状态,经查资料,了解到几种定时刷新数据的方式 常见的定时刷新有:Timer、 Alarm、Handle widgetapp更新中常用Alarm用的比较多&#xff0c;但有说用alarm会使系统反应变慢&#xff0c;由于急于完成项目&#xff0c;故未验证此方法。个人开…

Android之屏幕适配

第一次做屏幕适配,各种查资料,各种百度,自己现在也是一知半解,仅仅将网络上的资料简单做了测试,还要继续学习 首先,推荐几篇文章, 1、地址--->http://m.blog.csdn.net/article/details?id50564682 文章详细讲解了关于屏幕分辨率屏幕密度以及适配的一些原理 2、地址---&…

Android之获取屏幕分辨率、密度、尺寸

在实际应用中&#xff0c;为了适配屏幕&#xff0c;要知道所用的手机的分辨率。 本篇文章借鉴于http://blog.csdn.net/lincyang/article/details/42679589 并应用于实际项目中&#xff0c;得到了很大的帮助&#xff0c;感谢该博主的分享 1.获取分辨率 Android 早期的版本可…

Android之Activity销毁

需求:在一个Activity中需要销毁另一个Activity,方法有以下几种 1、onStop() 在A_Activity的onStop方法中添加finish(); 在跳转到另一个Actiity时会销毁A_activity 2、定义全局变量 A_Activity类中 public static A_Activity instance null; onCreate(){ instance this…

Android之Activity的启动模式

在AndroidManifest.xml中可配置Activity的启动模式 <activity android:name "com.mainActivity" android:launchMode "singleInstance"> </activity> Android系统中我们创建的activity都是以栈的形式呈现 每个应用都有独立的任务栈Tas…