陀螺仪LSM6DSV80X开发(1)----轮询获取陀螺仪数据
LSM6DSV80X是一款高性能IMU传感器,集成了80g高重力加速度计和低重力加速度计通道,适用于可穿戴设备及高强度运动追踪。该传感器支持I2C/SPI通信,具有机器学习核心、自适应配置等先进功能。本文介绍了基于STM32H503CB开发板的硬件连接,通过I2C接口以400k速率与LSM6DSV80X通信,并配置CS、SA0管脚设置设备地址。提供了串口重定向、堆栈修改等关键代码实现,以及GitH
陀螺仪LSM6DSV80X开发.1--轮询获取陀螺仪数据
概述
LSM6DSV80X 是可穿戴技术领域的一项突破。它能够处理高低加速度值,并结合其高能效和先进的处理能力,使其成为任何希望获取数据进行深入分析,并在排球、足球、网球、拳击或爆发力跳跃等运动的高强度冲击和追踪活动中取得更佳表现的人士的理想之选。这款 IMU 是一套适用于可穿戴设备、高强度冲击和活动追踪的综合解决方案,兼具精准度、集成度和效率。
LSM6DSV80X 是世界上第一款将高重力(80 g)和低重力能力结合在单一封装中的 IMU,集成了先进的功能(边缘处理和传感器融合),并为运动可穿戴设备的跟踪和高强度冲击检测提供一致的性能和有价值的数据。
最近在弄ST的课程,需要样片的可以加群申请:615061293 。

该设备支持边缘 AI,利用有限状态机 (FSM) 进行可配置运动跟踪,利用机器学习核心 (MLC) 进行情境感知,并为可穿戴应用提供可导出的 AI 功能。
LSM6DSV80X 支持自适应自配置 (ASC) 功能,该功能允许根据特定运动模式的检测或基于 MLC 中配置的特定决策树的输出实时自动重新配置设备,而无需主机处理器的任何干预。

视频教学
https://www.bilibili.com/video/BV1kJhizPECK/
陀螺仪LSM6DSV80X开发(1)----轮询获取陀螺仪数据
样品申请
https://www.wjx.top/vm/OhcKxJk.aspx#
源码下载
https://download.csdn.net/download/qq_24312945/92884602
硬件准备
首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为STM32H503CB,陀螺仪为LSM6DSV80X,磁力计为LIS2MDL。

参考程序
https://github.com/CoreMaker-lab/LSM6DSV80X
https://gitee.com/CoreMaker/LSM6DSV80X
所有功能
● 专用独立陀螺仪、低重力和高重力加速度计通道以及数据处理
● 智能 FIFO 高达 4.5 KB
● 双加速度计通道
○ 低重力通道±2/±4/±8/±16 g 满量程
○ 高 g 通道 ±32/±64/±80 g 满量程
● ±250/±500/±1000/±2000/±4000 dps 满量程
● SPI / I²C & MIPI I3C ® v1.1 串行接口,带主处理器数据同步
● 可编程有限状态机,用于高 g 和低 g 加速度计、陀螺仪和外部传感器数据处理,高速率 @ 960 Hz
● 具有可导出功能和适用于 AI 应用程序的过滤器的机器学习核心
● 嵌入式自适应自配置(ASC)
● 嵌入式传感器融合低功耗(SFLP)算法
● 嵌入式温度传感器
● 独立 I/O 供应
○ I²C电压范围:1.62 V至3.6 V
○ SPI/MIPI I3C®扩展电压范围:1.08 V 至 3.6 V
● 电源电流
○ 组合高性能模式下 6 轴配置 @ 0.67 mA
○ 9 轴配置 @ 0.80 mA 组合高性能模式
● 紧凑尺寸:2.5 毫米 x 3 毫米 x 0.83 毫米
● 符合 ECOPACK 和 RoHS 标准
生成STM32CUBEMX
用STM32CUBEMX生成例程,这里使用MCU为STM32H503CB。
配置时钟树,配置时钟为250M。

串口配置
查看原理图,PA9和PA10设置为开发板的串口。
配置串口,速率为2000000。
通信模式
对于LSM6DSV80X,可以使用SPI或者IIC进行通讯。
最小系统图如下所示。

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

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

管脚定义

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

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

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


