基于Arduino与MLX90614的红外测温变色灯制作全攻略
2026/7/29 4:15:45 网站建设 项目流程

1. 项目缘起:从“会变色”到“懂温度”的创意跃迁

几年前,我在一个创客展上看到一个挺有意思的小玩意儿:一个LED灯,用手摸上去,它的颜色就会从蓝色慢慢变成红色。当时觉得挺酷,但仔细一想,这玩意儿其实是个“被动”的玩具——它只是感知了你的体温,然后做出反应。这让我琢磨,能不能做一个更“聪明”的灯?一个不仅能感知,还能主动“看见”周围温度变化,并据此改变颜色的灯。这就是“红外变色小灯”这个项目的起点。

简单来说,这个项目就是做一个能通过非接触方式探测物体表面温度,并用不同颜色的光来直观显示温度高低的小装置。它不再是简单的触摸变色,而是升级为“红外测温变色”。听起来好像很高科技,但其实核心原理并不复杂,用一些常见的电子元件就能实现。这个项目非常适合电子爱好者、创客新手,或者任何想给生活加点科技感和互动感的朋友。你可以用它来做个酷炫的桌面摆件,实时显示你水杯的温度;或者放在鱼缸旁,监测水温变化;甚至,可以把它当作一个简易的非接触式体温筛查装置的雏形来理解。接下来,我就把从构思到实现的完整过程,包括踩过的坑和总结的经验,毫无保留地分享出来。

2. 核心原理拆解:红外测温与PWM调色的跨界组合

要实现“红外测温变色”,我们需要解决两个核心问题:第一,如何非接触地测量温度;第二,如何将温度数值映射为可视的灯光颜色。这分别对应着两个关键技术:红外测温传感和PWM(脉冲宽度调制)调光。

2.1 红外测温传感器:如何“看见”温度?

我们生活中感受到的热,本质上是物体分子热运动产生的电磁波辐射。任何温度高于绝对零度(-273.15°C)的物体,都会向外辐射红外线。红外测温传感器,比如本项目会用到的MLX90614,它的“眼睛”就是一个对特定波长红外线敏感的热电堆探测器。

它工作的过程可以这样理解:传感器前方有一个菲涅尔透镜(就像老式投影仪里那种一圈圈纹路的透镜),这个透镜的作用是把一定范围内的红外辐射能量聚焦到探测器上。探测器将接收到的红外能量转换成微弱的电压信号。这个电压信号非常小,且容易受到环境干扰,所以传感器内部集成了一个低噪声放大器和一个17位的模数转换器(ADC),把模拟信号变成数字信号。最后,传感器内部还有一个强大的数字信号处理器(DSP),它根据一个复杂的物理模型(斯蒂芬-玻尔兹曼定律)和传感器自身的出厂校准数据,将这个数字信号换算成我们能够理解的温度值,并通过I2C或PWM接口输出。

这里有一个关键点:MLX90614这类传感器通常提供两个温度读数,一个是物体温度(TObj),一个是传感器自身的环境温度(TAmb)。计算物体温度时,需要环境温度作为补偿参数,以消除传感器自身发热对测量的影响。所以,它的测量是相对精准的,并非简单的“感觉热不热”。

2.2 RGB LED与PWM调色:如何用数字创造色彩?

我们的灯要能变色,最常用的就是RGB LED。它内部封装了红(Red)、绿(Green)、蓝(Blue)三个独立的发光芯片。根据光学三原色原理,通过调节这三种颜色光的混合比例,理论上可以合成出人眼可见的绝大部分颜色。

如何调节每种颜色的亮度呢?直接改变电压?那太粗糙了,而且控制电路复杂。这里就用上了PWM技术。PWM的本质不是调节电压大小,而是控制在一个固定周期内,电压处于高电平(比如5V)的时间比例(占空比)。如果这个周期非常短(比如1毫秒),高电平时间占50%,那么对于LED这种响应速度极快的器件来说,其效果就等同于用2.5V的电压驱动它,亮度就是最大亮度的一半。通过微控制器(如Arduino)快速、精确地调节红、绿、蓝三个通道各自的PWM占空比,我们就能混合出任意颜色和亮度。

