0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

陀螺儀LSM6DSOW開發(fā)(8)----磁力計校準

嵌入式單片機MCU開發(fā) ? 來源:嵌入式單片機MCU開發(fā) ? 作者:嵌入式單片機MCU開 ? 2024-08-20 14:31 ? 次閱讀

概述

磁力計校準是確保傳感器數(shù)據(jù)準確性和可靠性的關鍵步驟。磁力計用于測量地球磁場,并在導航、定位、姿態(tài)測量等應用中起到重要作用。然而,磁力計在使用過程中會受到環(huán)境磁場、硬件偏差、安裝誤差等因素的影響,從而導致測量數(shù)據(jù)出現(xiàn)偏差。因此,校準磁力計以消除這些影響,是獲得精確測量數(shù)據(jù)的必要步驟。

本文將介紹如何使用ST提供的MotionFX庫在嵌入式系統(tǒng)中實現(xiàn)磁力計校準, 通過本文的介紹,讀者將能夠理解磁力計校準的基本概念,掌握使用MotionFX庫進行校準的步驟和方法,并學會如何在實際項目中實現(xiàn)磁力計的校準,以獲得高精度的磁場測量數(shù)據(jù)。

需要樣片的可以加群申請:615061293 。

視頻教學

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

樣品申請

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

源碼下載

[https://download.csdn.net/download/qq_24312945/89614581](

硬件準備

首先需要準備一個開發(fā)板,這里我準備的是自己繪制的開發(fā)板,需要的可以進行申請。

主控為STM32H503CB,陀螺儀為LSM6DSOW,磁力計為LIS2MDL。

DataLogFusion

這里參考ST提供的DataLogFusion程序,DataLogFusion示例應用展示了如何使用STMicroelectronics開發(fā)的MotionFX中間件庫進行實時運動傳感器數(shù)據(jù)融合。
DataLogFusion的主要執(zhí)行流程包括初始化硬件和傳感器、中間件庫(MotionFX)的配置與初始化、傳感器數(shù)據(jù)的采集、實時數(shù)據(jù)融合以及結果的輸出。

磁力計校準過程

MotionFX庫的磁力計校準庫用于補償硬鐵失真。磁力計校準可以以比傳感器融合輸出數(shù)據(jù)速率更慢的頻率進行(例如25 Hz)。
● 初始化磁力計校準庫:
● 調(diào)用 MotionFX_MagCal_init 或 MotionFX_CM0P_MagCal_init 函數(shù)。
● 定期調(diào)用校準函數(shù):
● 調(diào)用 MotionFX_MagCal_run 或 MotionFX_CM0P_MagCal_run 函數(shù),直到校準成功完成。
● 檢查校準是否成功:
● 調(diào)用 MotionFX_MagCal_getParams 或 MotionFX_CM0P_MagCal_getParams 函數(shù)。如果函數(shù)返回 mag_data_out.cal_quality = MFX_MAGCALGOOD 或 MFX_CM0P_CALQSTATUSBEST,則校準成功。

在app_mems.c中的Magneto_Sensor_Handler函數(shù)負責處理磁力計(磁傳感器)數(shù)據(jù)的獲取、校準和發(fā)送。該函數(shù)的主要功能是從磁力計傳感器獲取數(shù)據(jù),進行必要的校準,然后將處理后的數(shù)據(jù)傳輸給其他部分使用。具體包括以下步驟:

  1. 檢查傳感器是否啟用:函數(shù)首先檢查是否啟用了磁力計傳感器。如果傳感器未啟用,則函數(shù)不會執(zhí)行進一步操作。
  2. 獲取磁力計數(shù)據(jù):
    ○ 如果使用離線數(shù)據(jù)(即在調(diào)試或仿真模式下),函數(shù)會從預定義的離線數(shù)據(jù)數(shù)組中讀取磁力計數(shù)據(jù)。
    ○ 如果使用實時數(shù)據(jù),函數(shù)會通過調(diào)用BSP_SENSOR_MAG_GetAxes函數(shù)從實際的磁力計傳感器中讀取當前的磁力計數(shù)據(jù)。
  3. 執(zhí)行磁力計校準:
    ○ 函數(shù)檢查磁力計是否已經(jīng)校準。如果尚未校準,則會進行校準過程。
    ○ 將獲取的磁力計數(shù)據(jù)轉(zhuǎn)換為適當?shù)膯挝?,并準備校準輸入?shù)據(jù)。
    ○ 調(diào)用MotionFX_manager_MagCal_run函數(shù)運行校準算法
    ○ 如果校準結果良好(校準質(zhì)量達到標準),函數(shù)會保存校準偏移值,并停止進一步的校準。
  4. 應用校準偏移:將校準偏移應用到磁力計讀數(shù)中,以補償硬件偏差和環(huán)境干擾。
  5. 序列化并發(fā)送數(shù)據(jù):將校準后的磁力計數(shù)據(jù)序列化,并存儲到消息結構(Msg)中,以供系統(tǒng)其他部分使用。

