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

描述

概述

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

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

stm32cubemx

视频教学

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

样品申请

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

源码下载

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

硬件准备

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

stm32cubemx

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进行通讯。 最小系统图如下所示。

stm32cubemx

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

stm32cubemx

本文使用的板子原理图如下所示。

stm32cubemx

管脚定义

stm32cubemx

IIC通信模式

在在使用IIC通讯模式的时候,SA0是用来控制IIC的地址位的。

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

stm32cubemx

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

stm32cubemx

速率

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

stm32cubemx

生成STM32CUBEMX

用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。 配置时钟树,配置时钟为250M。

stm32cubemx

串口配置

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

stm32cubemx

配置串口,速率为2000000。

stm32cubemx

IIC配置

stm32cubemx

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

stm32cubemx

CS和SA0设置

stm32cubemx

stm32cubemx

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

stm32cubemx

stm32cubemx

ICASHE

stm32cubemx

修改堆栈

stm32cubemx

串口重定向

打开魔术棒,勾选MicroLIB

stm32cubemx

在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模式。

stm32cubemx

所以使能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

stm32cubemx

lsm6dso_device_id_get为获取函数。

stm32cubemx

对应的获取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进行复位。

stm32cubemx

lsm6dso_reset_set为重置函数。

stm32cubemx

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

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

stm32cubemx

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

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

设置量程和速率

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

stm32cubemx

stm32cubemx

设置加速度量程可以通过CTRL1 (10h)进行设置。

stm32cubemx

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

stm32cubemx

设置加速度和角速度的量程和速率可以使用如下函数。

/* 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)进行判断。

stm32cubemx

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

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

stm32cubemx

stm32cubemx

加速度数据首先以原始格式(通常是整数)读取,然后需要转换为更有意义的单位,如毫重力(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, ®);

    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.2ft%4.2ft%4.2frn",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);

    }

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

stm32cubemx

stm32cubemx

lsm6dso_gy_flag_data_ready_get(&dev_ctx, ®);

    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.2ft%4.2ft%4.2frn",
              angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);

    }

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

stm32cubemx

lsm6dso_temp_flag_data_ready_get(&dev_ctx, ®);

    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.2frn", 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, ®);

    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.2ft%4.2ft%4.2frn",
              acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);

    }

    lsm6dso_gy_flag_data_ready_get(&dev_ctx, ®);

    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.2ft%4.2ft%4.2frn",
              angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);

    }

    lsm6dso_temp_flag_data_ready_get(&dev_ctx, ®);

    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.2frn", temperature_degC);

    }        


    /* USER CODE END WHILE */

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

演示

stm32cubemx

审核编辑 黄宇

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分