那么,温度和颜色如何对应?这就是我们编程要实现的逻辑。我们可以设定一个温度区间,比如20°C到40°C。当传感器读到20°C时,我们让灯显示蓝色(R=0, G=0, B=255);读到40°C时,显示红色(R=255, G=0, B=0)。对于中间的温度值,比如30°C,我们就需要计算一个比例,让蓝色分量减少,红色分量增加,可能呈现出紫色(R=128, G=0, B=128)。这个映射关系(颜色渐变算法)是项目视觉效果的核心,后面会详细讲如何实现平滑的渐变。

3. 硬件选型与电路搭建:平衡精度、成本与易用性

硬件是整个项目的骨架,选型决定了项目的性能上限和制作难度。我的原则是在满足核心功能的前提下,尽量选择常见、易用、文档丰富的模块,降低入门门槛。

3.1 元器件清单与选型理由

下面这个表格列出了我最终采用的元件清单,并解释了为什么选它,以及有没有更便宜或更高级的替代方案。

元器件具体型号/规格数量选型理由与备选方案
主控板Arduino Nano1核心大脑。Nano体积小巧,引脚功能与UNO完全兼容,价格便宜,且有丰富的社区资源。对于本项目完全够用。备选:Arduino Uno(体积大)、ESP32(功能强但稍复杂)。
红外测温传感器MLX90614ESF-BCC (I2C接口)1项目核心。BCC版本测量精度为±0.5°C,距离系数比(D:S)为1:1,适合近距离(如5-10厘米)测量。I2C接口仅需两根信号线,接线简单。备选:MLX90614ESF-DCI(精度略低)、GY-906模块(已集成上拉电阻,更易用)。
RGB LED共阳极RGB LED (5mm)1显示单元。共阳极意味着三个阴极(R, G, B)分别控制,公共端接VCC。这种接法在与Arduino连接时,可以通过输出低电平来点亮,更符合常规思维。务必确认是共阳!
电阻220Ω 碳膜电阻3限流保护。每个LED通道必须串联一个,防止电流过大烧毁LED或Arduino引脚。220Ω是5V系统驱动普通LED的常用值。
面包板与杜邦线通用款若干用于原型搭建和测试。在最终定型后,可以考虑焊接万用板或定制PCB。
电源USB数据线/5V适配器1为整个系统供电。Arduino Nano可通过USB口直接供电,非常方便。

注意:购买MLX90614模块时,务必分清是I2C接口还是PWM接口。I2C版本更常见,编程也更灵活。模块上通常标有SCL、SDA引脚的就是I2C版本。

3.2 电路连接详解与原理图解读

接线是实操的第一步,接错了轻则不工作,重则烧元件。我们按照“电源-信号-地”的思路来梳理。

首先,给所有器件供上电。将Arduino Nano的5V引脚和GND引脚分别连接到面包板的电源正极轨和负极轨。这样,面包板上的所有VCCGND都可以从这两条轨上取电。

MLX90614传感器接线(I2C通信):

  • VIN-> 面包板5V
  • GND-> 面包板GND
  • SCL-> Arduino Nano的A5引脚(在Nano上,A4是SDA,A5是SCL,这是硬件I2C固定引脚)
  • SDA-> Arduino Nano的A4引脚

