STM32项目分享:智能家居(机智云)升级版

目录

一、前言

二、项目简介

1.功能详解

2.主要器件

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

六、实验效果 

七、资料内容

项目分享


一、前言

项目成品图片:

哔哩哔哩视频链接:

STM32智能家居(机智云)升级版

(资料分享见文末) 

二、项目简介

1.功能详解

基于STM32的智能家居(机智云)升级版

功能如下:

  1. 检测功能:监测环境温湿度、烟雾浓度、一氧化碳、空气质量、光照强度、大气压强
  2. 显示功能:将检测到的数据显示在OLED上
  3. 控制功能:系统可以控制LED灯、步进电机(窗户)
  4. 手动模式:机智云APP远程控制LED灯和步进电机。
  5. 自动模式:系统检测到烟雾浓度/一氧化碳/空气质量超出阈值时、蜂鸣报警并开窗通风;光线低于阈值时,自动开启LED灯
  6. 阈值调节:按键调节系统阈值
  7. 手机APP:通过ESP8266 WIFI模块连接网络,接入机智云服务器,实现数据上报和控制下发

2.主要器件

  • STM32F103C8T6单片机
  • OLED 屏幕
  • DHT11温湿度传感器
  • 光敏电阻
  • MQ-2烟雾传感器
  • MQ-7一氧化碳传感器
  • MQ-135空气质量传感器
  • ESP8266-01S(WIFI模块)
  • 步进电机
  • 有源蜂鸣器

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

#include "stm32f10x.h"                  // Device header
#include "oled.h"
#include "adcx.h"
#include "bmp280.h"
#include "sensormodules.h"
#include "dht11.h"
#include "key.h"
#include "tim2.h"
#include "tim3.h"
#include "flash.h"
#include "motor.h"
#include "led.h"
#include "usart.h"
#include "iwdg.h"

SensorModules sensorData;			//声明传感器模块的结构体变量
SensorThresholdValue Sensorthreshold;	//声明传感器阈值结构体变量

#define KEY_Long1	11

#define KEY_1	1
#define KEY_2	2
#define KEY_3	3
#define KEY_4	4

#define FLASH_START_ADDR	0x0801f000	//写入的起始地址

uint8_t motorFlag = 0;
uint8_t oledPages = 1;	//系统显示页面
uint8_t model;	//系统模式

typedef enum 
{
	DISPLAY_PAGE1 = 1,
	DISPLAY_PAGE2,
	SETTINGS_PAGE
} OLED_PAGES;

/**
  * @brief  显示菜单1的固定内容
  * @param  无
  * @retval 无
  */
void OLED_Menu1(void)
{
	//显示“温度:  C”
	OLED_ShowChinese(1,1,48);
	OLED_ShowChinese(1,2,49);
	OLED_ShowChar(1,5,':');
	OLED_ShowChar(1,8,'C');
	
	//显示“湿度:   %”
	OLED_ShowChinese(1,5,50);
	OLED_ShowChinese(1,6,51);
	OLED_ShowChar(1,13,':');	
	OLED_ShowChar(1,16,'%');
	
	//显示”光照强度:  Lux“
	OLED_ShowChinese(2, 1, 8);
	OLED_ShowChinese(2, 2, 9);	
	OLED_ShowChinese(2, 3, 10);
	OLED_ShowChinese(2, 4, 11);	
	OLED_ShowChar(2, 9, ':');
	OLED_ShowString(2, 14, "Lux");
	
	//显示“大气压强: ”
	OLED_ShowChinese(3, 1, 12);
	OLED_ShowChinese(3, 2, 13);
	OLED_ShowChinese(3, 3, 14);
	OLED_ShowChinese(3, 4, 15);
	OLED_ShowChar(3, 9, ':');
	OLED_ShowString(3, 14, "hPa");
	
	//显示“系统模式:”
	OLED_ShowChinese(4, 1, 28);
	OLED_ShowChinese(4, 2, 29);
	OLED_ShowChinese(4, 3, 30);
	OLED_ShowChinese(4, 4, 31);	
	OLED_ShowChar(4, 9, ':');
}

