e2studio开发磁力计LIS2MDL(2)----电子罗盘

news2024/11/23 3:34:47

e2studio开发磁力计LIS2MDL.2--电子罗盘

  • 概述
  • 使用硬件
  • 视频教学
  • 样品申请
  • 源码下载
  • 环境磁场建模
  • 消除硬铁误差
  • 软铁干扰
  • 演示
  • 主程序

概述

本文将介绍如何使用 LIS2MDL 传感器来读取数据来转化为指南针。
地磁场强度范围约为 23,000 至 66,000 nT ,并且可以建模为磁偶极子,其场线起源于地球地理南部附近的点,并终止于磁场附近的点。磁场具有七个分量,如图 所示。x,y和z分别表示北分量,东分量和垂直分量的磁场强度。H代表总水平强度,F代表磁场的总强度,而D和I分别代表磁偏角和磁倾角。

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

在这里插入图片描述

在这里插入图片描述

使用硬件

在这里插入图片描述

视频教学

样品申请

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

源码下载

环境磁场建模

尽管可以选择七个不同的元素来处理给定点的磁场,但并非所有元素都是进行定位的理想选择。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%x\n",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, &reg);

         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.2f\t%4.2f\t%4.2f\r\n",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.2f\r\n",temperature_degC);

           printf("i=%d,Magnetic field [mG]:%4.2f\t%4.2f\t%4.2f\r\n",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.2f\n",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.2f\n",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
}  

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

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

相关文章

YOLOv8改进 | Neck篇 | 利用ASF-YOLO改进特征融合层(适用于分割和目标检测)

一、本文介绍 本文给大家带来的改进机制是ASF-YOLO(发布于2023.12月份的最新机制),其是特别设计用于细胞实例分割。这个模型通过结合空间和尺度特征,提高了在处理细胞图像时的准确性和速度。在实验中,ASF-YOLO在2018年数据科学竞赛数据集上取得了卓越的分割准确性和速度,…

使用 Process Explorer 和 Windbg 排查软件线程堵塞问题

目录 1、问题说明 2、线程堵塞的可能原因分析 3、使用Windbg和Process Explorer确定线程中发生了死循环 4、根据Windbg中显示的函数调用堆栈去查看源码&#xff0c;找到问题 4.1、在Windbg定位发生死循环的函数的方法 4.2、在Windbg中查看变量的值去辅助分析 4.3、是循环…

IPv6路由协议---IPv6动态路由(OSPFv3-4)

OSPFv3的链路状态通告LSA类型 链路状态通告是OSPFv3进行路由计算的关键依据,链路状态通告包含链路状态类型、链路状态ID、通告路由器三元组唯一地标识了一个LSA。 OSPFv3的LSA头仍然保持20字节,但是内容变化了。在LSA头中,OSPFv2的LS age、Advertising Router、LS Sequence…

SpringBoot整合EasyExcel实现导入导出

1、EasyExcel是什么 EasyExcel是一个基于Java的、快速、简洁、解决大文件内存溢出的Excel处理工具。 他能让你在不用考虑性能、内存的等因素的情况下&#xff0c;快速完成Excel的读、写等功能。 2、相关网站 官网https://easyexcel.opensource.alibaba.com/ GitHubhttps://…

线性代数_同济第七版

contents 前言第1章 行列式1.1 二阶与三阶行列式1.1.1 二元线性方程组与二阶行列所式1.1.2 三阶行列式 1.2 全排列和对换1.2.1 排列及其逆序数1.2.2 对换 1.3 n 阶行列式的定义1.4 行列式的性质1.5 行列式按行&#xff08;列&#xff09;展开1.5.1 引理1.5.2 定理1.5.3 推论 * …

ULINK2仿真器安装使用之工程设置

一、 ULINK2仿真器 ULINK2是ARM公司最新推出的配套RealView MDK使用的仿真器&#xff0c;是ULink仿真器的升级版本。ULINK2不仅具有ULINK仿真器的所有功能&#xff0c;还增加了串行调试&#xff08;SWD&#xff09;支持&#xff0c;返回时钟支持和实时代理等功能。开发工程师通…

常用注解/代码解释(仅个人使用)

目录 第一章、代码解释①trim() 方法以及(Arrays.asList(str.split(reg)));②查询字典项②构建后端镜像shell命令解释 第二章、注解解释①PropertySource注解与Configurationproperties注解的区别 第三章、小知识①Linux系统中使用$符号表示变量 友情提醒: 先看文章目录&#…

强化学习求解TSP(二):Qlearning求解旅行商问题TSP(提供Python代码)

