【STM32项目开源】基于STM32的智能老人拐杖
目录
一、设计背景和意义
1.1设计背景
1.2设计意义
二、实物效果展示
2.1实物图片
2.2实物演示视频
三、硬件功能简介
3.1项目功能详解
3.2元器件清单
四、主框图与软件流程图
五、硬件PCB展示
六、软件程序设计
七、项目资料包内容
资料获取:查看主页介绍“充哥单片机设计”
一、设计背景和意义
1.1设计背景
随着我国老龄化社会进程的加速,老年人群体在社会总人口中的比例逐年上升。据国家统计局发布的数据,60岁及以上人口已超过2.8亿,占全国总人口的19.8%。这一趋势所带来的最直接挑战之一便是如何保障老年人在日常生活中的安全与健康。尤其是在独居或外出过程中,老年人往往因身体机能衰退、反应迟缓、视力减退等原因,容易发生摔倒、迷路或其他突发情况。而这些事故由于无法第一时间被外界知晓,往往造成严重后果甚至生命危险。
传统的老人拐杖虽然能够在一定程度上提供物理支撑,但无法满足对复杂环境的识别与响应,也缺乏与外界沟通的能力。而当前市面上部分所谓“智能拐杖”产品,普遍存在功能单一、系统不稳定、智能化水平低、缺乏云端数据管理与交互等问题,难以在实际应用中提供真正有效的智能守护。
1.2设计意义
本课题设计的智能老人拐杖不仅能够实现传统拐杖的基本支撑功能,更在摔倒检测、障碍预警、自动照明、定位追踪和语音求助等方面实现多重智能化升级,填补现有辅助工具在安全性、智能化和远程监护上的空白。通过高度集成的软硬件系统和完善的物联网平台,提升了设备的实用性与互动性,有助于老年人更独立、自信地出行,同时极大降低因意外导致的伤害风险,减轻社会医疗和护理资源的压力。
此外,该课题的研究过程也促进了学生对嵌入式系统设计、传感器融合、无线通信及云平台应用等多学科知识的综合运用与创新能力培养,推动智能硬件在老龄健康领域的技术进步与产业发展。长远来看,该系统所积累的用户行为和健康数据,还可为老年健康管理、疾病预防和智慧养老服务提供宝贵的数据支撑和决策依据,具有广阔的应用前景和社会价值。
二、实物效果展示
2.1实物图片
2.2实物演示视频
【开源】基于STM32的智能老人拐杖
三、硬件功能简介
3.1项目功能详解
1)障碍检测:超声波传感器检测前方的障碍物距离
2)跌倒检测:ADXL345三轴加速度传感器检测老人是否跌倒
3)GPS定位:GPS实时检测老人的经纬度坐标数据
4)光强检测:检测到天黑后,会自动打开闪光灯
5)水位检测:水位传感器检测前方水位过深进行报警
6)跌倒报警:老人跌倒后,语音模块会播报求助信息,求助路人
7)语音播报:当检测到的障碍物距离过近会语音提醒,老人跌倒会语音求助路人
8)数据显示:0.96OLED屏幕
9)短信求助:老人摔倒或按下求助按键发送求助短信给紧急联系人
3.2元器件清单
- 主控STM32F103C8T6最小系统板
- 0.96OLED显示屏幕
- 水位传感器
- 超声波传感器
- ADXL345三轴加速度传感器
- JQ6500语音模块
- GPS定位
- 光敏电阻
- 闪光灯
四、主框图与软件流程图
主框图
流程图
五、硬件PCB展示
六、软件程序设计
#include "delay.h"
#include "sys.h"
#include "bmp.h"
#include "usart.h"
#include "control.h"
#include "key.h"
#include "timer.h"
#include "oled.h"
#include "adc.h"
#include "hc-sr04.h"
#include "timer2.h"
#include "adxl345.h"
#include "iic.h"
#include "GSM.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];float longitude_Degree = 116.369856;
float latitude_Degree = 45.156986;
float adx,ady,adz;
float acc,acc2;
uint8_t tiltFlag = 0;
uint8_t fallTime = 9;
uint8_t send_flag = 0;
uint8_t sos_flag = 0;
uint8_t warn_flag = 9;uint8_t length_flag = 9;int light_door = 3000;
int length_door = 1;/**** 菜单变量 ****/
uint8_t keu_num = 0; //按键赋值
uint8_t page_num = 1; //页面ID
uint8_t option = 0; //阈值选项void get_all_sensor_data(); //传感器数据采集
void Sensor_Data_Handle(); //不同模式下控制效果
void Key_event_handle(void); //按键功能函数
void All_Pin_Init(void); //系统初始化函数
void LongiAndLatiChangeUnicode(char *str1,char *str2);//经纬度坐标转Unicode码void OLED_Show_FirstPage(); //第一屏显示内容
void OLED_Show_SecondPage(); //第二屏显示内容
void FallDetection(void); //摔倒检测void All_Pin_Init(void)
{delay_init(); //系统延时函数初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable,ENABLE);//改变指定管脚的映射,JTAG-DP 禁用 + SW-DP 使能OLED_Init(); //屏幕初始化uart3_init(115200); //串口3初始化,波特率115200uart1_init(9600); //串口1初始化,波特率9600uart2_init(9600); //串口2初始化,波特率9600KEY_Init(); //按键初始化TIME_Config(); //定时器初始化Control_Init(); //照明初始化Adc_Init(); //水位、光照检测初始化HC_SR04_Init(); //超声波测距初始化Timer2_Init(9,14398); //定时器初始化IIC_init(); //摔倒检测初始化adxl345_init();
}int main(void)
{All_Pin_Init();while(1) { if(Time_Period[1]>1000){get_all_sensor_data(); //传感器数据采集Time_Period[1] = 0;}Key_event_handle(); //按键监测Sensor_Data_Handle(); //数据处理if(page_num == 1){ //屏幕更新OLED_Show_FirstPage();}else if(page_num == 2){OLED_Show_SecondPage();}if(sos_flag==1){ //发送求助短信sos_flag = 0;GSM_Init();memset(SEND_BUF,0,400);delay_ms(100);strncpy(SEND_BUF,"62119047523056F096BEFF0C970089815E2E52A9FF01",44); //我遇到困难,需要帮助!GSM_send_msg(PhoneNumber,(char*)SEND_BUF);}}
}void Key_event_handle(void)
{keu_num = KEY_Scan(0); //按键扫描赋值switch(keu_num){case 1: //按键1按下if(page_num == 1){page_num++;OLED_Clear();OLED_Show_SecondPage();}else if(page_num == 2){option++;if(option == 3){page_num = 1;option = 0;OLED_Clear();OLED_Show_FirstPage();}else {OLED_Show_SecondPage();}}break;case 2: //按键2按下if(page_num == 2){if(option == 1){light_door += 1;}else if(option == 2){length_door += 1;}OLED_Show_SecondPage();}break;case 3: //按键3按下if(page_num == 2){if(option == 1){light_door -= 1;}else if(option == 2){length_door -= 1;}OLED_Show_SecondPage();}break;case 4: //按键4按下sos_flag = 1; //紧急求助,准备发送求助短信break;}
}void get_all_sensor_data()
{HC_SR04_Deboanle(&distance); //获取前方障碍物距离Get_Light_Value(&Light_Value); //获取环境光照强度Get_Water_Value(&Water_Value); //获取前方积水FallDetection(); //摔倒检测
}
void Sensor_Data_Handle()
{//光照强度低于阈值打开补光灯if(Light_Value<light_door)LED=0;else LED=1;if(Time_Period[0]>1000) //Time_Period[0] 在定时器中累加{Time_Period[0] = 0;if(tiltFlag==1)fallTime++;if(fallTime>10){ //摔倒检测,标志位累加超过10,判定为摔倒fallTime = 0;UART1_SendBuff(sound2_buf,6); //语音提醒}if(Water_Value>20)warn_flag++;if(warn_flag>10){ //积水检测,语音报警提醒warn_flag = 0;UART1_SendBuff(sound0_buf,6);}if(distance<length_door)length_flag++;if(length_flag>10){ //前方障碍物检测,语音报警提醒length_flag = 0;UART1_SendBuff(sound1_buf,6);}}
}/*经(0) 纬(1) 度(2) 光(3) 照(4) 障(5) 碍(6) 物(7) 距(8) 离(9) 心(10) 率(11) 血(12) 氧(13) 水(14) 位(15)活(16) 动(17) 状(18) 态(19) 正(20) 常(21) 摔(22) 倒(23) 阈(24) 值(25)
*/
void OLED_Show_FirstPage()
{OLED_ShowChinese(16*0,16,3,16,1);OLED_ShowChinese(16*1,16,4,16,1);OLED_ShowChar(16*2,16,':',16,1);OLED_ShowNum(16*2+8,16,Light_Value,4,16,1);if(sos_flag==1){OLED_ShowString(16*6+8,0,"SOS",16,1);}else{OLED_ShowString(16*6+8,0," ",16,1);}OLED_ShowChinese(16*0,0,14,16,1);OLED_ShowChinese(16*1,0,15,16,1);OLED_ShowChar(16*2,0,':',16,1);OLED_ShowNum(16*2+8,0,Water_Value,2,16,1);OLED_ShowChar(16*3+8,0,'%',16,1);OLED_ShowChinese(16*0,32,16,16,1);OLED_ShowChinese(16*1,32,17,16,1);OLED_ShowChinese(16*2,32,18,16,1);OLED_ShowChinese(16*3,32,19,16,1);OLED_ShowChar(16*4,32,':',16,1);if(tiltFlag==1){OLED_ShowChinese(16*4+8,32,22,16,1);OLED_ShowChinese(16*5+8,32,23,16,1);}else{OLED_ShowChinese(16*4+8,32,20,16,1);OLED_ShowChinese(16*5+8,32,21,16,1);}OLED_ShowChinese(16*0,48,5,16,1);OLED_ShowChinese(16*1,48,6,16,1);OLED_ShowChinese(16*2,48,7,16,1);OLED_ShowChinese(16*3,48,8,16,1);OLED_ShowChinese(16*4,48,9,16,1);OLED_ShowChar(16*5,48,':',16,1);OLED_ShowNum(16*5+8,48,distance,3,16,1);OLED_ShowChar(16*7,48,'m',16,1);OLED_Refresh();
}void OLED_Show_SecondPage()
{OLED_ShowChinese(16*0,0,3,16,1);OLED_ShowChinese(16*1,0,4,16,1);OLED_ShowChinese(16*2,0,24,16,1);OLED_ShowChinese(16*3,0,25,16,1);OLED_ShowChar(16*4,0,':',16,1);if(option==1)OLED_ShowNum(16*4+8,0,light_door,4,16,0);else OLED_ShowNum(16*4+8,0,light_door,4,16,1);OLED_ShowChinese(16*0,16,5,16,1);OLED_ShowChinese(16*1,16,6,16,1);OLED_ShowChinese(16*2,16,7,16,1);OLED_ShowChinese(16*3,16,8,16,1);OLED_ShowChinese(16*4,16,9,16,1);OLED_ShowChar(16*5,16,':',16,1);if(option==2)OLED_ShowNum(16*5+8,16,length_door,3,16,0);else OLED_ShowNum(16*5+8,16,length_door,3,16,1);sprintf((char *)display,"%10.6f ",longitude_Degree);OLED_ShowChinese(16*0,32,0,16,1); //经OLED_ShowChinese(16*1,32,2,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,1,16,1); //纬OLED_ShowChinese(16*1,48,2,16,1); //度OLED_ShowChar(16*2,48,':',16,1);OLED_ShowString(16*3,48,(u8*)display,16, 1);//显示纬度OLED_Refresh();
}
void FallDetection(void)//倾斜检测
{u8 i;adxl345_read_average(&adx,&ady,&adz,10);//获取数据acc=ady;acc2=adx;if(acc<0)acc=-acc;if(acc2<0)acc2=-acc2;if(((u16)acc)>=190 || ((u16)acc2)>=190)//检测到倾斜{tiltFlag=1;}else{tiltFlag=0;}
}