MotionFX_manager_MagCal_run函數(shù)用于運行磁力計校準算法。該函數(shù)接受磁力計輸入數(shù)據(jù),調(diào)用MotionFX庫中的校準算法對數(shù)據(jù)進行處理,并返回校準結果。
MotionFX_MagCal_run函數(shù)執(zhí)行校準算法,對輸入數(shù)據(jù)進行處理,計算出校準所需的參數(shù)。
MotionFX_MagCal_getParams函數(shù)從校準算法中獲取校準后的參數(shù),并存儲在輸出數(shù)據(jù)結構data_out中。這些參數(shù)包括磁力計的偏移和標度因子等校準信息

MotionFX_MagCal_getParams

MotionFX_MagCal_getParams函數(shù)用于獲取磁力計的校準參數(shù)。這些參數(shù)包括校準后的硬鐵偏移量和校準質(zhì)量指標。該函數(shù)通過傳入一個指向輸出數(shù)據(jù)結構的指針,返回校準結果的詳細信息。

調(diào)用MotionFX_MagCal_getParams函數(shù)后,可以通過檢查data_out結構體中的參數(shù)來評估校準結果的質(zhì)量,并應用偏移量來調(diào)整磁力計數(shù)據(jù)。
cal_quality:校準質(zhì)量因子,指示校準結果的準確性。具體值包括: MFX_MAGCALUNKNOWN = 0:校準參數(shù)的準確性未知。 MFX_MAGCALPOOR = 1:校準參數(shù)的準確性較差,不能被信任。 MFX_MAGCALOK = 2:校準參數(shù)的準確性尚可。 MFX_MAGCALGOOD = 3:校準參數(shù)的準確性良好。

校準移植

在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 */

磁力計數(shù)據(jù)官方文檔推薦20/40HZ。

在mian.c中添加磁力計校準執(zhí)行函數(shù)這里陀螺儀數(shù)據(jù)為416Hz,單次循環(huán)執(zhí)行10次,所以讓磁力計在單次循環(huán)中只執(zhí)行一次,頻率則為40Hz左右。

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

    if(fifo_flag)// 如果 FIFO 中斷標志被設置
    {        
        uint8_t acc_flag=0,gyr_flag=0;//加速度角速度標志位
        uint8_t deltatime_flag=0;//時間標志位        
//        printf("fifo_num=%dn",fifo_num);
        for(int i=0;i< fifo_num;i++)// 遍歷 FIFO 數(shù)據(jù)數(shù)組
        {
            // 獲取數(shù)據(jù)指針
            datax = (int16_t *)&fifo_data[i][1];
            datay = (int16_t *)&fifo_data[i][3];
            dataz = (int16_t *)&fifo_data[i][5];

            // 根據(jù)數(shù)據(jù)標簽處理不同類型的數(shù)據(jù)
            switch (fifo_data[i][0]) {
        case LSM6DSO_XL_NC_TAG:// 加速度數(shù)據(jù)
                    acc_flag=1;                
                    acc_x=lsm6dso_from_fs2_to_mg(*datax);
                    acc_y=lsm6dso_from_fs2_to_mg(*datay);
                    acc_z=lsm6dso_from_fs2_to_mg(*dataz);        
//                    printf("Acceleration [mg]:%4.2ft%4.2ft%4.2frn",
//                    acc_x, acc_y, acc_z);                
          break;                
        case LSM6DSO_GYRO_NC_TAG:// 角速度數(shù)據(jù)
                    gyr_flag=1;
                    gyr_x=lsm6dso_from_fs2000_to_mdps(*datax);
                    gyr_y=lsm6dso_from_fs2000_to_mdps(*datay);
                    gyr_z=lsm6dso_from_fs2000_to_mdps(*dataz);    
//                    printf("Angular rate [mdps]:%4.2ft%4.2ft%4.2frn",
//                                    gyr_x,gyr_y,gyr_z);            
          break;                
        case LSM6DSO_TIMESTAMP_TAG:// 時間戳數(shù)據(jù)
                    deltatime_flag=1;
             /* 讀取時間戳數(shù)據(jù) */
                uint32_t timestamp=0;
                        timestamp+= fifo_data[i][1];
                        timestamp+= fifo_data[i][2]< 8;                    
                        timestamp+= fifo_data[i][3]< 16;                        
                        timestamp+= fifo_data[i][4]< 24;    
                    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;
                    }
//                    printf("timestamp=%drn",timestamp);                            
          break;    
        default:
          break;                
                }
            if(i==0)
                Mag_flag=1;            
            // 如果加速度、角速度和時間戳數(shù)據(jù)都已獲取
            if(acc_flag&&gyr_flag&&deltatime_flag)
            {
                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;
                }    
                magnetic_mG[0] = magnetic_mG[0]-MagOffset[0];
                magnetic_mG[1] = magnetic_mG[1]-MagOffset[1];
                magnetic_mG[2] = magnetic_mG[2]-MagOffset[2];                
                lsm6dso_motion_fx_determin();// 調(diào)用 MotionFX 處理函數(shù)
                acc_flag=0;
                gyr_flag=0;
                deltatime_flag=0;
                deltatime_1=deltatime_2;    // 更新時間戳        
                Mag_flag=0;
            }

        }

        // 清除 FIFO 標志和數(shù)據(jù)量
        fifo_flag=0;
        fifo_num=0;

        }

    /* USER CODE END WHILE */

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

