树莓派+MLX90614红外测温:低成本防疫监控系统实战 1. 项目缘起一个被“遗忘”的测温需求去年冬天我负责的一个小型线下活动场地因为防疫要求需要在入口处安排专人进行体温检测。这活儿听起来简单但实际操作起来问题一大堆手持测温枪需要人一直举着数据全靠手抄遇到体温异常者还得临时找人、打电话层层上报流程繁琐效率低下而且记录容易丢失。更头疼的是这个岗位需要人一直盯着枯燥且容易出错。当时我就想能不能做个“无人值守”的智能测温点核心需求很明确非接触、自动测量、异常自动告警、数据可追溯。市面上成熟的商业解决方案要么太贵要么功能臃肿不适合我们这种小场景。于是我把目光投向了手边的树莓派Raspberry Pi和一些传感器模块。最终我用树莓派、MLX90614红外测温传感器和Python搭建了一个成本不到300元、能自动发送邮件通知的防疫测温装置。它安静地挂在入口处有人经过时自动测温体温正常绿灯亮体温异常则红灯闪烁并立即向指定邮箱发送告警邮件所有数据连同时间戳都记录在本地CSV文件里。这个项目并不复杂但完美解决了“最后一米”的自动化监控问题。今天我就把这个从硬件选型、电路连接、代码编写到实际部署的完整过程拆解出来。无论你是想复现一个类似装置还是学习如何将树莓派、Python和硬件传感器结合解决实际问题这篇内容都会给你提供清晰的路径和避坑指南。2. 核心硬件选型与电路连接为什么是它们一套稳定可靠的硬件是项目基石。这个项目的硬件清单非常精简但每一件都经过深思熟虑。2.1 主控板Raspberry Pi 4B/3B 的权衡主控板首选树莓派这是创客领域的“瑞士军刀”。我手头有Pi 4B和更老的Pi 3B。对于这个项目两者皆可但有些细微差别。树莓派4B性能更强有USB 3.0接口如果未来想扩展摄像头进行人脸检测或接入更复杂的应用它有充足的余量。但功耗和发热也略高。树莓派3B性能完全足够驱动一个传感器和运行Python脚本功耗更低更稳定。对于单纯的测温通知任务它是性价比更高的选择。注意如果你用的是树莓派Zero系列虽然更小巧便宜但需要额外购买USB Hub或焊接排针来连接传感器对新手不友好且GPIO通用输入输出引脚电流驱动能力较弱直接驱动LED需谨慎。因此建议初学者从3B或4B开始。最终我选择了树莓派3B理由很简单项目功能单一稳定性和低功耗优先且3B的GPIO驱动能力足够。2.2 测温传感器MLX90614 的非接触原理这是项目的核心“眼睛”。为什么选MLX90614而不是更便宜的DS18B20接触式或其他红外模块非接触安全防疫测温必须非接触避免交叉感染。MLX90614通过检测人体辐射的红外能量来测温距离通常在2-5厘米内效果最佳。精度尚可在室温环境下针对人体体温范围35-42°C其典型精度可达±0.5°C完全满足防疫初筛要求。它出厂前已校准无需用户再次校准。数字接口它通过I2C总线与树莓派通信只需要两根数据线SDA, SCL编程简单抗干扰能力比模拟传感器强。MLX90614有两种测量值物体温度TObject和环境温度TAmbient。我们关心的是物体温度即人的体表温度。需要注意的是体表温度通常比腋下或口腔等核心体温低1-2°C所以我们的告警阈值要相应调整例如设置体表温度≥37.3°C为异常。2.3 辅助元件LED与电阻的“配角”戏份LED指示灯我用了一个绿色LED和一个红色LED。绿色代表体温正常红色代表体温异常。这是给人最直观的反馈。如果没有LED当邮件发送延迟或失败时现场人员无法立即知晓结果。220Ω 限流电阻这是保护LED和树莓派GPIO口的关键树莓派GPIO引脚最大输出电流约16mA而LED的工作电流一般在20mA左右。直接连接会烧毁LED或损坏GPIO引脚。串联一个220Ω的电阻可以将电流限制在安全范围内约 (3.3V - LED压降) / 220Ω ≈ 10mA。杜邦线用于连接建议使用母对母的杜邦线。面包板用于临时搭建和测试电路非常方便。2.4 电路连接实战GPIO引脚图就是地图连接电路前务必找到你的树莓派型号的GPIO引脚图。树莓派3B/4B的40针GPIO引脚排列是标准的。以下是具体的连接方案元件连接至树莓派GPIO引脚说明MLX90614 VCCPin 1 (3.3V)绝对不要接5V会烧坏传感器。MLX90614 GNDPin 6 (GND)接地。MLX90614 SDAPin 3 (GPIO2, SDA)I2C数据线。MLX90614 SCLPin 5 (GPIO3, SCL)I2C时钟线。绿色LED 长脚(阳极)通过220Ω电阻接 Pin 11 (GPIO17)需串联电阻。绿色LED 短脚(阴极)Pin 9 (GND)直接接地。红色LED 长脚(阳极)通过220Ω电阻接 Pin 13 (GPIO27)需串联电阻。红色LED 短脚(阴极)Pin 14 (GND)直接接地。连接关键点电源确认MLX90614务必接3.3VPin 1。接5VPin 2或4瞬间报废。电阻位置电阻串联在LED阳极和GPIO引脚之间或串联在LED阴极和GND之间均可。我习惯放在阳极侧。LED极性长脚是阳极接GPIO短脚是阴极-接GND。接反了不亮。共地确保传感器和LED的GND都连接到树莓派的GND引脚上形成共同的参考零电位。连接好后硬件部分就准备好了。接下来是让树莓派“认识”这些硬件。3. 软件环境搭建与I2C通信调试树莓派默认系统是Raspberry Pi OS以前叫Raspbian。我们需要开启I2C接口并安装必要的Python库。3.1 系统配置开启硬件接口的“开关”在终端中执行以下命令sudo raspi-config这是一个图形化配置工具。依次选择Interface Options-I2C-Yes启用I2C驱动。同样在Interface Options里可以确认SSH已启用方便远程操作。退出raspi-config后建议更新一下软件包列表并升级现有软件sudo apt update sudo apt upgrade -y然后安装Python包管理工具pip和I2C工具sudo apt install python3-pip i2c-tools -y3.2 检测传感器与MLX90614“握手”安装i2c-tools后我们可以用它来探测连接到I2C总线上的设备。首先你需要知道你的树莓派使用的是哪个I2C总线。树莓派3B/4B通常有两个I2C总线i2c-0和i2c-1。GPIO引脚上的SDA/SCL对应的是i2c-1。运行探测命令sudo i2cdetect -y 1如果看到类似下面的输出就说明连接成功0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- 5A --这里的0x5A就是MLX90614默认的I2C设备地址。如果你看到的是--请检查1) 接线是否正确特别是VCC和GND2) I2C是否已启用3) 传感器是否完好。3.3 Python库安装装备我们的“武器库”我们需要两个核心Python库smbus2或smbus用于通过Python代码进行I2C通信。smbus2是更新、更活跃的版本。MLX90614库有现成的库封装了与MLX90614通信的底层协议让我们可以用一两行代码就读出温度值。当然你也可以直接用smbus2根据数据手册读写寄存器但用库更快捷。安装命令pip3 install smbus2 pip3 install PyMLX90614这里注意库名可能是PyMLX90614或mlx90614具体取决于作者。安装前可以pip3 search mlx90614搜索一下。我使用的是PyMLX90614。至此软硬件环境就绪。我们可以写一个简单的测试脚本验证传感器和LED是否工作正常。4. 核心代码实现从测温到邮件通知的完整链路整个项目的逻辑流非常清晰初始化 - 循环测温 - 判断 - 本地记录 - 控制LED - 条件触发邮件告警。我们将分模块构建这个系统。4.1 基础测温与LED控制首先我们创建一个名为temperature_monitor.py的Python脚本实现最基础的功能。#!/usr/bin/env python3 # -*- coding: utf-8 -*- import time import board import busio import adafruit_mlx90614 import RPi.GPIO as GPIO from datetime import datetime # 1. GPIO引脚设置 LED_GREEN 17 LED_RED 27 GPIO.setmode(GPIO.BCM) # 使用BCM编号模式 GPIO.setup(LED_GREEN, GPIO.OUT) GPIO.setup(LED_RED, GPIO.OUT) # 初始化时关闭所有LED GPIO.output(LED_GREEN, GPIO.LOW) GPIO.output(LED_RED, GPIO.LOW) # 2. 初始化MLX90614传感器 # 创建I2C总线对象SDAGPIO2, SCLGPIO3 i2c busio.I2C(board.SCL, board.SDA) mlx adafruit_mlx90614.MLX90614(i2c) # 3. 体温异常阈值体表温度单位摄氏度 FEVER_THRESHOLD 37.3 # 4. 数据记录函数 def log_temperature(temp_obj, status): timestamp datetime.now().strftime(%Y-%m-%d %H:%M:%S) log_entry f{timestamp}, {temp_obj:.2f}, {status}\n with open(/home/pi/temperature_log.csv, a) as f: f.write(log_entry) print(log_entry.strip()) # 同时在终端打印 # 5. LED控制函数 def set_leds(normalFalse, warningFalse): GPIO.output(LED_GREEN, GPIO.HIGH if normal else GPIO.LOW) GPIO.output(LED_RED, GPIO.HIGH if warning else GPIO.LOW) try: print(防疫测温系统启动...按CtrlC终止。) while True: # 读取物体温度目标温度 temp_object mlx.object_temperature # 也可以读取环境温度mlx.ambient_temperature status NORMAL if temp_object FEVER_THRESHOLD: status FEVER set_leds(normalFalse, warningTrue) # 这里后续会加入邮件发送 print(f警告检测到异常体温{temp_object:.2f}°C) else: set_leds(normalTrue, warningFalse) # 记录数据 log_temperature(temp_object, status) # 每秒测量一次 time.sleep(1) except KeyboardInterrupt: print(\n程序被用户中断。) finally: # 清理GPIO资源非常重要 GPIO.cleanup() print(GPIO已清理程序退出。)代码要点解析GPIO.setmode(GPIO.BCM)设置GPIO引脚编号模式为BCM。这是树莓派上最常用的模式引脚号对应的是芯片的GPIO编号而不是物理引脚顺序。adafruit_mlx90614这是一个由Adafruit维护的库用法非常简洁。你需要先pip3 install adafruit-circuitpython-mlx90614。如果安装失败可能需要先安装一些系统依赖sudo apt install python3-pip libatlas-base-dev。finally块中的GPIO.cleanup()这是良好编程习惯。确保程序无论正常结束还是异常退出都会释放GPIO引脚将其设置为安全状态输入模式避免下次运行时引脚状态冲突。运行这个脚本(python3 temperature_monitor.py)你应该能看到终端打印温度并且当用手靠近传感器使温度超过37.3°C时红色LED亮起绿色LED熄灭。4.2 集成邮件通知功能SMTP协议实战当检测到异常体温时我们需要自动发送邮件。Python内置了smtplib库来处理邮件发送。这里以QQ邮箱的SMTP服务为例其他邮箱163、Gmail等原理类似只是服务器地址和端口不同。首先你需要开启邮箱的SMTP服务并获取授权码。以QQ邮箱为例登录网页版QQ邮箱 - 设置 - 账户 - 开启“POP3/SMTP服务” - 生成授权码这是一串字母数字组合代替你的邮箱密码用于第三方登录。然后我们在代码中添加邮件发送模块import smtplib from email.mime.text import MIMEText from email.header import Header # 邮件配置替换为你的实际信息 SMTP_SERVER smtp.qq.com SMTP_PORT 465 # QQ邮箱SSL端口 SENDER_EMAIL your_emailqq.com SENDER_AUTH_CODE your_authorization_code # 注意是授权码不是邮箱密码 RECEIVER_EMAIL receiverexample.com # 可以是一个列表发送给多人 def send_alert_email(temp_value): 发送体温异常告警邮件 subject f[防疫告警] 检测到异常体温{temp_value:.2f}°C # 邮件正文内容 body f 时间{datetime.now().strftime(%Y-%m-%d %H:%M:%S)} 地点入口测温点 检测结果体温异常 测量值{temp_value:.2f}°C 阈值{FEVER_THRESHOLD}°C 请相关工作人员及时处理。 # 构建MIME邮件对象 message MIMEText(body, plain, utf-8) message[From] Header(f防疫测温系统 {SENDER_EMAIL}, utf-8) message[To] Header(RECEIVER_EMAIL, utf-8) message[Subject] Header(subject, utf-8) try: # 建立SSL安全连接 with smtplib.SMTP_SSL(SMTP_SERVER, SMTP_PORT) as server: server.login(SENDER_EMAIL, SENDER_AUTH_CODE) server.sendmail(SENDER_EMAIL, [RECEIVER_EMAIL], message.as_string()) print(f告警邮件已发送至 {RECEIVER_EMAIL}) return True except Exception as e: print(f邮件发送失败: {e}) # 这里可以加入失败重试逻辑或者记录到日志文件 return False接下来修改主循环中的告警部分调用邮件发送函数if temp_object FEVER_THRESHOLD: status FEVER set_leds(normalFalse, warningTrue) # 发送告警邮件 send_alert_email(temp_object) print(f警告检测到异常体温{temp_object:.2f}°C)重要安全提示千万不要将包含真实授权码的代码上传到公开的代码仓库如GitHub。最佳实践是将敏感配置邮箱、授权码、接收人写入一个单独的配置文件如config.py或settings.json并在.gitignore中忽略这个文件。或者使用环境变量来存储。4.3 防误报与状态保持优化在实际部署中我们遇到了一个问题人只是快速挥手经过传感器可能捕捉到一个瞬间的高值比如碰到了热源反射导致误报警。我们需要加入简单的防抖逻辑。另外当检测到异常后红色LED常亮可能不够醒目。我们可以让它闪烁。同时为了避免在短时间内因同一人连续触发多次邮件轰炸需要加入状态保持和延时。改进后的主循环逻辑如下# 在循环外定义状态变量 fever_detected False last_alert_time 0 ALERT_COOLDOWN 300 # 同一事件告警冷却时间单位秒5分钟 try: print(防疫测温系统启动...按CtrlC终止。) while True: temp_object mlx.object_temperature current_time time.time() is_fever_now temp_object FEVER_THRESHOLD # 状态判断与LED控制 if is_fever_now: status FEVER if not fever_detected: # 首次进入发烧状态 fever_detected True fever_start_time current_time print(f进入异常体温状态{temp_object:.2f}°C) # 控制红灯闪烁 if int(current_time) % 2 0: # 简单闪烁1秒周期 GPIO.output(LED_RED, GPIO.HIGH) else: GPIO.output(LED_RED, GPIO.LOW) GPIO.output(LED_GREEN, GPIO.LOW) # 发送告警邮件带冷却时间判断 if current_time - last_alert_time ALERT_COOLDOWN: if send_alert_email(temp_object): last_alert_time current_time else: # 邮件发送失败可以尝试记录或增加其他通知方式 pass else: # 体温正常 status NORMAL if fever_detected: # 从发烧状态恢复 fever_detected False print(f体温恢复正常。) # 绿灯常亮 GPIO.output(LED_GREEN, GPIO.HIGH) GPIO.output(LED_RED, GPIO.LOW) # 记录数据每次循环都记录 log_temperature(temp_object, status) time.sleep(0.5) # 提高检测频率到0.5秒一次 except KeyboardInterrupt: print(\n程序被用户中断。) finally: GPIO.cleanup()这段代码实现了状态机用fever_detected变量记录是否处于持续异常状态。LED闪烁在异常状态下红色LED以1秒为周期闪烁更醒目。告警冷却用last_alert_time和ALERT_COOLDOWN确保不会在短时间内重复发送邮件。冷却时间可以根据需要调整。5. 系统部署、优化与问题排查代码跑通只是第一步要让它在树莓派上稳定、可靠地作为后台服务运行还需要做一些部署和优化工作。5.1 开机自启动让服务“永生”我们不想每次树莓派重启后都手动登录去运行Python脚本。有几种方法实现开机自启这里推荐使用systemd服务这是最标准、最易于管理的方式。创建一个服务单元文件sudo nano /etc/systemd/system/covid-thermometer.service写入以下内容根据你的实际路径修改[Unit] DescriptionAnti-COVID Thermometer Service Afternetwork.target multi-user.target [Service] Typesimple Userpi WorkingDirectory/home/pi ExecStart/usr/bin/python3 /home/pi/temperature_monitor.py Restarton-failure RestartSec10 [Install] WantedBymulti-user.target保存退出CtrlX, 然后Y, 然后回车。重新加载systemd配置启用并启动服务sudo systemctl daemon-reload sudo systemctl enable covid-thermometer.service sudo systemctl start covid-thermometer.service检查服务状态sudo systemctl status covid-thermometer.service如果看到active (running)说明服务已成功在后台运行。你可以用sudo journalctl -u covid-thermometer.service -f来实时查看日志。5.2 性能与稳定性优化降低CPU占用我们的主循环里有一个time.sleep(0.5)。对于测温应用0.5秒甚至1秒的间隔完全足够没必要太快。过短的间隔会导致Python进程空转增加不必要的CPU负载。可以调整为time.sleep(1)。异常处理增强在try块内部可以捕获更具体的异常比如I2C读取错误并进行相应处理例如记录日志、尝试重新初始化传感器而不是让整个程序崩溃。日志轮转temperature_log.csv文件会不断增长。可以修改log_temperature函数或者使用Linux的logrotate工具按日期或大小分割日志文件避免单个文件过大。5.3 常见问题与排查指南在实际部署中你可能会遇到以下问题问题1运行脚本时报错ModuleNotFoundError: No module named board或adafruit_mlx90614原因Python库没有安装或者安装在了错误的Python环境比如系统Python vs 用户Python。解决确认安装命令使用了pip3pip3 install adafruit-circuitpython-mlx90614。如果还不行尝试用绝对路径/usr/bin/python3 -m pip install adafruit-circuitpython-mlx90614。对于board模块它通常是adafruit-blinka库的一部分这是一个用于在树莓派上模拟CircuitPython的库。安装pip3 install adafruit-blinka。问题2传感器读数不稳定偶尔跳变很大原因电气干扰杜邦线过长或接触不良。尽量使用短线并确保插接牢固。电源噪声树莓派的3.3V电源带载能力有限如果连接了其他大电流设备可能造成波动。尝试单独给传感器供电仍需共地。环境干扰传感器视场内有其他热源如阳光直射、暖气、灯光。测量距离/角度不当MLX90614需要正对目标且距离在建议范围内2-5cm。解决在代码中加入软件滤波。例如连续读取5次去掉最高最低值后取平均。检查硬件连接使用带屏蔽的线或缩短连接线。为传感器制作一个简单的遮光筒限制其视场只接收正前方的红外辐射。问题3邮件发送失败报错ssl.SSLError或smtplib.SMTPAuthenticationError原因ssl.SSLError通常是网络问题或服务器证书验证失败。可以尝试将SMTP_SSL换成SMTP并使用starttls()但安全性稍差。SMTPAuthenticationError99%是账号或授权码错误。请仔细检查发送邮箱地址是否正确。是否使用了授权码16位字符串而不是邮箱登录密码。SMTP服务器地址和端口是否正确QQ邮箱是smtp.qq.com:465/587。解决先在电脑上用Python脚本或邮件客户端测试邮箱配置是否正确。检查树莓派系统时间是否正确。错误的系统时间可能导致SSL证书验证失败。运行date命令查看如果不准可以设置NTP同步sudo timedatectl set-ntp true。问题4GPIO控制LED时灯不亮或非常暗原因LED极性接反长脚阳极必须接GPIO通过电阻短脚阴极接GND。电阻值过大如果用成了1kΩ或更大的电阻电流会太小LED发光微弱。220Ω-330Ω是常用值。GPIO引脚模式错误确保使用了GPIO.setup(pin, GPIO.OUT)设置为输出模式。代码逻辑错误检查GPIO.output(pin, GPIO.HIGH)是否确实被执行了。解决用万用表测量GPIO引脚在输出HIGH时的电压应为3.3V左右。如果电压正常但LED不亮肯定是LED或电阻坏了或者电路不通。这个项目从想法到落地最难的部分往往不是代码本身而是硬件环境的稳定性和实际部署中的细节打磨。比如给树莓派和传感器做一个合适的外壳既能保护电路又能固定传感器的测量距离和角度再比如将系统配置成真正的“无头模式”不接显示器键盘只通过SSH管理并做好断电恢复。这些工程化的思考才是将一个原型变成可靠产品的关键。