MLX90614红外测温实战:I2C寄存器级读取与稳定滤波

发布时间:2026/9/2 14:52:17
MLX90614红外测温实战:I2C寄存器级读取与稳定滤波 简介这是一份基于STM32与MLX90614的红外无接触测温工程源码面向嵌入式开发者、电子设计竞赛学生以及需要快速搭建非接触体温检测方案的工程师适用于人体体温监测、工业自动化和智能家居等场景。工程已实测通过MLX90614通过I2C接口与STM32通信硬件连接为SCK接PB6、SDA接PB7串口1持续输出实时温度值便于直接观察和二次开发非接触测量方式还能降低交叉污染风险在医疗健康与工业巡检等场景中更具优势。压缩包共110个文件大小约992KB以C源文件、H头文件为主体同时包含编译生成的o、d、hex、map及Keil工程配置文件可完整还原项目并用于烧录调试也方便对照外设库理解驱动实现。目前已有1076人学习下载适合需要快速参考I2C驱动、红外测温数据读取或STM32串口输出流程的开发者使用。整套资源目录结构清晰包含标准外设库文件与构建脚本能节省环境搭建时间帮助上手实测与排错。 前阵子把 MLX90614 红外无接触测温项目调通了数据读得稳、误差也控制在可接受范围内测试通过后顺手把工程文件打包发到了交流群。不少朋友问源码和接线图干脆把整个实现过程拆开写一写。这个方案不依赖现成的 Adafruit 库直接从 I2C 寄存器底层把温度算出来搞清楚了传感器内部到底在干什么。如果你也准备做测温小工具、手势检测或者非接触式温度采集这篇文章应该能帮你省掉不少踩坑时间。1. 项目背景与整体思路1.1 为什么选 MLX90614 做无接触测温测温方案其实不少但做非接触测温时热电阻、热电偶这类接触式传感器基本可以直接排除。它们响应慢而且必须贴在被测物体上很多场景根本没法用。热像仪效果最好可一块入门级热像模块动辄上千元个人项目实在没必要为一个小功能花这个钱。MLX90614 是 Melexis 推出的红外测温芯片利用物体表面的红外辐射能量来计算温度不需要物理接触响应时间只有几十毫秒分辨率能做到 0.02℃量程覆盖 -70℃ 到 380℃日常项目绰绰有余。更关键的是它走 I2C 接口主控随便接整个方案非常简单。我手上这块是 GY-906 模块板上带了 LDO 稳压管和 I2C 上拉电阻不会出现直接贴裸芯片那种难伺候的情况。模块上一共四个引脚VCC、GND、SDA、SCL接线难度基本为零。项目核心就三件事初始化 I2C、读取传感器 RAM 区原始数据、把原始值换算成物理温度。听起来简单但真正调通的过程中还是有不少小细节下面逐个讲。1.2 项目包内容拆解压缩包里主要几个文件main.ino是 Arduino 主程序包含初始化、循环读取和串口输出MLX90614.cpp和MLX90614.h是自己封装的最小驱动库没有依赖第三方库方便移植到其他平台Readme.txt写了接线说明和常见问题还有一张Schematic.png是接线示意图。整个项目在 Arduino Uno 上测试通过但代码里我用的是软件 I2C所以可以自由选择引脚如果你用 ESP32、STM32 这类主控也只要改一下引脚映射和延时函数即可。2. 硬件准备与接线细节2.1 物料清单物料型号/规格数量红外测温模块GY-906MLX906141主控板Arduino Uno / Nano1杜邦线母对母20cm4面包板可选标准面包板1电容可选100nF 陶瓷电容1面包板不是必须的如果模块直接插在 Arduino 排针上省掉面包板更稳。建议多备几根杜邦线很多时候数据线接触不良是导致 I2C 通信失败的元凶。2.2 接线方式与注意事项接线表非常直接模块 VCC 接 Arduino 5VGND 接 GNDSDA 接 A4SCL 接 A5。如果你的主控是 3.3V 逻辑电平比如部分 ESP32 板子的某些引脚也可以直接用 3.3V 给模块供电因为 GY-906 板载的 LDO 支持 3.3V 输入I2C 引脚同样是开漏结构配合上拉电阻不会有电平冲突。实际接线时有几个坑必须提醒供电线不要太长超过 20cm 的杜邦线会带来压降和干扰导致读数偶尔跳变。模块的 VCC 和 GND 之间并联一个 100nF 陶瓷电容能明显减少电源纹波干扰。如果项目中还有继电器、电机这类大功率设备一定要把传感器电源和它们隔开共用一个电源时读数经常会乱飘。模块上的上拉电阻一般默认焊接到 3.3V如果你的模块是二手或定制板上拉电阻被拆了需要自己补两个 4.7k-10k 电阻否则 I2C 信号没有上拉读不到任何数据。2.3 软件 I2C 与硬件 I2C 的选择I2C 分硬件和软件两种方式。硬件 I2C 是用单片机内部的专用外设速度快不占用 CPU软件 I2C 则是用 GPIO 模拟时序好处是任意引脚都能用。这个项目里我选了软件 I2C因为测试时 A4/A5 被一个 OLED 占用了不想重新插线就把 MLX90614 接到了 A0/A1用 SoftWire 库模拟。实测下来通信稳定唯一区别是每次读取需要约 2ms 的时序延迟测温本来就要求慢节奏读取所以完全够用。3. 核心代码实现与解析3.1 I2C 通信与寄存器地址MLX90614 内部有两个 RAM 地址最常用0x07存放物体温度原始值0x06存放环境温度原始值都是 16 位有符号数。除了 RAM它还有一块 EEPROM 区域专门存放发射率0x04、温度偏移0x24等配置出厂默认值已经适配大多数场景普通使用不需要修改。I2C 读取寄存器的时序比普通读器件多一个步骤。大致流程是先给从机地址加写位写入要读取的寄存器地址然后重新发送 Start 信号再给从机地址加读位之后连续读三个字节前两个是数据低位和高位第三个是 PEC 校验字节。如果第三个字节不读下次通信可能出问题因为从机会一直等主机把剩余数据读走。默认从机地址是0x5A这个值已经在芯片内部写死没有特殊焊接的话不需要改。3.2 温度读取与换算方法直接用 Wire 库写一个最小读取函数核心代码大概长这样#include Wire.h #define MLX90614_ADDR 0x5A #define MLX90614_TA 0x06 #define MLX90614_TOBJ 0x07 double readTemperature(uint8_t reg) { Wire.beginTransmission(MLX90614_ADDR); Wire.write(reg); Wire.endTransmission(false); Wire.requestFrom(MLX90614_ADDR, 3); if (Wire.available() 3) return -273.15; uint16_t raw Wire.read() | (Wire.read() 8); uint8_t pec Wire.read(); // PEC 校验字节这里只读取并丢弃 return raw * 0.02 - 273.15; } void setup() { Wire.begin(); Serial.begin(115200); } void loop() { double objectTemp readTemperature(MLX90614_TOBJ); double ambientTemp readTemperature(MLX90614_TA); Serial.print(Obj: ); Serial.print(objectTemp); Serial.print( C, Amb: ); Serial.print(ambientTemp); Serial.println( C); delay(200); }换算的原理其实很简单传感器输出的原始值是一个 16 位整数每一位代表 0.02℃所以原始值乘以 0.02 就得到开尔文温度再减去 273.15 就是摄氏温度。注意这里需要转换成有符号数如果高位为 1 就代表负数但日常测物温不会出现负到离谱的情况所以用uint16_t读出来也没问题只要知道温度低于 -273.15℃ 时肯定不正常即可。3.3 数据滤波与稳定性优化直接把readTemperature的值用起来串口监视器里会看到温度小数点末尾一直在跳个别时刻还会冒出一个明显偏离的值。这是因为红外传感器对热噪声十分敏感尤其是周围有风吹动或者目标物体表面有反射时。我加了一个 10 点滑动平均滤波效果很明显。#define FILTER_SIZE 10 float history[FILTER_SIZE]; uint8_t historyIndex 0; float smoothRead(uint8_t reg) { history[historyIndex] readTemperature(reg); historyIndex (historyIndex 1) % FILTER_SIZE; float sum 0; for (uint8_t i 0; i FILTER_SIZE; i) { sum history[i]; } return sum / FILTER_SIZE; }如果对实时性要求高窗口可以缩短到 5如果目标是剔除瞬时干扰建议用中值滤波把窗口内的最大值和最小值丢弃再求平均值。实测下来 10 点滑动平均滞后感轻微温度读取周期 200ms窗口覆盖 2 秒动态响应还能接受。4. 标定与精度优化4.1 发射率设置发射率Emissivity是红外测温里最容易被忽略的参数。不同材料表面向外辐射红外能量的能力不同黑体辐射率是 1.0而人体皮肤大约 0.98普通塑料在 0.85-0.95 之间抛光金属只有 0.2 甚至更低。如果传感器默认内部发射率是 1.0遇到低发射率目标读数会严重偏低。MLX90614 的发射率存放在 EEPROM 的0x04地址默认值为0xFFFF即 1.0。如果要修改成 0.95需要把0.95 * 65535 62258.25取整为62258转换成 16 进制写入 EEPROM。写入命令有点特殊不是普通写寄存器的流程需要打开 EEPROM 访问模式执行 Erase 命令再写数据。实际做项目时不建议频繁修改发射率因为 EEPROM 擦写次数有限反复写容易把配置搞坏。我的做法是代码里保留发射率变量做软件补偿这样不改硬件也能修正读数。4.2 环境温度补偿MLX90614 内部虽然带了环境温度补偿但芯片本身测的是自身封装附近的温度如果环境温度和被测物体温度差距过大补偿效果会打折扣。我实测过一次把传感器放在 60℃ 热水杯旁边再测手温读数会比正常值偏低不少因为传感器被热辐射干扰了。在代码里可以把环境温度也读出来做简单逻辑判断。我设了一个阈值当ambientTemp 50时输出警告说明传感器工作环境已超出可靠范围。普通室温场景基本不需要额外补偿但一定要让传感器远离发热源和阳光直射否则误差可能超过 ±2℃。4.3 距离与视场角影响MLX90614 的视场角有 35° 和 90° 两种规格模块侧面会打标。视场角越大传感器能接收到的目标区域越宽但同时也会混入更多背景环境温度。距离系数大概在 1:1 左右意思是测量距离每增加 1cm传感器识别到的目标直径也增加 1cm。所以测额头或手背温度时距离尽量控制在 2-3cm太近会受传感器外壳自身热传导影响太远测到的就是一块混合区域的平均温度根本不准。5. 常见问题与排查技巧5.1 温度一直读成 -273.15 或 0遇到这种情况第一个要查的是寄存器地址和从机地址。有些代码示例里写Wire.beginTransmission(0xB4)这是把左移一位后的地址写进去了会导致通信失败。正常在 Wire 库里应该写0x5A。其次是 PEC 校验字节如果requestFrom只收两个字节不读第三个 PEC 字节部分模块会认为主机没有读完整导致后续通信状态异常。最后还有一个常见坑传感器刚上电的第一次读取可能返回异常值简单delay(50)后重读一次即可解决。5.2 测量值明显偏低或偏高先检查发射率设置这是最大嫌疑。如果你没有改过 EEPROM默认是 1.0测人体会略微偏低 0.5℃ 左右。其次是距离和视场角测温目标如果小于传感器能覆盖的最小区域读数会偏向背景。再就是遮挡问题很多人习惯在传感器前面加透明塑料罩红外线会被阻挡测到的是罩子的温度误差一下就拉开了。最好的办法是不加任何遮挡或者用专门的红外窗口透镜。5.3 I2C 通信时好时坏这种现象多半是硬件问题。检查 SDA/SCL 是否松动杜邦线换新的一组试试如果模块和主控距离较远缩短连接线长度如果总线上同时挂了其他 I2C 设备确认地址没有冲突。还有一个细节MLX90614 的 I2C 引脚是开漏输出必须有上拉电阻才能正常通信。模块上默认有上拉电阻但某些定制板可能没有我遇到过一块精简版模块读不到数据补了两颗 10k 电阻后才正常。5.4 读取周期太频繁导致数据乱跳很多人为了实时显示把delay改得很短比如 10ms 读一次结果数据不仅没有更平滑反而开始剧烈跳变。原因是传感器内部 ADC 需要时间来刷新热堆电压读取间隔太短时两次读到的原始数据可能来自同一次采样或者采样尚未完成导致读取值波动。我的经验是每 200ms 读一次既能保证数据稳定也不会带来明显延迟。6. 测试过程与个人体会6.1 实测数据记录我在室温 25℃ 环境下做了几组对比测试参考值用的是水银温度计和热电偶距离控制在 3cm滑动平均窗口 10 点测试目标MLX90614 读数参考温度误差手掌29.2℃29.5℃-0.3℃陶瓷杯热水54.6℃54.3℃0.3℃桌面25.3℃25.0℃0.3℃暖风机出风口38.8℃39.2℃-0.4℃整体误差在 ±0.5℃ 以内符合标称精度。如果做体温检测建议测额头并提前静置 5-10 分钟让传感器和环境温度保持一致数据会更准。6.2 个人调试心得与扩展建议这个项目让我印象最深的一点是红外测温模块本身精度并不差但能不能测准很大程度上取决于使用方式。发射率、距离、环境温度、供电稳定性每一项都影响最终结果。如果只是把模块插上读一个数字就发布很容易被测量误差坑到。我的建议是做任何测温项目都要多备几种参考源做对比至少要有水银温度计或热电偶作为标定基准。扩展方向上可以给模块加一块 OLED 屏幕按键切换物温/体温模式或者把数据通过串口发到上位机做温度曲线记录再进一步可以用 ESP32 连接 WiFi做成一个居家环境温度监测节点。这个模块的 I2C 接口注定了它非常容易接入各种主控整套代码稍微改改就能移植到 STM32 或树莓派 Pico 上。最后分享一个自己的习惯每次调试测温项目都会在串口输出里同时打印环境温度和物体温度这样能快速判断环境因素是否干扰了测量结果能少走很多弯路。本文还有配套的精品资源点击获取