STM32项目分享:智能坐垫|座椅

目录

一、前言

二、项目简介

1.功能详解

2.主要器件

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

六、实验效果 

七、资料内容

项目分享


一、前言

项目成品图片:

哔哩哔哩视频链接:

STM32智能坐垫|座椅

(资料分享见文末) 

二、项目简介

1.功能详解

基于STM32的智能坐垫|座椅

功能如下:

  1. 使用STM32F103C8T6单片机作为主控单元
  2. 通过DHT11检测温湿度数据,当温度不在设定的范围内,则控制加热和散热
  3. 通过按键设置时长、温度上下限值、手动控制加热、散热、模式切换
  4. 通过HX711检测重量,当重量不为0,则表明有人坐在坐垫上,此时开始计时,当计时时间超过设定的最长时间,则语音提醒“久坐多时,注意起身运动”
  5. 通过OLED显示测量数据
  6. 通过蓝牙模块,可将坐下时长、温湿度发送到手机端,手机端也可控制加热、散热、模式切换

2.主要器件

  • STM32F103C8T6单片机
  • OLED 屏幕
  • DHT11温湿度传感器
  • HX711称重传感器
  • JR6001语音模块
  • BT04A蓝牙模块
  • 继电器
  • 风扇模块
  • PTC加热片

三、原理图设计

四、PCB硬件设计

PCB图 

五、程序设计 

#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
#include "math.h"
#include "delay.h"
#include "gpio.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "dht11.h"
#include "timer.h"
#include "hx711.h"


/**********************************
变量定义
**********************************/
uint8_t key_num = 0;									//按键扫描标志位	
uint8_t flag_display = 0;							//显示界面标志位
uint32_t time_num = 0;								//10ms计时
uint8_t temp_value = 0;							//温度值
uint8_t humi_value = 0;							//湿度值
uint32_t temp_max = 35;								//温度最大值
uint32_t temp_min = 15;								//温度最小值
char display_buf[16];									//显示数组

_Bool flag_mode = 0;									//模式标志位
_Bool flag_JR = 0;										//加热标志位
_Bool flag_SR = 0;										//散热标志位

uint8_t count_hour_old = 1;						//计时存储时
int count_minute_old = 0;							//计时存储分
int count_second_old = 0;							//计时存储秒
uint8_t count_hour = 0;								//计时时
int count_minute = 0;									//计时分
int count_second = 0;									//计时秒

_Bool flag_count_end = 0;							//计时结束标志位
extern uint8_t usart1_buf[256];				//串口1接收数组

extern uint8_t flag_timer_begin_1s;		//定时器开始标志位
extern uint8_t flag_1s;								//一秒钟到达标志位

_Bool flag_weight = 0;								//重量标志位
uint32_t weight_maopi = 0;						//毛皮重量
uint32_t weight_value = 0;						//总重量


/**********************************
函数声明
**********************************/
void Key_function(void);							//按键函数
void Monitor_function(void);					//监测函数
void Display_function(void);					//显示函数
void Manage_function(void);						//处理函数


/****
*******	主函数 
*****/
int main(void)
{
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //配置中断优先分组
	Delay_Init();	    	 								//延时初始化	  
	Gpio_Init();		  									//IO初始化
	Key_Init();		  										//按键初始化
	Oled_Init();		  									//OLED初始化
	DHT11_Init();												//DHT11初始化
	TIM2_Init(999,7199);								//定时器初始化
	Hx711_Init();												//HX711初始化
	Oled_Clear_All();										//清屏
	Usart1_Init(9600);    							//串口1初始化
	Usart2_Init(9600);									//串口2初始化
	UsartPrintf(USART2,"AF:30");
	Delay_ms(1000);
	UsartPrintf(USART2,"A7:00001");
	Delay_ms(1000);
	while(1)
	{
		Key_function();										//按键函数
		Monitor_function();								//监测函数
		Display_function();								//显示函数
		Manage_function();								//处理函数

		time_num++;												//计时变量+1
		Delay_ms(10);
		if(time_num %10 == 0)
			LED_SYS = ~LED_SYS;
		if(time_num >= 5000)
		{
			time_num = 0;
		}
	}
}