LSM6DSV80X最大IIC通讯速率为1M,配置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/lsm6dsv80x-pid
初始换管脚
由于需要向LSM6DSV80X_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);
lsm6dsv80x_reset_t rst;
stmdev_ctx_t dev_ctx;
// 累加器和计数器,用于计算均值
double_t lowg_xl_sum[3], hg_xl_sum[3], gyro_sum[3], temp_sum;
uint16_t lowg_xl_cnt = 0, hg_xl_cnt = 0, gyro_cnt = 0, temp_cnt = 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驱动程序,如下所示。
/* 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);
复位操作
可以向CTRL3 (12h)的SW_RESET寄存器写入1进行复位。
lsm6dsv80x_reset_set为重置函数。
对应的驱动程序,如下所示。
/* Restore default configuration */
lsm6dsv80x_reset_set(&dev_ctx, LSM6DSV80X_RESTORE_CTRL_REGS);
do {
lsm6dsv80x_reset_get(&dev_ctx, &rst);
} while (rst != LSM6DSV80X_READY);
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 */
lsm6dsv80x_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);
设置低量程加速度速率
低量程加速度速率可以通过CTRL1 (10h)设置加速度速率。

设置加速度速率可以使用如下函数。
// 设置量程与输出数据速率
lsm6dsv80x_xl_data_rate_set(&dev_ctx, LSM6DSV80X_ODR_AT_60Hz);
设置高量程加速度速率
高量程加速度速率可以通过CTRL1_XL_HG (4Eh)设置高量程加速度速率。

设置高量程加速度速率可以使用如下函数。
lsm6dsv80x_hg_xl_data_rate_set(&dev_ctx, LSM6DSV80X_HG_XL_ODR_AT_960Hz, 1);
设置角速度量程速率
角速度量程可以通过CTRL2 (11h)设置高量程加速度速率。

设置角速度速率可以使用如下函数。
lsm6dsv80x_gy_data_rate_set(&dev_ctx, LSM6DSV80X_ODR_AT_120Hz);
设置低量程加速度量程
低量程加速度量程可以通过CTRL8 (17h)设置。

设置加速度量程可以使用如下函数。
/* Set full scale */
lsm6dsv80x_xl_full_scale_set(&dev_ctx, LSM6DSV80X_2g);
设置高量程加速度量程
高量程加速度量程可以通过CTRL1_XL_HG (4Eh)设置。

设置高量程加速度量程可以使用如下函数。
lsm6dsv80x_hg_xl_full_scale_set(&dev_ctx, LSM6DSV80X_80g);
需要注意的是高量程加速度的精度问题。
设置角速度量程
角速度量程可以通过CTRL6 (15h)设置。
设置角速度量程量程可以使用如下函数。
lsm6dsv80x_gy_full_scale_set(&dev_ctx, LSM6DSV80X_2000dps);
配置滤波器
/* Configure filtering chain */
filt_settling_mask.drdy = PROPERTY_ENABLE;
filt_settling_mask.irq_xl = PROPERTY_ENABLE;
filt_settling_mask.irq_g = PROPERTY_ENABLE;
lsm6dsv80x_filt_settling_mask_set(&dev_ctx, filt_settling_mask);
lsm6dsv80x_filt_gy_lp1_set(&dev_ctx, PROPERTY_ENABLE);
lsm6dsv80x_filt_gy_lp1_bandwidth_set(&dev_ctx, LSM6DSV80X_GY_ULTRA_LIGHT);
lsm6dsv80x_filt_xl_lp2_set(&dev_ctx, PROPERTY_ENABLE);
lsm6dsv80x_filt_xl_lp2_bandwidth_set(&dev_ctx, LSM6DSV80X_XL_STRONG);
lowg_xl_sum[0] = lowg_xl_sum[1] = lowg_xl_sum[2] = 0.0;
hg_xl_sum[0] = hg_xl_sum[1] = hg_xl_sum[2] = 0.0;
gyro_sum[0] = gyro_sum[1] = gyro_sum[2] = 0.0;
temp_sum = 0.0;
轮询读取数据
进入一个无限循环,不断检查是否有新的数据(加速度、角速率、温度)可用。
对于每种类型的数据(加速度、角速率、温度),如果有新数据,就读取原始数据,转换为对应的单位(毫克、毫度每秒、摄氏度),并通过串行输出打印。
对于数据是否准备好,可以访问STATUS_REG (1Eh)进行判断。

lsm6dsv80x_data_ready_t drdy;
/* Read output only if new xl value is available */
lsm6dsv80x_flag_data_ready_get(&dev_ctx, &drdy);
对于低量程加速度数据,可以通过28-2D进行获取。


对于高量程加速度数据,可以通过34-39进行获取。


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