共阳极RGB LED接线(PWM控制):

  • 公共阳极(最长引脚)-> 面包板5V轨。这是关键!共阳LED的正极直接接电源。
  • 红色阴极(R)-> 串联一个220Ω电阻 -> Arduino Nano的D9引脚(这是一个支持PWM输出的引脚,标记为~9
  • 绿色阴极(G)-> 串联一个220Ω电阻 -> Arduino Nano的D10引脚(~10
  • 蓝色阴极(B)-> 串联一个220Ω电阻 -> Arduino Nano的D11引脚(~11

为什么阴极要接电阻再接Arduino引脚?因为当Arduino引脚设置为LOW(0V)时,LED两端形成电压差,电流从5V轨流过LED和电阻,流入Arduino引脚到地,从而点亮LED。电阻在这里限制了电流大小。当我们用PWM让引脚快速在HIGHLOW之间切换时,就实现了调光。

整个系统的数据流是这样的:MLX90614持续感知红外辐射,通过I2C总线将温度数据发送给Arduino。Arduino根据我们编写的程序,将温度值映射为对应的R、G、B亮度值,然后通过D9D10D11三个引脚输出特定占空比的PWM波,驱动RGB LED显示出对应的颜色。

4. 核心代码实现:从温度到色彩的平滑映射

硬件搭好了,接下来就是赋予它灵魂的代码。我们将使用Arduino IDE进行编程。首先需要安装必要的库,这对于使用现成模块至关重要。

4.1 库文件安装与传感器初始化

MLX90614有现成的优秀库Adafruit MLX90614 Library,它极大地简化了我们的操作。

  1. 打开Arduino IDE,点击工具->管理库...
  2. 在搜索框中输入“MLX90614”,找到由Adafruit提供的库,点击安装。
  3. 安装时,如果提示安装依赖库(如Adafruit BusIO),务必一并安装。

库安装好后,我们就可以开始编写代码了。代码的第一部分是引入头文件和初始化对象。

#include <Wire.h> // I2C通信必备库 #include <Adafruit_MLX90614.h> // 红外测温传感器库 Adafruit_MLX90614 mlx = Adafruit_MLX90614(); // 创建传感器对象 // 定义RGB LED连接的PWM引脚 const int redPin = 9; const int greenPin = 10; const int bluePin = 11; // 定义我们关心的温度范围(单位:摄氏度) float tempMin = 20.0; float tempMax = 40.0;

setup()函数中,我们需要初始化串口(用于调试输出)、初始化传感器、并将RGB引脚设置为输出模式。

void setup() { Serial.begin(9600); // 启动串口通信,方便查看数据 Serial.println("红外变色小灯启动中..."); // 尝试初始化MLX90614传感器 if (!mlx.begin()) { Serial.println("错误:未找到MLX90614传感器,请检查接线!"); while (1); // 如果初始化失败,程序停在这里 } Serial.println("MLX90614传感器初始化成功!"); // 设置RGB LED引脚为输出模式 pinMode(redPin, OUTPUT); pinMode(greenPin, OUTPUT); pinMode(bluePin, OUTPUT); // 初始化为灯灭状态(对于共阳LED,输出HIGH即关闭) digitalWrite(redPin, HIGH); digitalWrite(greenPin, HIGH); digitalWrite(bluePin, HIGH); }

4.2 温度读取与颜色映射算法

核心逻辑在loop()函数中循环执行。我们首先读取物体温度,然后将其映射到颜色。

void loop() { // 读取物体温度(单位摄氏度) float objectTemp = mlx.readObjectTempC(); // 也可以读取环境温度:float ambientTemp = mlx.readAmbientTempC(); // 通过串口监视器输出温度,用于调试 Serial.print("物体温度: "); Serial.print(objectTemp); Serial.println(" °C"); // 将温度映射为颜色 setColorByTemperature(objectTemp); delay(500); // 每500毫秒更新一次,避免数据刷新过快 }

最关键的函数是setColorByTemperature(float temp),它实现了从温度到颜色的转换。这里我采用了一种简单而有效的线性插值方法,实现从低温(蓝色)到高温(红色)的渐变,中间经过青色、绿色、黄色。

void setColorByTemperature(float temp) { int r, g, b; // 用于存储计算出的RGB值(0-255) // 将温度限制在我们定义的范围内 temp = constrain(temp, tempMin, tempMax); // 将温度映射到一个0.0到1.0的比例值 // map函数用于整数,这里我们手动计算浮点数比例 float ratio = (temp - tempMin) / (tempMax - tempMin); // 根据比例值,计算RGB分量 // 颜色过渡设计:蓝(0,0,255) -> 青(0,255,255) -> 绿(0,255,0) -> 黄(255,255,0) -> 红(255,0,0) if (ratio < 0.25) { // 阶段1: 蓝 -> 青 (增加绿色) r = 0; g = (int)(255 * (ratio / 0.25)); b = 255; } else if (ratio < 0.5) { // 阶段2: 青 -> 绿 (减少蓝色) r = 0; g = 255; b = (int)(255 * (1.0 - ((ratio - 0.25) / 0.25))); } else if (ratio < 0.75) { // 阶段3: 绿 -> 黄 (增加红色) r = (int)(255 * ((ratio - 0.5) / 0.25)); g = 255; b = 0; } else { // 阶段4: 黄 -> 红 (减少绿色) r = 255; g = (int)(255 * (1.0 - ((ratio - 0.75) / 0.25))); b = 0; } // 将计算出的RGB值,通过PWM输出到LED // 注意:对于共阳极LED,PWM值越高,实际亮度越暗,所以要用255减去计算值 analogWrite(redPin, 255 - r); analogWrite(greenPin, 255 - g); analogWrite(bluePin, 255 - b); // 调试输出RGB值 Serial.print("RGB: "); Serial.print(r); Serial.print(", "); Serial.print(g); Serial.print(", "); Serial.print(b); Serial.println(); }

这段代码的逻辑是:先将温度归一化到0-1之间。然后把这个范围分成四段,分别对应蓝-青、青-绿、绿-黄、黄-红四个渐变区间。在每个区间内,对变化的颜色分量进行线性插值。这样得到的颜色变化是平滑且符合直觉的。最后,因为驱动的是共阳极LED,analogWrite的值是“低电平有效”的占空比,所以需要用255 - 计算值

5. 调试、校准与效果优化实战

把代码上传到Arduino后,小灯应该就能工作了。但要让它的表现更精准、更稳定,还需要一些调试和优化步骤。

5.1 串口监视器:你的第一双“调试之眼”

上传代码后,打开Arduino IDE的工具->串口监视器(快捷键Ctrl+Shift+M)。确保右下角波特率设置为9600。你会看到温度数据和RGB值在不断打印。

这时,你可以用手靠近传感器(注意不要触摸,避免污染和静电),观察温度值的变化是否灵敏,以及RGB数值的变化是否符合预期(温度升高,r值增大,b值减小)。这是排查硬件连接和基础逻辑问题最直接的方法。如果看不到数据,首先检查USB线是否连接稳定,然后检查代码中Serial.begin(9600)的波特率是否与监视器设置一致。

5.2 传感器校准与测量精度提升

MLX90614出厂已校准,但在不同环境下仍有误差。影响精度的主要因素有两个:发射率测量距离/角度

发射率:物体表面辐射红外线的能力。MLX90614默认发射率设置为0.95,这是针对大多数有机材料和氧化表面的典型值。但如果你测量的是光亮的金属(如铝箔),其发射率可能低至0.1以下,会导致读数严重偏低。对于这类物体,需要查找其材料的标准发射率值,并通过库函数进行设置(mlx.writeEmissivity(0.23)),但这通常需要更专业的应用场景。对于我们这个创意项目,主要测量手、杯子、书本等常见物体,默认值已足够。

测量距离与角度:传感器有一个视场角(FOV)。以D:S=1:1的传感器为例,在10厘米距离处,它测量的约是直径10厘米的圆形区域的平均温度,而不是一个点。因此,要测量小物体(如指尖)的温度,必须靠近。同时,应尽量让被测物体表面垂直于传感器透镜,倾斜角度过大会导致接收到的红外能量减少,读数偏低。

一个实用的校准方法是:用一个已知准确温度的温度计(如酒精温度计)测量一杯温水的温度,然后将传感器对准水面(距离2-3厘米),比较串口读数和温度计读数。如果存在固定偏差,可以在代码中对读取的温度值进行偏移补偿,例如:float objectTemp = mlx.readObjectTempC() + 0.5; // 假设普遍偏低0.5度

5.3 灯光效果优化:从生硬跳变到柔和渐变

你可能会发现,灯的颜色变化有时有点“跳”,不够平滑。这有几个优化方向:

  1. 增加PWM分辨率:Arduino Nano的analogWrite默认是8位PWM(0-255)。对于颜色渐变,256级有时略显粗糙。可以考虑使用定时器设置更高精度的PWM,但这会复杂很多。一个更简单的办法是软件平滑
  2. 软件平滑滤波:温度读数可能会有微小波动,导致颜色频繁轻微闪烁。我们可以对温度值进行平滑处理,比如取最近几次读数的平均值。
    const int numReadings = 5; float readings[numReadings]; int readIndex = 0; float total = 0; float average = 0; void loop() { total = total - readings[readIndex]; // 减去最旧的读数 readings[readIndex] = mlx.readObjectTempC(); // 读取新值 total = total + readings[readIndex]; // 加上最新读数 readIndex = (readIndex + 1) % numReadings; // 循环索引 average = total / numReadings; // 计算平均值 setColorByTemperature(average); // 使用平滑后的温度 delay(100); // 采样间隔可以更短 }
    setup()中需要初始化readings数组为0。这样,颜色变化就会稳定很多。
  3. 非线性映射与色彩空间:我们之前的线性映射虽然简单,但在某些色彩区间过渡可能不自然。更高级的做法是使用HSL(色相、饱和度、亮度)或HSV色彩空间。你可以将温度直接映射到色相(Hue,0-360度),饱和度和亮度固定,这样能获得非常平滑的彩虹渐变。这需要额外的色彩空间转换函数,代码会复杂一些,但视觉效果提升显著。

6. 项目进阶与扩展思路

一个基础版本完成后,我们可以从多个方向对它进行升级,让它变得更实用、更智能。

6.1 硬件扩展:增加交互与显示

  • 添加OLED显示屏:一个0.96寸的I2C OLED屏幕成本很低,但能极大提升实用性。可以在屏幕上实时显示精确的温度数值、颜色对应的温度区间,甚至绘制一个简单的温度变化曲线。接线只需将屏幕的SCL、SDA也接到Arduino的A5、A4(与传感器共享I2C总线),VCC和GND接好即可。
  • 加入蜂鸣器报警:定义某个温度阈值(如高于38°C),当检测到温度超过阈值时,不仅灯变红色,还可以让蜂鸣器发出警报声。这使它从一个显示装置变成了一个报警装置。
  • 改用WS2812B智能LED:如果你觉得一个RGB灯不够炫,可以换用WS2812B灯带或灯环。这种LED内部集成了控制芯片,只需要一根信号线就能控制上百个灯珠,每个都可以独立设置颜色。你可以用一条灯带做成温度计的样子,低温端蓝色,高温端红色,中间渐变,视觉效果会非常震撼。编程上需要使用Adafruit_NeoPixel库。

6.2 软件逻辑升级:更智能的“行为”

  • 模式切换:通过一个按钮,可以在不同显示模式间切换。比如模式一:实时温度颜色映射;模式二:最高/最低温度记录与显示;模式三:颜色呼吸灯效果(暂停测温)。
  • 温度日志:搭配一个SD卡模块,可以将带有时间戳的温度数据记录到存储卡中,用于后续的简单数据分析,比如监控一天内房间某个角落的温度变化。
  • 无线传输与远程监控:将主控换成ESP8266或ESP32,接入Wi-Fi。你可以把实时温度数据上传到物联网平台(如Blynk、ThingsBoard),或者在手机APP上远程查看温度和控制灯光。这相当于把你的小灯接入了智能家居网络。

6.3 外壳设计与应用场景挖掘

一个好看的外壳能让项目从“实验品”变成“产品”。可以用3D打印设计一个外壳,将传感器透镜露出来,LED灯部分做成柔光罩(可以用磨砂亚克力或者乳白色的塑料片),让光线更柔和。外壳上可以开孔固定USB接口和可能的按钮。

关于应用场景,除了开头提到的,还可以:

  • 厨房助手:放在厨房,对准锅具,灯光颜色快速提醒你锅温是否合适(低温蓝色适合融化黄油,高温红色表示油已热可下菜)。
  • 创意互动艺术:将多个这样的灯组成阵列,放在展馆,当不同体温的观众走过时,形成一片随人群流动而变化的色彩波浪。
  • 宠物关怀:安装在宠物窝附近,监控窝内温度,确保毛孩子不会着凉或中暑。

这个项目的魅力在于,它从一个简单的想法出发,通过硬件拼接和软件编程,创造出了一个能感知物理世界并与之互动的智能节点。它涉及了传感器技术、微控制器编程、电路基础、色彩理论等多个领域的入门知识,是一个绝佳的综合性学习项目。希望我的这些分享,能帮你顺利点亮属于你自己的那盏“懂温度”的变色小灯。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询