陀螺仪LSM6DSV16X与AI集成(1)----轮询获取陀螺仪数据

陀螺仪LSM6DSV16X与AI集成.1--轮询获取陀螺仪数据

  • 概述
  • 视频教学
  • 样品申请
  • 通信模式
  • 管脚定义
  • IIC通信模式
  • 速率
  • 生成STM32CUBEMX
  • 串口配置
  • IIC配置
  • CS和SA0设置
  • 串口重定向
  • 参考程序
  • 初始换管脚
  • 获取ID
  • 复位操作
  • BDU设置
  • 设置量程和速率
  • 配置过滤链
  • 轮询读取数据
  • 主程序
  • 演示

概述

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

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

在这里插入图片描述

视频教学

样品申请

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

通信模式

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

在CS管脚为1的时候,为IIC模式
在这里插入图片描述

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

管脚定义

在这里插入图片描述

IIC通信模式

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

在这里插入图片描述

IIC接口如下所示。
主要使用的管脚为CS、SCL、SDA、SA0。
在这里插入图片描述

速率

该模块支持的速度为普通模式(100k)和快速模式(400k)。
在这里插入图片描述

生成STM32CUBEMX

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

在这里插入图片描述

串口配置

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

在这里插入图片描述
配置串口。

在这里插入图片描述

IIC配置

在这里插入图片描述
配置IIC为快速模式,速度为400k。
在这里插入图片描述

CS和SA0设置

在这里插入图片描述

串口重定向

打开魔术棒,勾选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/lsm6dsv16x-pid/tree/main

初始换管脚

由于需要向LSM6DSV16X_I2C_ADD_L写入以及为IIC模式。
在这里插入图片描述

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

	printf("123123123");lsm6dsv16x_reset_t rst;stmdev_ctx_t dev_ctx;/* Initialize mems driver interface */dev_ctx.write_reg = platform_write;dev_ctx.read_reg = platform_read;dev_ctx.handle = &SENSOR_BUS;HAL_GPIO_WritePin(CS_GPIO_Port, CS_Pin, GPIO_PIN_SET);HAL_GPIO_WritePin(SA0_GPIO_Port, SA0_Pin, GPIO_PIN_RESET);

获取ID

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

在这里插入图片描述

lsm6dsv16x_device_id_get为获取函数。

在这里插入图片描述

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

  /* Wait sensor boot time */platform_delay(BOOT_TIME);/* Check device ID */lsm6dsv16x_device_id_get(&dev_ctx, &whoamI);printf("LSM6DSV16X_ID=0x%x,whoamI=0x%x",LSM6DSV16X_ID,whoamI);if (whoamI != LSM6DSV16X_ID)while (1);

复位操作

可以向CTRL3 (12h)的SW_RESET寄存器写入1进行复位。
在这里插入图片描述

