<acronym id="s8ci2"><small id="s8ci2"></small></acronym>
<rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
<acronym id="s8ci2"></acronym>
<acronym id="s8ci2"><center id="s8ci2"></center></acronym>
0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
創作中心

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

3天內不再提示

e2studio開發磁力計LIS2MDL(2)----電子羅盤

嵌入式單片機MCU開發 ? 來源:嵌入式單片機MCU開發 ? 作者:嵌入式單片機MCU開 ? 2024-05-16 17:00 ? 次閱讀

概述

本文將介紹如何使用 LIS2MDL 傳感器來讀取數據來轉化為指南針。 地磁場強度范圍約為 23,000 至 66,000 nT ,并且可以建模為磁偶極子,其場線起源于地球地理南部附近的點,并終止于磁場附近的點。磁場具有七個分量,如圖 所示。x,y和z分別表示北分量,東分量和垂直分量的磁場強度。H代表總水平強度,F代表磁場的總強度,而D和I分別代表磁偏角和磁傾角。

最近在弄ST和瑞薩RA的課程,需要樣片的可以加群申請:615061293 。

使用硬件

視頻教學

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

樣品申請

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

源碼下載

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

環境磁場建模

盡管可以選擇七個不同的元素來處理給定點的磁場,但并非所有元素都是進行定位的理想選擇。X,Y 和 Z 的三個元素是從磁力計獲得的基本值,而其他四個元素是使用這些元素來計算的。前三個元素隨移動設備方位角的改變而偏離,因此,對于許多基于磁場的室內定位系統通常假設以固定方位工作,行人可以更改方向,但不能更改設備方位。
在大地坐標系的水平面上,假設磁北和x軸的夾角為a, x方向的磁分量是Mx,y方向的分量是My,則
ɑ=arctan(My/Mx)
這是電子羅盤定向的基本原理。實際應用中,電子羅盤不能總是保持在水平面上,如下圖所示一樣存在俯仰角和橫滾角。將羅盤坐標系下的 z軸向下, 3個軸的磁分量投影到水平面上可以得到Xh,Yh,相應的磁感應值:
Xh=Xcosф+Ysinфsinθ - Zsinфcosθ
Yh=Ycosθ + Zsinθ
相應的
ɑ=arctan(Yh/Xh)

Angle_XY=atan2( (magnetic_mG[1]-Xoffset),(magnetic_mG[0]-Yoffset) ) * (180/3.14159265)+180;//計算角度
                Angle_XZ=atan2( (magnetic_mG[2]-Zoffset),(magnetic_mG[0]-Yoffset) ) * (180/3.14159265)+180;//計算角度
                Angle_YZ=atan2( (magnetic_mG[2]-Zoffset),(magnetic_mG[1]-Yoffset) ) * (180/3.14159265)+180;//計算角度

消除硬鐵誤差

電子羅盤有兩種工作模式,一種是正常工作模式,另一種是出廠設置模式,這種出場設置模式就是為了消除硬鐵干擾。硬鐵干擾產生于永久磁鐵,和被磁化的金屬,或羅盤平臺上的鋼。這些干擾會保持大小恒定,與羅盤的相對位置固定,而與羅盤指向無關。所以當羅盤安裝好后,它周圍的硬鐵干擾就幾乎不會改變了,只要對羅盤做一次準確的標定,就能很輕松的消除這項干擾。
硬鐵干擾在羅盤輸出的每個軸向加了一個定值,輸出曲線圖的圓心被移動了,對于航向的影響則是一個周期性的誤差,如下圖所示在理想狀態時,在 360 度范圍內,傳感器輸出極值分別為 ymax ymin xmax xmin 坐標原點為O,受到硬鐵干擾后,極值變為 y’max ,y’min , x’max , x’max , 坐標原點變為O’ 。要消除硬鐵干擾,可以將羅盤和平臺旋轉一周,得
到圓上的足夠的點再得到圓心偏移。

