【STM32项目开源】基于STM32的智能宠物防丢监控系统

目录

一、设计背景和意义

1.1设计背景

1.2设计意义

二、实物效果展示

2.1实物图片

2.2实物演示视频

三、硬件功能简介

3.1项目功能详解

3.2元器件清单

四、主框图与软件流程图

五、硬件PCB展示

六、软件程序设计

七、项目资料包内容

资料获取:查看主页介绍"充哥单片机设计"


一、设计背景和意义

1.1设计背景

随着人们生活质量的不断提升,宠物在人类生活中的地位逐渐从"陪伴者"上升为"家庭成员"。尤其在城市生活节奏加快、人口结构变化的背景下,宠物成为许多家庭缓解孤独、丰富精神生活的重要方式。然而,与之相对的是,宠物饲养过程中的管理难题也逐渐凸显。尤其是在宠物活动自由度较高的情况下,宠物意外走失、突发健康状况未被及时察觉等问题频繁发生,给宠物本身带来潜在风险,也让主人承受了不小的心理与经济负担。目前市面上虽已有部分宠物定位设备或健康监测产品,但普遍存在功能单一、系统集成度低、智能化水平不高的问题。许多产品仅能实现基础的GPS定位功能,无法同步监测宠物的健康数据,且缺乏有效的互动方式,例如远程语音唤回或状态告警等,无法在紧急情况下为主人提供有力支持。部分带有心率或体温监测功能的高端设备虽然技术先进,但价格昂贵,难以大范围普及。

1.2设计意义

本研究的实施不仅能够提升宠物看护的智能化水平,提高宠物安全与健康保障能力,还可以为后续智能宠物硬件的开发提供理论支撑和实践基础。更重要的是,该系统具有良好的推广前景,不仅适用于普通家庭养宠场景,也可延伸应用于宠物医院、寄养中心、动物救助机构等多种领域,对推动智慧养宠、促进宠物科技产业发展具有积极的现实意义与长远价值。

二、实物效果展示

2.1实物图片

2.2实物演示视频

【开源】基于STM32的宠物防丢监控定位系统

三、硬件功能简介

3.1项目功能详解

1)心率血氧检测:检测宠物的心率、血氧数据。

2)体温检测:检测宠物的体温数据。

3)阈值设定:设定宠物的心率、血氧、体温的阈值数据。

4)异常报警:心率、血氧、体温数据超过阈值,蜂鸣器报警。

5)GPS定位:实时定位宠物的经纬度坐标数据。

6)蓝牙App:与系统进行连接,将心率、血氧、体温、经纬度数据。

7)远离报警:当宠物远离蓝牙的范围,自动开启报警提醒主人。

8)语音呼唤:当宠物远离主人的蓝牙手机范围,语音呼唤宠物返回。

9)数据显示:0.96OLED屏幕显示全部的传感器数据以及传感器的阈值等数据。

3.2元器件清单

  1. 主控STM32F103C8T6最小系统板
  2. 0.96OLED显示屏幕
  3. JDY-31蓝牙模块
  4. DS18B20温度传感器
  5. MAX30102心率血氧传感器
  6. GPS定位模块
  7. 按键

四、主框图与软件流程图

主框图

流程图

五、硬件PCB展示

六、软件程序设计

cpp 复制代码
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"	 
//#include "OLED.h"
#include "string.h" 	
#include "max30102.h"
#include "ds18b20.h"
#include "beep.h"
#include "key.h"
#include "timer.h"
#include "oled.h"


/****  数据变量  ****/
#define STM32_RX1_BUF       Usart1RecBuf 
#define STM32_Rx1Counter    Rx1Counter
#define STM32_RX1BUFF_SIZE  USART1_RXBUFF_SIZE

#define GPS_STR_LEN 48

unsigned char display[16];

int temp_door = 38;			//体温上限
int oxy_door = 90;			//血氧下限
int heart_door = 100;		//心率上线

uint8_t send_flag = 0;
uint8_t send_time = 3;
uint8_t printd_flag = 0;

/****  菜单变量  ****/
uint8_t option = 0;			//阈值选项
uint8_t key_num = 0;		//按键赋值
uint8_t page_id = 1;		//页面ID

/****  功能函数声明  ****/
void oled_show_onepage();		//第一屏显示内容
void oled_show_twopage();		//第二屏显示内容

void get_all_sensor_data();		//传感器数据采集
void Sensor_Data_Handle();		//不同模式下控制效果

