基于STM32的智能手环(一)-------计步、速度、距离、卡路里的功能实现

计步、速度、距离、卡路里的功能实现

代码已上传,可下载!!!
https://download.csdn.net/download/weixin_46704960/12674679

⒈硬件部分

①芯片:

​ STM32F103ZET6(主控芯片) ADXL345(加速度传感器芯片)

②硬件连接

在这里插入图片描述

③IIC协议通信

在这里插入图片描述
在这里插入图片描述

​ ★ALT ADDRESS引脚为SDO引脚,接地时选择备用IIC地址0X53,器件地址+写命令为0XA6,器件地址+读命令为0XA7

​ ★本次使用的ADXL345模块,使用IIC模式时 CS引脚接着上拉电阻并与VS、Vdd连接3.3V电源

⒉软件部分

①ADXL345初始化

void ad345_Init(void)
{
signal_write_ad345(0x2E,0x00);   //0000 0000 禁用中断
signal_write_ad345(0x31,0x0B); //0000 1011 禁用自测模式 测量范围,正负16g,13位模式  1 LSB代表3.9 mg 
signal_write_ad345(0x2C,0x09);// 0000	1001  位4为0:正常功率运行  速率设定为50HZ 
signal_write_ad345(0x2D,0x08);//0000 1000	测量位设置为1,置于测量模式  器件处于正常工作模式
signal_write_ad345(0x2F,0x00); //1000 0000将DATA_READY中断映射到INT1	
signal_write_ad345(0x2E,0x80);   //1000 0000使能 DATA_READY 中断	
signal_write_ad345(0x1E,0xF9);   //X 偏移量 使用水平仪测量参数校准
signal_write_ad345(0x1F,0xFF);   //Y 偏移量 
signal_write_ad345(0x20,0x00);   //Z 偏移量 
}

②Step算法

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);
	}
}

③商用改进方案

​ ★使用ADXL345的FIFO和自动休眠唤醒功能达到低功耗的目的

​ ★接上INT2作为外部中断,并通过INT_SOURCE寄存器的D4、43进行活动和静止判断

3资料参考

https://www.analog.com/cn/analog-dialogue/articles/pedometer-design-3-axis-digital-acceler.html

https://www.cnblogs.com/qsyll0916/p/6691413.html

ADXL345数据手册

评论 50
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值