陀螺仪LSM6DSV80X开发(6)----单双击检测

陀螺仪LSM6DSV80X开发.6--单双击检测

概述

本实验主要演示如何使用 LSM6DSV80X 的 Tap Detection 功能,实现对单击和双击动作的识别。通过配置传感器的 Tap 检测轴、敲击阈值、时间窗口以及中断输出,将 Single Tap 和 Double Tap 事件映射到 INT1 引脚。当检测到敲击动作后,MCU 通过外部中断唤醒主循环,并读取 LSM6DSV80X 的事件源寄存器,判断当前触发的是单击还是双击事件,最后通过串口打印检测结果。

需要样片的可以加群申请:925643491/615061293 。

视频教学

https://www.bilibili.com/video/BV1tYGJ6vEHK/

样品申请

https://www.wjx.top/vm/OhcKxJk.aspx#

源码下载

硬件准备

首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。

主控为STM32H503CB,陀螺仪为LSM6DSV80X,磁力计为LIS2MDL。

参考程序

https://github.com/CoreMaker-lab/LSM6DSV80X

https://gitee.com/CoreMaker/LSM6DSV80X

生成STM32CUBEMX

用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。

配置时钟树,配置时钟为250M。

串口配置

查看原理图,PA9和PA10设置为开发板的串口。

配置串口,速率为2000000。

IIC配置

LSM6DSV80X最大IIC通讯速率为1M,配置IIC速度为400k

CS和SA0设置

由于还有一个磁力计,需要把该CS也使能。

INT配置

INT1管脚为PB0。

配置如下所示。

开启中断。

ICASHE

修改堆栈

串口重定向

打开魔术棒,勾选MicroLIB

在main.c中,添加头文件,若不添加会出现 identifier "FILE" is undefined报错。

c 复制代码
/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

函数声明和串口重定向:

c 复制代码
/* USER CODE BEGIN PFP */
int fputc(int ch, FILE *f){
	HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1, 0xFFFF);
	return ch;
}
/* USER CODE END PFP */

参考程序

https://github.com/STMicroelectronics/lsm6dsv80x-pid

变量定义

c 复制代码
/* USER CODE BEGIN 0 */
#define SENSOR_BUS hi2c1


/* Private macro -------------------------------------------------------------*/
#define    BOOT_TIME            10 //ms
#define    CNT_FOR_OUTPUT       100

/* Private variables ---------------------------------------------------------*/
static int16_t data_raw_motion[3];
static int16_t data_raw_temperature;
static float_t acceleration_mg[3];
static float_t angular_rate_mdps[3];
static float_t temperature_degC;
static uint8_t whoamI;
static uint8_t tx_buffer[1000];

static lsm6dsv80x_filt_settling_mask_t filt_settling_mask;

/* Extern variables ----------------------------------------------------------*/

/* Private functions ---------------------------------------------------------*/

/*
 *   WARNING:
 *   Functions declare in this section are defined at the end of this file
 *   and are strictly related to the hardware platform used.
 *
 */
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,
                              uint16_t len);
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                             uint16_t len);
static void tx_com( uint8_t *tx_buffer, uint16_t len );
static void platform_delay(uint32_t ms);
static void platform_init(void);

static   stmdev_ctx_t dev_ctx;
static volatile uint8_t stap_event_catched = 0;
static volatile uint8_t dtap_event_catched = 0;

static   uint8_t thread_wake = 0;
static lsm6dsv80x_interrupt_mode_t irq;
static lsm6dsv80x_tap_detection_t tap;
static lsm6dsv80x_tap_thresholds_t tap_ths;
static lsm6dsv80x_tap_time_windows_t tap_win;



/* USER CODE END 0 */

初始换管脚

由于需要向LSM6DSV80X_I2C_ADD_L写入以及为IIC模式。

所以使能CS为高电平,配置为IIC模式。

配置SA0为低电平。

c 复制代码
	printf("HELLO!\n");
  HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET);
  HAL_GPIO_WritePin(SA0_GPIO_Port, SA0_Pin, GPIO_PIN_RESET);
  HAL_GPIO_WritePin(CS2_GPIO_Port, CS2_Pin, GPIO_PIN_SET);
	HAL_Delay(100);

  lsm6dsv80x_pin_int_route_t pin_int = { 0 };
  /* Initialize mems driver interface */
  dev_ctx.write_reg = platform_write;
  dev_ctx.read_reg = platform_read;
  dev_ctx.mdelay = platform_delay;
  dev_ctx.handle = &SENSOR_BUS;


  /* Init test platform */
//  platform_init();

  /* Wait sensor boot time */
  platform_delay(BOOT_TIME);

获取ID

可以向WHO_AM_I (0Fh)获取固定值,判断是否为0x73。

lsm6dsv80x_device_id_get为获取函数。

对应的获取ID驱动程序,如下所示。

