陀螺仪LSM6DSOW开发(1)----轮询获取陀螺仪数据

147 篇文章 63 订阅
103 篇文章 3 订阅

概述

本文将介绍如何使用 LSM6DSOW 传感器来读取数据。主要步骤包括初始化传感器接口、验证设备ID、配置传感器的数据输出率和滤波器,以及通过轮询方式持续读取加速度、角速率和温度数据。读取到的数据会被转换为适当的单位并通过串行通信输出。这个代码是一个很好的起点,用于了解如何操作 LSM6DSOW 传感器并获取其数据。

最近在弄ST和瑞萨RA的课程,需要样片的可以加群申请:615061293 。

在这里插入图片描述

视频教学

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

陀螺仪LSM6DSOW开发(1)----轮询获取陀螺仪数据

样品申请

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

源码下载

https://download.csdn.net/download/qq_24312945/89590384

硬件准备

首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为STM32H503CB,陀螺仪为LSM6DSOW,磁力计为LIS2MDL。

在这里插入图片描述

LSM6DSOW & LSM6DSO

LSM6DSOW 和 LSM6DSO 是两款惯性测量单元(IMU),都具备三轴数字加速度计和三轴数字陀螺仪功能。它们之间的主要区别如下:

  1. FIFO 容量和数据压缩:
    ○ LSM6DSOW:支持高达 9 KB 的 FIFO,具备动态数据分批和压缩功能,可以实现高效的省电和数据存储。
    ○ LSM6DSO:同样支持 9 KB 的 FIFO,更注重压缩效率,可以实现 2 到 3 倍的数据压缩。
  2. 输出数据速率 (ODR):
    ○ LSM6DSOW:提供广泛的加速度计和陀螺仪的 ODR 范围,支持高达 6.66 kHz 的值。
    ○ LSM6DSO:也支持高 ODR,但在配置和具体值上略有不同。
  3. 显著运动检测:
    ○ LSM6DSOW:包含显著运动检测功能,主要利用加速度计来实现此功能。
    ○ LSM6DSO:类似地实现显著运动检测,并突出其他功能如计步器、步态检测和倾斜感应。
  4. 有限状态机 (FSM):
    ○ LSM6DSOW:具有多达 16 个独立的有限状态机,可编程用于各种运动检测任务。
    ○ LSM6DSO:同样包含多达 16 个 FSM,具备类似功能,但更强调与外部传感器的集成。
  5. 功耗和模式:
    ○ LSM6DSOW:设计用于低功耗,具有多种工作模式,包括高性能和超低功耗模式。
    ○ LSM6DSO:具有类似的低功耗特性,特定模式适用于 Android 兼容和高效运动跟踪。
  6. 中断和事件检测:
    ○ LSM6DSOW:支持多种事件检测中断,如自由落体、唤醒、6D 定位、单击和双击检测等。
    ○ LSM6DSO:实现了类似的事件检测功能,重点是 Android 兼容和显著运动检测。
    总结来说,尽管两款传感器在核心功能上相似,LSM6DSOW 优化了高级运动检测和省电特性,适用于需要高效数据管理和复杂运动跟踪的应用。LSM6DSO 则强调 Android 兼容性和强大的数据压缩,适合需要多功能传感器集成的移动和物联网应用。
    有关详细的规格和功能,可以参考 STMicroelectronics 提供的 LSM6DSOW 和 LSM6DSO 的数据手册和技术说明。

通信模式

对于LSM6DSOW,可以使用SPI或者IIC进行通讯。
最小系统图如下所示。
在这里插入图片描述

在CS管脚为1的时候,为IIC模式。

在这里插入图片描述
本文使用的板子原理图如下所示。
在这里插入图片描述

管脚定义

在这里插入图片描述

IIC通信模式

在在使用IIC通讯模式的时候,SA0是用来控制IIC的地址位的。
对于IIC的地址,可以通过SDO/SA0引脚修改。SDO/SA0引脚可以用来修改设备地址的最低有效位。如果SDO/SA0引脚连接到电源电压,LSb(最低有效位)为’1’(地址1101011b);否则,如果SDO/SA0引脚连接到地线,LSb的值为’0’(地址1101010b)。

在这里插入图片描述

接口如下所示。
主要使用的管脚为CS、SCL、SDA、SA0。

在这里插入图片描述

速率

该模块支持的速度为普通模式(100k)和快速模式(400k)。

在这里插入图片描述

生成STM32CUBEMX

用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。
配置时钟树,配置时钟为250M。
在这里插入图片描述

串口配置

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

在这里插入图片描述
配置串口,速率为2000000。

在这里插入图片描述

IIC配置

在这里插入图片描述

LSM6DSOW最大IIC通讯速率为400k,配置IIC速度为400k

在这里插入图片描述

CS和SA0设置

在这里插入图片描述

在这里插入图片描述

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

在这里插入图片描述

在这里插入图片描述

ICASHE

在这里插入图片描述

修改堆栈

在这里插入图片描述

串口重定向

打开魔术棒,勾选MicroLIB

在这里插入图片描述

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

/* USER CODE BEGIN Includes */
#include "stdio.h"
/* USER CODE END Includes */

函数声明和串口重定向:

/* 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/lsm6dso-pid

初始化管脚

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

在这里插入图片描述

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

	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);
	
	
  stmdev_ctx_t dev_ctx;
  /* 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)获取固定值,判断是否为0x6C

在这里插入图片描述

lsm6dso_device_id_get为获取函数。

在这里插入图片描述

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

  /* Check device ID */
  lsm6dso_device_id_get(&dev_ctx, &whoamI);
	printf("LSM6DSO_ID=0x%x,whoamI=0x%x",LSM6DSO_ID,whoamI);
  if (whoamI != LSM6DSO_ID)
    while (1);