在app.h中添加磁力計校準函數(shù)定義。

#define FROM_UT50_TO_MGAUSS  500.0f
void Magneto_Sensor_Handler(void);

在app.c中添加磁力計校準函數(shù)。

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。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 傳感器
    +關注

    關注

    2541

    文章

    49935

    瀏覽量

    747415
  • 陀螺儀
    +關注

    關注

    44

    文章

    768

    瀏覽量

    98173
  • 磁力計
    +關注

    關注

    1

    文章

    71

    瀏覽量

    20744
收藏 人收藏

    評論

    相關推薦

    陀螺儀LSM6DSV16X與AI集成(2)----姿態(tài)解算

    LSM6DSV16X包含三軸陀螺儀與三軸加速度。
    的頭像 發(fā)表于 12-18 10:51 ?1684次閱讀
    <b class='flag-5'>陀螺儀</b><b class='flag-5'>LSM6</b>DSV16X與AI集成(2)----姿態(tài)解算

    驅(qū)動LSM6DS3TR-C實現(xiàn)高效運動檢測與數(shù)據(jù)采集(10)----融合磁力計進行姿態(tài)解算

    MotionFX庫包含用于校準陀螺儀、加速度磁力計傳感器的例程。 將磁力計的數(shù)據(jù)與加速度
    的頭像 發(fā)表于 08-02 15:50 ?1804次閱讀
    驅(qū)動<b class='flag-5'>LSM6</b>DS3TR-C實現(xiàn)高效運動檢測與數(shù)據(jù)采集(10)----融合<b class='flag-5'>磁力計</b>進行姿態(tài)解算

    陀螺儀LSM6DSOW開發(fā)(1)----輪詢獲取陀螺儀數(shù)據(jù)

    本文將介紹如何使用 LSM6DSOW 傳感器來讀取數(shù)據(jù)。主要步驟包括初始化傳感器接口、驗證設備ID、配置傳感器的數(shù)據(jù)輸出率和濾波器,以及通過輪詢方式持續(xù)讀取加速度、角速率和溫度數(shù)據(jù)。讀取到的數(shù)據(jù)會被
    的頭像 發(fā)表于 08-05 09:44 ?1049次閱讀
    <b class='flag-5'>陀螺儀</b><b class='flag-5'>LSM6DSOW</b><b class='flag-5'>開發(fā)</b>(1)----輪詢獲取<b class='flag-5'>陀螺儀</b>數(shù)據(jù)

    陀螺儀LSM6DSOW開發(fā)(3)----FIFO數(shù)據(jù)讀取與配置

    本文檔旨在詳細介紹如何配置和讀取LSM6DSOW傳感器的FIFO數(shù)據(jù)。LSM6DSOW是一款高性能的6軸IMU(慣性測量單元),集成了三軸加速度和三軸
    的頭像 發(fā)表于 08-05 10:03 ?1133次閱讀
    <b class='flag-5'>陀螺儀</b><b class='flag-5'>LSM6DSOW</b><b class='flag-5'>開發(fā)</b>(3)----FIFO數(shù)據(jù)讀取與配置

    陀螺儀LSM6DSOW開發(fā)(5)----MotionFX庫解析空間坐標

    本文將探討如何使用MotionFX庫解析空間坐標。MotionFX庫是一種用于傳感器融合的強大工具,可以將加速度、陀螺儀磁力計的數(shù)據(jù)融合在一起,實現(xiàn)精確的姿態(tài)和位置估計。本文將介紹如何初始化
    的頭像 發(fā)表于 08-15 18:13 ?1308次閱讀
    <b class='flag-5'>陀螺儀</b><b class='flag-5'>LSM6DSOW</b><b class='flag-5'>開發(fā)</b>(5)----MotionFX庫解析空間坐標

    陀螺儀LSM6DSV16X與AI集成(11)----融合磁力計進行姿態(tài)解算

    MotionFX庫包含用于校準陀螺儀、加速度磁力計傳感器的例程。 將磁力計的數(shù)據(jù)與加速度
    的頭像 發(fā)表于 09-06 16:57 ?1317次閱讀
    <b class='flag-5'>陀螺儀</b><b class='flag-5'>LSM6</b>DSV16X與AI集成(11)----融合<b class='flag-5'>磁力計</b>進行姿態(tài)解算

    請問有和ADIS16488性能差不多,包含加速度,陀螺儀磁力計,壓力,同時陀螺儀量程大于450dps的產(chǎn)品嗎?

    你好,有和ADIS16488性能差不多,包含加速度陀螺儀,磁力計,壓力,同時陀螺儀量程大于450dps的產(chǎn)品嗎?
    發(fā)表于 07-31 10:58

    LSM9DS0磁力計出現(xiàn)故障

    我一直使用LSM9DS0傳感器組裝和測試帶有城堡形連接的小型分線板,它們都為accel / mag和陀螺儀返回正確的WHO_AM_I寄存器內(nèi)容。當我跳線連接到微控制器時,我得到了加速器和陀螺儀的預期
    發(fā)表于 09-25 17:12

    LSM9DS0陀螺儀磁力計有哪些?

    LSM9DS0數(shù)據(jù)表似乎只提到了加速度的準確性?????? 那么陀螺儀磁力計有哪些?請解釋??!以上來自于谷歌翻譯以下為原文 The LSM
    發(fā)表于 12-05 16:16

    請問通常使用的磁力計、加速度、陀螺儀等傳感器在安裝之前為什么要先校準

    問題一:通常使用的磁力計、加速度陀螺儀等傳感器在安裝之前為什么要先校準?問題二:現(xiàn)有程序中, 如何實現(xiàn)校準? (調(diào)什么, 怎么調(diào))問題三
    發(fā)表于 06-17 04:35

    MicroStrain 3DM-GX5-25陀螺儀

    傳感器:三軸加速度,三軸陀螺儀,三軸磁力計,溫度傳感器,量 程:±8 g (標準)±2 g, ±4 g, ±20 g,±40 g (定制)
    發(fā)表于 12-09 16:20

    使用LSM9DS1的應用程序,磁力計結果不穩(wěn)定怎么解決?

    我有一個使用 LSM9DS1 的應用程序,目的是準確測量以大約 33 rpm 的速度旋轉(zhuǎn)的盤片的轉(zhuǎn)速。我通過每 10 毫秒從陀螺儀讀取一次讀數(shù)來測量速度。之前我對偏移量和斜率進行了初始校準,但我想通
    發(fā)表于 01-12 08:42

    lsm6dsox的陀螺儀數(shù)據(jù)有很多尖峰是什么原因?如何解決?

    在我的測試板上,加速度磁力計的數(shù)據(jù)很穩(wěn)定。但是陀螺儀數(shù)據(jù)有很多尖峰,即使它放在桌子上并且沒有移動。您知道造成這種情況的原因以及解決方法嗎?lsm6dsox 和 lis3mdl 用于
    發(fā)表于 01-13 08:07

    IMU中三軸加速、陀螺儀磁力計的工作原理

    IMU:Inertial Measurement Unit,即慣性測量單元。它是由三軸加速、三軸陀螺儀、三軸磁力計等多種傳感器組成的模塊。 IMU在無人駕駛汽車、無人機上面應用的比較多,包括手機等
    的頭像 發(fā)表于 12-26 10:14 ?1.4w次閱讀
    IMU中三軸加速<b class='flag-5'>計</b>、<b class='flag-5'>陀螺儀</b>和<b class='flag-5'>磁力計</b>的工作原理

    淺析IMU中加速度、陀螺儀磁力計原理

    IMU:Inertial Measurement Unit,即慣性測量單元。它是由三軸加速、三軸陀螺儀、三軸磁力計等多種傳感器組成的模塊。 IMU在無人駕駛汽車、無人機上面應用的比較多,包括手機等很多電子設備也有IMU傳
    的頭像 發(fā)表于 03-02 10:34 ?3872次閱讀
    淺析IMU中加速度<b class='flag-5'>計</b>、<b class='flag-5'>陀螺儀</b>、<b class='flag-5'>磁力計</b>原理