int main(void)
{
	delay_init();
	OLED_Init(); //OLED初始化
	uart2_init(9600);
	USART1_Config();
	uart3_init(9600);
	DS18B20_Init();
	MAX30102_Init();
  
	un_min=0x3FFFF;
	un_max=0;
	Max30102_right_data();

  BEEP_Init();
  beep = 0;
  KEY_Init();
  
	TIME_Config();
	while(1)
	{
		get_all_sensor_data();		//传感器数据采集
		if(Time_Period[1]>1000)		//Time_Period[1] 在定时器中累加
		{
			Time_Period[1] = 0;
			if(page_id == 1){		//屏幕更新
				oled_show_onepage();
			}else if(page_id == 2){
				oled_show_twopage();
			}
			
			if(send_flag==1){		//发送语音提醒
				send_time++;
				if(send_time>=5){
					send_time=0;
					BY_U2_SendBuff(sound_buf,7);
				}
			}
			printd_flag = !printd_flag;
			if(printd_flag==1){		//蓝牙消息发送
				printf("\r\n\r\n\r\n\r\n");	
				printf("*********************\r\n");
				printf("心率:%d次/分钟 血氧:%d%%\r\n",dis_hr,dis_spo2);
				printf("体温:%d℃\r\n",body_temp);
				printf("经度:%10.6f\r\n",longitude_Degree);
				printf("纬度:%10.6f\r\n",latitude_Degree);
				printf("*********************\r\n");		
			}				
		}
		Sensor_Data_Handle();		//数据处理

	}
}

void Sensor_Data_Handle()
{
	//体温超过上限 或 心率超过上限 或 血氧低于下限且大于0,蜂鸣器报警提醒
	if(body_temp>temp_door||dis_hr>heart_door||(dis_spo2<oxy_door&&dis_spo2>0))beep=1;
	else beep=0;
	
}
void get_all_sensor_data()		//获取数据
{
	body_temp = DS18B20_Get_Temp();		//获取体温数据
	Get_Max30102_Data();				//获取心率血氧

}
// 心(0) 率(1) 血(2) 氧(3) 体(4) 温(5) ℃(6) 宠(7) 物(8) 状(9) 态(10) 正(11) 常(12) 经(13) 纬(14) 度(15) 阈(16) 值(17)

void oled_show_onepage(){
	
	OLED_ShowChinese(16*0,0,0,16,1);			//心
	OLED_ShowChinese(16*1,0,1,16,1);			//率
	OLED_ShowChar(16*2,0,':',16,1);
	OLED_ShowNum(16*2+8,0,dis_hr,3,16,1);		//心率数据
	
	OLED_ShowChinese(16*4,0,2,16,1);			//血
	OLED_ShowChinese(16*5,0,3,16,1);			//氧
	OLED_ShowChar(16*6,0,':',16,1);
	OLED_ShowNum(16*6+8,0,dis_spo2,3,16,1);		//血氧数据

	OLED_ShowChinese(16*0,16,4,16,1);			//体
	OLED_ShowChinese(16*1,16,5,16,1);			//温
	OLED_ShowChar(16*2,16,':',16,1);
	OLED_ShowNum(16*2+8,16,body_temp,2,16,1);	//体温数据
	
	OLED_ShowNum(16*6+8,16,lanya_flag,3,16,1);

	sprintf((char *)display,"%10.6f ",longitude_Degree);
	OLED_ShowChinese(16*0,32,13,16,1);			//经
	OLED_ShowChinese(16*1,32,15,16,1);			//度
	OLED_ShowChar(16*2,32,':',16,1);
	OLED_ShowString(16*3,32,(u8*)display,16, 1);//显示经度

	sprintf((char *)display,"%10.6f ",latitude_Degree);
	OLED_ShowChinese(16*0,48,14,16,1);			//纬
	OLED_ShowChinese(16*1,48,15,16,1);			//度
	OLED_ShowChar(16*2,48,':',16,1);
	OLED_ShowString(16*3,48,(u8*)display,16, 1);//显示纬度
	
	OLED_Refresh();
}