c 复制代码
  /* Check device ID */
  lsm6dsv80x_device_id_get(&dev_ctx, &whoamI);
	printf("LSM6DSV80X_ID=0x%x,whoamI=0x%x",LSM6DSV80X_ID,whoamI);
  if (whoamI != LSM6DSV80X_ID)
    while (1);

软件上电复位

写 0x01(FUNC_CFG_ACCESS)这个寄存器,把 SW_POR 置 1,然后等待芯片完成复位。

lsm6dsv80x_sw_por为 软件上电复位 / 全局复位 函数。

对应的驱动程序,如下所示。

c 复制代码
  /* Perform device power-on-reset */
  lsm6dsv80x_sw_por(&dev_ctx);

BDU设置

在很多传感器中,数据通常被存储在输出寄存器中,这些寄存器分为两部分:MSB和LSB。这两部分共同表示一个完整的数据值。例如,在一个加速度计中,MSB和LSB可能共同表示一个加速度的测量值。

连续更新模式(BDU = '0'):在默认模式下,输出寄存器的值会持续不断地被更新。这意味着在你读取MSB和LSB的时候,寄存器中的数据可能会因为新的测量数据而更新。这可能导致一个问题:当你读取MSB时,如果寄存器更新了,接下来读取的LSB可能就是新的测量值的一部分,而不是与MSB相对应的值。这样,你得到的就是一个"拼凑"的数据,它可能无法准确代表任何实际的测量时刻。

块数据更新(BDU)模式(BDU = '1'):当激活BDU功能时,输出寄存器中的内容不会在读取MSB和LSB之间更新。这就意味着一旦开始读取数据(无论是先读MSB还是LSB),寄存器中的那一组数据就被"锁定",直到两部分都被读取完毕。这样可以确保你读取的MSB和LSB是同一测量时刻的数据,避免了读取到代表不同采样时刻的数据。

简而言之,BDU位的作用是确保在读取数据时,输出寄存器的内容保持稳定,从而避免读取到拼凑或错误的数据。这对于需要高精度和稳定性的应用尤为重要。

可以向CTRL3 (12h)的BDU寄存器写入1进行开启。

对应的驱动程序,如下所示。

c 复制代码
  /* Enable Block Data Update */
  lsm6dsv80x_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);

Tap 中断配置说明

LSM6DSV80X 内部可以识别 Single Tap 和 Double Tap 事件,但如果希望 MCU 通过外部中断方式响应这些事件,需要将对应的事件映射到传感器的中断引脚上。

将 Single Tap 和 Double Tap 事件都映射到 INT1 引脚。

Single Tap 和 Double Tap 事件映射到 INT1 引脚,对应 MD1_CFG 寄存器 5Eh。

对应的驱动程序,如下所示。

c 复制代码
	pin_int.double_tap = PROPERTY_ENABLE;
  pin_int.single_tap = PROPERTY_ENABLE;
  lsm6dsv80x_pin_int1_route_set(&dev_ctx, &pin_int);

使能中断输出

完成中断路由配置后,还需要使能 LSM6DSV80X 的中断输出功能。

中断信号触发后不会一直保持,需要及时读取事件源寄存器。

如果希望中断保持到软件读取状态寄存器后再清除,可以考虑将 lir 配置为 1。

对应的驱动程序,如下所示。

c 复制代码
    irq.enable = 1;
  irq.lir = 0;
  lsm6dsv80x_interrupt_enable_set(&dev_ctx, irq);

使能 Z 轴 Tap 检测

Tap 检测是基于加速度计数据实现的。LSM6DSV80X 可以配置 X、Y、Z 三个方向的 Tap 检测轴。

本实验中只开启 Z 轴 Tap 检测,也就是主要检测垂直于模块表面的敲击动作。

具体是否需要开启多个方向,需要根据实际产品安装方向和敲击方向来决定。

Tap 检测轴配置对应 TAP_CFG0 寄存器 56h。

对应的驱动程序,如下所示。

c 复制代码
  tap.tap_z_en = 1;
  lsm6dsv80x_tap_detection_set(&dev_ctx, tap);

配置 Tap 阈值

Z 轴 Tap 阈值对应 TAP_THS_6D 寄存器 59h。

该配置实际对应的是写入 TAP_THS_6D(59h) 寄存器的低 5 位 TAP_THS_Z4:0。在当前 ±8g 量程下,1 LSB 对应 0.25g,因此阈值 3 对应约 0.75g。

对应的驱动程序,如下所示。

c 复制代码
  tap_ths.z = 3;
  lsm6dsv80x_tap_thresholds_set(&dev_ctx, tap_ths);

配置 Tap 时间窗口

LSM6DSV80X 的单击 / 双击识别不仅需要配置 Tap 阈值,还需要配置 Tap 识别的时间窗口。时间窗口主要用于判断一次敲击的持续时间、敲击后的静默时间,以及两次敲击之间的最大间隔。

Tap 时间窗口由 TAP_DUR 寄存器 配置,该寄存器地址为 5Ah.

c 复制代码
bit7~bit4:DUR[3:0]

用于配置双击识别时,两次 Tap 之间允许的最大时间间隔。

