0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

驱动LSM6DS3TR-C实现高效运动检测与数据采集(9)----获取磁力计数据

嵌入式单片机MCU开发 来源:嵌入式单片机MCU开发 作者:嵌入式单片机MCU开 2024-08-02 15:47 次阅读

概述

本文将介绍如何使用 LIS2MDL 传感器来主要步骤包括初始化传感器接口、验证设备ID、配置传感器的数据输出率和滤波器,以及通过轮询方式持续读取磁力数据和温度数据。读取到的数据会被转换为适当的单位并通过串行通信输出。
需要样片的可以加群申请:615061293 。

视频教学

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

样品申请

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

源码下载

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

九轴融合

在六轴基础上添加磁力计执行九轴融合 ,MotionFX库实现了一种传感器融合算法,用于估计空间中的3D方向。它使用基于卡尔曼滤波器的数字滤波器理论来融合来自多个传感器的数据,并补偿单个传感器的局限性。例如:
陀螺仪数据可能会漂移,这会影响方向估计;使用磁力计可以提供绝对方向信息来解决这个问题。
● 磁力计带宽不高且易受磁干扰影响,但这些弱点可以通过陀螺仪补偿。
● 九轴传感器融合使用加速度计、陀螺仪和磁力计的数据,提供包括航向(即磁北方向)的绝对方向。
● 六轴传感器融合仅使用加速度计和陀螺仪数据,计算量较小,但不提供绝对方向信息。
● 六轴传感器融合适用于快速移动的场景(如游戏)和不需要绝对方向的情况。

通信模式

对于LIS2MDL,可以使用SPI或者IIC进行通讯。 最小系统图如下所示。

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

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

速率

该模块支持的速度为普通模式(100k)、快速模式(400k)、快速模式+(1M)、高速模式(3.4M)。

参考程序

