ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

MLX90393三轴霍尔传感器Arduino应用:角度与位移测量指南

2026/9/10 16:17:46 拓冰建站 浏览量
MLX90393三轴霍尔传感器Arduino应用:角度与位移测量指南 简介面向单片机与嵌入式开发者的MLX90393数字霍尔传感器开发例程覆盖位移、角度、旋转量测量等常见项目需求适合物联网设备验证、电子竞赛备赛和课程设计参考。例程基于Arduino平台包含14个ino主程序、4个cpp与4个h库文件以及原理图png/pdf、说明文档md/txt等共41个文件压缩包仅2.94MB目录按库文件、基础读取示例、传感器配置示例、原理图等分模块组织方便快速定位。目前已有723人学习下载。所有例程均经过实战验证代码中直接定义接线引脚并配套CJMCU-90393原理图与MLX90393库可对照快速完成接线和烧录调试示例覆盖基本读取、传感器配置等操作有助于理解寄存器配置、数据转换和量程设定等关键点同系列芯片理论通用便于移植到其他单片机适合想要快速上手数字霍尔传感器开发的读者。1. 为什么单片机项目选 MLX90393 做位移和角度测量MLX90393 是 Melexis 出品的三轴磁力计不靠磁阻而用霍尔效应感知空间磁场 XYZ 三个分量。在非接触旋转和线性位移测量场景里它比常见的编码器或电位器更耐污染、无机械磨损还能抗一定程度的震动和偏轴安装误差。项目包带完整的 Arduino 库、两个配置例程和 CJMCU-90393 模块原理图跑一遍就能通过 I2C 读出磁场原始值并折算成位移或旋转量。这套方案适合做旋钮、电子油门踏板、阀位反馈、云台角度环等应用也适合作为入门 3D 霍尔传感器的第一块试验板。2. MLX90393 工作原理与寄存器操作基础2.1 三轴霍尔感到底怎么工作常规霍尔开关只输出高低电平线性霍尔只能测一个方向的磁场强度而 MLX90393 内部集成了多组霍尔板和旋转电流技术能同时测出 X、Y、Z 三个正交方向上的磁通密度分量再经 16 位 ADC 转换为数字量。芯片内部还集成了温度补偿和数字滤波因此在温度变化环境中也能保持不错的稳定性。实际应用中通过反正切函数就能得到磁铁在平面上的旋转角度通过磁场矢量模值或单轴分量的变化可以推算线性位移。在很多项目里这个芯片被直接当作 3D 霍尔旋转传感器使用省去了光码盘和机械挡块。2.2 I2C 地址与通信时序MLX90393 的默认 I2C 地址是 0x0C 或 0x0E由 A0、A1 引脚的电平组合决定。如果总线上挂多片可以把这两个引脚接高低电平来区分。I2C 时钟最高约 1 MHz支持标准、快速和快速模式。Arduino 的 Wire 库默认 100 kHz但实际测速时建议用Wire.setClock(400000)提升到快速模式否则一次读三轴数据会占用较长的总线时间。读写时序上主机先发送命令字节典型的命令有读取结果 0x4E、启动单次测量 0x3E、写寄存器 0x41 等然后等待芯片响应状态。库已经封装好这些细节但理解命令码可以帮助你排查总线异常。2.3 寄存器配置位速查MLX90393 的配置集中在 CONFIG1 和 CONFIG2 两个寄存器里。CONFIG1 控制霍尔电流脉冲和增益CONFIG2 控制分辨率、过采样和数字滤波。下表是常用的配置位说明实际使用时这些位会通过库的封装函数去修改但直接面向寄存器操作时必须知道哪个位对应哪个功能。寄存器位功能常见设置CONFIG1[7:6]霍尔电流脉冲00 或 01对应约 0.15mA 或 0.08mACONFIG1[5:4]增益档位00/01/10/11 对应 1/2/4/8 倍CONFIG2[7:6]分辨率模式00 低功耗11 高分辨率 16 位CONFIG2[5:3]数字滤波强度0-7滤波越强噪声越低但响应变慢CONFIG2[2:0]过采样次数0-7分别代表 2、4、8 次等量程和增益容易搞混。量程决定芯片在某个增益下能承受的最大磁场而增益是内部模拟放大倍数。磁场超过量程会饱和输出值锁定在满幅磁场太弱则量化误差明显。选参数时先估算磁铁在安装位置的剩磁强度再反推需要多大的量程和增益。2.4 单次测量与连续轮询的取舍MLX90393 支持单次测量和连续测量两种模式。单次测量适合电池供电和低占空比场景主机发一个启动命令稍等转换完成再读结果。转换时间由分辨率、滤波和过采样次数共同决定一般几百微秒到几毫秒。连续测量适合主轴转速较高的动态应用芯片会按内部设定的刷新率不断更新数据寄存器主机无需频繁发启动命令。Arduino 库示例默认走单次测量路线每次调用 readXYZ 前先触发一次测量逻辑简单功耗也低。高速旋转或需要低延迟时可以在初始化后切到连续模式并改用轮询状态寄存器的方式读数据。3. Arduino 环境下的库安装与基本读数测试3.1 库目录结构和安装方式解压项目包后会看到 arduino-MLX90393-master 文件夹里面包含 MLX90393.cpp、MLX90393.h、LICENSE 和 examples 目录。把整个文件夹复制到 Arduino 的 libraries 目录或者用 IDE 的“安装 ZIP 库”直接选中压缩包重启 IDE 后就能在文件菜单的示例列表里看到 MLX90393 相关的例程。examples 下有三个子目录Example1-BasicReadings 用于基础读数Example2-ConfigureSensor 用于演示配置修改MLX90393-Tester 是板级检测工具。如果你的板子不是 AVR比如 ESP32、STM32F103只要 Wire 库兼容代码同样能编译寄存器命令字和地址都跨平台固定。3.2 最小读取程序新建一个 Arduino 草稿先初始化 I2C再调用 MLX90393.begin() 做软复位并读取芯片 ID之后循环读 X/Y/Z 三个磁场分量。下面是我在 Uno 上验证过的最小读取逻辑。#include Wire.h #include MLX90393.h MLX90393 sensor; void setup() { Serial.begin(115200); Wire.begin(); // Uno: A4SDA, A5SCL Wire.setClock(400000); // 提高到快速模式 if (sensor.begin() ! MLX90393_SUCCESS) { Serial.println(MLX90393 连接失败); while (1); } sensor.setGainSel(0x01); // 2 倍增益 sensor.setResolution(0, 0, 0); // X/Y/Z 均为最高分辨率 sensor.setOverSampling(MLX90393_OSR_2); sensor.setDigitalFilter(MLX90393_FILTER_5); Serial.println(MLX90393 就绪); } void loop() { MLX90393_XYZ data; uint8_t status sensor.readXYZ(data); if (status MLX90393_STATUS_ERROR) { Serial.println(读数错误); } else { Serial.print(X); Serial.print(data.x); Serial.print( Y); Serial.print(data.y); Serial.print( Z); Serial.println(data.z); } delay(50); }代码里的 setGainSel 参数 0x01 对应 2 倍增益适合中等强度的磁铁。setResolution 的三个数字分别对应 X、Y、Z 的分辨率模式0 表示最高精度。setOverSampling 设为 OSR_2内部会对每个轴做 2 次采样平均setDigitalFilter 设为 FILTER_5相当于 5 级低通滤波。实际使用时如果响应速度要求高可以把滤波级别降到 1 或 2如果噪声明显则提高过采样次数。readXYZ 返回的状态字节同时包含数据就绪位和溢出标志最好先检查 error 位再使用数据否则图像上会偶尔冒出毛刺值。3.3 接线与模块说明CJMCU-90393 模块引出 VCC、GND、SDA、SCL 四个引脚。5V 的 Arduino Uno 板子上要确认模块是否带稳压和电平转换否则 I2C 电平不匹配会导致偶发错误。常见的接法是Arduino Uno CJMCU-90393 3.3V/5V -------- VCC GND -------- GND A4 (SDA) -------- SDA A5 (SCL) -------- SCLESP32 默认用 GPIO21/22STM32 的 I2C 引脚可在代码里另行定义。如果读回的数据全是 0 或 0xFFFF优先检查 SDA/SCL 是否接反、电源是否稳定其次检查模块上 I2C 上拉电阻有没有焊好。项目包里的原理图能看到两个 4.7k 上拉电阻到 VCC如果自己飞线搭电路必须补上这两个电阻否则总线容易受噪声干扰。3.4 串口输出验证原始数据运行上面的程序后串口会打印 X/Y/Z 原始值。拿一个径向充磁的小磁铁从模块上方慢慢划过三个轴的数值会跟随变化。数值范围从负几千到正几千具体取决于量程和分辨率。如果想让数据更直观可以在串口绘图仪里同时绘制 X 和 Y 两条曲线旋转磁铁时会出现正弦和余弦波形说明传感器工作正常。这个原始值还不能直接当角度下一步要做配置和标定。4. 传感器参数配置实战从例程到自定义4.1 例程 Example2-ConfigureSensor 的配置流程Example2 不只读取数据还会在 begin 之后重新配置传感器并验证配置是否生效。它的逻辑可以拆成三步先读取当前寄存器值再修改目标位最后回读确认。库里的 setGainSel 函数就采用“读-改-写”方式更新 CONFIG1 寄存器。uint8_t setGainSel(MLX90393_gain_t gain) { uint8_t regs[1]; readRegisters(MLX90393_CONF1, regs, 1); regs[0] ~(0x03 4); // 清掉第 4、5 位 regs[0] | ((uint8_t)gain 4); // 写入新的增益值 writeRegisters(MLX90393_CONF1, regs, 1); return MLX90393_SUCCESS; }这里先读回 CONFIG1把增益位清成 00再按新值写回。为什么不能直接写整个寄存器因为 CONFIG1 里还有其他关键位比如霍尔电流脉冲和量程选择直接覆写可能破坏不该动的配置。这种读-改-写的方式在单片机寄存器操作里非常常见需要形成习惯。4.2 量程、增益和分辨率之间怎么配量程、增益、分辨率三个参数互相影响。量程一度决定可测的磁场上限增益决定模拟放大倍数分辨率决定输出量化步长。相同的原始码值在不同量程下对应不同的实际磁场强度。实际磁场值 D 与原始码值 N 的关系是D N * 量程 / 32768高分辨率模式下 ADC 是 16 位有效。我常用的搭配参考如下。磁铁与芯片距离典型磁场强度推荐量程推荐增益靠近模块 2mm10-20 mT±50 mT1 倍中等距离 5mm3-8 mT±20 mT2 倍较远 10mm0.5-2 mT±5 mT4-8 倍注意增益不是越大越好带宽内噪声也会被同步放大。比如在 8 倍增益下芯片自身噪声可能从 0.1 mT 变成 0.8 mT 的分辨率噪声导致角度抖动加剧。通常用串口连续读 100 个数据点计算标准差若超过量程的 1%就要考虑降低增益或缩短磁铁距离。4.3 数字滤波和过采样的设定数字滤波和过采样都能减少读数抖动但代价是减慢响应。过滤和过采样会把多次 ADC 结果做平均等效于降低输出带宽。对于静态角度检测比如旋钮位置滤波级别设为 5 到 7 能获得很干净的角度曲线。但对于动态测量比如电机轴转速检测过强的滤波会让相位延迟变大导致控制环不稳定。sensor.setOverSampling(MLX90393_OSR_8); sensor.setDigitalFilter(MLX90393_FILTER_7);OSR_8 表示每个轴做 8 次采样转换然后取平均单次测量耗时会在毫秒级别。如果采用单次测量模式每次读取都要等待内部转换完成这个耗时不可忽略。建议先用默认参数在串口绘图仪观察数据波动趋势再逐步调高滤波直到稳定性和响应时间的平衡点被找到。4.4 原理图要点与模块 PCB 检查项目包中 CJMCU-90393 原理图显示这个模块仅仅是把 MLX90393 芯片、两个 4.7k 上拉电阻和一个 100nF 去耦电容画在一块小板上。虽然包里的原理图文件命名为 MAX30105但内容对应的是 CJMCU-90393要注意甄别。去耦电容必须靠近电源引脚放置否则高频噪声容易注入模拟电源使 ADC 结果跳动。如果自己画板A0 引脚悬空默认地址是 0x0CA1 引脚同样决定地址位走线时让 SDA 和 SCL 保持短距离与 VCC 之间不要形成大环路。4.5 配置后怎么验证参数是否合适配置完成后把磁铁放在目标量程的 30% 到 80% 位置串口读数应接近量程上限的 1/3 到 4/5。如果最大输出只占满量程的 5%说明磁场过弱要么降低量程要么把磁铁移近。如果数据频繁达到 32767 或 -32768 附近的边界值说明已经饱和磁场过强需要切换更大量程。建议在代码里加一个统计最小值和最大值的功能通过串口打印比盯着波形更直观。以下是一个简单的静态配置验证代码片段。long minX 32767, maxX -32768; long minY 32767, maxY -32768; for (int i 0; i 100; i) { MLX90393_XYZ d; sensor.readXYZ(d); minX min(minX, d.x); maxX max(maxX, d.x); minY min(minY, d.y); maxY max(maxY, d.y); delay(10); } Serial.print(X range: ); Serial.print(minX); Serial.print( ~ ); Serial.println(maxX);如果 minX 和 maxX 之间的跨度只有几百说明模拟前端增益不够后续角度计算分辨率有限。如果跨度接近 65000则要考虑饱和角度会在某些位置出现明显非线性这时需要把磁铁移远或者降低增益。5. 位移和角度计算从原始值到工程单位的进阶技巧5.1 角度计算与零偏校准对于旋转角度检测最常用的是 X 和 Y 轴组成平面上的反正切。下面这个函数把原始值转成 0 到 360 度适合旋钮类应用。float angleDeg(float x, float y) { float a atan2(y, x) * 180.0 / PI; if (a 0) a 360.0; return a; }但由于磁铁与芯片不可能完全同心实测角度往往存在固定的零偏和不等幅因子。更好用的方法是先让磁铁旋转一圈采集 X、Y 的最大最小值然后做归一化修正。float correctedX (x - offsetX) * (2.0 / (maxX - minX)); float correctedY (y - offsetY) * (2.0 / (maxY - minY)); float angle atan2(correctedY, correctedX) * RAD_TO_DEG; if (angle 0) angle 360;这里的 offsetX 取 (maxX minX)/2offsetY 同理。经过归一化后角度线性度在 1 度以内的概率较高代价是必须做一次静态标定。5.2 线性位移检测的做法如果一个轴向充磁的小磁铁从芯片上方沿垂直方向移动Z 轴磁场会随距离变化但曲线不是直线而是近似 1/d^3。直接用比例换算会带来较大误差更适合做分段标定。在几个已知位置记录实际 Z 值例如 0mm、2mm、4mm、6mm然后按区间线性插值。下面给出两段插值的核心逻辑。float getDisplacement(float z) { float knownDis[] {0, 2, 4, 6}; float knownVal[] {6000, 4000, 2500, 1500}; for (int i 0; i 3; i) { if (z knownVal[i1] z knownVal[i]) { return knownDis[i] (knownDis[i1]-knownDis[i]) * (knownVal[i]-z)/(knownVal[i]-knownVal[i1]); } } return -1; }注意插值区间的顺序要保证分母不为零。这种方法对安装位置的变化非常敏感每次改磁铁或 IC 位置后标定表都要重新录入。5.3 通信错误的快速定位如果读回的状态寄存器的 ERROR 位经常置位第一步用 I2CScanner 扫描地址确认芯片在不在 0x0C 或 0x0E 上。第二步检查电源电压MLX90393 供电范围是 2.2V 到 3.6V直接接 5V 有损坏风险模块带稳压则另当别论。第三步检查模块上的上拉电阻是否缺失无上拉时 SDA/SCL 悬空容易让总线卡死。实际调试中我还会在每次 readXYZ 后加一个超时计数连续出错时打印错误码而不是死循环这样能避免程序卡在等待状态。库函数begin()已包含软复位和 ID 读取如果连接失败优先怀疑接线问题而不是代码问题。5.4 边界处理与输出平滑角度计算在 359 度和 0 度交界处会产生跳变如果直接把角度送入 PID 或滤波器会出现很大的微分冲击。解决办法是记录上一次角度值当新角度减去旧角度大于 180 度时对新角度减 360 度小于 -180 度时对新角度加 360 度。这样递推后的角度成为连续曲线边界跳变被消除。对于需要低抖动的输出可以再加一阶低通滤波但滤波系数不要超过 0.2否则旋钮位置的阶跃响应会变得迟钝。推荐在串口绘图仪同时显示原始角度和滤波后角度对比两者的延迟就能判断滤波系数是否合适。本文还有配套的精品资源点击获取