/**
  * @brief  显示菜单2的固定内容
  * @param  无
  * @retval 无
  */
void OLED_Menu2(void)
{
	//显示“烟雾浓度:  ppm”
	OLED_ShowChinese(1, 1, 20);
	OLED_ShowChinese(1, 2, 21);
	OLED_ShowChinese(1, 3, 22);
	OLED_ShowChinese(1, 4, 23);	
	OLED_ShowChar(1, 9, ':');
	OLED_ShowString(1,13,"ppm");
	
	//显示“一氧化碳:  ppm”
	OLED_ShowChinese(2, 1, 16);
	OLED_ShowChinese(2, 2, 17);
	OLED_ShowChinese(2, 3, 18);
	OLED_ShowChinese(2, 4, 19);	
	OLED_ShowChar(2, 9, ':');
	OLED_ShowString(2,13,"ppm");	
	
	//显示“空气质量:  ppm”
	OLED_ShowChinese(3, 1, 24);
	OLED_ShowChinese(3, 2, 25);
	OLED_ShowChinese(3, 3, 26);
	OLED_ShowChinese(3, 4, 27);	
	OLED_ShowChar(3, 9, ':');
	OLED_ShowString(3,13,"ppm");		
}

/**
  * @brief  显示菜单1的传感器数据
  * @param  无
  * @retval 无
  */
void SensorDataDisplay1(void)
{
	//显示温度数据
	OLED_ShowNum(1, 6, sensorData.temp, 2);
	
	//显示湿度数据
	OLED_ShowNum(1, 14, sensorData.humi, 2);
	
	//显示光照强度数据
	OLED_ShowNum(2, 10, sensorData.lux, 4);	
	
	//显示大气压强数据
	OLED_ShowNum(3, 10, 1020, 4);
	
	
	//显示系统状态数据
	if (!model)
	{
		OLED_ShowChinese(4, 6, 36);
		OLED_ShowChinese(4, 7, 37);		
	}
	else
	{
		OLED_ShowChinese(4, 6, 32);
		OLED_ShowChinese(4, 7, 33);			
	}
}

/**
  * @brief  显示菜单2的传感器数据
  * @param  无
  * @retval 无
  */
void SensorDataDisplay2(void)
{
	
	//显示烟雾浓度数据
	OLED_ShowNum(1, 10, sensorData.smoke, 3);	
	
	//显示一氧化碳数据
	OLED_ShowNum(2, 10, sensorData.CO, 3);	
	
	//显示空气质量数据
	OLED_ShowNum(3, 10, sensorData.AQI, 3);
}

/**
  * @brief  显示系统阈值设置界面1
  * @param  无
  * @retval 无
  */
void OLED_SetInterfacevoid(void)
{
	//显示“光照阈值”
	OLED_ShowChinese(1, 2, 8);
	OLED_ShowChinese(1, 3, 9);	
	OLED_ShowChinese(1, 4, 42);
	OLED_ShowChinese(1, 5, 43);	
	OLED_ShowChar(1, 11, ':');

	//显示“烟雾阈值”
	OLED_ShowChinese(2, 2, 20);
	OLED_ShowChinese(2, 3, 21);	
	OLED_ShowChinese(2, 4, 42);
	OLED_ShowChinese(2, 5, 43);	
	OLED_ShowChar(2, 11, ':');
	
	//显示“一氧化碳阈值”
	OLED_ShowString(3, 3, "CO");
	OLED_ShowChinese(3, 4, 42);
	OLED_ShowChinese(3, 5, 43);	
	OLED_ShowChar(3, 11, ':');
	
	//显示“空气质量阈值”
	OLED_ShowString(4, 3, "AQI");
	OLED_ShowChinese(4, 4, 42);
	OLED_ShowChinese(4, 5, 43);	
	OLED_ShowChar(4, 11, ':');
	
	//显示光照阈值数值
	OLED_ShowNum(1, 12, Sensorthreshold.luxValue, 4);
	
	//显示烟雾阈值数值
	OLED_ShowNum(2, 12, Sensorthreshold.smokeValue, 3);
		
	//显示一氧化碳阈值数值
	OLED_ShowNum(3, 12, Sensorthreshold.COValue, 3);
	
	//显示空气质量阈值数值
	OLED_ShowNum(4, 12, Sensorthreshold.AQIValue, 3);
}