c 复制代码
bit3~bit2:QUIET[1:0]

用于配置第一次 Tap 检测后的静默时间。在 quiet time 内,不能再出现超过阈值的事件,否则可能会影响 Tap 判断。

c 复制代码
bit1~bit0:SHOCK[1:0]

用于配置一次 Tap 允许的最大冲击持续时间。如果超过阈值的时间太长,传感器可能不会将其识别为一次有效 Tap。

在当前 ODR_XL = 480Hz 条件下,双击最大间隔约为 466.7 ms,Tap 后静默时间约为 25 ms,单次 Tap 最大冲击持续时间约为 50 ms。实际产品调试时,如果双击不容易触发,可以适当增大 tap_gap;如果单击容易被误识别为双击,可以适当调整 quiet 和 tap_gap;如果敲击动作持续时间较长但无法识别,可以适当调整 shock 参数。

对应的驱动程序,如下所示。

c 复制代码
  tap_win.tap_gap = 7;
  tap_win.shock = 3;
  tap_win.quiet = 3;
  lsm6dsv80x_tap_time_windows_set(&dev_ctx, tap_win);

配置 Single Tap / Double Tap 检测模式

LSM6DSV80X 的单击 / 双击模式选择由 WAKE_UP_THS 寄存器 配置,该寄存器地址为 5Bh.

LSM6DSV80X 会同时支持 Single Tap 和 Double Tap 检测。

当只检测到一次有效敲击时,可以产生 Single Tap 事件;

当在设定的 TAP_DUR(5Ah) 时间窗口内连续检测到两次有效敲击时,可以产生 Double Tap 事件。

对应的驱动程序,如下所示。

c 复制代码
  lsm6dsv80x_tap_mode_set(&dev_ctx, LSM6DSV80X_BOTH_SINGLE_DOUBLE);

设置量程和速率

c 复制代码
  /* Set Output Data Rate.*/
  lsm6dsv80x_xl_setup(&dev_ctx, LSM6DSV80X_ODR_AT_480Hz, LSM6DSV80X_XL_HIGH_PERFORMANCE_MD);
  /* Set full scale */
  lsm6dsv80x_xl_full_scale_set(&dev_ctx, LSM6DSV80X_8g);

外部中断回调函数

当 LSM6DSV80X 检测到 Single Tap 或 Double Tap 后,INT1 引脚会产生中断信号。

c 复制代码
void HAL_GPIO_EXTI_Rising_Callback(uint16_t GPIO_Pin)
{
  if (GPIO_Pin == INT1_Pin) {
    thread_wake = 1;
  }
}

主程序

c 复制代码
  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		if(thread_wake==1)
		{
			thread_wake=0;
			lsm6dsv80x_all_sources_t status;
			/* Read output only if new xl value is available */
			lsm6dsv80x_all_sources_get(&dev_ctx, &status);

			if (status.single_tap) {
				stap_event_catched = 1;
			}
			if (status.double_tap) {
				dtap_event_catched = 1;
			}		

			if (stap_event_catched) {
				stap_event_catched = 0;
        printf("Single TAP\r\n");
			}
			if (dtap_event_catched) {
        dtap_event_catched = 0;
        printf("Double TAP\r\n");
			}			
		
		}

    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */

演示

相关推荐
记帖4 小时前
STM32C542开发(2)----BOOT_SEL设置
stm32·stm32cubemx·stm32cubeide·stm32cubemx2·stm32c542cct6·boot_set·串口烧录
好好学仿真1 个月前
MEMS开关+频率选择表面:GNSS L1频段可重构智能反射面新方案
重构·gnss·mems·天线设计·fss·cst仿真·射频开关
送外卖的CV工程师2 个月前
STM32 CubeMX Makefile 工程编译 入门指南
stm32·单片机·嵌入式硬件·学习·makefile·stm32cubemx
资深流水灯工程师3 个月前
MEMS加速度计的原理
mems·加速度计
意法半导体STM324 个月前
【官方原创】防止STM32CubeMX删除用户文件的方法 LAT1442
stm32·单片机·嵌入式硬件·stm32cubemx·stm32开发·stm32生态
苏州知芯传感5 个月前
成本与性能的平衡术:面向亿级市场的消费电子MEMS微振镜,其设计是如何“做减法”的?
3d·机器视觉·mems·消费电子·微振镜
苏州知芯传感5 个月前
柔性抓取的“慧眼”:MEMS 3D视觉如何让机器人精准识别无序堆叠的复杂钣金件?
算法·3d·机器人·mems
wotaifuzao5 个月前
STM32最新的CubeMx v6-16-1下载及安装-包含固件库下载教程(免费提供下多版本载链接)(二)
stm32·单片机·嵌入式硬件·cubemx·stm32cubemx·stm32f407
brave and determined5 个月前
传感器学习(day11):MEMS摄像头:颠覆手机影像的未来
嵌入式硬件·智能手机·嵌入式开发·mems·电子设计·嵌入式应用·嵌入式设计