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

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

3天内不再提示

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

嵌入式单片机MCU开发 来源:嵌入式单片机MCU开发 作者:嵌入式单片机MCU开 2024-08-23 09:57 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

概述

磁力计校准是确保传感器数据准确性和可靠性的关键步骤。磁力计用于测量地球磁场,并在导航、定位、姿态测量等应用中起到重要作用。然而,磁力计在使用过程中会受到环境磁场、硬件偏差、安装误差等因素的影响,从而导致测量数据出现偏差。因此,校准磁力计以消除这些影响,是获得精确测量数据的必要步骤。

本文将介绍如何使用ST提供的MotionFX库在嵌入式系统中实现磁力计校准, 通过本文的介绍,读者将能够理解磁力计校准的基本概念,掌握使用MotionFX库进行校准的步骤和方法,并学会如何在实际项目中实现磁力计的校准,以获得高精度的磁场测量数据。

需要样片的可以加群申请:615061293 。

视频教学

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

样品申请

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

源码下载

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

硬件准备

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

DataLogFusion

这里参考ST提供的DataLogFusion程序,DataLogFusion示例应用展示了如何使用STMicroelectronics开发的MotionFX中间件库进行实时运动传感器数据融合。

DataLogFusion的主要执行流程包括初始化硬件和传感器、中间件库(MotionFX)的配置与初始化、传感器数据的采集、实时数据融合以及结果的输出。

磁力计校准过程

MotionFX库的磁力计校准库用于补偿硬铁失真。磁力计校准可以以比传感器融合输出数据速率更慢的频率进行(例如25 Hz)。
● 初始化磁力计校准库:
● 调用 MotionFX_MagCal_init 或 MotionFX_CM0P_MagCal_init 函数。
● 定期调用校准函数:
● 调用 MotionFX_MagCal_run 或 MotionFX_CM0P_MagCal_run 函数,直到校准成功完成。
● 检查校准是否成功:
● 调用 MotionFX_MagCal_getParams 或 MotionFX_CM0P_MagCal_getParams 函数。如果函数返回 mag_data_out.cal_quality = MFX_MAGCALGOOD 或 MFX_CM0P_CALQSTATUSBEST,则校准成功。

在app_mems.c中的Magneto_Sensor_Handler函数负责处理磁力计(磁传感器)数据的获取、校准和发送。该函数的主要功能是从磁力计传感器获取数据,进行必要的校准,然后将处理后的数据传输给其他部分使用。具体包括以下步骤:

  1. 检查传感器是否启用:函数首先检查是否启用了磁力计传感器。如果传感器未启用,则函数不会执行进一步操作。
  2. 获取磁力计数据:
    ○ 如果使用离线数据(即在调试或仿真模式下),函数会从预定义的离线数据数组中读取磁力计数据。
    ○ 如果使用实时数据,函数会通过调用BSP_SENSOR_MAG_GetAxes函数从实际的磁力计传感器中读取当前的磁力计数据。
  3. 执行磁力计校准:
    ○ 函数检查磁力计是否已经校准。如果尚未校准,则会进行校准过程。
    ○ 将获取的磁力计数据转换为适当的单位,并准备校准输入数据。
    ○ 调用MotionFX_manager_MagCal_run函数运行校准算法
    ○ 如果校准结果良好(校准质量达到标准),函数会保存校准偏移值,并停止进一步的校准。
  4. 应用校准偏移:将校准偏移应用到磁力计读数中,以补偿硬件偏差和环境干扰。
  5. 序列化并发送数据:将校准后的磁力计数据序列化,并存储到消息结构(Msg)中,以供系统其他部分使用。

MotionFX_manager_MagCal_run函数用于运行磁力计校准算法。该函数接受磁力计输入数据,调用MotionFX库中的校准算法对数据进行处理,并返回校准结果。
MotionFX_MagCal_run函数执行校准算法,对输入数据进行处理,计算出校准所需的参数。
MotionFX_MagCal_getParams函数从校准算法中获取校准后的参数,并存储在输出数据结构data_out中。这些参数包括磁力计的偏移和标度因子等校准信息。

MotionFX_MagCal_getParams

MotionFX_MagCal_getParams函数用于获取磁力计的校准参数。这些参数包括校准后的硬铁偏移量和校准质量指标。该函数通过传入一个指向输出数据结构的指针,返回校准结果的详细信息。