[https://github.com/STMicroelectronics/lis2mdl-pid]

变量定义

int16_t data_raw_magnetic[3];
static float magnetic_mG[3];
/* 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 lis2mdl_platform_write(void *handle, uint8_t reg, const uint8_t *bufp,
                              uint16_t len);
static int32_t lis2mdl_platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                             uint16_t len);

获取ID

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

is2mdl_device_id_get为获取函数。

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

/* Check device ID */
  lis2mdl_device_id_get(&lis2mdl_dev_ctx, &whoamI);
    printf("LIS2MDL_ID=0x%x,whoamI=0x%x",LIS2MDL_ID,whoamI);
  if (whoamI != LIS2MDL_ID)
    while (1) {
      /* manage here device not found */
    }

复位操作

可以向CFG_REG_A (60h)的SOFT_RST寄存器写入1进行复位。

lis2mdl_reset_set为重置函数。

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

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

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

BDU设置

在很多传感器中,数据通常被存储在输出寄存器中,这些寄存器分为两部分:MSB和LSB。这两部分共同表示一个完整的数据值。例如,在一个加速度计中,MSB和LSB可能共同表示一个加速度的测量值。
连续更新模式(BDU = ‘0’):在默认模式下,输出寄存器的值会持续不断地被更新。这意味着在你读取MSB和LSB的时候,寄存器中的数据可能会因为新的测量数据而更新。这可能导致一个问题:当你读取MSB时,如果寄存器更新了,接下来读取的LSB可能就是新的测量值的一部分,而不是与MSB相对应的值。这样,你得到的就是一个“拼凑”的数据,它可能无法准确代表任何实际的测量时刻。
块数据更新(BDU)模式(BDU = ‘1’):当激活BDU功能时,输出寄存器中的内容不会在读取MSB和LSB之间更新。这就意味着一旦开始读取数据(无论是先读MSB还是LSB),寄存器中的那一组数据就被“锁定”,直到两部分都被读取完毕。这样可以确保你读取的MSB和LSB是同一测量时刻的数据,避免了读取到代表不同采样时刻的数据。
简而言之,BDU位的作用是确保在读取数据时,输出寄存器的内容保持稳定,从而避免读取到拼凑或错误的数据。这对于需要高精度和稳定性的应用尤为重要。
可以向CFG_REG_C (62h)的BDU寄存器写入1进行开启。

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

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

设置速率

速率可以通过CFG_REG_A (60h)的ODR设置速率。

设置速率可以使用如下函数。

/* Set Output Data Rate */
  lis2mdl_data_rate_set(&lis2mdl_dev_ctx, LIS2MDL_ODR_50Hz);

启用偏移消除

LIS2MDL 磁力计的配置寄存器(CFG_REG_B)的OFF_CANC - 这个位用于启用或禁用偏移消除。

这意味着每次磁力计准备输出新的测量数据时,它都会自动进行偏移校准,以确保数据的准确性。这通常用于校准传感器,以消除由于传感器偏移或环境因素引起的任何误差。

/* Set / Reset sensor mode */
  lis2mdl_set_rst_mode_set(&dev_ctx, LIS2MDL_SENS_OFF_CANC_EVERY_ODR);

开启温度补偿

开启温度补偿可以通过CFG_REG_A (60h)的COMP_TEMP_EN进行配置。

/* Enable temperature compensation */
  lis2mdl_offset_temp_comp_set(&dev_ctx, PROPERTY_ENABLE);

设置为连续模式

LIS2MDL 磁力计 CFG_REG_A (60h) 配置寄存器的MD1 和 MD0 - 这两个位用于选择设备的工作模式。
00 - 连续模式,设备连续进行测量并将结果放在数据寄存器中。
01 - 单次模式,设备进行单次测量,然后返回到空闲模式。
10 和 11 - 空闲模式,设备被置于空闲模式,但I2C和SPI接口仍然激活

/* Set device in continuous mode */
  lis2mdl_operating_mode_set(&dev_ctx, LIS2MDL_CONTINUOUS_MODE);

初始化

/* Initialize mems driver interface */
  stmdev_ctx_t lis2mdl_dev_ctx;
  lis2mdl_dev_ctx.write_reg = lis2mdl_platform_write;
  lis2mdl_dev_ctx.read_reg = lis2mdl_platform_read;
  lis2mdl_dev_ctx.mdelay = platform_delay;
  lis2mdl_dev_ctx.handle = &SENSOR_BUS;
  /* Initialize platform specific hardware */
//  platform_init();
  /* Wait sensor boot time */
  platform_delay(BOOT_TIME);

  /* Check device ID */
  lis2mdl_device_id_get(&lis2mdl_dev_ctx, &whoamI);
    printf("LIS2MDL_ID=0x%x,whoamI=0x%x",LIS2MDL_ID,whoamI);
  if (whoamI != LIS2MDL_ID)
    while (1) {
      /* manage here device not found */
    }

  /* Restore default configuration */
  lis2mdl_reset_set(&lis2mdl_dev_ctx, PROPERTY_ENABLE);

  do {
    lis2mdl_reset_get(&lis2mdl_dev_ctx, &rst);
  } while (rst);

  /* Enable Block Data Update */
  lis2mdl_block_data_update_set(&lis2mdl_dev_ctx, PROPERTY_ENABLE);
  /* Set Output Data Rate */
  lis2mdl_data_rate_set(&lis2mdl_dev_ctx, LIS2MDL_ODR_50Hz);
  /* Set / Reset sensor mode */
  lis2mdl_set_rst_mode_set(&lis2mdl_dev_ctx, LIS2MDL_SENS_OFF_CANC_EVERY_ODR);
  /* Enable temperature compensation */
  lis2mdl_offset_temp_comp_set(&lis2mdl_dev_ctx, PROPERTY_ENABLE);
  /* Set device in continuous mode */
  lis2mdl_operating_mode_set(&lis2mdl_dev_ctx, LIS2MDL_CONTINUOUS_MODE);

轮询读取数据

对于数据是否准备好,可以查看STATUS_REG (67h)的Zyxda位,判断是否有新数据到达。

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

数据OUTX_L_REG(68h)-OUTZ_H_REG(6Dh)获取。

memset(data_raw_magnetic, 0x00, 3 * sizeof(int16_t));
      lis2mdl_magnetic_raw_get(&lis2mdl_dev_ctx, data_raw_magnetic);
      magnetic_mG[0] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[0]);
      magnetic_mG[1] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[1]);
      magnetic_mG[2] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[2]);
            if(i==0)
      printf("Magnetic field [mG]:%4.2ft%4.2ft%4.2frn",
              magnetic_mG[0], magnetic_mG[1], magnetic_mG[2]);            
//                    lsm6ds3tr_c_motion_fx_determin();

添加到如下所示地方。

演示

主程序

/* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {

    if(fifo_flag)
    {
        for(int i=0;i< fifo_num;i++)// 遍历 FIFO 数据数组
        {    

            int16_t gyr;                
            gyr=(gyr_fifo[i][1]< < 8) + gyr_fifo[i][0];
            gyr_x =lsm6ds3tr_c_from_fs2000dps_to_mdps(gyr);
            gyr=(gyr_fifo[i][3]< < 8) + gyr_fifo[i][2];                
            gyr_y =lsm6ds3tr_c_from_fs2000dps_to_mdps(gyr);
            gyr=(gyr_fifo[i][5]< < 8) + gyr_fifo[i][4];                
            gyr_z =lsm6ds3tr_c_from_fs2000dps_to_mdps(gyr);
//            printf(
//                            "gyr_x:%4.2ft%4.2ft%4.2frn",
//                            gyr_x, gyr_y, gyr_z);            
            int16_t acc;
            acc=(acc_fifo[i][1]< < 8) + acc_fifo[i][0];
            acc_x =lsm6ds3tr_c_from_fs4g_to_mg(acc);
            acc=(acc_fifo[i][3]< < 8) + acc_fifo[i][2];                
            acc_y =lsm6ds3tr_c_from_fs4g_to_mg(acc);
            acc=(acc_fifo[i][5]< < 8) + acc_fifo[i][4];                
            acc_z =lsm6ds3tr_c_from_fs4g_to_mg(acc);

//            printf(
//                            "acc_x:%4.2ft%4.2ft%4.2frn",
//                            acc_x, acc_y, acc_z);    

         /* 读取时间戳数据 */
            uint32_t timestamp=0;
            timestamp=(timestamp_fifo[i][1]< < 16)|(timestamp_fifo[i][0]< < 8)
                |(timestamp_fifo[i][3]);
//        printf("Timestamp: %urn", timestamp);        

            if(deltatime_first==0)//第一次
                {
                    deltatime_1=timestamp;
                    deltatime_2=deltatime_1;
                    deltatime_first=1;
                }
                else
                {
                    deltatime_2=timestamp;
                }
      memset(data_raw_magnetic, 0x00, 3 * sizeof(int16_t));
      lis2mdl_magnetic_raw_get(&lis2mdl_dev_ctx, data_raw_magnetic);
      magnetic_mG[0] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[0]);
      magnetic_mG[1] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[1]);
      magnetic_mG[2] = lis2mdl_from_lsb_to_mgauss(data_raw_magnetic[2]);
            if(i==0)
      printf("Magnetic field [mG]:%4.2ft%4.2ft%4.2frn",
              magnetic_mG[0], magnetic_mG[1], magnetic_mG[2]);            
//                    lsm6ds3tr_c_motion_fx_determin();    
                deltatime_1=deltatime_2;

            }
            fifo_flag=0;                
        }


    /* USER CODE END WHILE */

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

审核编辑 黄宇

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

    关注

    38

    文章

    5478

    浏览量

    113077
  • 运动检测
    +关注

    关注

    0

    文章

    33

    浏览量

    12592
  • 磁力计
    +关注

    关注

    1

    文章

    71

    浏览量

    20737
