文章来源:https://uudwc.com/A/on0G
文章目录
- 一、项目简介
- 二、项目组成
- 三、原理图设计
- 四、源码设计
- 五、小程序设计
- 六、成品展示
- 七、资料获取与联系
项目视频
哔哩哔哩视频链接:
1.项目开题
2.原理图讲解
3.程序讲解
3-1OLED显示
3-2独立按键的使用
3-3蜂鸣器的驱动
3-4温湿度获取
3-5人体红外检测
3-6亮度烟雾传感器检测
3-7步进电机控制
3-8PWM调节LED亮度
3-9本地功能整合
3-10最终代码讲解+成品演示
3-11小程序导入
一、项目简介
至今我们生活中已有许许多多的物联网设备,比如我们的智能空调,智能台灯,智能窗户,智能窗帘,智能汽车等等,今天我们将带给大家一款基于微信小程序控制的智能家居系统,该系统实现了自动控制、手动控制和远程控制,还可以加装语音控制。
我们这个系统主要实现的功能有以下几部分:
①温湿度采集
②烟雾浓度采集
③环境亮度采集
④检测是否有人
⑤OLED显示数据
⑥根据温湿度控制风扇(温度高于30℃打开风扇降温或者湿度大于90%RH打开风扇除湿)
⑦室内烟雾浓度过高,蜂鸣器报警
⑧有人时环境亮度控制灯光的亮暗
⑨根据环境亮度自动开关窗帘(亮度范围0~100,亮度>70开窗帘,亮度<=70关窗帘,开关窗帘使用步进电机模拟)
⑩所有执行器可以通过手动按键本地控制
⑪使用微信小程序显示环境数据
⑫通过微信小程序控制执行器
是不是觉得功能很多,这就对了,功能越多学的也就越多,对自己的锻炼也会多。
此项目我们会做两个版本,万用板版本和PCB版本
二、项目组成
先上图
PCB版本
万用板版本元器件
(万用板散件使用的有几个模块有修改,图中没列出来)
看完图后我们再来看一下系统的组成部分:
万用板
①STM32F103C8T6最小系统板1
②DHT11温湿度传感器1
③MQ-2烟雾浓度传感器1
④光敏电阻传感器1
⑤热释电人体红外传感器1
⑥OLED显示屏1
⑦ESP82661+转接板
⑧L298N1
⑨蜂鸣器1
⑩LED灯1
⑪风扇1
⑫步进电机驱动+步进电机1
⑬按键4
⑭万用板1
⑮HGD01-DC-DC电源模块1
⑯12V电源适配器1
再附上一张系统组成框图
三、原理图设计
原理图也分为万用板和PCB版本,需要PDF原版的看文章尾部获取
万用板版本
PCB版本
四、源码设计
源码分为单片机源码和小程序源码
具体代码讲解看视频
main.c
//单片机头文件
#include "stm32f10x.h"
//网络协议层
#include "onenet.h"
//网络设备
#include "net_device.h"
//硬件驱动
#include "led.h"
#include "oled.h"
#include "delay.h"
#include "usart.h"
#include "hwtimer.h"
#include "SysTick.h"
#include "system.h"
#include "iwdg.h"
#include "fault.h"
#include "selfcheck.h"
#include "info.h"
#include "oled.h"
#include "bmp.h"
#include "adc.h"
#include "lsens.h"
#include "dht11.h"
#include "rthw.h"
#include "pwm.h"
#include "fmq.h"
#include "bjdj.h"
#include "key.h"
//C库
#include <string.h>
u8 led_flag=0;
u8 fs_flag=0;
u8 mode_flag=0;
u8 lsens=0;
u32 mq2=0;
u8 temp=0,humi=0;
u16 led_pwm=900;
u8 ch_flag=0;
//数据流
DATA_STREAM dataStream[] = {
{"wendu", &temp, TYPE_UCHAR, 1},
{"shidu", &humi, TYPE_UCHAR, 1},
{"led_flag", &led_flag, TYPE_UCHAR, 1},
{"fs_flag", &fs_flag, TYPE_UCHAR, 1},
{"mode_flag", &mode_flag, TYPE_UCHAR, 1},
{"lsens", &lsens, TYPE_UCHAR, 1},
{"mq2", &mq2, TYPE_UINT, 1},
{"led_pwm", &led_pwm, TYPE_UCHAR, 1},
{"ch_flag", &ch_flag, TYPE_UCHAR, 1},
};
unsigned char dataStreamLen = sizeof(dataStream) / sizeof(dataStream[0]);
/*
************************************************************
* 函数名称: Hardware_Init
*
* 函数功能: 硬件初始化
*
* 入口参数: 无
*
* 返回参数: 无
*
* 说明: 初始化单片机功能以及外接设备
************************************************************
*/
void Hardware_Init(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //中断控制器分组设置
}
/*
************************************************************
* 函数名称: main
*
* 函数功能:
*
* 入口参数: 无
*
* 返回参数: 0
*
* 说明:
************************************************************
*/
int main(void)
{
u16 i;
unsigned char *dataPtr;
unsigned int runTime = 0;
_Bool sendFlag = 0;
u8 t=0;
SysTick_Init(72);
Delay_Init(); //systick初始化
Led_Init(); //LED初始化
Usart1_Init(115200); //初始化串口 115200bps
netDeviceInfo.reboot = 0;
TIM2_Int_Init(49, 35999); //72MHz,36000分频-500us,50重载值。则中断周期为500us * 50 = 25ms
TIM3_Int_Init(1999, 35999); //72MHz,36000分频-500us,2000重载值。则中断周期为500us * 2000 = 1s
OLED_Init();
Lsens_Init();
DHT11_Init();
RTHW_Init();
FMQ_Init();
BJDJ_Init();
KEY_Init();
TIM4_PWM_Init(899,0);
NET_DEVICE_IO_Init(); //网络设备IO初始化
NET_DEVICE_Reset(); //网络设备复位
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式(例如ESP8266要区分AT的返回还是平台下发数据的返回)
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);//0正常显示 1 屏幕翻转显示
OLED_ShowChinese(0,0,0,16,1);//温度
OLED_ShowChinese(15,0,2,16,1);
OLED_ShowChar(30,0,':',16,1);
OLED_ShowChinese(60,0,1,16,1);//湿度
OLED_ShowChinese(75,0,2,16,1);
OLED_ShowChar(90,0,':',16,1);
OLED_ShowChinese(0,17,5,16,1);//亮度
OLED_ShowChinese(15,17,2,16,1);
OLED_ShowChar(30,17,':',16,1);
OLED_ShowChinese(60,17,3,16,1);//烟雾
OLED_ShowChinese(75,17,4,16,1);
OLED_ShowChar(90,17,':',16,1);
OLED_ShowChinese(0,34,13,16,1);//窗帘 关
OLED_ShowChinese(15,34,14,16,1);
OLED_ShowChinese(40,34,16,16,1);
OLED_ShowChar(30,34,':',16,1);
OLED_ShowChinese(60,34,10,16,1);//风扇 关
OLED_ShowChinese(75,34,11,16,1);
OLED_ShowChinese(100,34,16,16,1);
OLED_ShowChar(90,34,':',16,1);
OLED_ShowString(10,49,"LED:",12,1);//灯 0挡
OLED_ShowNum(40,49,0,1,12,1);
OLED_ShowString(60,49,"PEOPLE:",12,1);//人 无
OLED_ShowNum(100,49,0,1,12,1);
OLED_Refresh();
while(1)
{
t=KEY_Scan(0); //按键
switch(t)
{
case KEY1_PRES: //模式切换0自动1手动
mode_flag=!mode_flag;
if(mode_flag==1)
{
led_pwm=900;
TIM_SetCompare2(TIM4,led_pwm);
OLED_ShowNum(40,49,100-led_pwm/9,3,12,1);
}
break;
case KEY2_PRES:
if(mode_flag==1)
{
fs_flag=!fs_flag;
}
break;
case KEY3_PRES:
if(mode_flag==1)
{
led_pwm=led_pwm-200;
if(led_pwm<=0||led_pwm>900)
{
led_pwm=900;
}
TIM_SetCompare2(TIM4,led_pwm);
OLED_ShowNum(40,49,100-led_pwm/9,3,12,1);
}
break;
case KEY4_PRES:
if(mode_flag==1)
{
if(ch_flag==0)//如果窗户关
{
for(i=0;i<150;i++)
{
FZ;
}
TZ;
ch_flag=1;
}
else
{
for(i=0;i<150;i++)
{
ZZ;
}
TZ;
ch_flag=0;
}
}
break;
default:
delay_ms(10);
}
DHT11_Read_Data(&temp,&humi); //获取湿度
OLED_ShowNum(40,0,temp,2,16,1);
OLED_ShowNum(100,0,humi,2,16,1);
lsens=Lsens_Get_Val(); //获取亮度
mq2=Mq2_Get_Val(); //获取烟雾浓度
OLED_ShowNum(36,17,lsens,3,16,1);
OLED_ShowNum(98,17,mq2,4,16,1);
if(mode_flag==0)
{
OLED_ShowNum(122,0,0,1,12,1);
if(RTHW==1) //有人
{
OLED_ShowNum(100,49,1,1,12,1);
led_pwm=lsens*9;
TIM_SetCompare2(TIM4,led_pwm);
OLED_ShowNum(40,49,100-led_pwm/9,3,12,1);
}
else
{
TIM_SetCompare2(TIM4,900);
OLED_ShowNum(100,49,0,1,12,1);
}
if(temp>30||humi>90)//温度大于30或湿度大于90打开风扇
{
fs_flag=1;
OLED_ShowChinese(100,34,15,16,1);
}
else
{
fs_flag=0;
OLED_ShowChinese(100,34,16,16,1);
}
if(ch_flag==0)//如果窗户关
{
if(lsens>70)//亮度>70开窗帘,<=70关窗帘
{
for(i=0;i<150;i++)
{
FZ;
}
TZ;
ch_flag=1;
}
else
{
TZ;
}
}
else
{
if(lsens>70)//亮度>70开窗帘,<=70关窗帘
{
TZ;
}
else
{
for(i=0;i<150;i++)
{
ZZ;
}
TZ;
ch_flag=0;
}
}
}
else //手动
{
OLED_ShowNum(122,0,1,1,12,1);
}
if(mq2>500) //烟雾浓度大于00打开蜂鸣器
{
GPIO_SetBits(GPIOB,FMQ);
}
else
{
GPIO_ResetBits(GPIOB,FMQ);
}
if(fs_flag==0)
{
GPIO_ResetBits(GPIOB,FS);
OLED_ShowChinese(100,34,16,16,1);
}
else
{
GPIO_SetBits(GPIOB,FS);
OLED_ShowChinese(100,34,15,16,1);
}
if(ch_flag==0)
{
OLED_ShowChinese(40,34,16,16,1);
}
else
{
OLED_ShowChinese(40,34,15,16,1);
}
OLED_Refresh();
if(oneNetInfo.netWork == 1)
{
OLED_ShowNum(122,49,1,1,12,1);
OLED_Refresh();
// OLED_ShowNum(110,6,1,1,16);
/******************************************************************************
数据与心跳
******************************************************************************/
if(timInfo.timer6Out - runTime >= 100) //25s一次(25ms中断)
{
runTime = timInfo.timer6Out;
if(sendFlag)
{
TIM_Cmd(OS_TIMER, DISABLE);
OneNet_HeartBeat(); //心跳连接
TIM_Cmd(OS_TIMER, ENABLE);
}
else
{
TIM_Cmd(OS_TIMER, DISABLE);
OneNet_SendData(kTypeSimpleJsonWithoutTime, dataStreamLen); //数据发送
TIM_Cmd(OS_TIMER, ENABLE);
}
sendFlag = !sendFlag;
}
/******************************************************************************
平台下发命令解析
******************************************************************************/
if(oneNetInfo.netWork && NET_DEVICE_Get_DataMode() == DEVICE_DATA_MODE) //当有网络 且 在命令接收模式时
{
dataPtr = NET_DEVICE_GetIPD(0); //不等待,获取平台下发的数据
if(dataPtr != NULL) //如果数据指针不为空,则代表收到了数据
{
OneNet_App(dataPtr); //集中处理
}
}
/******************************************************************************
错误处理
******************************************************************************/
if(faultType != FAULT_NONE) //如果错误标志被设置
{
UsartPrintf(USART_DEBUG, "WARN: Fault Process\r\n");
Fault_Process(); //进入错误处理函数
}
/******************************************************************************
数据反馈
******************************************************************************/
if(oneNetInfo.sendData)
{
oneNetInfo.sendData = OneNet_SendData(kTypeSimpleJsonWithoutTime, dataStreamLen);
}
}
else
{
OLED_ShowNum(122,49,0,1,12,1);
OLED_Refresh();
// OLED_ShowNum(110,6,0,1,16);
/******************************************************************************
初始化网络设备、接入平台
******************************************************************************/
if(!oneNetInfo.netWork && (checkInfo.NET_DEVICE_OK == DEV_OK)) //当没有网络 且 网络模块检测到时
{
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式
if(!NET_DEVICE_Init()) //初始化网络设备,能连入网络
{
OneNet_DevLink(oneNetInfo.devID, oneNetInfo.apiKey); //接入平台
if(oneNetInfo.netWork)
{
runTime = timInfo.timer6Out; //更新时间
}
else
{
}
}
}
/******************************************************************************
网络设备检测
******************************************************************************/
if(checkInfo.NET_DEVICE_OK == DEV_ERR) //当网络设备未做检测
{
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式
if(timerCount >= NET_TIME) //如果网络连接超时
{
UsartPrintf(USART_DEBUG, "Tips: Timer Check Err\r\n");
NET_DEVICE_Reset(); //复位网络设备
timerCount = 0; //清零连接超时计数
faultType = FAULT_NONE; //清除错误标志
}
if(!NET_DEVICE_SendCmd("AT\r\n", "OK")) //网络设备检测
{
UsartPrintf(USART_DEBUG, "NET Device :Ok\r\n");
checkInfo.NET_DEVICE_OK = DEV_OK; //检测到网络设备,标记
NET_DEVICE_Set_DataMode(DEVICE_DATA_MODE); //设置为数据收发模式
}
else
{
UsartPrintf(USART_DEBUG, "NET Device :Error\r\n");
}
}
}delay_ms(10);
}
}
五、小程序设计
小程序使用小程序开发者工具开发
小程序界面
六、成品展示
最后是激动人心的时刻,来吧,先上一张实物图
万用板
PCB
微信小程序智能家居最后一讲 程序讲解加成果展示
七、资料获取与联系
关注公众号“HG电子”发送“微信小程序智能家居”可获取PDF版本原理图
有别的需求也可加我V:HGbishe文章来源地址https://uudwc.com/A/on0G