具體操作過程如下:接通電源后,將羅盤勻速旋轉,使微控制器采集 360 °范圍內的數據,通過數值比較,找出 x 、 y 方向的極值,得出偏移坐標 O’, 即電橋的偏置電壓,并將此電壓值保存,每次羅盤讀數時都會減去此偏移。實際上,本設計在方位角的計算過程就是此過程,所以在計算方位角的同時已經消除了硬鐵干擾。這種方法也可以消除由于溫度漂移產生的誤差。

軟鐵干擾

軟鐵干擾來源于地球磁場和羅盤附近的任何磁性材料之間的相互作用,同硬鐵材料一樣,軟金屬也干擾地球的磁力線,不同點是,軟磁的干擾程度,與羅盤的方向有關。對軟鐵干擾的校正,比較復雜,下面討論采用霍尼韋爾公司的 Michal.J.Caruso 提出橢圓假設的誤差補償原理進行誤差補償的方法 。

根據 Michal.J.Caruso 的研究,羅盤在理想的沒有任何干擾的磁場水平面里作圓形旋轉時,磁力計的顯示應該呈現上圖的狀態,其中圓中心在 0,0 點處,每個計數代表 67微高斯,在 X 和 Y 平面中的地球磁場強度值讀到 2800 個計數,約為 190 毫高斯,根據下面公式可以對每個讀數確定一個方位角。

如果將磁力計安裝在有發動機或者其他鐵磁材料的環境中,圓形旋轉時,磁力計的顯示應該下圖的狀態。

這里的圖形不是一個圓 ( 有點橢圓 ) ,而它偏移 0,0 點為 -480 和 -795 個計數,這偏移和橢圓效應是干擾磁場對地球磁場作用的結果。通過確定兩個定標因數 Xsf 和 Ysf 可以將橢圓改為圓。隨后計算偏移值 Xoff 和 Yoff, 將圓中心定在 0,0 原點,用下面公式來計算 Y,X 值。

X 值 =Xsf×X 讀數 +Xoff
Y 值 =Ysf×Y 讀數 +Yoff

這里的定標因數 Xsf 和 Ysf 可由下述方法獲得。
①將羅盤在水平面做旋轉運動
②找出 X 和 Y 讀數的最大值和最小值
③用這四個數值確定 X 和 Y 定標因數 (Xsf , Ysf) ,以及零偏移值 (Xoff , Yoff)

Xsf=1 或 (Y 最大 -Y 最小 )/2(X 最大 -Y 最小 )

以較大的數值為準

Ysf=1 或 (X 最大 -Y 最小 )/2(Y 最大 -Y 最小 )

以較大的數值為準

Xoff=[(X 最大 -X 最小 ) /2-X 最大 ]×Xsf
Yoff=[(Y 最大 -Y 最小 ) /2-Y 最大 ]×Ysf

演示

主程序

在主程序中添加開機校準。

#include "hal_data.h"

#include < stdio.h >
#include "lis2mdl_reg.h"

fsp_err_t err = FSP_SUCCESS;
volatile bool uart_send_complete_flag = false;
void user_uart_callback (uart_callback_args_t * p_args)
{
    if(p_args- >event == UART_EVENT_TX_COMPLETE)
    {
        uart_send_complete_flag = true;
    }
}


/* Callback function */
i2c_master_event_t i2c_event = I2C_MASTER_EVENT_ABORTED;
uint32_t  timeout_ms = 100000;
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    i2c_event = I2C_MASTER_EVENT_ABORTED;
    if (NULL != p_args)
    {
        /* capture callback event for validating the i2c transfer event*/
        i2c_event = p_args- >event;
    }
}



#ifdef __GNUC__                                 //串口重定向
    #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
    #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif

PUTCHAR_PROTOTYPE
{
        err = R_SCI_UART_Write(&g_uart9_ctrl, (uint8_t *)&ch, 1);
        if(FSP_SUCCESS != err) __BKPT();
        while(uart_send_complete_flag == false){}
        uart_send_complete_flag = false;
        return ch;
}

int _write(int fd,char *pBuffer,int size)
{
    for(int i=0;i< size;i++)
    {
        __io_putchar(*pBuffer++);
    }
    return size;
}

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


#define SENSOR_BUS g_i2c_master0_ctrl