调用MotionFX_MagCal_getParams函数后,可以通过检查data_out结构体中的参数来评估校准结果的质量,并应用偏移量来调整磁力计数据。
cal_quality:校准质量因子,指示校准结果的准确性。具体值包括:
MFX_MAGCALUNKNOWN = 0:校准参数的准确性未知。
MFX_MAGCALPOOR = 1:校准参数的准确性较差,不能被信任。
MFX_MAGCALOK = 2:校准参数的准确性尚可。
MFX_MAGCALGOOD = 3:校准参数的准确性良好。

校准移植

在main.c中添加变量定义。

/* USER CODE BEGIN 0 */
float MagOffset[3]={0.0f,0.0f,0.0f};//磁力计偏差
int Mag_TimeStamp,Mag_TimeStamp_1,Mag_TimeStamp_2;//磁力计时间戳

uint8_t Mag_flag=0;
/* USER CODE END 0 */

磁力计数据官方文档推荐20/40HZ。

在mian.c中添加磁力计校准执行函数这里陀螺仪数据为416Hz,单次循环执行10次,所以让磁力计在单次循环中只执行一次,频率则为40Hz左右。

/* 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]);

            if(i==0)
                Mag_flag=1;        
            if(deltatime_first==0)//第一次
                {
                    deltatime_1=timestamp;
                    deltatime_2=deltatime_1;
                    deltatime_first=1;
                    Mag_TimeStamp_1=timestamp;
                    Mag_TimeStamp_2=timestamp;  
                }
                else
                {
                    deltatime_2=timestamp;
                    Mag_TimeStamp_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(Mag_flag)
            {
                Mag_TimeStamp=Mag_TimeStamp_2-Mag_TimeStamp_1;
                if(Mag_TimeStamp_2 >Mag_TimeStamp_1)
                    Mag_TimeStamp=(int)((Mag_TimeStamp_2-Mag_TimeStamp_1)*25.0f/1000);
                else if(Mag_TimeStamp_1 >Mag_TimeStamp_2)
                    Mag_TimeStamp=(int)((0xffffffff-Mag_TimeStamp_2+Mag_TimeStamp_1)*25.0f/1000);
                else if(Mag_TimeStamp_1==Mag_TimeStamp_2)
                    Mag_TimeStamp=0;
                Magneto_Sensor_Handler();
                Mag_TimeStamp_1=Mag_TimeStamp_2;
                Mag_flag=0;
            }    
            magnetic_mG[0] = magnetic_mG[0]-MagOffset[0];
            magnetic_mG[1] = magnetic_mG[1]-MagOffset[1];
            magnetic_mG[2] = magnetic_mG[2]-MagOffset[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 */

在app.h中添加磁力计校准函数定义。

#define FROM_UT50_TO_MGAUSS  500.0f
void Magneto_Sensor_Handler(void);

在app.c中添加磁力计校准函数。

typedef struct
{
  uint8_t hours;
  uint8_t minutes;
  uint8_t seconds;
  uint8_t subsec;
  float pressure;
  float humidity;
  float temperature;
  int32_t acceleration_x_mg;
  int32_t acceleration_y_mg;
  int32_t acceleration_z_mg;
  int32_t angular_rate_x_mdps;
  int32_t angular_rate_y_mdps;
  int32_t angular_rate_z_mdps;
  int32_t magnetic_field_x_mgauss;
  int32_t magnetic_field_y_mgauss;
  int32_t magnetic_field_z_mgauss;
} offline_data_t;

#define OFFLINE_DATA_SIZE  8
uint8_t UseOfflineData = 0;
uint8_t MagCalStatus = 0;
offline_data_t OfflineData[OFFLINE_DATA_SIZE];
extern float MagOffset[3];
extern float magnetic_mG[3];
extern int Mag_TimeStamp;
/**
  * @brief  Handles the MAG axes data getting/sending
  * @param  Msg the MAG part of the stream
  * @retval None
  */