lsm6dsv16x_reset_set为重置函数。
在这里插入图片描述

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

  /* Restore default configuration */lsm6dsv16x_reset_set(&dev_ctx, LSM6DSV16X_RESTORE_CTRL_REGS);do {lsm6dsv16x_reset_get(&dev_ctx, &rst);} while (rst != LSM6DSV16X_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 */lsm6dsv16x_block_data_update_set(&dev_ctx, PROPERTY_ENABLE);

设置量程和速率

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

在这里插入图片描述

在这里插入图片描述
设置加速度量程可以通过CTRL8 (17h)进行设置。
设置角速度量程可以通过CTRL6 (15h)进行设置。

在这里插入图片描述
在这里插入图片描述

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

  /* Set Output Data Rate.* Selected data rate have to be equal or greater with respect* with MLC data rate.*/lsm6dsv16x_xl_data_rate_set(&dev_ctx, LSM6DSV16X_ODR_AT_7Hz5);lsm6dsv16x_gy_data_rate_set(&dev_ctx, LSM6DSV16X_ODR_AT_15Hz);/* Set full scale */lsm6dsv16x_xl_full_scale_set(&dev_ctx, LSM6DSV16X_2g);lsm6dsv16x_gy_full_scale_set(&dev_ctx, LSM6DSV16X_2000dps);

配置过滤链

  /* Configure filtering chain */filt_settling_mask.drdy = PROPERTY_ENABLE;filt_settling_mask.irq_xl = PROPERTY_ENABLE;filt_settling_mask.irq_g = PROPERTY_ENABLE;lsm6dsv16x_filt_settling_mask_set(&dev_ctx, filt_settling_mask);lsm6dsv16x_filt_gy_lp1_set(&dev_ctx, PROPERTY_ENABLE);lsm6dsv16x_filt_gy_lp1_bandwidth_set(&dev_ctx, LSM6DSV16X_GY_ULTRA_LIGHT);lsm6dsv16x_filt_xl_lp2_set(&dev_ctx, PROPERTY_ENABLE);lsm6dsv16x_filt_xl_lp2_bandwidth_set(&dev_ctx, LSM6DSV16X_XL_STRONG);

轮询读取数据

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

对于数据是否准备好,可以访问STATUS_REG (1Eh)进行判断。
在这里插入图片描述

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

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

在这里插入图片描述

● LSM6DSV16X 加速度计通常会有一个固定的位分辨率,比如 16 位(即输出值是一个 16 位的整数)。这意味着加速度计可以输出的不同值的总数是 2^16=65536。这些值均匀地分布在 -2g 到 +2g 的范围内。
● 因此,这个范围(4g 或者 4000 mg)被分成了 65536 个步长。
● 每个步长的大小是 4000 mg/65536≈0.061 mg/LSB
所以,函数中的乘法 ((float_t)lsb) * 0.061f 是将原始的整数值转换为以毫重力(mg)为单位的加速度值。这个转换对于将加速度计的原始读数转换为实际的物理测量值是必需的。

    if (drdy.drdy_xl) {/* Read acceleration field data */memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));lsm6dsv16x_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acceleration_mg[0] =lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[0]);acceleration_mg[1] =lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[1]);acceleration_mg[2] =lsm6dsv16x_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-2D进行获取。

在这里插入图片描述
在这里插入图片描述

在 LSM6DSV16X 传感器中,函数 lsm6dsv16x_from_fs2000_to_mdps(int16_t lsb) 用于将原始的传感器数据(以最小可分辨位(Least Significant Bit,简称 LSB)为单位)转换为以毫度每秒(mdps)为单位的角速度值。这里的 70.0f 是一个转换因子,用于从原始数据单位转换到实际的物理单位。
具体来说,这个转换因子是基于传感器的灵敏度或比例因子。对于 LSM6DSV16X 传感器,当设置为 ±2000 dps (度每秒) 的满量程时,每个 LSB 代表的角速度值为 70 mdps。

在这里插入图片描述

    /* Read output only if new xl value is available */if (drdy.drdy_gy) {/* Read angular rate field data */memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));lsm6dsv16x_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);angular_rate_mdps[0] =lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[0]);angular_rate_mdps[1] =lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[1]);angular_rate_mdps[2] =lsm6dsv16x_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进行获取。

    if (drdy.drdy_temp) {/* Read temperature data */memset(&data_raw_temperature, 0x00, sizeof(int16_t));lsm6dsv16x_temperature_raw_get(&dev_ctx, &data_raw_temperature);temperature_degC = lsm6dsv16x_from_lsb_to_celsius(data_raw_temperature);printf("Temperature [degC]:%6.2f\r\n", temperature_degC);}

