前言
本文给大家介绍一款基于STM32智能家居的课程设计,其实也可以用作毕业设计啦,视难度而定,希望能给大家一些思路,从而做出自己满意的作品。需要单片机资料什么的可以拉到文末进行领取哈~
1,器件准备
- 采用STM32F103C8T6单片机
- 使用DHT11检测温湿度
- 使用MQ-2传感器检测烟雾浓度
- 使用CO2传感器检测二氧化碳浓度
- OLED显示温度,湿度,烟雾浓度,CO2浓度
- 烟雾浓度、二氧化碳浓度超标时蜂鸣器报警,同时打开风扇通风
- ESP8266模块实现 WIFI通讯数据传输,wifi通讯需借助一个有网络wifi热点
- 中国移动物联网平台可实时查看传感器数据,控制风扇,蜂鸣器和LED
2,硬件功能
在硬件设计方面,系统主要包括STM32单片机、温湿度传感器、烟雾传感器、二氧化碳浓度传感器、OLED显示器、蜂鸣器、风扇以及WiFi通信模块等部件。
其中,STM32单片机负责整个系统的控制和数据处理;
传感器用于采集环境参数,如温湿度、烟雾浓度和二氧化碳浓度等;OLED显示器用于实时显示采集到的环境参数;
蜂鸣器和风扇则用于在特定条件下触发报警和通风功能;
WiFi通信模块则实现系统与中国移动物联网平台等外部网络的通信,以实现远程监控和控制。
3,原理图
原理图是在很适合新手入门的立创画的,新手用立创,学的深入了可以用AD之类的画图软件。
4,硬件代码
1. 主函数main.c
int main(void)
{
u16 adcx;
char buf[20];
unsigned char *dataPtr;
unsigned int runTime = 0;
_Bool sendFlag = 0;
unsigned int Num = 0;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置中断优先级分组为组2:2位抢占优先级,2位响应优先级
delay_init(); //延时函数初始化
LED_Init(); //初始化与控制设备连接的硬件接口
uart_init(115200); //串口初始化为9600
DHT11_Init();
printf( "开始\r\n");
I2C_Configuration();
OLED_Init();
OLED_Fill(0x00);
OLED_ShowCN(0,0,0); //二氧化碳
OLED_ShowCN(16,0,1);
OLED_ShowCN(32,0,2);
OLED_ShowCN(48,0,3);
OLED_ShowStr(64,0,":---ppm",2);
OLED_ShowCN(0,2,4); //烟雾
OLED_ShowCN(16,2,5);
OLED_ShowStr(32,2,":--%",2);
OLED_ShowCN(0,4,17); //温度
OLED_ShowCN(16,4,19);
OLED_ShowStr(32,4,":--C",2);
OLED_ShowCN(0,6,18); //湿度
OLED_ShowCN(16,6,19);
OLED_ShowStr(32,6,":--%",2);
Adc_Init();
if(RCC_GetFlagStatus(RCC_FLAG_IWDGRST) == SET) //如果是看门狗复位则提示
{
printf( "WARN: IWDG Reboot\r\n");
RCC_ClearFlag(); //清除看门狗复位标志位
faultTypeReport = faultType = FAULT_REBOOT; //标记为重启错误
netDeviceInfo.reboot = 1;
}
else
{
printf( "2.SSID: %s, PSWD: %s\r\n"
"DEVID: %s, APIKEY: %s\r\n"
, netDeviceInfo.staName, netDeviceInfo.staPass
, oneNetInfo.devID, oneNetInfo.apiKey);
netDeviceInfo.reboot = 0;
}
Timer3_4_Init(TIM3, 49, 35999); //72MHz,36000分频-500us,50重载值。则中断周期为500us * 50 = 25ms
Timer3_4_Init(TIM4, 1999, 35999); //72MHz,36000分频-500us,2000重载值。则中断周期为500us * 2000 = 1s
//定时检查网络状态标志位
printf("3.Hardware init OK\r\n");
NET_DEVICE_IO_Init(); //网络设备IO初始化
NET_DEVICE_Reset(); //网络设备复位
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式(例如ESP8266要区分AT的返回还是平台下发数据的返回)
uart3_init(9600); //串口三
while(1)
{
if(oneNetInfo.netWork == 1)
{
/******************************************************************************
数据与心跳
******************************************************************************/
if(timInfo.timer6Out - runTime >= 400) //25s一次(25ms中断)25*1000=25S
{
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) //如果数据指针不为空,则代表收到了数据
{
printf("收到1\r\n");
OneNet_App(dataPtr); //集中处理
}
}
/******************************************************************************
传感器
******************************************************************************/
if(Num++>20)
{
Num = 0;
}
CO2=read_CO2_concentration();
sprintf(buf,"%4dppm ",CO2);
OLED_ShowStr(64,0,(unsigned char*)buf,2);
MQ2=(Get_Adc_Average(ADC_Channel_0,10)*330*2/4096)*100/25;
sprintf(buf,"%3d%% ",MQ2);
OLED_ShowStr(32,2,(unsigned char*)buf,2);
delay_ms(10);
DHT11_Read(&temp,&humi);
sprintf(buf,"%3dC",temp);
OLED_ShowStr(32,4,(unsigned char*)buf,2);
sprintf(buf,"%3d%% ",humi);
OLED_ShowStr(32,6,(unsigned char*)buf,2);
delay_ms(10);
if(mode==0) //处于自动模式下?
{
if(MQ2>50||CO2>1000) //烟雾或者CO2超标 开风扇
{
Jd0_Set(GPIO_ON); //开风扇
Beep_Set(GPIO_ON); //开报警
}
else
{
Jd0_Set(GPIO_OFF); //关风扇
Beep_Set(GPIO_OFF); //关报警
}
}
else //非自动模式
{
}
/******************************************************************************
错误处理
******************************************************************************/
if(faultType != FAULT_NONE) //如果错误标志被设置
{
printf( "WARN: Fault Process\r\n");
Fault_Process(); //进入错误处理函数
}
/******************************************************************************
数据反馈
******************************************************************************/
if(oneNetInfo.sendData)
{
oneNetInfo.sendData = OneNet_SendData(kTypeSimpleJsonWithoutTime, dataStreamLen);
}
}
else
{
/******************************************************************************
初始化网络设备、接入平台
******************************************************************************/
if(!oneNetInfo.netWork && (checkInfo.NET_DEVICE_OK == DEV_OK)) //当没有网络 且 网络模块检测到时
{
//LCD_ShowString(30,20,220,24,24,"Connectting... ");
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式
if(!NET_DEVICE_Init()) //初始化网络设备,能连入网络
{
OneNet_DevLink(oneNetInfo.devID, oneNetInfo.apiKey); //接入平台
if(oneNetInfo.netWork)
{
//LCD_ShowString(30,20,220,24,24,"Connectted OK ");
runTime = timInfo.timer6Out; //更新时间
}
else
{
//LCD_ShowString(30,20,220,24,24,"Not Connected ");
}
}
}
/******************************************************************************
网络设备检测
******************************************************************************/
if(checkInfo.NET_DEVICE_OK == DEV_ERR) //当网络设备未做检测
{
NET_DEVICE_Set_DataMode(DEVICE_CMD_MODE); //设置为命令收发模式
if(timerCount >= NET_TIME) //如果网络连接超时
{
printf( "Tips: Timer Check Err\r\n");
NET_DEVICE_Reset(); //复位网络设备
timerCount = 0; //清零连接超时计数
faultType = FAULT_NONE; //清除错误标志
}
if(!NET_DEVICE_SendCmd("AT\r\n", "OK")) //网络设备检测
{
printf( "NET Device :Ok\r\n");
checkInfo.NET_DEVICE_OK = DEV_OK; //检测到网络设备,标记
NET_DEVICE_Set_DataMode(DEVICE_DATA_MODE); //设置为数据收发模式
}
else
printf( "NET Device :Error\r\n");
}
}
}
}
2,DHT11模块—检测温湿度
/***注解:
1. 在dht11.h中定义了DHT11_GPIO和DHT11_PIN,分别表示DHT11传感器所连接的GPIO口和引脚号。
2. DHT11_Init函数用于初始化DHT11传感器所连接的GPIO口,将其设置为输出模式,并将引脚电平设置为高电平。
3. DHT11_Read函数用于读取DHT11传感器的温度和湿度数据。首先将DHT11_GPIO设置为输出模式,并将引脚电平设置为低电平,延时18ms,然后将引脚电平设置为高电平,延时40us,最后将DHT11_GPIO设置为输入模式,并等待DHT11传感器的响应信号。
4. 如果DHT11传感器响应信号正确,则开始读取DHT11传感器的数据。每个数据包含40个位,其中第1个字节为湿度的整数部分,第3个字节为温度的整数部分,第5个字节为校验和。读取每个位时,先等待50us的低电平,然后再等待30us的高电平,根据高电平的持续时间判断该位是0还是1。
5. 如果读取的数据校验和正确,则将湿度和温度的整数部分存储在temperature和humidity变量中,并返回1;否则返回0。
****/
#include "delay.h"
#include "dht11.h"
void DHT11_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO, &GPIO_InitStructure);
GPIO_SetBits(DHT11_GPIO, DHT11_PIN);
}
uint8_t DHT11_Read(uint8_t *temp, uint8_t *humi)
{
uint8_t data[5];
uint8_t i, j;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(DHT11_GPIO, &GPIO_InitStructure);
GPIO_ResetBits(DHT11_GPIO, DHT11_PIN);
delay_ms(18);
GPIO_SetBits(DHT11_GPIO, DHT11_PIN);
delay_us(40);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(DHT11_GPIO, &GPIO_InitStructure);
if (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == RESET)
{
while (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == RESET)
;
while (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == SET)
;
for (i = 0; i < 5; i++)
{
for (j = 0; j < 8; j++)
{
while (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == RESET)
;
delay_us(30);
if (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == SET)
{
data[i] |= (1 << (7 - j));
}
while (GPIO_ReadInputDataBit(DHT11_GPIO, DHT11_PIN) == SET)
;
}
}
if ((data[0] + data[1] + data[2] + data[3]) == data[4])
{
*humi = data[0];
*temp = data[2];
return 1;
}
else
{
return 0;
}
}
else
{
return 0;
}
}
3,JW01
void uart3_init(u32 bound)
{
NVIC_InitTypeDef NVIC_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // GPIOB时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3,ENABLE); //串口3时钟使能
USART_DeInit(USART3); //复位串口3
//USART3_TX PB10
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //PB10
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB10
//USART3_RX PB11
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
GPIO_Init(GPIOB, &GPIO_InitStructure); //初始化PB11
USART_InitStructure.USART_BaudRate = bound;//波特率一般设置为9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8位数据格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一个停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//无奇偶校验位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件数据流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收发模式
USART_Init(USART3, &USART_InitStructure); //初始化串口 3
USART_Cmd(USART3, ENABLE); //使能串口
//使能接收中断
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);//开启中断
//设置中断优先级
NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=1 ;//抢占优先级3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子优先级3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根据指定的参数初始化VIC寄存器
}
由于篇幅有限,只展示部分模块的部分代码~
5,软件部分
在软件设计方面,系统主要实现以下功能:首先,通过传感器采集环境参数,并将数据传输给STM32单片机进行处理;然后,单片机将处理后的数据通过OLED显示器实时显示出来;同时,根据设定的阈值,判断是否需要触发蜂鸣器报警和风扇通风功能;最后,通过WiFi通信模块将数据传输到外部网络,以便用户通过手机APP或其他方式实时查看和控制环境参数。
使用的是onenet平台,进行数据的传输~
APP界面是可以定制,也支持小程序,支持网页等形式。
当然,硬件部分也允许做一些模块的更换修改的,例如CO2不需要,换成CO,或者增加或减少模块,都是支持的~
6,应用场景
基于设计的STM32智能家居,也可以称作是环境检测的功能,以下是一些应用场景:
1,智能家居安全监控:
可以将您的设备安装在家庭中的关键区域,如厨房、客厅或卧室,以监测室内环境的温湿度、烟雾和二氧化碳浓度。一旦烟雾或二氧化碳浓度超标,蜂鸣器会发出报警,同时启动风扇通风,以减少潜在的安全风险。
2,工业自动化与监控:
在仓库、工厂或其他需要严格控制环境条件的场所,可以使用您的设备来监控环境的温湿度、烟雾和二氧化碳浓度。这些数据可以通过WiFi传输到远程监控系统,以便工作人员进行实时监控和调整。
3,农业温室监控:
在温室环境中,温湿度、烟雾和二氧化碳浓度对植物的生长至关重要。您的设备可以实时检测这些参数,并通过WiFi将数据传输到移动物联网平台,农民或农业技术人员可以根据数据调整温室内的环境,以促进植物的健康生长。
4,学校与实验室安全监控:
在学校或实验室中,可能需要进行各种实验或活动,这些活动可能会产生烟雾或二氧化碳。使用您的设备可以实时监测这些有害物质的浓度,并在超标时发出报警,确保学生和实验人员的安全。
5,公共场所空气质量监测:
这个设备也可以用于公共场所,如购物中心、博物馆、图书馆等,以监测室内空气质量。通过WiFi传输数据到移动物联网平台,管理者可以了解各个区域的空气质量情况,并采取相应的措施来改善空气质量。
6,定制化的环境监测解决方案:
对于需要特定环境监测解决方案的客户,如博物馆需要保护珍贵文物免受潮湿和污染,或医院需要确保病房内的空气质量良好,您的设备可以根据客户需求进行定制和配置。
==================
资料可以点击链接进行获取:免费领取单片机资料