void Magneto_Sensor_Handler(void)
{
  float ans_float;
  MFX_MagCal_input_t mag_data_in;
  MFX_MagCal_output_t mag_data_out;


        mag_data_in.mag[0] = (float)magnetic_mG[0] * FROM_MGAUSS_TO_UT50;
        mag_data_in.mag[1] = (float)magnetic_mG[1] * FROM_MGAUSS_TO_UT50;
        mag_data_in.mag[2] = (float)magnetic_mG[2] * FROM_MGAUSS_TO_UT50;

        mag_data_in.time_stamp = (int)Mag_TimeStamp;
//        Mag_TimeStamp += (uint32_t)ALGO_PERIOD;


        MotionFX_MagCal_run(&mag_data_in);
        MotionFX_MagCal_getParams(&mag_data_out);
        printf("mag_data_out=%d,MFX_MAGCALGOOD=%dn",mag_data_out.cal_quality,MFX_MAGCALGOOD);
        if (mag_data_out.cal_quality == MFX_MAGCALGOOD)
        {

//            MagCalStatus = 1;

            ans_float = (mag_data_out.hi_bias[0] * FROM_UT50_TO_MGAUSS);
            MagOffset[0] = (int32_t)ans_float;
            ans_float = (mag_data_out.hi_bias[1] * FROM_UT50_TO_MGAUSS);
            MagOffset[1] = (int32_t)ans_float;
            ans_float = (mag_data_out.hi_bias[2] * FROM_UT50_TO_MGAUSS);
            MagOffset[2] = (int32_t)ans_float;

//          /* Disable magnetometer calibration */
//          MotionFX_manager_MagCal_stop(ALGO_PERIOD);
        }

}

演示

未校准成功时未0。

校准成功时为3。

审核编辑 黄宇

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

    关注

    2574

    文章

    54401

    浏览量

    786222
  • 驱动
    +关注

    关注

    12

    文章

    1928

    浏览量

    88206
  • 数据采集
    +关注

    关注

    40

    文章

    7820

    浏览量

    119873
  • 运动检测
    +关注

    关注

    0

    文章

    40

    浏览量

    12809