主程序

  /* Infinite loop *//* USER CODE BEGIN WHILE */while (1){lsm6dsv16x_data_ready_t drdy;/* Read output only if new xl value is available */lsm6dsv16x_flag_data_ready_get(&dev_ctx, &drdy);if (drdy.drdy_xl) {/* Read acceleration field data */memset(data_raw_acceleration, 0x00, 3 * sizeof(int16_t));lsm6dsv16x_acceleration_raw_get(&dev_ctx, data_raw_acceleration);acceleration_mg[0] =lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[0]);acceleration_mg[1] =lsm6dsv16x_from_fs2_to_mg(data_raw_acceleration[1]);acceleration_mg[2] =lsm6dsv16x_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]);}		/* Read output only if new xl value is available */if (drdy.drdy_gy) {/* Read angular rate field data */memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));lsm6dsv16x_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);angular_rate_mdps[0] =lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[0]);angular_rate_mdps[1] =lsm6dsv16x_from_fs2000_to_mdps(data_raw_angular_rate[1]);angular_rate_mdps[2] =lsm6dsv16x_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]);}if (drdy.drdy_temp) {/* Read temperature data */memset(&data_raw_temperature, 0x00, sizeof(int16_t));lsm6dsv16x_temperature_raw_get(&dev_ctx, &data_raw_temperature);temperature_degC = lsm6dsv16x_from_lsb_to_celsius(data_raw_temperature);printf("Temperature [degC]:%6.2f\r\n", temperature_degC);}		HAL_Delay(100);/* USER CODE END WHILE *//* USER CODE BEGIN 3 */}/* USER CODE END 3 */

演示

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/194947.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

脏读、不可重复读、幻读

一、脏读 A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏…

Python链表排序相关问题解法

1 问题 链表实现选择排列中经常会遇到一些问题,那么该如何解决它们呢? 2 方法 这一类问题的基本都是根据题目给定的条件,对链表进行各种组合,如:基于归并排序思想,根据节点的数值,合并两个链表&…

PPT设置背景颜色

问题描述:PPT如何设置背景颜色? 问题解决:设计→设置背景格式→颜色→蓝色(最好选择看着比较舒服的颜色)

131. 分割回文串

