• 【毕业设计】基于单片机的智能手环 -计步器 嵌入式 物联网 stm32



    1 简介

    Hi,大家好,这里是丹成学长,今天向大家介绍一个 单片机项目

    基于单片机的智能手环 -计步器

    大家可用于 课程设计 或 毕业设计


    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    1 项目背景意义

    随着智能化时代的来临, 无线互联与智能化处理软件的大面积普及。 传统的就医形式已经通过网络互联科技而变得高效, 但是, 纵然在这种趋势下, 老年人就医依然面临很多困境, 种种的原因导致很多老年人突发疾病但是没能得多及时的救治。 老年智能手环主要致力于深入到整个救治老年人环节中, 促进几个关键人群的及时反应、 智能互联、 信息互通。 如何高效、 精准、 相对简洁的去实现种种义务之间的平衡, 包括子女对老人的赡养义务, 在大批量救治病患的过程中, 医生如何平衡好对每一个病人的义务。

    随着科学技术的革新,智能化生活已经开始实现,更多的人们的目光聚焦在智能化产品上面,一方面是对自身健康的关注,另一方面是对便携轻松的生活的向往,智能手环就作为其中的一种代表性产物。其主要应用于运动显示比如显示行走及跑步的步数,距离,速度。同时可以实时健康监测比如心率,血氧,体温等。是一款突出个性与人性的智能化产物。

    2 系统方案的设计

    本设计是由STM32F103C8T6最小系统电路,DS3231时钟模块,ADXL345计步模块,MAX30100血氧心率模块,DS18B20温度模块,MPU6050体位检测模块,1.44寸TFT彩色液晶屏显示模块组成的嵌入式智能手环系统。

    • (1)通过DS3231时钟模块实现日期显示的功能

    • (2)使用传感器ADXL345检测人步数

    • (3)通过MAX30100传感器实时检测血氧心率;

    • (4)通过传感器DS18B20进行温度测量。

    • (5)通过MPU6050体位检测卧床病人是否跌倒或可以通过此功能蜂鸣器警报呼叫。

    • (6)通过1.44寸TFT彩色液晶屏实时显示日期,步数,距离,心率,血氧,跌倒状态以及温度值。

    3 系统总体结构

    在这里插入图片描述

    4 系统硬件设计

    4.1 主控模块

    STM32C8T6(最小核心板),当然,用其他型号的32,如STM32ZET6也是可以的。

    在这里插入图片描述

    4.2 姿态解算模块:MPU6050

    在这里插入图片描述

    4.3 DS3231实物图

    在这里插入图片描述

    4.4 TFT显示模块

    在这里插入图片描述

    4.5 硬件连接效果

    在这里插入图片描述

    5 跌倒检测算法原理

    当人体正常行走时, 合成加速度在 1g 至 2.5g 左右, 如下图所示。 当人体不论从何方向跌落时, 垂直方向的位置和速度都将会改变, 所以加速度和俯仰角也会随着而变化。 如图 4.7 中设置采样频率为 350Hz 并且可以看出图中跌倒过程中各个方向加速度变化情况。 当手环佩戴者跌落时, 整个过程持大约持续约 2 秒, 其加速度曲线变化是先减小然后增加, 最后稳定。 可以得出结论, 坠落是一个暂时的过程, 在这个过程中, 测试者经历失重、 撞击和静止三个状态。 在下降过程中, 合成加速度的最大值约为 2.6 g, 并且有 7 个连续采样点的合成加速度为 2.0 g 或更多。 当人摔倒时, 通过对人体姿态角的采样, 人体的俯仰角和侧翻角都会发生变化, 在跌倒后有一个或更多姿态角的绝对值大于 45°。

    在这里插入图片描述

    5.1 跌倒检测的判定流程

    在这里插入图片描述
    跌倒最开始的加速度会是最大的, 当跌倒后人的自然反应会让加速度有所减小,所以跌倒有两个阈值, 第一个阈值较大为触发阈值, 第二个阀组为持续阈值, 然后在50 个周期内计时, 是否有 80%时间为大于第二个跌倒阈值的, 有这两个持续过程则判定为跌倒, 否则丢弃跌倒判定数据, 跌倒流程图如上图。

    5.2 关键算法实现

    if(adxl345_flag == 1)
    	{	
    		adxl345_flag = 0;
    		Multiple_Byte_Read(0x32);//采样
    		sampling_cnt++;//采样次数
    		sampling_cnt0++;
    /*-------------------平均滤波算法-----------------*/
    	
    	for(i=0;i<3;i++)//0->x 1->y 2->z
    	{
    
    		reg_buf3[i] =  reg_buf2[i];
    
    		reg_buf2[i] =  reg_buf1[i];
    
    		reg_buf1[i] =  reg_buf0[i];
    		reg_buf0[i] =  (buf[2*i+1] << 8) + buf[2*i];//数据合成
    		
    		filter_out[i] = (reg_buf0[i] + reg_buf1[i] + reg_buf2[i] +reg_buf3[i])/4;
    		
    		if(filter_max[i] < filter_out[i]) filter_max[i] = filter_out[i];
    		if(filter_min[i] > filter_out[i]) filter_min[i] = filter_out[i];
    	}
    /*-------------------动态阈值和动态精度算法------------------*/
    	if(sampling_cnt == 50)
    	{
    		sampling_cnt = 0;
    		/*printf("cnt:%ldms\r\n",cnt);//50次测量所用的时间
    		cnt=0;*/
    		//printf("interval:%ld\r\n",interval);
    		for(i=0;i<3;i++)
    		{
    			Vpp[i] = filter_max[i] - filter_min[i];//计算双峰值
    			Dynamic_threshold[i] = (filter_max[i] + filter_min[i])/2;//计算动态阈值
    			
    			filter_max[i] = 0;//重新初始各轴的最大、最小值
    			filter_min[i] = 4095;
    			Error_flag[i] = 0;
    			
    			//>100		
    			if(Vpp[i] >= 250)		Dynamic_precision[i] = Vpp[i]/50;//跑步
    				else if( (Vpp[i] >= 100) && (Vpp[i]<250) )	Dynamic_precision[i] = 3;//走路
    				else {Dynamic_precision[i] = 2;Error_flag[i] = 1;}
    	
    		}
    	
    	}
    /*------------------线性移位 消除高频噪声--------------------*/	
    	for(i=0;i<3;i++)
    	{
    	
    		sample_old[i] = sample_new[i];
    		if(filter_out[i] >= sample_new[i])
    		{		
    			if((filter_out[i] - sample_new[i]) > Dynamic_precision[i])
    				sample_new[i] = filter_out[i];			
    		}
    		else if(filter_out[i] < sample_new[i])
    		{		
    			if((sample_new[i] - filter_out[i]) > Dynamic_precision[i])
    				sample_new[i] = filter_out[i];			
    		}
    	}
    /*--------------------最大峰值检测,判断活跃轴,步伐判断----------------*/
    //sample_new < Dynamic_threshold 表示已迈过动态阈值下方
    //sample_new - sample_old < 0 表示加速度的变化小于0,斜率为负数
    	if( (Vpp[0] >= Vpp[1]) && (Vpp[0] >= Vpp[2]) ) //x轴活跃
    	{
    	
    		if( (sample_old[0] > Dynamic_threshold[0]) && (sample_new[0] < Dynamic_threshold[0]) && (Error_flag[0] == 0) )
    		{
    		
    			if( (interval > 10 ) && ( interval < 100 ) )
    			{
    				Step_Out+=1;
    				regulation3 = regulation2;
    				regulation2 = regulation1;
    				regulation1 = regulation0;
    				regulation0 = 1;
    				if( regulation3 && regulation2 && regulation1 && regulation0 )
    					printf("Step:%d\r\n",Step_Out);
    			}
    			else 
    			{
    			
    				regulation3 = 0;
    				regulation2 = 0;
    				regulation1 = 0;
    				regulation0 = 0;
    			
    			}
    			interval = 0;
    		}
    	}
    	else if( (Vpp[1] >= Vpp[0]) && (Vpp[1] >= Vpp[2]) ) //y轴活跃
    	{
    	
    		if( (sample_old[1] > Dynamic_threshold[1]) && (sample_new[1] < Dynamic_threshold[1]) && (Error_flag[1] == 0) )
    		{
    			/*----------时间窗口--------*/
    			if( (interval > 10 ) && ( interval < 100 ) )
    			{
    				Step_Out+=1;
    				/*-----------计数规则--------------*/
    				regulation3 = regulation2;
    				regulation2 = regulation1;
    				regulation1 = regulation0;
    				regulation0 = 1;
    				if( regulation3 && regulation2 && regulation1 && regulation0 )
    					printf("Step:%d\r\n",Step_Out);
    			}
    			else 
    			{
    			
    				regulation3 = 0;
    				regulation2 = 0;
    				regulation1 = 0;
    				regulation0 = 0;
    			
    			}
    			interval = 0;
    		
    		}
    	}		
    	else if( (Vpp[2] >= Vpp[0]) && (Vpp[2] >= Vpp[1]) ) //z轴活跃
    	{
    	
    		if( (sample_old[2] > Dynamic_threshold[2]) && (sample_new[2] < Dynamic_threshold[2]) && (Error_flag[2] == 0) )
    		{
    		
    			if( (interval > 10 ) && ( interval < 100 ) )
    			{
    				Step_Out+=1;
    				regulation3 = regulation2;
    				regulation2 = regulation1;
    				regulation1 = regulation0;
    				regulation0 = 1;
    				if( regulation3 && regulation2 && regulation1 && regulation0 )
    					printf("Step:%d\r\n",Step_Out);
    			}
    			else 
    			{
    			
    				regulation3 = 0;
    				regulation2 = 0;
    				regulation1 = 0;
    				regulation0 = 0;
    			
    			}
    			interval = 0;
    		}
    	}
    	
    	//printf("Step:%d\r\n",Step_Out);
    
    	/*------速度 距离 卡路里-----*/
    	if(sampling_cnt0 == 100)
    	{
    		i_cnt++;
    		sampling_cnt0 = 0;
    		m_nPedometerValue = Step_Out;
    		Dynamic_step = m_nPedometerValue - m_nLastPedometer;//2s的步数变化
    		/*---每步距离----*/
    		if( Dynamic_step == 1 ) //身高取 170cm = 1.70m
    			StepLen = 1.70/5;
    		else if(  Dynamic_step == 2  )
    			StepLen = 1.70/4;
    		else if(  Dynamic_step == 3 )
    			StepLen = 1.70/3;
    		else if( Dynamic_step == 4  )
    			StepLen = 1.70/2;
    		else if( Dynamic_step == 5 )
    			StepLen = 1.70/1.2;
    		else if( ( Dynamic_step >= 6 ) && ( Dynamic_step < 8 ) )
    			StepLen = 1.70;
    		else if( Dynamic_step >= 8 )	StepLen = 1.70*1.2;
    		
    		Speed = StepLen/2;
    		calories = Speed * weight/400;
    		printf("Dynamic_step:%d\t",Dynamic_step);
    		
    		m_nLastPedometer = m_nPedometerValue;
    		printf("StepLen:%.3f\t",StepLen);
    		printf("Speed:%.3f\t",Speed);
    		printf("calories:%.3f\r\n",calories);
    	}
    }
    
    • 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
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187

    单片机-嵌入式毕设选题大全及项目分享:

    https://blog.csdn.net/m0_71572576/article/details/125409052


    6 最后

  • 相关阅读:
    iOS 17 跳转到系统设置页面(蓝牙、wifi、键盘、壁纸、铃声、iCloud等等)
    网页自动跳转到其他页面,点击浏览器返回箭头,回不到原来页面的问题
    GoJS 使用笔记
    分析key原理
    深入理解C语言(1):数据在内存中的存储
    Django——ORM增删改查
    在微信公众号怎么添加电子优惠券
    如何使用Java进行安全测试?
    3.7 学会这2招,让你的笔记分分钟上热门 【玩赚小红书】
    典型数据结构-图,图的存储、基本操作和遍历
  • 原文地址:https://blog.csdn.net/m0_71572576/article/details/125505572