收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    LSM6DSV iNEMO™惯性模块:为下一代智能设备提供高性能运动感知

    的配置、滤波和处理功能。LSM6DSV在高性能模式下提升性能(0.65mA时),具有不间断低功耗特性,实现最佳的消费者运动体验。该器件嵌入了高级专用功能,例如有限状态机和数据滤波,用于
    的头像 发表于 10-28 11:25 334次阅读
    <b class='flag-5'>LSM6</b>DSV iNEMO™惯性模块:为下一代智能设备提供高性能<b class='flag-5'>运动</b>感知

    LSM6DSV16B:面向TWS与可穿戴设备的6轴IMU,融合传感与低功耗智能

    于提供精确的加速度和角速度感测数据处理。 LSM6DSV16B具有专用于运动跟踪、设备电源管理、游戏3D头部跟踪和增强音频体验的双通道,提供无与伦比的多用性和功能。该器件还具有单独通
    的头像 发表于 10-25 14:28 822次阅读
    <b class='flag-5'>LSM6</b>DSV16B:面向TWS与可穿戴设备的<b class='flag-5'>6</b>轴IMU,融合传感与低功耗智能

    MEMS加速度:小身材里藏着怎样的&amp;quot;运动感知&amp;quot;大能量?

    优势,正广泛应用于振动检测、姿态控制、安全报警领域。当它与陀螺仪、磁力计结合成惯性测量单元(IMU)时,更构成了智能系统的“神经末梢”,让设备感知世界如虎添翼。
    的头像 发表于 10-21 15:00 177次阅读
    MEMS加速度<b class='flag-5'>计</b>:小身材里藏着怎样的&amp;quot;<b class='flag-5'>运动</b>感知&amp;quot;大能量?

    LSM6DSV320X:面向高端应用的智能6轴惯性测量单元

    。STMicroelectronics IMU设计用于提供精确的运动检测和传感器融合功能,因此非常适合用于汽车碰撞检测运动监控和物联网 (IoT) 设备。LSM6DSV320X采用四
    的头像 发表于 10-21 14:34 305次阅读
    <b class='flag-5'>LSM6</b>DSV320X:面向高端应用的智能<b class='flag-5'>6</b>轴惯性测量单元

    浅谈HMC5883L和QMC5883P磁力计的区别及STM32F103驱动

    HMC5883L和QMC5883P是两款硬件兼容但软件不兼容的磁力计芯片,主要区别在于寄存器地址、设备地址和磁场方向定义。本文提供了HMC5883L的初始化代码和寄存器配置说明,包括采样率、量程设置
    的头像 发表于 08-30 10:10 5877次阅读
    浅谈HMC5883L和QMC5883P<b class='flag-5'>磁力计</b>的区别及STM32F103<b class='flag-5'>驱动</b>

    实时、高效,解锁气象数据采集新速度——气象数据采集

    在气象监测的宏大版图中,气象数据采集器宛如一颗精准跳动的心脏,为整个气象研究与应用体系输送着至关重要的“血液”——气象数据。它以实时、高效的特性,解锁了气象数据采集的新速度,为气象监测
    的头像 发表于 08-22 17:27 645次阅读

    需要将lsm6ds3tr-c传感器集成到展锐平台android系统,请问有示例文档吗?

    您好,我现在需要将lsm6ds3tr-c传感器集成到展锐平台android系统,请问有示例文档吗
    发表于 06-18 08:28

    LSM6DS3TRC FIFO模式,长时间运行\"卡死\"有人遇到过吗

    问题吗?刚开始是正常运行的,但是可能过几个小时后就会出现这个问题,导致用中断唤醒不了我的mcu了 附带我的初始化 Lsm6ds3_SoftwareReset(); // 加速度26HZ, 2g量程
    发表于 06-08 15:08

    labview数据采集同步性及获取时间问题

    请问在labview中进行数据采集,为保证不同设备之间采集数据的同步性,准备利用PPS进行触发开始任务,利用DAQmx设备内部时钟源来设置数据采集的一些参数,但是为了防止pps信号的缺失,准备能够周期性的利用pps对内部晶振进行
    发表于 04-27 10:54

    labview进行的数据采集

    请问在labview中进行数据采集,为保证不同设备之间采集数据的同步性,准备利用PPS进行触发开始任务,利用DAQmx设备内部时钟源来设置数据采集的一些参数,但是为了防止pps信号的缺失,准备能够周期性的利用pps对内部晶振进行
    发表于 04-27 10:19

    LSM6DS3TR-C长时间读取后角速度输出为0是怎么回事?

    LSM6DS3TR-C 长时间读取后角速度输出为0
    发表于 03-14 07:42

    使用iic对mpu9250进行读取数据,读取磁力计数据时采用的是主控iic方式,但是读取的速度特别慢,为什么?

    使用iic对mpu9250进行读取数据,读取磁力计数据时采用的是主控iic方式,但是读取的速度特别慢,几秒一次,网上说磁力计数据输出的速率最快是100hz,几秒一次也太慢了;另外在初始化函数中开启了延时,但是一次读取
    发表于 03-14 07:40

    LSM6DS3TRC读取加速度数据不对是哪里的问题?

    LSM6DS3TRC初始化后,读取加速度(理论应是 0,0,1000),得出的加速度慢慢上升变化,读取几十个(每次读取都是判断XDLA位是否为1)后的加速度值才是正确的。这个什么原因?如附图是慢慢变化上升的加速度(只打印了Z轴的)。
    发表于 03-13 06:10

    十轴姿态传感器模块 | 集成加速度、陀螺仪、磁力计,自带BLE5.0蓝牙

    海凌科全新推出HLK-AS2001十轴姿态传感器模块,集成加速度、陀螺仪和磁力计,自带BLE5.0蓝牙,开发简单,应用广泛。什么是十轴姿态传感器模块?HLK-AS2001十轴姿态传感器模块是海凌科
    的头像 发表于 01-06 12:47 1498次阅读
    十轴姿态传感器模块 | 集成加速度<b class='flag-5'>计</b>、陀螺仪、<b class='flag-5'>磁力计</b>,自带BLE5.0蓝牙

    振弦式位移数据采集频率可以调整吗?

    是否可以调整?答案是肯定的。一般来说,振弦式位移数据采集是通过与之连接的MCU数据采集设备或系统来实现的。这些采集设备通常具备参数设置功
    的头像 发表于 12-20 11:00 1041次阅读
    振弦式位移<b class='flag-5'>计</b>的<b class='flag-5'>数据采集</b>频率可以调整吗?