/* Private macro -------------------------------------------------------------*/
#define    BOOT_TIME        20 //ms

/* Private variables ---------------------------------------------------------*/
static int16_t data_raw_magnetic[3];
static int16_t data_raw_temperature;
static float magnetic_mG[3];
static float temperature_degC;
static uint8_t whoamI, rst;
static uint8_t tx_buffer[1000];

/* Extern variables ----------------------------------------------------------*/

/* 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 platform_write(void *handle, uint8_t reg, const uint8_t *bufp,
                              uint16_t len);
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,
                             uint16_t len);
static void tx_com(uint8_t *tx_buffer, uint16_t len);
static void platform_delay(uint32_t ms);
static void platform_init(void);






/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */


    /* Open the transfer instance with initial configuration. */
       err = R_SCI_UART_Open(&g_uart9_ctrl, &g_uart9_cfg);
       assert(FSP_SUCCESS == err);

       printf("hello world!n");

       R_IOPORT_PinWrite(&g_ioport_ctrl, BSP_IO_PORT_00_PIN_14, BSP_IO_LEVEL_HIGH);
       /* Initialize the I2C module */
       err = R_IIC_MASTER_Open(&g_i2c_master0_ctrl, &g_i2c_master0_cfg);
       /* Handle any errors. This function should be defined by the user. */
       assert(FSP_SUCCESS == err);

       /* Initialize mems driver interface */
       stmdev_ctx_t dev_ctx;
       dev_ctx.write_reg = platform_write;
       dev_ctx.read_reg = platform_read;
       dev_ctx.handle = &SENSOR_BUS;

       /* Wait sensor boot time */
       platform_delay(BOOT_TIME);

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

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

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

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

       int Xmax=0,Xmin=0;
       int Ymax=0,Ymin=0;
       int Zmax=0,Zmin=0;

       int i=0;

       int Xoffset,Yoffset,Zoffset;
       float angle;
       static float Angle_XY;
       static float Angle_XZ;
       static float Angle_YZ;
       static float Xsf;
       static float Ysf;
       static float Zsf;
       while (1)
       {

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

         if (reg) {
           /* Read magnetic field data */
           memset(data_raw_magnetic, 0x00, 3 * sizeof(int16_t));
           lis2mdl_magnetic_raw_get(&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]);
//           printf("Magnetic field [mG]:%4.2ft%4.2ft%4.2frn",magnetic_mG[0], magnetic_mG[1], magnetic_mG[2]);

//           /* Read temperature data */
//           memset(&data_raw_temperature, 0x00, sizeof(int16_t));
//           lis2mdl_temperature_raw_get(&dev_ctx, &data_raw_temperature);
//           temperature_degC = lis2mdl_from_lsb_to_celsius(data_raw_temperature);
//           printf("Temperature [degC]:%6.2frn",temperature_degC);

           printf("i=%d,Magnetic field [mG]:%4.2ft%4.2ft%4.2frn",i,magnetic_mG[0], magnetic_mG[1], magnetic_mG[2]);
                  if(i< 500)
                  {
                      i++;
                      if(magnetic_mG[0]< Xmin)
                          Xmin=magnetic_mG[0];
                      else if(magnetic_mG[0] >Xmax)
                          Xmax=magnetic_mG[0];


                      if(magnetic_mG[1]< Ymin)
                          Ymin=magnetic_mG[1];
                      else if(magnetic_mG[1] >Ymax)
                          Ymax=magnetic_mG[1];

                          if(magnetic_mG[2]< Zmin)
                          Zmin=magnetic_mG[2];
                      else if(magnetic_mG[2] >Zmax)
                          Zmax=magnetic_mG[2];
                  }
                  else if(i==500)
                  {
                      i++;


                      Xsf = (Ymax - Ymin) / (Xmax - Xmin);
                      Ysf = (Xmax - Xmin) / (Ymax - Ymin);
                      if (Xsf < 1)
                              Xsf = 1;
                      if (Ysf < 1)
                              Ysf = 1;

                      Xoffset=( (Xmax-Xmin)/2 - Xmax) *Xsf;
                      Yoffset=( (Ymax-Ymin)/2 - Ymax) *Ysf;
      //              Zoffset=( (Zmax-Zmin)/2 - Zmax) *Xsf;

                  }
                  else
                  {
                      Angle_XY=atan2( (magnetic_mG[1]-Yoffset),(magnetic_mG[0]-Xoffset) ) * (180/3.14159265)+180;//計算角度
                      printf("Angle_XY=%3.2fn",Angle_XY);
      //              Angle_XZ=atan2( (magnetic_mG[2]-Zoffset),(magnetic_mG[0]-Xoffset) ) * (180/3.14159265)+180;//計算角度
      //              Angle_YZ=atan2( (magnetic_mG[2]-Zoffset),(magnetic_mG[1]-Yoffset) ) * (180/3.14159265)+180;//計算角度
      //              printf("Angle_XY=%3.2f,Angle_XZ=%3.2f,Angle_YZ=%3.2fn",Angle_XY,Angle_XZ,Angle_YZ);
                  }
         }
         R_BSP_SoftwareDelay(10, BSP_DELAY_UNITS_MILLISECONDS);
       }