/**
  * @brief  记录阈值界面下按KEY1的次数
  * @param  无
  * @retval 返回次数
  */
uint8_t SetSelection(void)
{
	static uint8_t count = 1;
	if(KeyNum == KEY_1)
	{
		KeyNum = 0;
		count++;
		if (count > 4)
		{
			count = 1;
		}
	}
	return count;
}

/**
  * @brief  显示阈值界面的选择符号
  * @param  num 为显示的位置
  * @retval 无
  */
void OLED_Option(uint8_t num)
{
	switch(num)
	{
		case 1:	
			OLED_ShowChar(1,1,'>');
			OLED_ShowChar(2,1,' ');
			OLED_ShowChar(3,1,' ');
			OLED_ShowChar(4,1,' ');
			break;
		case 2:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,'>');
			OLED_ShowChar(3,1,' ');
			OLED_ShowChar(4,1,' ');
			break;
		case 3:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,' ');
			OLED_ShowChar(3,1,'>');
			OLED_ShowChar(4,1,' ');
			break;
		case 4:	
			OLED_ShowChar(1,1,' ');
			OLED_ShowChar(2,1,' ');
			OLED_ShowChar(3,1,' ');
			OLED_ShowChar(4,1,'>');
			break;
		default: break;
	}
}

/**
  * @brief  对阈值界面的传感器阈值进行修改
  * @param  num 为当前用户需要更改的传感器阈值位置
  * @retval 无
  */
void ThresholdModification(uint8_t num)
{
	switch (num)
	{
		case 1:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.luxValue += 10;
				if (Sensorthreshold.luxValue > 2000)
				{
					Sensorthreshold.luxValue = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.luxValue -= 10;
				if (Sensorthreshold.luxValue > 2000)
				{
					Sensorthreshold.luxValue = 2000;
				}				
			}
			break;
			
		case 2:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.smokeValue += 10;
				if (Sensorthreshold.smokeValue > 500)
				{
					Sensorthreshold.smokeValue = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.smokeValue -= 10;
				if (Sensorthreshold.smokeValue > 500)
				{
					Sensorthreshold.smokeValue = 500;
				}				
			}	
			break;
		case 3:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.COValue += 10;
				if (Sensorthreshold.COValue > 500)
				{
					Sensorthreshold.COValue = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.COValue -= 10;
				if (Sensorthreshold.COValue > 500)
				{
					Sensorthreshold.COValue = 500;
				}				
			}
			break;
		case 4:
			if (KeyNum == KEY_3)
			{
				KeyNum = 0;
				Sensorthreshold.AQIValue += 10;
				if (Sensorthreshold.AQIValue > 500)
				{
					Sensorthreshold.AQIValue = 0;
				}
			}
			else if (KeyNum == KEY_4)
			{
				KeyNum = 0;
				Sensorthreshold.AQIValue -= 10;
				if (Sensorthreshold.AQIValue > 500)
				{
					Sensorthreshold.AQIValue = 500;
				}				
			}
			break;
		default: break;		
	}
}

/**
  * @brief  根据标志位控制步进电机的运行
  * @param  无
  * @retval 无
  */
void MotorOperation(void)
{
	if (motorFlag == 1)
	{
		MOTOR_Direction_Angle(1, 0, 90, 1);
		MOTOR_STOP();
		motorFlag = 0;
	}
	else if (motorFlag == 2)
	{
		MOTOR_Direction_Angle(0, 0, 90, 1);
		MOTOR_STOP();
		motorFlag = 0;		
	}

}