/****
*******按键函数
*****/
void Key_function(void)
{
	key_num = Chiclet_Keyboard_Scan(0);		//按键扫描
	if(key_num != 0)											//有按键按下
	{
		switch(key_num)
		{
			case 1:								            //按键1,切换设置界面
				flag_display++;
				if(flag_display >= 6)
					flag_display = 0;
				
				Oled_Clear_All();					      //清屏
			break;

			case 2:											      //按键2:设定值加
				switch(flag_display)
				{
					case 0:									      //界面0:手动控制加热
						flag_mode = 1;	
						JR = !JR;
						SR = 0;
					break;
					
					case 1:												//界面1:温度最大值加
						if(temp_max < 99)
							temp_max++;
					break;
					
					case 2:												//界面2:温度最小值加
						if(temp_min < temp_max-1)
							temp_min++;
					break;
					
					case 3:												//界面3:设定时间“时”加
						if(count_hour_old < 100)
							count_hour_old++;
					break;
					
					case 4:												//界面4:设定时间“分”加
						count_minute_old++;
						if(count_minute_old >= 60)
							count_minute_old = 0;
					break;
					
					case 5:												//界面5:设定时间“秒”加
						count_second_old++;
						if(count_second_old >= 60)
							count_second_old = 0;
					break;
					default:
					break;
				}
			break;

			case 3:														//按键3:设定值减
				switch(flag_display)
				{
					case 0:									      //界面0:手动控制散热
						flag_mode = 1;	
						JR = 0;
						SR = !SR;
					break;
					
					case 1:												//界面1:温度最大值减
						if(temp_max > temp_min+1)
							temp_max--;
					break;
					
					case 2:												//界面2:温度最小值减
						temp_min--;
					break;
					
					case 3:												//界面3:设定时间“时”减
						if(count_hour_old > 0)
							count_hour_old--;
					break;
					
					case 4:												//界面4:设定时间“分”减
						count_minute_old--;
						if(count_minute_old < 0)
							count_minute_old = 59;
					break;
					
					case 5:												//界面5:设定时间“秒”减
						count_second_old--;
						if(count_second_old < 0)
							count_second_old = 59;
					break;
					default:
					break;
				}
			break;		
				
			case 4:														//按键4:手动自动模式切换
				if(flag_display == 0)
					flag_mode = 0;			
			break;
			default:
				
			break;
		}
	}
}

/****
*******监测函数
*****/
void Monitor_function(void)
{
	u32 weight_test = 0;
	
	if(flag_display == 0)									//测量界面
	{
		if(time_num % 3 == 0)							//获取数据
		{
			DHT11_Read_Data(&temp_value,&humi_value);
			if(flag_weight == 0)
			{
				weight_maopi = Hx711_Get_Maopi();								//获取毛皮重量
				flag_weight = 1;
			}
			else
				weight_test = Hx711_Get_Weight(weight_maopi);	//获取总重量
				if(weight_test < 5000)
					weight_value = weight_test;
		}
		
		if(time_num % 50 == 0)							//发送数据
		{
			UsartPrintf(USART1,"温度:%dC\r\n",temp_value);
			UsartPrintf(USART1,"湿度:%d%%\r\n",humi_value);
			UsartPrintf(USART1,"时间:%d%d:%d%d:%d%d\r\n",count_hour/10,count_hour%10,count_minute/10,count_minute%10,count_second/10,count_second%10);
		}
		
		if(USART1_WaitRecive() == 0)				//如果接收到蓝牙数据
		{
			switch(usart1_buf[0])
			{
				case('A'):											//A:切换自动模式
					if(flag_display == 0)
						flag_mode = 0;	
				break;

				case('B'):											//B:加热					
					flag_mode = 1;	
					JR = !JR;
					SR = 0;
				break;
				
				case('C'):											//C:散热
					flag_mode = 1;	
					JR = 0;
					SR = !SR;
				break;

				default:
				
				break;
			}	
			USART1_Clear();
		}
	}
}