题目描述 给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。 回文串 是正着读和反着读都一样的字符串。 示例 1: 输入:s "aab" 输出:[["a",&q…

数据库SQL中的三个语句:DROP、TRUNCATE 、DELETE 以上三种的区别? 效率?

数据库SQL中的三个语句:DROP、TRUNCATE 、DELETE 以上三种的区别? 效率? DROP、TRUNCATE和DELETE是数据库SQL中用于删除数据或表的三种不同语句,它们之间有以下区别: 1. DROP: - DROP用于删除整个表…

如何通过缺口发现短线机会?

一、认识缺口形态 新手一开始接触技术分析,可能都以为“缺口”是一个很高深的技术形态。其实缺口很简单,就是K线图中的价格空白区域,也就是股价上涨或下跌的过程中,跳过了这个价格。根据跳空的方向不同,缺口可以分为向…

AArch64中的虚拟化

运行在EL2或更高级别的软件具有对虚拟化的几个控制权限: • 第二阶段翻译(Stage 2 translation) • EL1/0指令和寄存器访问trapping • 虚拟异常生成 非安全状态和安全状态下的异常级别(ELs)如下图所示: 在…

Mongodb与MySQL的异同,使用场景,优缺点。。。

Mongodb与MySQL的使用场景有什么不同?列出详细异同及各自的优缺点? 两者对内在的要求如何? MongoDB与MySQL是两种不同类型的数据库管理系统,它们在使用场景、优缺点和内在要求上有很大的不同。 使用场景的不同: Mong…

二分查找算法:搜索有序数组中目标元素的利器

🚀 作者主页: 有来技术 🔥 开源项目: youlai-mall 🍃 vue3-element-admin 🍃 youlai-boot 🌺 仓库主页: Gitee 💫 Github 💫 GitCode 💖 欢迎点赞…

解决从cmake编译TensorRT头文件找不到无法调试问题

正常情况下配置c_cpp_properties.json文件 {"configurations": [{"name": "Linux","includePath": ["${workspaceFolder}/**","/home/sang/packages/TensorRT-8.5.1.7/include" ],"defines&…

uniapp长按图片识别二维码

引用&#xff1a;https://blog.csdn.net/weixin_48596030/article/details/125405779 <image :src"url" mode"widthFix" click.self"previewImage" show-menu-by-longpress"true" style"width: 350rpx;"></image…

每周一算法:背包问题(二)完全背包

完全背包 有 N N N件物品和一个容量是 M M M的背包。每种物品都有无限件可用。第 i i i件物品的体积是 v i v_i vi​&#xff0c;价值是 w i w_i wi​。 求解将哪些物品装入背包&#xff0c;可使这些物品的总体积不超过背包容量&#xff0c;且总价值最大。 输出最大价值。…

SAP_ABAP_RZ11解决SAP运行超时问题 TIME_OUT / rdisp/scheduler/prio_high/max_runtime

SAP ABAP 顾问&#xff08;开发工程师&#xff09;能力模型_Terry谈企业数字化的博客-CSDN博客文章浏览阅读510次。目标&#xff1a;基于对SAP abap 顾问能力模型的梳理&#xff0c;给一年左右经验的abaper 快速成长为三年经验提供超级燃料&#xff01;https://blog.csdn.net/j…

shell_80.Linux函数的递归

函数递归 局部函数变量的一个特性是自成体系&#xff08;self-containment&#xff09;。 除了获取函数参数&#xff0c;自成体系的函数不需要使用任何外部资源。 递归算法的经典例子是计算阶乘。一个数的阶乘是该数之前的所有数乘以该数的值。因此 要计算 5 的阶乘&#xff0c…

音频处理关键知识点

1 引言 现实生活中&#xff0c;我们听到的声音都是时间连续的&#xff0c;我们称为这种信号叫模拟信号。模拟信号需要进行数字化以后才能在计算机中使用。 目前我们在计算机上进行音频播放都需要依赖于音频文件。音频文件的生成过程是将声音信息采样、量化和编码产生的数字信号…

linux无网络 无ip,显示网络未连接

标题:linux无网络 无ip&#xff0c;显示网络未连接 参考blog&#xff1a;Linux无网络连接问题排查 首先我们发现ens33没有ip地址&#xff0c;说明这个接口并没有被分到ip&#xff1b; 我们可以通过手动方式来给ens33获得网络ip sudo dhclient ens33&#xff0c;之后再输入ifc…

FPGA UltraScale GTH 全网最细讲解,aurora 8b/10b编解码,HDMI视频传输,提供2套工程源码和技术支持

目录 1、前言免责声明 2、我这里已有的 GT 高速接口解决方案3、详细设计方案设计框图视频源选择ADV7611解码芯片配置及采集动态彩条视频数据组包UltraScale GTH 全网最细解读UltraScale GTH 基本结构参考时钟的选择和分配UltraScale GTH 发送和接收处理流程UltraScale GTH 发送…

【小沐学Python】Python实现Web服务器(Flask+celery,生产者-消费者)

文章目录 1、简介2、安装和下载2.1 flask2.2 celery2.3 redis 3、功能开发3.1 创建异步任务的方法3.1.1 使用默认的参数3.1.2 指定相关参数3.1.3 自定义Task基类 3.2 调用异步任务的方法3.2.1 app.send_task3.2.2 Task.delay3.2.3 Task.apply_async 3.3 获取任务结果和状态 4、…

web前端之JavaScript实现数据的流式获取、一边传输一边解析、fetch、getReader、TextDecoder、read、decode

MENU 前言代码TextDecodergetReaderfetch 前言 1、此功能类似于GTP一样一点一点的解析数据&#xff0c;不需要等到所有数据都返回才解析&#xff0c;这个是回来多少解析多少。 2、代码中的url是真实的URL&#xff0c;只是读取的是列表&#xff0c;所以流式的效果不是很明显&…

C++ priority_queue

一、简介 Priority Queue&#xff08;优先队列&#xff09; 是一种常用的数据结构&#xff0c;它基于每个元素关联的优先级而组织元素&#xff0c;确保高优先级的元素先被处理。在实际应用中&#xff0c;优先队列常用于解决与优先级相关的问题&#xff0c;如任务调度、图算法等…