/**
  * @brief  传感器数据扫描
  * @param  无
  * @retval 无
  */
void SensorScan(void)
{
	DHT11_Read_Data(&sensorData.humi, &sensorData.temp);
	Get_Average_LDR_LUX(&sensorData.lux);
	Get_Average_MQ2_PPM(&sensorData.smoke);
	Get_Average_MQ7_PPM(&sensorData.CO);
	Get_Average_MQ135_PPM(&sensorData.AQI);
	sensorData.hPa = (uint32_t)BMP280_Get_Pressure();
}


int main(void)
{
	ADCX_Init();
    Timer2_Init(9,14398);
	Uart2_Init(9600);
	Uart1_Init(115200);
	IWDG_Init();
	
	OLED_Init();
	Bmp_Init();
	DHT11_Init();
	Key_Init();
	MOTOR_Init();
	LED_Init();
	Buzzer_Init();
	
	Sensorthreshold.luxValue = FLASH_R(FLASH_START_ADDR);	//从指定页的地址读FLASH
	Sensorthreshold.smokeValue = FLASH_R(FLASH_START_ADDR+2);	//从指定页的地址读FLASH
	Sensorthreshold.COValue = FLASH_R(FLASH_START_ADDR+4);	//从指定页的地址读FLASH
	Sensorthreshold.AQIValue = FLASH_R(FLASH_START_ADDR+6);	//从指定页的地址读FLASH
	
	GENERAL_TIM_Init();
	userInit();		//完成机智云初始赋值
	gizwitsInit();	//开辟一个环形缓冲区
	while (1)
	{
			
		IWDG_ReloadCounter();	//使能重装载寄存器计数
		SensorScan();	//获取传感器数据
		
		
		switch (oledPages)
		{
			case DISPLAY_PAGE1:
				OLED_Menu1();	//显示主页面1固定信息
				SensorDataDisplay1();//显示传感器1数据
				MotorOperation();
			
				/*按键按下时进入主页面2*/
				if (KeyNum == KEY_2)
				{
					KeyNum = 0;
					oledPages = DISPLAY_PAGE2;
					OLED_Clear();
				}
				
				/*按键按下时切换模式*/
				if (KeyNum == KEY_1)
				{
					KeyNum = 0;
					
					model = !model;
					if (!model)
					{
						LED_OFF();
						Buzzer_OFF();
					}
				}
				
				/*按键按下时进入阈值设计界面*/
				if (KeyNum == KEY_Long1)
				{
					KeyNum = 0;
					oledPages = SETTINGS_PAGE;
					OLED_Clear();
				}
				break;
				
			case DISPLAY_PAGE2:
				OLED_Menu2();
				SensorDataDisplay2();
				MotorOperation();
			
				/*按键按下时进入主页面2*/
				if (KeyNum == KEY_2)
				{
					KeyNum = 0;
					oledPages = DISPLAY_PAGE1;
					OLED_Clear();
				}				
				break;
				
			case SETTINGS_PAGE:
				OLED_SetInterfacevoid();	//显示阈值设置界面的固定内容
				OLED_Option(SetSelection());	//实现阈值设置页面的选择功能
				ThresholdModification(SetSelection());	//实现阈值调节功能	
			
				//判断是否退出阈值设置界面
				if (KeyNum == KEY_2)
				{
					KeyNum = 0;
					oledPages = DISPLAY_PAGE1;	//跳转到主界面
					OLED_Clear();	//清屏
					
					//存储修改的传感器阈值至flash内	
					FLASH_W(FLASH_START_ADDR, Sensorthreshold.luxValue, Sensorthreshold.smokeValue, 
						Sensorthreshold.COValue, Sensorthreshold.AQIValue);
				}
				break;
			default: break;
		}
		
		userHandle();	//更新机智云数据点变量存储的值
		gizwitsHandle((dataPoint_t *)&currentDataPoint);	//数据上传至机智云					
	}
}

六、实验效果 

七、资料内容

项目分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值