void oled_show_twopage(){
	
	uint8_t a,b,c,d;
	if(option==1){a=0;b=1;c=1;d=1;}
	else if(option==2){a=1;b=0;c=1;d=1;}
	else if(option==3){a=1;b=1;c=0;d=1;}
	else {a=1;b=1;c=1;d=1;}
	
	OLED_ShowChinese(16*0,0,0,16,1);			//	"心"
	OLED_ShowChinese(16*1,0,1,16,1);			//	"率"
	OLED_ShowChinese(16*2,0,16,16,1);			//	"阈"
	OLED_ShowChinese(16*3,0,17,16,1);			//	"值"
	OLED_ShowChar(16*4,0,':',16,1);				//	":"
	OLED_ShowNum(16*4+8,0,heart_door,3,16,a);		//	heart_door
	
	OLED_ShowChinese(16*0,16,2,16,1);			//	"血"
	OLED_ShowChinese(16*1,16,3,16,1);		  	//	"氧"
	OLED_ShowChinese(16*2,16,16,16,1);			//	"阈"
	OLED_ShowChinese(16*3,16,17,16,1);			//	"值"
	OLED_ShowChar(16*4,16,':',16,1);			//	":"
	OLED_ShowNum(16*4+8,16,oxy_door,3,16,b);		//	oxy_door

	
	OLED_ShowChinese(16*0,32,4,16,1);		//	"体"
	OLED_ShowChinese(16*1,32,5,16,1);		//	"温"
	OLED_ShowChinese(16*2,32,16,16,1);		//	"阈"
	OLED_ShowChinese(16*3,32,17,16,1);		//	"值"
	OLED_ShowChar(16*4,32,':',16,1);			//	":"
	OLED_ShowNum(16*4+8,32,temp_door,3,16,c);		//	temp_door

	
	OLED_Refresh();
}

void TIM3_IRQHandler(void)
{
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)  //检测更新中断是否发生
	{
	key_num = KEY_Scan(0);		//按键扫描赋值
	switch(key_num)
	{
		case 1:		//按键1按下
			if(page_id==1){
				page_id=2;
				OLED_Clear();oled_show_twopage();
			}else if(page_id==2){
				option++;
				if(option>3){
					option=0;
					page_id=1;
					OLED_Clear();oled_show_onepage();
				}else oled_show_twopage();
			}
			break;
		case 2:		//按键2按下
			if(page_id==2){
				if(option==1)heart_door+=1;
				else if(option==2)oxy_door+=1;
				else if(option==3)temp_door+=1;
				oled_show_twopage();
			}
			break;
		case 3:		//按键3按下
			if(page_id==2){
				if(option==1)heart_door-=1;
				else if(option==2)oxy_door-=1;
				else if(option==3)temp_door-=1;
				oled_show_twopage();
			}
			break;
		case 4:		//按键4按下
			lanya_flag = 0;		//未连接蓝牙时,按键手动将标志位置0
			break;

	}
		
		Time_Period[0]++;
		Time_Period[1]++;
	
		if(Time_Period[0]>1000)
		{
			lanya_flag++;		//蓝牙断连后,标志位每秒钟累加
			if(lanya_flag>=10)send_flag=1;		//超过10之后,开始发送提醒语音
			else send_flag=0;
			Time_Period[0] = 0;
		}
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);  //清楚更新中断标志位,如果不清除,会一直进中断
	}
}

七、项目资料包内容

资料获取:查看主页介绍"充哥单片机设计"

相关推荐
d111111111d5 分钟前
在STM32中,中断服务函数的命名有什么要求?
笔记·stm32·单片机·嵌入式硬件·学习·c#
易水寒陈14 分钟前
MultiTimer源码分析
stm32·单片机
白羽陌24 分钟前
STM32入门教程
stm32·单片机·嵌入式硬件
高工智能汽车1 小时前
车规MCU,开启“巨变”
单片机·嵌入式硬件
TEL136997627501 小时前
PTCB818A说明书 配套PL27A1芯片MCU参数说明
网络·单片机·嵌入式硬件
硬汉嵌入式2 小时前
【无标题】
stm32·wifi·英飞凌·sdio·赛普拉斯·cyw43·cyw55
客家元器件2 小时前
LPDDR5选型参数
嵌入式硬件
一个平凡而乐于分享的小比特2 小时前
单片机内部时钟 vs 外部时钟详解
单片机·嵌入式硬件·内部时钟·外部时钟
d111111111d3 小时前
编码器测速详情解释:PID闭环控制
笔记·stm32·单片机·嵌入式硬件·学习·算法
福大大架构师每日一题3 小时前
ollama v0.13.4 发布——全新模型与性能优化详解
stm32·嵌入式硬件·性能优化·ollama