【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);  //清楚更新中断标志位,如果不清除,会一直进中断
	}
}

七、项目资料包内容

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

相关推荐
mc23563 小时前
以江协科技STM32入门教程的方式打开FreeRTOS——STM32C8T6如何移植FreeRTOS
科技·stm32·嵌入式硬件
v_for_van4 小时前
STM32简单的串口Bootloader入门
笔记·stm32·单片机·嵌入式硬件·物联网·学习
东木君_5 小时前
RK3588:MIPI底层驱动学习——入门第四篇(驱动精华:OV13855驱动加载时究竟发生了什么?)
单片机·嵌入式硬件·学习
东方欲晓w5 小时前
STM32 UART篇
stm32·单片机·嵌入式硬件
A9better7 小时前
嵌入式开发学习日志33——stm32之PWM舵机简单项目
stm32·单片机·嵌入式硬件·学习
CiLerLinux7 小时前
第三十八章 ESP32S3 SPIFFS 实验
图像处理·人工智能·单片机·嵌入式硬件
国科安芯7 小时前
关于软错误的常见问题解答
单片机·嵌入式硬件·安全·硬件架构·软件工程
jianqiang.xue7 小时前
ESP32-S3入门第九天:摄像头入门与应用
单片机·嵌入式硬件·物联网
一枝小雨9 小时前
FreeRTOS下STM32双缓冲ADC数据采集与处理
stm32·单片机·dma·嵌入式·arm·freertos·adc