计步、速度、距离、卡路里的功能实现
代码已上传,可下载!!!
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数据手册