收藏 人收藏

    评论

    相关推荐

    驱动LSM6DS3TR-C实现高效运动检测数据采集(1)----获取ID

    本文将介绍如何驱动和利用LSM6DS3TR-C传感器,实现精确的运动感应功能。LSM6DS3TR-C是一款先进的
    的头像 发表于 11-13 15:45 1757次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(1)----<b class='flag-5'>获取</b>ID

    驱动LSM6DS3TR-C实现高效运动检测数据采集(6)----FIFO数据读取与配置

    LSM6DS3TR-C是STMicroelectronics公司推出的iNEMO惯性模块,集成了三轴加速度计和三轴陀螺仪,具备低功耗、强大的运动检测功能。该传感器支持多种操作模式,并内置FIFO
    的头像 发表于 07-18 10:58 775次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(<b class='flag-5'>6</b>)----FIFO<b class='flag-5'>数据</b>读取与配置

    驱动LSM6驱动LSM6DS3TR-C实现高效运动检测数据采集(7)----MotionFX库解析空间坐标DS3TR-C实现高效运动检测数据

    本文将探讨如何使用MotionFX库解析空间坐标。MotionFX库是一种用于传感器融合的强大工具,可以将加速度计、陀螺仪和磁力计数据融合在一起,实现精确的姿态和位置估计。本文将介绍如何初始化
    的头像 发表于 07-18 11:02 815次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6</b><b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(7)----MotionFX库解析空间坐标<b class='flag-5'>DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据</b>采

    驱动LSM6DS3TR-C实现高效运动检测数据采集(10)----融合磁力计进行姿态解算

    MotionFX库包含用于校准陀螺仪、加速度计和磁力计传感器的例程。 将磁力计数据与加速度计和陀螺仪的数据融合,可以大幅提高姿态估计的精度。三轴加速度计提供设备的倾斜信息,陀螺仪提供
    的头像 发表于 08-02 15:50 1791次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(10)----融合<b class='flag-5'>磁力计</b>进行姿态解算

    lsm6ds3tr-c传感器集合模式无法使用的原因?

    );/*读取外挂磁力计代码*///禁用I2C直通,禁用内部上拉,禁用I2Cbsp_spi_write(LSM6DS3TR_MASTER_CONFIG, 0x00, 2);//关闭加速度计
    发表于 03-07 06:26

    LSM6DS3TR-C使用时工作电流比datasheet上大很多是什么原因?

    使用场景是LSM6DS3TR-C通过SPI一拖四连接单片机,一共有四路这样的一拖四。 测试时发现电流很大,感觉有点不对,编写程序使LSM6DS3TR-C间隔5s一个一个使能,会发现稳压源的输出电流从
    发表于 03-07 08:08

    请问LSM6DS3TRLSM6DS3TR-C两个型号能否完全兼容?

    LSM6DS3TR停产买不到了,准备切换LSM6DS3TR-C型号使用。 请问两者有什么差别?能否直接替换?有成功替换案例吗?
    发表于 03-14 06:40

    LSM6DS3TR-C数据读取异常是安利的问题?怎么处理?

    我在使用lsm6ds3tr-c 6轴传感器时发现,读取的温度以及角速度值异常,配置为官方lsm6ds3tr_c_read_data_polling.c文件中
    发表于 03-19 08:15

    LSM6DS3TR-C的FIFO读取数据出错是什么原因造成的?怎么解决?

    使用LSM6DS3TR-C的FIFO,先获取了FIFO的WaterM标志,该标志置位之后再去获取当前存在FIFO缓存的数据长度,再去读取FIFO中对应长度的
    发表于 03-27 06:05

    请问LSM6DS3TR-C有没有windows下的测试工具?

    LSM6DS3TR-C有没有windows下的测试工具
    发表于 05-20 06:22

    LSM6DS3的应用笔记

    专门设计,可在硬件上实现大幅运动检测、倾斜度检测、硬件计步功能、时间戳,并支持对外部磁力计数据采集,且支持铁磁校准 (硬铁修正,软铁修正)
    发表于 09-13 08:23

    驱动LSM6DS3TR-C实现高效运动检测数据采集(2)----配置滤波器

    LSM6DS3TR-C中,加速度计和陀螺仪可以独立地开启/关闭,并且可以拥有不同的ODR和功耗模式。 LSM6DS3TR-C有三种可用的操作模式: ● 仅加速度计活动,陀螺仪处于断电状态 ● 仅陀螺仪活动,加速度计处于断电状态 ● 加速度计和陀螺仪传感器同时活动
    的头像 发表于 11-14 09:45 751次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(2)----配置滤波器

    驱动LSM6DS3TR-C实现高效运动检测数据采集(3)----获取传感器数据

    一旦传感器被正确初始化,可以通过SPI或I2C接口向传感器发送读取命令,并接收传感器返回的数据。这个读取过程包括获取LSM6DS3TR传感器提供的加速度计和陀螺仪
    的头像 发表于 11-14 09:59 628次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(<b class='flag-5'>3</b>)----<b class='flag-5'>获取</b>传感器<b class='flag-5'>数据</b>

    驱动LSM6DS3TR-C实现高效运动检测数据采集(4)----上报匿名上位机实现可视化

    LSM6DS3TR-C是单芯片“3轴陀螺仪 + 3轴加速度计”的惯性 测量单元(IMU), 五种种可选满量程的陀螺仪(125/250/500/1000/2000 dps)和加速度计(2/4/8/16
    的头像 发表于 11-14 10:05 695次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(4)----上报匿名上位机<b class='flag-5'>实现</b>可视化

    驱动LSM6DS3TR-C实现高效运动检测数据采集(11)----磁力计校准

    导致测量数据出现偏差。因此,校准磁力计以消除这些影响,是获得精确测量数据的必要步骤。 本文将介绍如何使用ST提供的MotionFX库在嵌入式系统中实现
    的头像 发表于 08-23 09:57 151次阅读
    <b class='flag-5'>驱动</b><b class='flag-5'>LSM6DS3TR-C</b><b class='flag-5'>实现</b><b class='flag-5'>高效</b><b class='flag-5'>运动检测</b>与<b class='flag-5'>数据采集</b>(11)----<b class='flag-5'>磁力计</b>校准