ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Arduino与MLX90614红外测温仪制作:非接触测温原理与实战

Arduino与MLX90614红外测温仪制作:非接触测温原理与实战 1. 项目缘起为什么选择非接触式红外测温方案最近在整理工作室的电子元件翻出来几个之前做项目剩下的MLX90614红外测温传感器模块。这玩意儿精度不错价格也亲民但之前都是用在一些工业监测的小项目里总觉得有点大材小用。正好手边还有一块Arduino Uno和几个超声波模块一个想法就冒出来了能不能做个简单、实用又有点意思的非接触式红外测温仪这个想法其实挺有现实意义的。传统的接触式测温比如水银温度计或者热电偶你得贴上去才能测测个开水温度还行但要是测个正在运行的电机外壳、或者想快速筛查一下物体表面温度分布就很不方便了。非接触红外测温就没这个烦恼它通过测量物体表面辐射出的红外能量来反推温度完全不用碰响应速度还快毫秒级就能出结果。对于电子爱好者、创客或者只是想做个智能家居小工具的人来说用Arduino搭配MLX90614来实现这个功能是个成本低、门槛也合适的入门级选择。你可能在网上搜“Arduino测温”会看到很多基于DS18B20或者LM35的方案那些都是接触式的。而“Non-Contact Infrared Thermometer”这个组合核心就在于“红外”和“非接触”。MLX90614就是干这个的它内部集成了红外热电堆传感器和专用的信号处理芯片能直接把接收到的红外辐射转换成数字温度值通过I2C接口传给Arduino我们几乎不用处理复杂的模拟信号。再配合一个超声波测距模块我们还能实现“靠近自动测量”或者“测量距离补偿”让这个小设备更智能一些。所以这个项目不只是简单地把传感器数据读出来更是对一种实用测量原理的动手实践。2. 核心器件选型与工作原理深潜工欲善其事必先利其器。做一个非接触红外测温仪核心就三样负责思考的微控制器、负责“看”温度的红外传感器以及可选但能大大提升体验的“眼睛”超声波模块。我们来逐一拆解搞清楚为什么选它们以及它们到底是怎么工作的。2.1 大脑Arduino Uno的稳定之选市面上Arduino板子很多从Nano到Mega为什么首选Uno对于这个项目核心考量是稳定性和易用性。MLX90614采用I2C通信只需要两根信号线SDA, SCL。Arduino Uno的I2C引脚A4, A5位置固定连接非常直观避免了像一些迷你板型需要飞线或额外定义的麻烦。同时Uno的供电5V和IO电平与常见的MLX90614模块工作电压3.3V或5V兼容电平完美匹配不需要额外的电平转换电路。更重要的是生态和调试便利性。Uno的USB转串口芯片非常成熟在Arduino IDE里几乎不会遇到驱动问题上传代码、查看串口监视器的数据都极其顺畅。项目后期如果需要增加显示如OLED屏或声光提示蜂鸣器、LEDUno丰富的数字和模拟引脚也留有充足余量。虽然ESP32等功能更强大但对于专注于传感器数据采集和逻辑控制的红外测温仪Uno的ATmega328P芯片性能完全够用且因其经典相关的库支持和社区解答也最丰富能有效降低新手排查问题的难度。2.2 眼睛MLX90614如何“看见”温度这是本项目的绝对核心。MLX90614不是一个简单的热敏电阻它是一个完整的红外测温系统封装。其工作原理可以分为三步红外能量收集传感器前方的透镜通常是硅透镜负责收集目标物体发射的红外辐射。所有高于绝对零度-273.15°C的物体都会向外辐射红外线辐射的强度与物体表面温度的四次方成正比斯蒂芬-玻尔兹曼定律。透镜将这些红外线聚焦到传感器内部的“热电堆”上。热电堆转换热电堆由一系列热电偶串联而成。当红外光照射到热电堆的热结点黑色吸收面时结点温度升高而冷结点通常连接至传感器外壳保持相对恒定。这个温差会产生一个微弱的温差电动势电压信号。温度差越大产生的电压信号就越强。信号处理与输出这个微伏级别的电压信号极其微弱且容易受干扰。MLX90614内部集成了一个低噪声放大器、一个17位模数转换器ADC和一个强大的数字信号处理器DSP。ADC将放大后的模拟电压信号转换为数字量DSP则根据传感器自身的校准参数、环境温度补偿MLX90614也内置了一个测量自身芯片温度的PTAT传感器以及复杂的算法最终计算出目标物体的绝对温度值。所有计算都在传感器内部完成它通过I2C接口直接输出一个已经换算好的、以摄氏度或华氏度为单位的数字比如23.75这极大简化了我们的编程工作。这里有一个关键点需要注意MLX90614测量的是物体表面的“辐射温度”。这个值要准确转换为真实的“表面温度”依赖于一个叫“发射率”的参数。发射率是一个介于0完美镜面不辐射和1理想黑体完全辐射之间的系数。大多数有机材料皮肤、木材和氧化后的金属表面发射率在0.95左右而光亮金属表面可能低至0.1。MLX90614库函数通常允许我们设置发射率默认为0.95。对于精度要求不高的通用场景默认值即可如果需要测量特定材料如铝板、不锈钢就必须查找该材料在相应波段的发射率并进行校正。2.3 感知HC-SR04超声波模块的角色红外测温仪为什么需要超声波模块这不是必需的但它能实现一个非常实用的功能触发测量或距离补偿。MLX90614有一个固定的视场角FOV比如常见的版本是90°或110°。这意味着它测量的不是一个点而是一个圆锥形区域的平均温度。当被测物体距离传感器很近时传感器“看到”的基本就是物体表面的一小块区域但当距离变远时视场覆盖的面积变大如果背景温度比如墙壁与目标物体温度不同就会引入测量误差。超声波模块HC-SR04可以精确测量传感器到物体表面的距离。我们可以利用这个距离信息做两件事自动触发设置一个阈值例如5-15厘米当超声波检测到有物体进入这个范围时自动触发一次红外温度测量并显示结果实现“抬手即测”的体验无需按钮。距离提醒在屏幕上实时显示当前距离提示用户将设备保持在最佳测量距离根据传感器数据手册通常建议在2-5厘米内以获得最准确的“点”温度避免因距离过远导致视场内包含非目标物体。超声波模块的原理是发送一束40kHz的超声波脉冲并接收从物体反射回来的回波。通过计算发射和接收的时间差结合声速约340m/s就能算出距离。虽然声速受温湿度影响但在室内短距离测量中这个误差对于我们的触发或提示功能来说可以接受。3. 硬件连接与电路搭建详解理论清楚了接下来就是动手连接。这一步看似简单但连接的正确性和稳定性直接决定了后续程序能否顺利运行以及测量结果的可靠性。我们按照信号流和电源流来梳理。3.1 系统连接总图与电源考量首先我们需要一张清晰的接线图。以下是基于Arduino Uno、MLX90614I2C接口和HC-SR04超声波模块的典型连接方式元件引脚连接到 Arduino Uno说明MLX90614VIN5V供电引脚接5V稳定电源GNDGND共地至关重要SDAA4I2C数据线SCLA5I2C时钟线HC-SR04VCC5V供电引脚GNDGND共地Trig数字引脚 D2触发控制引脚Echo数字引脚 D3回波接收引脚可选OLED屏VCC5V供电GNDGND共地SDAA4 (与MLX90614并联)I2C数据线可并联SCLA5 (与MLX90614并联)I2C时钟线可并联注意多个I2C设备如MLX90614和OLED屏可以共享SDA和SCL线这是I2C总线的好处。但务必确保每个设备有唯一的I2C地址。MLX90614的默认地址通常是0x5A而常见的0.96寸OLED屏地址是0x3C它们不会冲突。电源是隐形的关键。整个系统从USB取电对于Uno来说通常足够。但如果你发现测量值跳动异常大尤其是超声波模块工作时可能是电源纹波导致的。一个简单的改进方法是在Arduino的5V和GND引脚之间靠近传感器模块的位置并联一个10μF的电解电容和一个0.1μF的陶瓷电容用于滤除低频和高频噪声。特别是MLX90614内部的ADC对电源质量比较敏感干净的电源能提升读数稳定性。3.2 连接实操与常见坑点焊接或使用杜邦线连接时有几点需要特别留意I2C上拉电阻MLX90614模块板上通常已经集成了4.7kΩ的上拉电阻连接在SDA和SCL到VCC之间。如果你的模块没有或者连接线较长超过20厘米信号质量可能变差。这时需要在Arduino端的A4SDA和A5SCL引脚上分别通过一个4.7kΩ电阻连接到5V。大多数现成模块已内置无需额外添加。超声波模块的干扰HC-SR04在发射超声波时会产生一个瞬间的较大电流。如果它与MLX90614共用一条很细或很长的电源线可能会引起电压瞬间跌落干扰MLX90614的测量。解决办法是使用较粗、较短的导线为它们供电或者如前所述在电源入口处增加滤波电容。GND共地所有模块的GND引脚必须可靠地连接到Arduino的GND。这是电路正常工作的基础任何“浮地”都会导致通信失败或读数错误。建议使用面包板或PCB的电源总线来确保所有地线连接在一起。连接完成后先不要急于上传复杂代码。可以分别测试各个模块。例如先上传一个简单的I2C扫描程序确认Arduino能正确识别到MLX90614的地址0x5A。再单独测试超声波模块的测距功能。分步验证能极大简化故障排查过程。4. 软件实现从数据读取到智能逻辑硬件搭建好了接下来就是赋予它灵魂的代码部分。我们将使用Arduino IDE进行开发。首先需要安装必要的库这对于功能实现至关重要。4.1 库文件安装与环境准备打开Arduino IDE进入“工具” - “管理库...”在库管理器中搜索并安装以下库Adafruit MLX90614 Library这是最常用、维护最好的MLX90614驱动库。搜索“Adafruit MLX90614”并安装它通常会连带安装“Adafruit BusIO”等依赖库。Ultrasonic Library用于简化HC-SR04的操作。搜索“Ultrasonic by Erick Simões”并安装。当然你也可以不用库直接通过pulseIn()函数处理回声但使用库代码更简洁。(可选) Adafruit SSD1306 及 GFX Library如果你连接了I2C接口的OLED屏需要安装这两个库来驱动屏幕和显示图形文本。安装完成后建议通过“文件” - “示例”菜单找到对应库的示例程序比如运行一下Adafruit MLX90614库中的mlxtest示例看看串口监视器能否正确输出环境温度和物体温度以此验证传感器和连线是否正常。4.2 核心代码逐行解析下面是一个整合了红外测温、超声波测距和基础串口输出的核心代码框架并附上详细注释。// 引入必要的库 #include Wire.h // Arduino内置的I2C库 #include Adafruit_MLX90614.h // 红外测温库 #include Ultrasonic.h // 超声波测距库 // 初始化传感器对象 Adafruit_MLX90614 mlx Adafruit_MLX90614(); // 创建MLX90614对象使用默认I2C地址0x5A // 初始化超声波对象Trig引脚接D2Echo引脚接D3 Ultrasonic ultrasonic(2, 3); // 定义变量 float objectTempC; // 物体温度摄氏度 float ambientTempC; // 环境温度摄氏度 float distanceCM; // 测量距离厘米 const float MIN_DISTANCE 2.0; // 最小有效测量距离厘米 const float MAX_DISTANCE 15.0; // 最大有效测量距离厘米超出此范围提示太远 void setup() { Serial.begin(9600); // 启动串口通信用于调试输出 Serial.println(Non-Contact IR Thermometer Starting...); // 初始化MLX90614 if (!mlx.begin()) { Serial.println(Error connecting to MLX90614. Check wiring!); while (1); // 如果初始化失败程序停在这里 } Serial.println(MLX90614 Found!); // 超声波模块无需特别的初始化库内部处理了 } void loop() { // 1. 读取超声波距离 distanceCM ultrasonic.read(CM); // 读取距离单位厘米 delay(50); // 短延时稳定读数 // 2. 判断距离是否在有效范围内决定是否进行测温 if (distanceCM MIN_DISTANCE distanceCM MAX_DISTANCE) { // 距离合适进行红外测温 objectTempC mlx.readObjectTempC(); // 读取物体温度摄氏度 ambientTempC mlx.readAmbientTempC(); // 读取环境传感器自身温度 // 3. 通过串口输出结果 Serial.print(Distance: ); Serial.print(distanceCM); Serial.print( cm | ); Serial.print(Object Temp: ); Serial.print(objectTempC); Serial.print(°C | ); Serial.print(Ambient Temp: ); Serial.print(ambientTempC); Serial.println(°C); // 这里可以添加代码将数据显示到OLED屏上 // displayData(objectTempC, distanceCM); // 4. (可选) 简单的距离提示逻辑 if (distanceCM 5.0) { Serial.println(提示距离过近请稍远离以获得更准的‘点’温度。); } } else if (distanceCM MIN_DISTANCE) { Serial.println(物体太近了无法有效测量。); } else { Serial.println(物体太远了请靠近。); } delay(500); // 主循环延时控制测量频率每秒约2次 }代码关键点解析mlx.begin()这个函数不仅初始化I2C通信还会尝试与传感器握手。如果失败最常见的原因是I2C连线错误SDA/SCL接反、电源问题或传感器损坏。返回的错误信息能帮我们快速定位。mlx.readObjectTempC()这是核心函数它返回的是经过发射率校正后的物体温度。发射率默认是0.95。如果你想测量特定材料可以使用mlx.writeEmissivity(0.90)来修改参数范围0.1-1.0但请注意发射率写入传感器的EEPROM有写入次数限制不要频繁修改。距离判断逻辑代码中设置了一个MIN_DISTANCE和MAX_DISTANCE。太近如2cm可能超出传感器最小聚焦范围且物体可能堵塞传感器视场太远如15cm则视场过大容易受背景干扰。这个阈值可以根据你使用的MLX90614的具体型号视场角不同进行调整。延时控制loop()中的delay(500)控制了测量频率。MLX90614的转换时间很快但过于频繁的读取可能意义不大。500ms的间隔对于手持式测温仪来说比较合适。超声波模块的测量周期也需要几十毫秒所以主循环不宜过快。4.3 功能扩展添加OLED显示与声光反馈仅有串口输出显然不够实用。接下来我们为其添加一个0.96寸OLED显示屏I2C接口让测量结果直观可见。首先确保已安装Adafruit SSD1306和GFX库。然后在代码开头添加相关库和对象初始化#include Adafruit_GFX.h #include Adafruit_SSD1306.h #define SCREEN_WIDTH 128 #define SCREEN_HEIGHT 64 #define OLED_RESET -1 Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, Wire, OLED_RESET);在setup()函数中初始化显示屏if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { Serial.println(F(SSD1306 allocation failed)); for(;;); // 卡住 } display.display(); // 显示Adafruit的启动logo delay(2000); display.clearDisplay(); display.setTextSize(1); display.setTextColor(SSD1306_WHITE);然后创建一个显示函数在测温和测距完成后调用void displayData(float temp, float dist) { display.clearDisplay(); display.setCursor(0,0); display.print(Temp: ); display.print(temp, 1); // 显示一位小数 display.println( C); display.setCursor(0, 20); display.print(Dist: ); display.print(dist, 1); display.println( cm); // 距离状态提示 display.setCursor(0, 40); if(dist 5.0) { display.print(Too Close!); } else if (dist 10.0) { display.print(Good); } else { display.print(Too Far); } display.display(); // 将缓存内容刷到屏幕上 }在loop()函数中在串口打印的代码附近调用displayData(objectTempC, distanceCM);。更进一步可以添加一个蜂鸣器和LED。例如当测量到温度超过某个阈值如38.0°C时让蜂鸣器短鸣一声同时红色LED闪烁实现一个简单的发烧预警功能。这只需要在判断温度后用digitalWrite()控制对应的数字引脚即可。硬件上将蜂鸣器有源正极通过一个220Ω电阻接到一个数字引脚如D8负极接GNDLED同样串联一个220Ω电阻后接到另一个数字引脚如D9。5. 校准、测试与精度提升实战设备组装完成代码也跑通了但读出来的温度准不准这才是检验项目成功与否的最终标准。非接触红外测温的精度受多种因素影响我们不能指望它达到医疗级水准但通过一些方法可以使其在特定应用场景下足够可靠。5.1 初始验证与交叉比对首先进行一个简单的“黑体”测试。找一个已知温度、表面发射率较高的物体。最方便的就是一杯恒温的水。用一支精度较好的数字温度计最好是探针式的插入水中测量水的实际温度作为参考。等待几分钟让水温均匀同时确保水面平静无蒸汽蒸汽会影响红外测量。将你的Arduino测温仪传感器正对水面距离水面约3-5厘米读取显示的温度。比较两者读数。在室温环境下比如25°C左右对于一杯30-40°C的温水你的设备读数与参考温度计的差值在±1°C以内都可以认为是相当不错的。如果偏差较大比如超过2°C就需要进行以下排查和校准。5.2 影响精度的关键因素与应对策略发射率Emissivity这是最大的误差来源。MLX90614库默认发射率是0.95。对于绝大多数非金属、非光亮表面这个值是合理的。但如果你测量的是光亮金属如铝罐、不锈钢杯发射率可能低至0.1-0.2。直接测量会严重偏低。解决方法是在被测表面贴一小块电工胶布或涂一层哑光黑漆等待其温度与环境平衡后测量胶布或漆面的温度这时的发射率接近0.95。人体皮肤皮肤发射率约为0.98。你可以尝试在代码中将发射率设置为0.98使用mlx.writeEmissivity()函数注意慎用有写入寿命或者在后续数据处理中软件补偿。更稳妥的方法是通过“偏移量”校准。测量距离与视场如前所述距离太远视场FOV内包含背景物体会导致读数混合。最佳实践是固定一个测量距离比如5厘米并制作一个简单的物理卡尺或支架确保每次测量都在这个固定距离进行。这样可以将距离因素固定化简化校准。环境温度补偿MLX90614内部已经通过PTAT传感器进行了环境温度补偿。mlx.readAmbientTempC()读出的就是传感器芯片自身的温度。确保传感器不在发热源如Arduino板子的稳压芯片旁边并且有适当通风让环境温度读数准确这有助于提升物体温度的计算精度。传感器自身温度稳定性刚上电时传感器芯片本身可能未达到热平衡前几十秒的读数可能会有漂移。建议设备上电后预热1-2分钟再进行正式测量读数会稳定很多。5.3 软件校准偏移量修正法对于DIY项目最实用的校准方法是“两点偏移量”法。我们不轻易改动传感器内部的发射率参数而是在软件层面对读数进行加减补偿。找一个“低温”参考点测量一个已知低温物体比如放在室内一段时间的一瓶矿泉水温度接近室温用接触式温度计测得其精确温度例如T_low_ref 24.5°C。用你的设备在固定距离下测量得到读数T_low_read例如24.0°C。找一个“高温”参考点测量一个已知高温物体比如一杯热水同样用接触式温度计测得其温度T_high_ref例如45.2°C。用你的设备测量得到T_high_read例如44.5°C。计算偏移量这里假设误差在整个量程内是线性的对于小范围如20-50°C近似成立。可以计算一个平均偏移offset ( (T_low_ref - T_low_read) (T_high_ref - T_high_read) ) / 2。应用校准在代码中将最终显示的温度修正为T_corrected mlx.readObjectTempC() offset。例如上面例子中offset ((24.5-24.0)(45.2-44.5))/2 (0.50.7)/2 0.6°C。那么所有读数都加上0.6°C。这个方法能有效消除系统性的固定偏差。6. 外壳设计与实际应用场景拓展一个裸露着电路板和连线的设备既不安全也不实用。3D打印一个外壳是完美的解决方案。设计外壳时需要考虑以下几点传感器开孔为MLX90614的透镜和超声波传感器的收发头预留精确的圆形开孔。孔洞要干净避免有毛刺遮挡。显示屏开窗为OLED屏幕开一个矩形窗口可以用透明亚克力板覆盖保护。按键与接口预留一个按钮孔用于切换模式如物体/环境温度显示或启动测量。预留USB接口的开口方便供电和编程。散热与结构避免将Arduino板上的发热元件如稳压芯片紧贴外壳内壁。可以设计一些通风栅格。结构上要考虑电池仓如果想做成便携式的位置。设计工具可以使用免费的Fusion 360或Tinkercad。测量好所有元件的实际尺寸特别是安装孔位。可以在Thingiverse等网站搜索“Arduino Uno Case”、“MLX90614 case”寻找灵感或现成模型进行修改。应用场景举例3D打印机热床温度巡检将设备固定在打印头上定期移动测量热床不同位置的温度检查其加热均匀性。电子设备散热检查快速扫描电路板上芯片、MOS管等元件的温升情况排查过热点。家庭趣味应用测量开水、咖啡的温度注意不要有蒸汽遮挡测量宠物窝的温度甚至可以用来粗略比较阳光下和阴影处物体的温差。教学演示工具非常直观地展示非接触测温、红外辐射、I2C通信、超声波测距等物理和电子学概念。最后的几点心得在这个项目里电源去耦电容对稳定读数真的有奇效尤其是当你同时驱动屏幕和传感器时。MLX90614的读数偶尔跳变是正常的软件上可以做一点平滑滤波比如连续读5次取中位数。超声波模块在柔软表面如布料或复杂表面测距可能不准这是声波反射特性决定的在代码里要做好异常值过滤。这个项目最大的乐趣在于它从原理到实践是一条完整的链路你能亲手验证物理定律如何通过几块便宜的芯片和代码变成看得见摸得着的功能。
返回列表