#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

審核編輯 黃宇

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

    關注

    2528

    文章

    48322

    瀏覽量

    741183
  • 電子羅盤
    +關注

    關注

    1

    文章

    121

    瀏覽量

    23146
  • 磁力計
    +關注

    關注

    1

    文章

    57

    瀏覽量

    20614
收藏 人收藏

    評論

    相關推薦

    磁力計LIS2MDL開發(1)----輪詢獲取磁力計數據

    本文將介紹如何使用 LIS2MDL 傳感器來讀取數據。主要步驟包括初始化傳感器接口、驗證設備ID、配置傳感器的數據輸出率和濾波器,以及通過輪詢方式持續讀取磁力數據和溫度數據。讀取到的數據會被轉換為適當的單位并通過串行通信輸出。
    的頭像 發表于 12-18 10:56 ?765次閱讀
    <b class='flag-5'>磁力計</b><b class='flag-5'>LIS2MDL</b><b class='flag-5'>開發</b>(1)----輪詢獲取<b class='flag-5'>磁力計</b>數據

    磁力計LIS2MDL開發(2)----電子羅盤

    本文將介紹如何使用 LIS2MDL 傳感器來讀取數據來轉化為指南針。
    的頭像 發表于 12-18 11:01 ?802次閱讀
    <b class='flag-5'>磁力計</b><b class='flag-5'>LIS2MDL</b><b class='flag-5'>開發</b>(2)----<b class='flag-5'>電子</b><b class='flag-5'>羅盤</b>

    e2studio開發磁力計LIS2MDL(1)----輪詢獲取磁力計數據

    本文將介紹如何使用 LIS2MDL 傳感器來讀取數據。主要步驟包括初始化傳感器接口、驗證設備ID、配置傳感器的數據輸出率和濾波器,以及通過輪詢方式持續讀取磁力數據和溫度數據。讀取到的數據會被轉換
    的頭像 發表于 05-16 16:54 ?449次閱讀
    <b class='flag-5'>e2studio</b><b class='flag-5'>開發</b><b class='flag-5'>磁力計</b><b class='flag-5'>LIS2MDL</b>(1)----輪詢獲取<b class='flag-5'>磁力計</b>數據

    有沒有辦法用LIS2MDL檢測溢出?

    問候我正在使用LIS2MDL為教育市場構建磁場傳感器。當測量的磁場超過最大允許值時,我注意到LIS2MDL返回不可預測的數據而不是0x7fff(32767)或0x8000(-32768)。有沒有
    發表于 09-25 17:16

    LSM9DS1磁力計的自檢是否與LIS3MDL相同

    我正在嘗試在LSM9DS1傳感器上測試磁力計。我可以應用與LIS3MDL指南針相同的自測范圍值來檢查LSM9DS1嗎?事實是LSM9DS1中的磁力計似乎是LIS3MDL(寄存器的相同文
    發表于 10-09 11:43

    LIS2MDL上設置新閾值后是否需要最少時間?

    嗨,我試圖在LIS2MDL上動態配置中斷閾值。似乎有時在設置新閾值后,舊閾值仍然有效并導致輸出引腳上的中斷轉換。在LIS2MDL上設置新閾值后是否需要最少(穩定)時間?謝謝。以上來自于谷歌翻譯以下
    發表于 03-04 14:44

    LIS2MDL偏移取消問題

    這是他們的初始化代碼: i2c_LIS2MDL_Read_8Bit(LIS2MDL_WHO_AM_I,&amp; b); i2c_LIS2MDL
    發表于 03-29 09:57

    如何在LIS3MDL磁力計傳感器中禁用DRDY和INT輸出

    你好,如何在LIS3MDL磁力計傳感器中禁用DRDY和INT輸出。 #lis3mdl以上來自于谷歌翻譯以下為原文 Hello,How to disable DRDY and INT outputs in
    發表于 04-17 14:17

    無法將LIS2MDL置于低功耗模式

    你好,我在傳感器集線器模式下使用LSM6DSL和LIS2MDL,使用IKS01A2中的示例我已經設法激活LIS2MDL并從中讀取數據。我目前的問題是我無法將LIS2MDL置于低功耗模式
    發表于 04-26 14:39

    LIS3MDL三軸磁力計能滿足磁通密度為0.23高斯的應用程序嗎

    我正在研究在具有高頻振蕩磁場的應用中使用 LIS3MDL 3 軸磁力計。我查看了 LIS3MDL 的數據表,它似乎滿足我檢查過的大多數要求。我的應用程序的磁通密度為 0.23 高斯,處于磁力計
    發表于 12-14 08:31

    用于生成每個輸出樣本的樣本數量而言LIS3mdl磁力計的操作模式有何不同?

    就用于生成每個輸出樣本的樣本數量而言,LIS3mdl 磁力計的操作模式有何不同?例如,我發現在 ISM303DAC 中,用于生成的樣本數輸出樣本在低功耗模式下比在低功耗模式下使用的數量少四倍高分辨率
    發表于 01-06 07:31

    LIS2MDL軸標簽是否指示正軸方向?

    LIS2MDL 數據表的圖 2 顯示了磁力計軸方向的下圖。但是,完全不清楚它們是否標記了軸的正方向。如果他們確實用 X/Y/Z 標簽標記了正方向,它就會有一個左手方向(違反所有慣例)。軸標簽是否指示正軸方向?這是左手坐標系嗎?
    發表于 01-09 08:56

    STLIS2MDL磁力計傳感器相關的使用信息和應用提示

    LIS2MDL是系統級封裝的3D數字磁力計,具有數字I2C和3線SPI串口標準輸出,在高分辨率模式下功耗200 μA,在低功耗模式下功耗不超過50 μA(在20 Hz輸出數據速率下)。由于磁力計具有超低噪聲性能,始終具有低功耗特
    發表于 09-06 08:24

    LIS2MDL磁力計傳感器相關資料

    LIS2MDL進行配置,使其產生用于磁場檢測的中斷信號,并自動補償由較高應用層提供的硬鐵偏移。LIS2MDL的ST軟件支持包括驅動、傾斜補償的電子羅盤、動態
    發表于 09-13 07:48

    LIS2MDL 3D數字磁力計應用筆記

    電子發燒友網站提供《LIS2MDL 3D數字磁力計應用筆記.pdf》資料免費下載
    發表于 07-31 10:12 ?4次下載
    <b class='flag-5'>LIS2MDL</b> 3D數字<b class='flag-5'>磁力計</b>應用筆記
    亚洲欧美日韩精品久久_久久精品AⅤ无码中文_日本中文字幕有码在线播放_亚洲视频高清不卡在线观看
    <acronym id="s8ci2"><small id="s8ci2"></small></acronym>
    <rt id="s8ci2"></rt><rt id="s8ci2"><optgroup id="s8ci2"></optgroup></rt>
    <acronym id="s8ci2"></acronym>
    <acronym id="s8ci2"><center id="s8ci2"></center></acronym>