4、磁力计(电子罗盘):工作原理与选型实战

各位同学,今天我们来聊聊磁力计,也就是电子罗盘。这东西在无人机、手机导航、机器人里太常见了。我最早接触磁力计,是在一个四轴飞行器项目里,当时飞机在天上老是转圈,后来才发现是磁力计没校准好。嗯,今天就把这些坑都给你们填上。

4.1 工作原理:霍尔效应 vs 磁阻效应

磁力计的核心,说白了就是测量磁场强度。市面上主流方案有两种:霍尔效应和磁阻效应。我分别说说。

4.1.1 霍尔效应

霍尔效应很简单:给一块半导体通上电流,再外加一个垂直磁场,载流子就会偏转,在材料两侧产生电压。这个电压大小正比于磁场强度。

优点?便宜、耐用。缺点?灵敏度低,分辨率也就高斯级别。我一般只在低端玩具或者开关检测里用霍尔传感器。做电子罗盘?不太够用。

4.1.2 磁阻效应

这才是做电子罗盘的主流。磁阻效应,就是某些材料的电阻会随外加磁场变化。最常见的是AMR(各向异性磁阻)和TMR(隧道磁阻)。

AMR传感器,灵敏度比霍尔高两个数量级。TMR更猛,功耗低、灵敏度极高。我现在的项目,只要不是成本敏感,一律上TMR。

为什么会这样?因为地球磁场本身很弱,只有0.25到0.65高斯。你想想看,用霍尔传感器去测这么弱的信号,信噪比太差了。磁阻传感器才能搞定。

核心要点:做电子罗盘,首选磁阻效应传感器。霍尔效应只适合做接近开关或电流检测。

4.2 硬磁/软磁校准:避坑指南

校准这块,我吃过不少亏。磁力计最怕什么?怕周围有铁磁性物质。这些物质会改变磁场分布,导致你测出来的方向不准。

校准分两种:硬磁校准和软磁校准。

4.2.1 硬磁干扰

硬磁干扰,就是电路板上的永磁体、喇叭、马达这些。它们会产生一个固定的偏置磁场。你想想看,本来地球磁场是0.5高斯,结果旁边一个喇叭贡献了0.2高斯,那你的读数就偏了。

校准方法很简单:把传感器在水平面转一圈,采集X、Y轴的最大最小值。然后计算偏移量:

// 硬磁校准示例
float offset_x = (max_x + min_x) / 2.0;
float offset_y = (max_y + min_y) / 2.0;

// 校准后的值
float calibrated_x = raw_x - offset_x;
float calibrated_y = raw_y - offset_y;

我曾经在一个项目里,怎么校准都不对。后来发现是PCB上有个螺丝是铁的。换成铜螺丝,问题解决。嗯,细节决定成败。

4.2.2 软磁干扰

软磁干扰更麻烦。它不是固定偏置,而是会改变磁场的形状。比如你电路板上的铁氧体电感、变压器,它们会像透镜一样扭曲磁场。

软磁校准需要做椭圆拟合。因为理想情况下,传感器转一圈,X、Y轴数据应该画出一个圆。有软磁干扰,圆就变成了椭圆。

校准步骤:

  1. 采集一圈数据
  2. 计算椭圆的长轴和短轴
  3. 计算缩放因子,把椭圆拉回圆
// 软磁校准示例
float scale_x = 1.0;
float scale_y = (max_y - min_y) / (max_x - min_x);

// 完整校准
float final_x = (raw_x - offset_x) * scale_x;
float final_y = (raw_y - offset_y) * scale_y;

警告:软磁校准必须在硬磁校准之后做。顺序搞反了,数据全废。我见过有人把顺序弄反,折腾了两天没搞定。

4.3 芯片选型:HMC5883L vs MMC5983MA

这两款芯片,我都有实际项目经验。直接上对比表:

参数 HMC5883L MMC5983MA
测量范围 ±8 高斯 ±30 高斯
分辨率 5 毫高斯 0.4 毫高斯
接口 I2C I2C/SPI
功耗 约 100 μA 约 25 μA
温度稳定性 一般 优秀
价格 约 1-2 美元 约 3-5 美元

4.3.1 HMC5883L:老将出马

HMC5883L是霍尼韦尔的经典产品。我2015年做第一个无人机项目用的就是它。优点:便宜、资料多、Arduino库一抓一大把。

缺点也很明显:分辨率一般,温度漂移大。夏天和冬天测出来的方向能差好几度。另外,它只有I2C接口,地址还固定,多传感器共用总线时很麻烦。

我个人习惯,如果做消费级产品、成本敏感、对精度要求不高,选HMC5883L没问题。

4.3.2 MMC5983MA:后起之秀

MMC5983MA是MEMSIC的。我第一次用这芯片,是被它的分辨率惊到了——0.4毫高斯!什么概念?地球磁场才500毫高斯,它能分辨出千分之一的变化。

而且它支持SPI接口,速率快。温度稳定性也好,工业级应用完全没问题。我最近做的一个AGV小车导航项目,就用的MMC5983MA。

缺点?贵。而且资料相对少,需要自己啃datasheet。

我的建议:做原型验证用HMC5883L,快速出活。量产产品、尤其是对精度和稳定性有要求的,直接上MMC5983MA。省下来的调试时间,比芯片差价值钱多了。

4.4 实战:读取MMC5983MA数据

最后给个代码示例。这是我实际项目里用的,读取MMC5983MA的原始数据:

#include <SPI.h>

#define MMC5983MA_CS 10

void setup() {
  SPI.begin();
  pinMode(MMC5983MA_CS, OUTPUT);
  digitalWrite(MMC5983MA_CS, HIGH);
  
  // 初始化芯片
  writeRegister(0x09, 0x01); // 连续测量模式
}

void loop() {
  uint8_t x_low, x_mid, x_high;
  uint32_t x_raw;
  
  digitalWrite(MMC5983MA_CS, LOW);
  SPI.transfer(0x00); // X轴数据寄存器地址
  x_high = SPI.transfer(0x00);
  x_mid  = SPI.transfer(0x00);
  x_low  = SPI.transfer(0x00);
  digitalWrite(MMC5983MA_CS, HIGH);
  
  // 20位数据拼接
  x_raw = ((uint32_t)x_high << 12) | ((uint32_t)x_mid << 4) | (x_low >> 4);
  
  Serial.print("X: ");
  Serial.println(x_raw);
  
  delay(100);
}

void writeRegister(uint8_t addr, uint8_t data) {
  digitalWrite(MMC5983MA_CS, LOW);
  SPI.transfer(addr | 0x80); // 写操作
  SPI.transfer(data);
  digitalWrite(MMC5983MA_CS, HIGH);
}

注意看,MMC5983MA的数据是20位的,需要从三个8位寄存器里拼出来。我第一次读数据时,忘了右移低4位,结果数值大了16倍。嗯,这种低级错误,犯过一次就记住了。

好了,磁力计的内容就这些。记住:原理搞懂、校准做对、选型看需求。下一章我们聊惯性测量单元,也就是IMU,那个更有意思。