概述
磁力计测量结果容易受到周围环境中的硬铁(Hard Iron)和软铁(Soft Iron)效应的干扰,从而影响精度。为了解决这一问题,磁力计校准变得至关重要。STMicroelectronics提供的MotionMC库是一个高效的中间件解决方案,专门用于实时校准磁力计数据,以消除这些误差。
MotionMC库能够通过测量不同方向的磁场数据,自动计算并补偿硬铁和比例因子效应。它集成了在嵌入式系统中运行的轻量级算法,能够在系统运行期间进行动态校准,确保磁力计的输出数据始终准确可靠。
在本文中,将介绍如何使用LIS2MDL磁力计与MotionMC库执行磁力计校准。我们将探讨从传感器初始化、数据采集到最终应用校准参数的整个流程,并提供相应的代码示例,以帮助开发者更好地集成和利用MotionMC库提升系统的磁力测量精度。
需要样片的可以加群申请:615061293 。
视频教学
[https://www.bilibili.com/video/BV1PE421A7iu/]
样品申请
[https://www.wjx.top/vm/OhcKxJk.aspx#]
源码下载
[https://download.csdn.net/download/qq_24312945/89653033]
硬件准备
首先需要准备一个开发板,这里我准备的是自己绘制的开发板,需要的可以进行申请。
主控为STM32H503CB,陀螺仪为LSM6DS3TR-C,磁力计为LIS2MDL。
开启CRC
串口设置
设置串口速率为2000000。
开启X-CUBE-MEMS1
速率选择
磁力计数据最大可以设置100Hz。
参考程序
这里参考 IKS01A3_MagnetometerCalibration 。
磁力计校准过程
MotionMC 是一个用于校准磁力计传感器的库。校准过程旨在消除硬铁效应(由于设备内部或附近的磁性材料引起的误差)和软铁效应(由于设备内部或附近的导电材料引起的误差),从而提高磁力计的精度。
建议在三维空间中缓慢旋转。这个动作的重点在于它不是一个简单的平面运动,而是需要在不同的空间角度进行倾斜和旋转,以覆盖尽可能多的三维空间位置。
初始化定义
/* USER CODE BEGIN 2 */
printf("HELLO!n");
HAL_GPIO_WritePin(CS1_GPIO_Port, CS1_Pin, GPIO_PIN_SET);
HAL_GPIO_WritePin(CS2_GPIO_Port, CS2_Pin, GPIO_PIN_SET);
HAL_Delay(100);
/* Initialize mems driver interface */
stmdev_ctx_t dev_ctx;
dev_ctx.write_reg = platform_write;
dev_ctx.read_reg = platform_read;
dev_ctx.mdelay = platform_delay;
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(&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_50Hz);
/* 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);
MX_MEMS_Init();
/* USER CODE END 2 */
MotionMC文件
主要包含app_mems.c和app_mems.h, 它们提供了一些与MEMS传感器相关的初始化、处理和管理函数。这些文件在磁力计校准、数据处理以及传感器初始化等方面发挥着重要作用。
● MX_MEMS_Init(void) 和 MX_MEMS_Process(void):这些函数用于初始化和处理MEMS传感器的操作。
● MotionMC_manager_init(int sampletime, unsigned short int enable):初始化MotionMC库。
● MotionMC_manager_update(MMC_Input_t *data_in):使用新的传感器数据更新MotionMC库。
● MotionMC_manager_get_params(MMC_Output_t *data_out):获取校准后的参数。
● MotionMC_manager_compensate(MOTION_SENSOR_Axes_t *data_raw, MOTION_SENSOR_Axes_t *data_comp):对传感器数据应用校准补偿。
MotionMC_Initialize
MotionMC_manager_init中主要执行MotionMC_Initialize,MotionMC_Initialize用途主要初始化MotionMC库并设置内部机制。这个函数在使用磁力计校准库之前必须调用。
参数:
sampletime: 设置更新函数调用之间的时间间隔(以毫秒为单位)。
enable: 启用(1)或禁用(0)该库。
MotionMC_manager_get_version
MotionMC_manager_get_version中主要执行MotionMC_GetLibVersion,MotionMC_GetLibVersion用途主要是检索库的版本信息。
参数:
version: 一个指向字符数组的指针,用于存储版本字符串。
返回值: 版本字符串中的字符数量。
MotionMC_manager_update
MotionMC_manager_update中主要执行MotionMC_Update,MotionMC_Update用途主要是运行磁力计校准算法。这个函数需要周期性地调用,其周期与初始化函数中设置的sampletime参数相同。
参数:
data_in: 指向包含输入数据的结构体的指针。这个结构体包含了当前的磁力计传感器数据和时间戳。
MotionMC_manager_get_params
MotionMC_manager_get_params中主要执行MotionMC_GetCalParams,MotionMC_GetCalParams用途主要是获取磁力计的硬铁(HI)和比例因子(SF)校准系数。
参数:
data_out: 指向包含输出数据的结构体的指针。这个结构体包括了HI偏置、SF矩阵和校准质量因子。
CalQuality = 0:校准参数的准确性未知。
CalQuality = 1:校准参数的准确性较差,不能被信任。
CalQuality = 2:校准参数的准确性尚可。
CalQuality = 3:校准参数的准确性良好。
MotionMC_manager_compensate
MotionMC_manager_compensate 的主要作用是对磁力计数据进行硬铁(Hard Iron)和软铁(Soft Iron)校准,从而补偿磁力计测量中的误差。
/**
* @brief Do hard & soft iron calibration
* @param data_raw Raw magnetometer data [mGauss]
* @param data_comp Calibrated (compensated) data (hard & soft iron calibration) [mGauss]
* @retval None
*/
void MotionMC_manager_compensate(MOTION_SENSOR_Axes_t *data_raw, MOTION_SENSOR_Axes_t *data_comp)
{
MMC_Output_t data_out;
MotionMC_GetCalParams(&data_out);
float mag_raw_mG[3];
float mag_comp_mG[3];
mag_raw_mG[0] = (float)data_raw- >x;
mag_raw_mG[1] = (float)data_raw- >y;
mag_raw_mG[2] = (float)data_raw- >z;
/* Compensate magnetometer data */
/* NOTE: Convert hard iron coefficients [uT] to [mGauss] */
for (int i = 0; i < 3; i++)
{
mag_comp_mG[i] = 0.0f;
for (int j = 0; j < 3; j++)
{
mag_comp_mG[i] += (mag_raw_mG[j] - data_out.HI_Bias[j] * 10.0f) * data_out.SF_Matrix[i][j];
}
mag_comp_mG[i] += (mag_comp_mG[i] >= 0.0f) ? 0.5f : -0.5f;
}
data_comp- >x = (int32_t)mag_comp_mG[0];
data_comp- >y = (int32_t)mag_comp_mG[1];
data_comp- >z = (int32_t)mag_comp_mG[2];
}
● 硬铁效应:由设备内部或附近的永久磁铁或磁性材料引起的偏移,会导致测量结果出现恒定的误差。
● 软铁效应:由设备内部或附近的导磁材料(如铁)引起的误差,会影响测量结果的方向和幅度。
● 补偿计算:
● 对每个轴(X, Y, Z)进行硬铁和软铁效应的补偿计算。计算过程中:
○ 硬铁效应补偿:从原始数据中减去硬铁偏置,单位从微特斯拉(uT)转换为毫高斯(mGauss),即乘以10。
○ 软铁效应补偿:通过乘以校正矩阵 SF_Matrix,对软铁效应进行补偿。
● 结果修正和输出:
● 补偿后的磁力计数据 mag_comp_mG 进行四舍五入,然后转换为整数并存储到 data_comp 中。
主程序执行流程
/* Infinite loop */
/* USER CODE BEGIN WHILE */
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]);
MX_MEMS_Process();
// 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);
}
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
演示
未校准成功时未0。
校准成功时为3。
指向北数据。
指向南数据。
审核编辑 黄宇