复位操作

可以向CTRL3 (12h)的SW_RESET寄存器写入1进行复位。

在这里插入图片描述

lsm6dso_reset_set为重置函数。

在这里插入图片描述

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

  /* Restore default configuration */
  lsm6dso_reset_set(&dev_ctx, PROPERTY_ENABLE);

  do {
    lsm6dso_reset_get(&dev_ctx, &rst);
  } while (rst);

关闭I3C

  /* Disable I3C interface */
  lsm6dso_i3c_disable_set(&dev_ctx, LSM6DSO_I3C_DISABLE);

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进行开启。

在这里插入图片描述

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

  /* Enable Block Data Update */
  lsm6dso_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);

设置量程和速率

速率可以通过CTRL1 (10h)设置加速度速率和CTRL2 (11h)进行设置角速度速率。

在这里插入图片描述
在这里插入图片描述
设置加速度量程可以通过CTRL1 (10h)进行设置。

在这里插入图片描述

设置角速度量程可以通过CTRL2 (11h)进行设置。

在这里插入图片描述
设置加速度和角速度的量程和速率可以使用如下函数。

  /* Set Output Data Rate */
  lsm6dso_xl_data_rate_set(&dev_ctx, LSM6DSO_XL_ODR_12Hz5);
  lsm6dso_gy_data_rate_set(&dev_ctx, LSM6DSO_GY_ODR_12Hz5);
  /* Set full scale */
  lsm6dso_xl_full_scale_set(&dev_ctx, LSM6DSO_2g);
  lsm6dso_gy_full_scale_set(&dev_ctx, LSM6DSO_2000dps);

配置滤波器

  /* Configure filtering chain(No aux interface)
   * Accelerometer - LPF1 + LPF2 path
   */
  lsm6dso_xl_hp_path_on_out_set(&dev_ctx, LSM6DSO_LP_ODR_DIV_100);
  lsm6dso_xl_filter_lp2_set(&dev_ctx, PROPERTY_ENABLE);

轮询读取数据

进入一个无限循环,不断检查是否有新的数据(加速度、角速率、温度)可用。
对于每种类型的数据(加速度、角速率、温度),如果有新数据,就读取原始数据,转换为对应的单位(毫克、毫度每秒、摄氏度),并通过串行输出打印。

对于数据是否准备好,可以访问STATUS_REG (1Eh)进行判断。

在这里插入图片描述

    /* Read output only if new xl value is available */
    lsm6dso_xl_flag_data_ready_get(&dev_ctx, &reg);

对于加速度数据,可以通过28-2D进行获取。

在这里插入图片描述
在这里插入图片描述
加速度数据首先以原始格式(通常是整数)读取,然后需要转换为更有意义的单位,如毫重力(mg)。这里的转换函数 lsm6dso_from_fs2_to_mg() 根据加速度计的量程(这里假设为±2g)将原始数据转换为毫重力单位。
acceleration_mg[0] = lsm6dso_from_fs2_to_mg(data_raw_acceleration[0]);等三行代码分别转换 X、Y、Z 轴的加速度数据。

    /* Read output only if new xl value is available */
    lsm6dso_xl_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read acceleration field data */
      memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
      lsm6dso_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
      acceleration_mg[0] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[0]);
      acceleration_mg[1] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[1]);
      acceleration_mg[2] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[2]);
      printf( "Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);

    }

对于角速度数据,可以通过22-27进行获取。

在这里插入图片描述

在这里插入图片描述

    lsm6dso_gy_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read angular rate field data */
      memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));
      lsm6dso_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);
      angular_rate_mdps[0] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[0]);
      angular_rate_mdps[1] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[1]);
      angular_rate_mdps[2] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[2]);
      printf("Angular rate [mdps]:%4.2f\t%4.2f\t%4.2f\r\n",
              angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);

    }

对于温度数据,可以通过20-21进行获取。

在这里插入图片描述

    lsm6dso_temp_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read temperature data */
      memset(&data_raw_temperature, 0x00, sizeof(int16_t));
      lsm6dso_temperature_raw_get(&dev_ctx, &data_raw_temperature);
      temperature_degC =
        lsm6dso_from_lsb_to_celsius(data_raw_temperature);
      printf("Temperature [degC]:%6.2f\r\n", temperature_degC);

    }

主程序

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
		
    uint8_t reg;
    /* Read output only if new xl value is available */
    lsm6dso_xl_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read acceleration field data */
      memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));
      lsm6dso_acceleration_raw_get(&dev_ctx, data_raw_acceleration);
      acceleration_mg[0] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[0]);
      acceleration_mg[1] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[1]);
      acceleration_mg[2] =
        lsm6dso_from_fs2_to_mg(data_raw_acceleration[2]);
      printf( "Acceleration [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);

    }

    lsm6dso_gy_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read angular rate field data */
      memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));
      lsm6dso_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);
      angular_rate_mdps[0] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[0]);
      angular_rate_mdps[1] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[1]);
      angular_rate_mdps[2] =
        lsm6dso_from_fs2000_to_mdps(data_raw_angular_rate[2]);
      printf("Angular rate [mdps]:%4.2f\t%4.2f\t%4.2f\r\n",
              angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);

    }

    lsm6dso_temp_flag_data_ready_get(&dev_ctx, &reg);

    if (reg) {
      /* Read temperature data */
      memset(&data_raw_temperature, 0x00, sizeof(int16_t));
      lsm6dso_temperature_raw_get(&dev_ctx, &data_raw_temperature);
      temperature_degC =
        lsm6dso_from_lsb_to_celsius(data_raw_temperature);
      printf("Temperature [degC]:%6.2f\r\n", temperature_degC);

    }		
		
		
    /* USER CODE END WHILE */

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

演示

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

记帖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值