【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元器件清单
- 主控STM32F103C8T6最小系统板
- 0.96OLED显示屏幕
- JDY-31蓝牙模块
- DS18B20温度传感器
- MAX30102心率血氧传感器
- GPS定位模块
- 按键
四、主框图与软件流程图
主框图
流程图
五、硬件PCB展示
六、软件程序设计
#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 48unsigned 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_doorOLED_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_doorOLED_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_doorOLED_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; //未连接蓝牙时,按键手动将标志位置0break;}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); //清楚更新中断标志位,如果不清除,会一直进中断}
}