7.5、LSM6DSL嵌入式功能
文章目录
项目里面主要是用了计步、绝对手腕倾斜等两个嵌入功能,此外还有双击检测功能,下面分别介绍一下这三个功能的使用注意事项.
7.5.1、计步功能
基本用下图可以简单理解计步功能的原理.
首先,当振幅低于最小THS的时候,基本可以认为无动作,但是当大于该水平线的时候,基本可以认为有步数了.这里面的最小THS可以通过CONFIG_PEDO_THS_MIN
里面的ths_min
进行配置.具体如下.
当
PEDO_FS
位为0时,1LSB = 32mg,为1时,1LSB = 62.5mg.
注意事项:
- 加速度ORD至少为26HZ,量程一般为±2g,但是也可以配置为±4g.
- 开始检测步数的开始,在连续7步(可以配置)之后才会生成第一个中断.该功能被称为去抖动功能.
- 在器件不活动约1S后(时间可配置),重新启动去抖动功能.
7.5.1.1、例程
具体生成工程参考7.4.2.2、MEMS库移植,唯一不一样的地方如下图所示.
具体效果如下.
这里的效果就是官方自带的效果了,简单试了一下,效果并不是很好(用手来回抖动也能触发),我是用的参数都是例程默认的,不知道通过调参能不能让效果好一些.
7.5.2、绝对手腕倾斜
7.5.2.1、原理
它能检测可选加速度计半轴与水平面之间的角度何时高于特定的用户可选值.
如果器件配置为进行绝对手腕倾斜事件检测,则当器件倾斜角度大于可配置阈值并持续倾斜了最小可配置时间时,会产生一个中断:如果倾斜角度大于阈值角度并且持续倾斜时间大于等于延迟时间,则会产生 AWT 中断信号。
如上,可配置项有延时时间值,角度阈值,加速度轴.
-
延时时间值,配置
A_WRIST_TILT_LAT
寄存器的WRIST_TILT_TIMER
字段,1LSB为40ms,默认为0Fh
(600ms). -
角度阈值,配置
A_WRIST_TILT_THS
的WRIST_TILT_THS
字段.该字段必须小于40h
,1LSB为15.625mg,上电后默认值为20h
,20h = 32d = 500mg
,相当于30°倾角.具体计算方式:
180 π ∗ a r c s i n W R I S T _ T I L T _ T H S 64 \frac{180}{π}*arcsin\frac{WRIST\_TILT\_THS}{64} π180∗arcsin64WRIST_TILT_THS -
加速度轴,通过配置
A_WRIST_TILT_Mask
寄存器的位进行选择.默认的位X正轴AWT检测.
备注: 上述的三个寄存器属于嵌入功能寄存器的B区,所以每次加速度计退出下电模式的时候,这些都会恢复默认值,所以都要对其重置.
7.5.2.2、实现
具体生成工程参考7.4.2.2、MEMS库移植,唯一不一样的地方如下图所示.
官方DEMO没有给出打印效果,具体效果只能通过硬件的LED显示,就不贴图了.
7.5.3、双击检测功能
7.5.3.1、原理
器件可配置为沿任意方向,敲击时在专用引脚上输出中断信号。 可以配置为单击或者双击,两者相互独立.
LSM6DSL 器件中,单击和双击识别功能利用两个连续加速度采样之间的斜率来检测点击事件;斜率数据利用以下
公式计算 :
s
l
o
p
e
(
t
n
)
=
[
a
c
c
(
t
n
)
−
a
c
c
(
t
n
−
1
)
]
/
2
slope(t_n) = [acc(t_n)-acc(t_{n-1})]/2
slope(tn)=[acc(tn)−acc(tn−1)]/2
此功能可完全由用户编程,利用专门的寄存器组对所期望的斜率数据幅度和时序进行编程。
单击和双击识别独立于所选输出数据率而工作。对于这些功能,建议的加速度计 ODR 为 416 Hz 和 833 Hz。
要启用单击和双击识别功能,必须将 TAP_CFG
寄存器中的 INTERRUPTS_ENABLE
位置为 1。
具体有许多可以配置的项,可以参考AN5040的第5.5节,里面有很详细的介绍.下面简单提一下双击的相关事项.
看下图.
注意红色的线代表的是斜率而不是加速度.
双击过程中主要分为三个阶段.SHOCK,QUIET,DURATION.、
- SHOCK 定义了超阈值事件的最大持续时间:在 Shock 窗口结束前,加速度必须返回到低于阈值之下,否则不能检测到该点击事件。
- QUIET 定义了第一次点击识别后的时间,期间不能发生超阈值。
- DUARTION 定义了连续两次检测到点击之间的最大时间
关于上述的三个时间的主要配置,默认参数及代表时间含义参考下图(ODR_XL代表加速度计输出速率).
7.5.3.2、实现
具体生成工程参考7.4.2.2、MEMS库移植,唯一不一样的地方如下图所示.
7.5.4、移植
7.5.1、准备文件
首先CUBEMX生成的工程目录如下所示.
-
绿色框内的,这是我手动添加的文件,主要目的方便调试.
-
红色框内的就是需要我们添加到工程内的文件.
除此之外,还有几个文件在CUBEMX的组件安装包路径下,我的电脑路径在D:\Local\cubemx_packet\Packs\STMicroelectronics\X-CUBE-MEMS1\8.2.0\Drivers\BSP\Components\lsm6dsl
目录下,主要有以下四个文件.
-
lsm6dsl.c
-
lsm6dsl.h
-
lsm6dsl_reg.c
-
lsm6dsl_reg.h
7.5.2、修改文件
- 修改
custom_motion_sensor.c
文件中的LSM6DSL_0_Probe
函数(下面只贴出了修改的部分).
io_ctx.Address = LSM6DSL_I2C_ADD_L; /* SA0 = VDD */
// io_ctx.GetTick = BSP_GetTick;
具体地址根据硬件接线选择.
- 修改
custom_mems_conf.h
,添加和修改如下内容
//添加内容如下
#include "custom_errno.h"
#include "iic.h"
//修改内容如下
#define CUSTOM_LSM6DSL_0_I2C_Init IIC_Init
#define CUSTOM_LSM6DSL_0_I2C_DeInit IIC_Init
#define CUSTOM_LSM6DSL_0_I2C_ReadReg I2C_Read_Byte_Len
#define CUSTOM_LSM6DSL_0_I2C_WriteReg I2C_Write_Reg_Len
-
外部中断(这点不是必须的,根据需求).硬件方面sensor的
int1
接入到了PA5
.所以要保证EXTI9_5_IRQHandler
开启.保证PA5
引脚初始化正常. -
参考原工程
app_mems.c
文件创建自己的逻辑层内容.例子如下
#include "lsm6dstdr_thread.h"
#include "custom_motion_sensors.h"
#include "custom_motion_sensors_ex.h"
#include "app_mems_int_pin_a_interface.h"
volatile uint8_t MemsEventDetected = 0;
static uint16_t StepCount = 0;
void lsm6d_init()
{
/* 初始化函数 */
set_mems_int_pin_a_exti();
(void)CUSTOM_MOTION_SENSOR_Init(CUSTOM_LSM6DSL_0, MOTION_ACCELERO | MOTION_GYRO);
/* 计步器使能 */
(void)CUSTOM_MOTION_SENSOR_Enable_Pedometer(CUSTOM_LSM6DSL_0);
/* 单击功能 使能*/
if(CUSTOM_MOTION_SENSOR_Enable_Single_Tap_Detection(CUSTOM_LSM6DSL_0, CUSTOM_MOTION_SENSOR_INT1_PIN) != BSP_ERROR_NONE)
{
Error_Handler();
}
/* 双击功能 使能*/
if (CUSTOM_MOTION_SENSOR_Enable_Double_Tap_Detection(CUSTOM_LSM6DSL_0, CUSTOM_MOTION_SENSOR_INT1_PIN) != BSP_ERROR_NONE)
{
Error_Handler();
}
/* 直连模式 使能*/
if (CUSTOM_MOTION_SENSOR_Enable_Sensor_Hub_Direct_Connect(CUSTOM_LSM6DSL_0) != BSP_ERROR_NONE)
{
Error_Handler();
}
}
/* 任务处理 */
void sensor_thread_entry(void *para)
{
CUSTOM_MOTION_SENSOR_Event_Status_t status;
while(1)
{
if(MemsEventDetected != 0U) // 这个地方改为信号量触发更合适,有需求自行修改
{
MemsEventDetected = 0;
if(CUSTOM_MOTION_SENSOR_Get_Event_Status(CUSTOM_LSM6DSL_0, &status) == BSP_ERROR_NONE)
{
if(status.StepStatus != 0U)
{
Step_Count();
}
if(status.TapStatus != 0U)//如果单击触发
{
}
if(status.DoubleTapStatus != 0U)//如果双击触发
{
}
}
}
rt_thread_delay(50);
}
}
上面的
MemsEventDetected
变量只会在外部中断中触发,具体的外部中断需要根据硬件连接确认(LSM6DSL的INT1接入的IO).
备注:
-
上述我使用的是软件iic,如果使用硬件iic的话,参考原工程的
custom_bus.c
文件内容. -
可能有的文件会报错,基本都是缺少某个宏定义,查找到定义该宏所在的头文件,包含到缺少的地方即可.我在移植过程中基本都是缺少
iic.h
,custom_errno.h
.