对于温度数据,可以通过20-21进行获取。
主程序
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
lsm6dsv80x_data_ready_t drdy;
/* Read output only if new xl value is available */
lsm6dsv80x_flag_data_ready_get(&dev_ctx, &drdy);
// 低g加速度数据
if (drdy.drdy_xl) {
/* Read acceleration field data */
memset(data_raw_motion, 0x00, 3 * sizeof(int16_t));
lsm6dsv80x_acceleration_raw_get(&dev_ctx, data_raw_motion);
acceleration_mg[0] = lsm6dsv80x_from_fs2_to_mg(data_raw_motion[0]);
acceleration_mg[1] = lsm6dsv80x_from_fs2_to_mg(data_raw_motion[1]);
acceleration_mg[2] = lsm6dsv80x_from_fs2_to_mg(data_raw_motion[2]);
lowg_xl_sum[0] += acceleration_mg[0];
lowg_xl_sum[1] += acceleration_mg[1];
lowg_xl_sum[2] += acceleration_mg[2];
lowg_xl_cnt++;
}
// 高g加速度数据
if (drdy.drdy_hgxl) {
/* Read acceleration field data */
memset(data_raw_motion, 0x00, 3 * sizeof(int16_t));
lsm6dsv80x_hg_acceleration_raw_get(&dev_ctx, data_raw_motion);
acceleration_mg[0] = lsm6dsv80x_from_fs80_to_mg(data_raw_motion[0]);
acceleration_mg[1] = lsm6dsv80x_from_fs80_to_mg(data_raw_motion[1]);
acceleration_mg[2] = lsm6dsv80x_from_fs80_to_mg(data_raw_motion[2]);
hg_xl_sum[0] += acceleration_mg[0];
hg_xl_sum[1] += acceleration_mg[1];
hg_xl_sum[2] += acceleration_mg[2];
hg_xl_cnt++;
}
// 陀螺仪数据
/* Read output only if new xl value is available */
if (drdy.drdy_gy) {
/* Read angular rate field data */
memset(data_raw_motion, 0x00, 3 * sizeof(int16_t));
lsm6dsv80x_angular_rate_raw_get(&dev_ctx, data_raw_motion);
angular_rate_mdps[0] = lsm6dsv80x_from_fs2000_to_mdps(data_raw_motion[0]);
angular_rate_mdps[1] = lsm6dsv80x_from_fs2000_to_mdps(data_raw_motion[1]);
angular_rate_mdps[2] = lsm6dsv80x_from_fs2000_to_mdps(data_raw_motion[2]);
gyro_sum[0] += angular_rate_mdps[0];
gyro_sum[1] += angular_rate_mdps[1];
gyro_sum[2] += angular_rate_mdps[2];
gyro_cnt++;
}
if (drdy.drdy_temp) {
/* Read temperature data */
memset(&data_raw_temperature, 0x00, sizeof(int16_t));
lsm6dsv80x_temperature_raw_get(&dev_ctx, &data_raw_temperature);
temperature_degC = lsm6dsv80x_from_lsb_to_celsius(data_raw_temperature);
temp_sum += temperature_degC;
temp_cnt++;
}
if (lowg_xl_cnt >= CNT_FOR_OUTPUT) {
/* print media low-g xl data */
acceleration_mg[0] = lowg_xl_sum[0] / lowg_xl_cnt;
acceleration_mg[1] = lowg_xl_sum[1] / lowg_xl_cnt;
acceleration_mg[2] = lowg_xl_sum[2] / lowg_xl_cnt;
printf("lg xl (media of %d samples) [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
lowg_xl_cnt, acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
lowg_xl_sum[0] = lowg_xl_sum[1] = lowg_xl_sum[2] = 0.0;
lowg_xl_cnt = 0;
/* print media high-g xl data */
acceleration_mg[0] = hg_xl_sum[0] / hg_xl_cnt;
acceleration_mg[1] = hg_xl_sum[1] / hg_xl_cnt;
acceleration_mg[2] = hg_xl_sum[2] / hg_xl_cnt;
printf("hg xl (media of %d samples) [mg]:%4.2f\t%4.2f\t%4.2f\r\n",
hg_xl_cnt, acceleration_mg[0], acceleration_mg[1], acceleration_mg[2]);
hg_xl_sum[0] = hg_xl_sum[1] = hg_xl_sum[2] = 0.0;
hg_xl_cnt = 0;
/* print media gyro data */
angular_rate_mdps[0] = gyro_sum[0] / gyro_cnt;
angular_rate_mdps[1] = gyro_sum[1] / gyro_cnt;
angular_rate_mdps[2] = gyro_sum[2] / gyro_cnt;
printf("gyro (media of %d samples) [mdps]:%4.2f\t%4.2f\t%4.2f\r\n",
gyro_cnt, angular_rate_mdps[0], angular_rate_mdps[1], angular_rate_mdps[2]);
gyro_sum[0] = gyro_sum[1] = gyro_sum[2] = 0.0;
gyro_cnt = 0;
/* print media temperature data */
temperature_degC = temp_sum / temp_cnt;
printf("Temperature (media of %d samples) [degC]:%6.2f\r\n\r\n",
temp_cnt, temperature_degC);
temp_cnt = 0;
temp_sum = 0.0;
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
演示

更多推荐



所有评论(0)