/****
*******显示函数
*****/
void Display_function(void)
{
	switch(flag_display)									//根据不同的显示模式标志位,显示不同的界面
	{
		case 0:									      			//界面0:显示模式,温度,湿度,时间
			Oled_ShowCHinese(1,0,"模式:");
			Oled_ShowCHinese(2,0,"温度:");
			sprintf(display_buf,"%dC",temp_value);
			Oled_ShowString(2,6,display_buf);
			Oled_ShowCHinese(3,0,"湿度:");			
			sprintf(display_buf,"%d%%",humi_value);
			Oled_ShowString(3,6,display_buf);				
			Oled_ShowCHinese(4,0,"时间:");
			sprintf(display_buf,"%d%d:%d%d:%d%d",count_hour/10,count_hour%10,count_minute/10,count_minute%10,count_second/10,count_second%10);
			Oled_ShowString(4,6,display_buf);
			if(flag_mode == 0)
				Oled_ShowCHinese(1,3,"自动");
			else
				Oled_ShowCHinese(1,3,"手动");
		break;
		
		case 1:															//界面1:显示设置温度最大值
			Oled_ShowCHinese(1,1,"设置温度最大值");
			if(time_num % 10== 0)
			{
				sprintf(display_buf,"%d%d",temp_max/10,temp_max%10);
				Oled_ShowString(2,7,display_buf);
			}
			if(time_num % 20 == 0)
			{
				Oled_ShowString(2,7,"    ");
			}	
		break;
		
		case 2:															//界面2:显示设置温度最小值
			Oled_ShowCHinese(1,1,"设置温度最小值");
			if(time_num % 10== 0)
			{
				sprintf(display_buf,"%d%d",temp_min/10,temp_min%10);
				Oled_ShowString(2,7,display_buf);
			}
			if(time_num % 20 == 0)
			{
				Oled_ShowString(2,7,"    ");
			}	
		break;
		
		case 3:															//界面3:显示设置时间时
			Oled_ShowCHinese(1,1,"设置时间时");
			if(time_num % 10== 0)
			{
				sprintf(display_buf,"%d%d:%d%d:%d%d",count_hour_old/10,count_hour_old%10,count_minute_old/10,count_minute_old%10,count_second_old/10,count_second_old%10);
				Oled_ShowString(2,4,display_buf);
			}
			if(time_num % 20 == 0)
			{
				Oled_ShowString(2,4,"  ");
			}	
		break;
		
		case 4:															//界面4:显示设置时间分
			Oled_ShowCHinese(1,1,"设置时间分");
			if(time_num % 10== 0)
			{
				sprintf(display_buf,"%d%d:%d%d:%d%d",count_hour_old/10,count_hour_old%10,count_minute_old/10,count_minute_old%10,count_second_old/10,count_second_old%10);
				Oled_ShowString(2,4,display_buf);
			}
			if(time_num % 20 == 0)
			{
				Oled_ShowString(2,7,"  ");
			}	
		break;
		
		case 5:															//界面5:显示设置时间秒
			Oled_ShowCHinese(1,1,"设置时间秒");
			if(time_num % 10== 0)
			{
				sprintf(display_buf,"%d%d:%d%d:%d%d",count_hour_old/10,count_hour_old%10,count_minute_old/10,count_minute_old%10,count_second_old/10,count_second_old%10);
				Oled_ShowString(2,4,display_buf);
			}
			if(time_num % 20 == 0)
			{
				Oled_ShowString(2,10,"  ");
			}	
		break;	
			
		default:
			
		break;
	}
}

/****
*******处理函数
*****/
void Manage_function(void)
{
	if(flag_display == 0)                  								//测量界面
	{
		if(flag_mode == 0)
		{
			if(temp_value > temp_max)											//温度高于最大值开启散热
			{
				SR = 1;		
				JR = 0;
			}
			else if(temp_value < temp_min)									//温度小于最小值加热
			{
				SR = 0;		
				JR = 1;
			}
			else																							//温度低于最大值且温度大于最小值,关闭散热和加热
			{
				SR = 0;		
				JR = 0;
			}
		}
		
		if(weight_value > 5 )																//人坐上坐垫开始计时
		{
			flag_timer_begin_1s = 1;											
			
			if(count_hour_old != 0 || count_minute_old != 0 || count_second_old != 0)	//设置时间不为零,同时到达设置时间时播报"请劳逸结合,注意起身运动"
			{
				if(count_hour == count_hour_old && count_minute == count_minute_old && count_second == count_second_old)
				{
					UsartPrintf(USART2,"A7:00002");
					Delay_ms(1500);
				}
			}								
		}		
		else																									//人离开坐垫		
		{
			flag_timer_begin_1s = 0;	
			count_hour = 0;																			//重新赋值计时时间
			count_minute = 0;
			count_second = 0;
		}
	}
	else													         									//设置界面:关闭加热,散热,定时器
	{
		flag_timer_begin_1s = 0;	
		SR = 0;		
		JR = 0;	
	}
}

六、实验效果 

七、资料内容

项目分享

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值