一、Qlearning简介 Q-learning是一种强化学习算法&#xff0c;用于解决基于奖励的决策问题。它是一种无模型的学习方法&#xff0c;通过与环境的交互来学习最优策略。Q-learning的核心思想是通过学习一个Q值函数来指导决策&#xff0c;该函数表示在给定状态下采取某个动作所获…

AI大模型引领未来智慧科研暨ChatGPT在地学、GIS、气象、农业、生态、环境应用

以ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diffusion、星火大模型、文心一言、千问为代表AI大语言模型带来了新一波人工智能浪潮&#xff0c;可以面向科研选题、思维导图、数据清洗、统计分析、高级编程、代码调试、算法学习、论文检索、写作、翻译、润色、文献辅助…

办公文档,私人专用

一、安装Minio 1.1、创建文件夹&#xff0c;并在指定文件夹中下载minio文件 cd /opt mkdir minio cd minio touch minio.log wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.2、赋予minio文件执行权限 chmod 777 minio1.3、启动minio ./minio server /…

SpiderFlow爬虫平台 前台RCE漏洞复现(CVE-2024-0195)

0x01 产品简介 SpiderFlow是新一代爬虫平台,以图形化方式定义爬虫流程,以流程图的方式定义爬虫,不写代码即可完成爬虫,是一个高度灵活可配置的爬虫平台。 0x02 漏洞概述 SpiderFlow爬虫平台src/main/java/org/spiderflow/controller/FunctionController.java文件的Functi…

三、POD详解

目录 一、Pod创建过程&#xff1a; 二、Pod的终止 三、pod配置详解 四、查看每种资源的可配置项 五、Pod状态 六、Pod调度 七、Pod探针 1、Pod 探针的检测方式&#xff1a; 一、Pod创建过程&#xff1a; 用户提交创建pod请求API Server处理用户请求&#xff0c;存储Pod…

【心得】SSRF攻击面利用个人笔记

SSRF的利用面 目录 1 任意文件读取 前提是知道要读取的文件名 2 探测内网资源 3 使用gopher协议扩展攻击面 4 php原生类进行ssrf 5 ssrf绕过 1 任意文件读取 前提是知道要读取的文件名 2 探测内网资源 127.0.0.1 mysql服务端监听了127.0.0.1这个地址&#xff0c;也就表示…

Linux 网络设置与基础服务

一 配置网络设置 主机名 hostname IP地址/netmask ifconfig &#xff1b; ip a 路由&#xff1a;默认网关 route -n DNS服务器 cat /etc/resolv.conf 网络连接状态 ss netstat 域名解析 ns…

前端炫酷动画特效分享(附在线预览)

分享7款非常有趣的前端特效源码 其中包含css动画特效、js原生特效、svg特效以及小游戏等 下面我会给出特效样式图或演示效果图 但你也可以点击在线预览查看源码的最终展示效果及下载源码资源 canvas鼠标粒子跟随动画 canvas鼠标粒子跟随动画 当鼠标移入背景区域时 粒子动画会…

Node.js和npm

目录 01_Node.js01.什么是 Node.js目标讲解小结 02.fs模块-读写文件目标讲解小结 03.path模块-路径处理目标讲解小结 04.案例-压缩前端html目标讲解小结 05.认识URL中的端口号目标讲解小结 06.http模块-创建Web服务目标讲解小结 07.案例-浏览时钟目标讲解小结 02_Node.js模块化…

解决vscode无法运行npm和node.js命令的问题

第一次安装npm和node.js想要在vscode中直接输入控制台命令会因为权限问题无法执行。 这里可以修改本机权限来解决。 搜索powershell并且以管理员权限运行 打开之后输入下面的命令即可 PS C:\Users\Administrator> Get-ExecutionPolicy Restricted PS C:\Users\Administra…

electron自定义窗口和右键菜单样式

前言 electron默认沿用系统UI&#xff0c;并没有提供很多接口供使用者定制样式&#xff0c;如果想要完全自定义的样式&#xff0c;目前我能想到的方案只能是通过前端自定义样式&#xff0c;然后通过进程通信来实现系统基础功能&#xff1a;最大/小化、关闭、拖动窗口等。 效果…

canvas绘制路径之 beginPath() 和 closePath()

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

权威mcc mnc 列表网址

MCC-MNC.net 链接: MCC-MNC.net 这个网站提供的mcc mnc 比下面itu文档中更全。 itu.int 2023年发布的mcc mnc分配信息&#xff1a; 链接: PDF T-SP-E.212B-2023 若想获取最新的可以参考如下截图查询&#xff1a;