基于行空板与MLX90614的红外测温传送枪DIY全流程解析

📅 2026/7/29 10:04:15
基于行空板与MLX90614的红外测温传送枪DIY全流程解析
1. 项目缘起当创意遇上开源硬件最近在整理工作室的物料翻出来一块闲置已久的行空板看着它集成的屏幕、按键和丰富的扩展接口总觉得不拿来做点有趣的东西有点浪费。正好手头还有一个之前做项目剩下的MLX90614非接触式红外测温模块一个大胆的想法就冒了出来能不能用它们造一个看起来像科幻电影里“传送枪”一样的测温设备不是那种严肃的工业测温仪而是带点游戏感和互动性的玩意儿拿在手里对着物体“biu”一下屏幕上就能显示出温度最好还能有点音效和动画。这个想法其实源于一个很实际的痛点。我经常需要快速测量一些电子元件、3D打印件或者咖啡杯表面的温度传统的手持测温枪虽然准但操作单一数据也不方便记录。而行空板本身就是一个运行着完整Linux系统、自带Python环境的微型电脑加上它的Wi-Fi和蓝牙功能完全有能力在完成基础测温的同时玩出更多花样——比如把数据实时上传到云端看曲线或者通过语音播报温度。用“传送枪”这个外壳来包装它不仅是为了酷更是想探索一下开源硬件如何能让一个简单的功能变得更有体验感和扩展性。所以这个项目本质上是一个软硬件结合的创意实现。核心是利用行空板作为主控和显示交互终端通过Python编程驱动红外测温传感器并将结果以直观、有趣的方式呈现出来。下面我就把从构思到实现的完整过程包括硬件连接、代码编写、外壳设计中的坑与收获毫无保留地分享出来。2. 核心硬件选型与连接逻辑要实现一个“测温传送枪”我们需要几样核心硬件负责计算和显示的行空板、负责感知温度的红外测温模块以及为整个系统供电的电源。选型不是随便抓一个就用每个选择背后都关系到项目的稳定性、精度和最终体验。2.1 为什么是行空板市面上能跑Python的单板计算机很多比如树莓派。但行空板在这个项目中有几个不可替代的优势高度集成开箱即用行空板自带一块分辨率不错的IPS屏幕、多个实体按键和一个麦克风。这意味着我们不需要额外连接显示器、键盘鼠标就能进行开发和交互极大简化了外设让“枪”的形态更紧凑。对Python和图形化编程友好它预装了基于Debian的系统并深度集成了Jupyter和PinPong库。PinPong库是一个对硬件IO输入输出进行高级封装的Python库让操作GPIO、I2C、UART等接口像调用普通函数一样简单非常适合快速原型开发。供电与接口设计合理它可以通过Type-C接口供电同时板载了锂电池管理芯片方便后续改为电池供电。其上的Gravity接口兼容PH2.0-4P直接提供了3.3V/5V电源、GND和信号线连接Gravity系列的传感器模块很多测温模块都是此接口无需焊接即插即用。2.2 测温模块的抉择MLX90614 vs 其他测温模块的选择直接决定了“枪”的感知能力。我手头有MLX90614这也是一个经过市场验证的选择。MLX90614这是一款通过I2C通信的非接触式红外测温芯片。它的优点在于测量相对准确出厂校准、响应速度快并且可以同时测量物体温度和自身环境温度即环境温度补偿。其I2C通信方式与行空板连接非常简单只需要四根线VCC, GND, SDA, SCL。与其他方案的对比热电偶/热电阻如PT100、NTC这些是接触式测温需要探头紧贴被测物。对于想做“隔空测温”的传送枪来说显然不适用。它们通常需要复杂的模拟电路如三线制、查表法来消除导线电阻和进行非线性校正硬件和软件复杂度都更高。其他红外模块有些更便宜的红外模块输出的是模拟电压或PWM信号需要行空板进行AD转换和复杂的计算校准精度和稳定性往往不如数字输出的MLX90614。因此选择MLX90614是基于项目需求非接触、快速、数字接口和开发便利性的平衡。它的精度对于日常定性观察和大多数DIY场景来说已经足够。2.3 硬件连接实战与避坑连接本身不复杂但有几个细节决定了第一次上电能否成功。物理连接将MLX90614模块的Gravity接口PH2.0-4P连接到行空板上任意一个标有I2C的Gravity端口。行空板的这些端口引脚定义是统一的黑色-GND红色-VCC通常是3.3V蓝色-SDA绿色-SCL。务必确认红线对准VCC接反可能烧毁模块。电源确认MLX90614的工作电压通常是3.3V。行空板的Gravity接口默认输出是3.3V还是5V需要查看具体板子的说明书。我的这块板子I2C口输出是3.3V正好匹配。如果不确定可以用万用表测量一下或者先从3.3V开始尝试。I2C地址识别这是第一个容易卡住的地方。MLX90614的默认I2C地址是0x5A。但有些模块可能因为制造商不同而略有差异。连接好后我们可以在行空板上运行一个简单的Python脚本来扫描I2C总线上的设备确认模块是否被正确识别。# i2c_scanner.py from pinpong.board import Board from pinpong.libs.dfrobot_mlx90614 import MLX90614 import time Board().begin() # 初始化行空板 # 扫描I2C设备 import smbus bus smbus.SMBus(1) # 行空板上I2C-1是常用的总线 for address in range(0x03, 0x78): try: bus.read_byte(address) print(fI2C device found at address: 0x{address:02X}) except OSError: pass运行这个脚本如果看到控制台输出类似I2C device found at address: 0x5A的信息恭喜你硬件连接成功。如果没有请依次检查接口是否插紧、电源电压、模块是否完好。3. 软件环境搭建与核心驱动硬件通了接下来就是让软件跑起来。行空板虽然预装了环境但我们还是需要针对性地安装和配置一些库。3.1 Python环境与依赖库安装行空板默认的Python版本可能是3.7或3.8这完全够用。我们需要确保pinpong库及其依赖已安装。通常行空板镜像已经内置但为了保险可以通过终端更新一下# 通过pip更新pinpong库它会自动处理相关依赖 sudo pip3 install -U pinpongpinpong库的强大之处在于它统一了不同硬件平台Arduino, micro:bit, 行空板等的API。对于MLX90614我们通常使用dfrobot_mlx90614这个驱动子库。如果pinpong安装后没有这个驱动可能需要单独安装厂商提供的库或者使用更通用的smbus库直接操作。幸运的是新版的pinpong通常包含了常用传感器驱动。3.2 编写基础测温脚本我们先写一个最基础的脚本验证传感器读数是否正常。# basic_temp_read.py from pinpong.board import Board from pinpong.libs.dfrobot_mlx90614 import MLX90614 import time # 初始化 Board().begin() # 创建传感器对象参数是I2C端口号行空板上通常是1 sensor MLX90614(bus_num1) try: while True: # 读取物体温度默认单位是摄氏度 obj_temp sensor.obj_temp # 读取环境温度 amb_temp sensor.amb_temp print(f物体温度: {obj_temp:.2f} °C) print(f环境温度: {amb_temp:.2f} °C) print(- * 20) time.sleep(1) # 每秒读取一次 except KeyboardInterrupt: print(程序停止)运行这个脚本你应该能在终端看到不断刷新的温度数据。用手靠近传感器物体温度应该会明显上升。这个简单的回环测试是后续所有复杂功能的基础。3.3 常见驱动问题排查如果运行上述脚本报错比如ModuleNotFoundError: No module named pinpong.libs.dfrobot_mlx90614说明这个特定驱动没有安装。这时我们有两条路使用通用smbus库这是更底层但更通用的方法。MLX90614有公开的通信协议。import smbus2 import time class MLX90614(): def __init__(self, address0x5A, bus1): self.address address self.bus smbus2.SMBus(bus) def read_temp(self, reg): # 读取两个字节的数据 data self.bus.read_i2c_block_data(self.address, reg, 3) temp (data[1] 8) | data[0] temp temp * 0.02 - 273.15 # 将原始数据转换为摄氏度 return temp def obj_temp(self): return self.read_temp(0x07) # 物体温度寄存器 def amb_temp(self): return self.read_temp(0x06) # 环境温度寄存器 # 使用 sensor MLX90614() print(sensor.obj_temp())寻找替代驱动在行空板的社区或PyPI上搜索mlx90614可能会有其他第三方库如Adafruit-MLX90614但可能需要根据行空板的I2C设置稍作调整。我建议新手先从尝试pinpong库开始如果不行再使用上面的通用类。这能让你理解传感器驱动的本质。4. 从命令行到图形界面打造“传送枪”UI在命令行看数字太枯燥了我们要把它变成“枪”的显示器。行空板预装了unihiker库这是一个基于tkinter的图形库特别针对其触摸屏进行了优化比直接使用tkinter更方便。4.1 设计UI布局想象一下传送枪的屏幕中间应该有一个巨大的、动态变化的温度数字周围有一些状态信息比如环境温度、电池电量后续可扩展底部或许有几个按钮比如切换单位°C/°F、锁定读数、查看历史记录。我们先搭建一个最简单的UI只显示物体温度。# gun_ui_basic.py from pinpong.board import Board from pinpong.libs.dfrobot_mlx90614 import MLX90614 import time from unihiker import GUI # 初始化硬件和UI Board().begin() sensor MLX90614(bus_num1) gui GUI() # 创建UI组件 # 大标题 title_label gui.draw_text(x120, y30, text红外测温传送枪, font_size20, colorblue) # 温度显示使用大字体 temp_text gui.draw_text(x120, y120, text--.- °C, font_size80, colorred) # 状态提示 status_label gui.draw_text(x120, y220, text瞄准目标..., font_size15, colorblack) # 更新温度的循环函数 def update_temperature(): try: obj_temp sensor.obj_temp # 更新温度文本 temp_text.config(textf{obj_temp:.1f} °C) # 根据温度改变颜色增加视觉效果 if obj_temp 40: temp_text.config(colordark red) elif obj_temp 20: temp_text.config(colorblue) else: temp_text.config(colorgreen) # 更新状态 status_label.config(textf环境温度: {sensor.amb_temp:.1f} °C) except Exception as e: status_label.config(textf读取错误: {e}) # 每隔500毫秒调用一次自己实现循环更新 gui.after(500, update_temperature) # 启动第一次更新 update_temperature() # 保持窗口运行 gui.mainloop()这段代码创建了一个持续更新的界面。gui.after()方法是非阻塞的定时器它比在while True循环里用time.sleep()更友好不会卡住UI线程。4.2 添加交互功能按钮与音效一个真正的“枪”应该有扳机。我们可以用行空板上的物理按键A/B键来模拟扳机实现“按下测温松开显示”的功能甚至配上音效。首先我们需要引入按键检测和播放声音的模块。# gun_ui_interactive.py from pinpong.board import Board, Pin from pinpong.libs.dfrobot_mlx90614 import MLX90614 import time from unihiker import GUI import pygame # 用于播放音效 # 初始化 Board().begin() sensor MLX90614(bus_num1) gui GUI() # 初始化Pygame混音器播放音效 pygame.mixer.init() # 加载一个音效文件需要提前将beep.wav等文件放到行空板上 try: beep_sound pygame.mixer.Sound(beep.wav) except: print(未找到音效文件将继续无声运行) beep_sound None # 初始化板载按键A假设作为扳机 trigger_button Pin(Pin.P23, Pin.IN) # P23对应行空板按键A具体引脚号需查手册 # UI组件 temp_text gui.draw_text(x120, y120, text就绪, font_size80, colorgray) status_label gui.draw_text(x120, y220, text按下A键测温, font_size15, colorblack) last_temp None def check_trigger(): global last_temp if trigger_button.read_digital() 0: # 按键被按下低电平有效 # 扳机按下开始测温 try: current_temp sensor.obj_temp temp_text.config(textf{current_temp:.1f} °C, colorred) last_temp current_temp status_label.config(text测量中...) # 播放音效 if beep_sound: beep_sound.play() except Exception as e: status_label.config(text传感器错误) else: # 扳机松开显示最后一次测量的温度 if last_temp: temp_text.config(textf{last_temp:.1f} °C, colorblue) status_label.config(text测量完成 (锁定)) else: temp_text.config(text就绪, colorgray) status_label.config(text按下A键测温) # 每隔100毫秒检查一次按键状态响应更快 gui.after(100, check_trigger) # 启动按键检测循环 check_trigger() gui.mainloop()现在你的“传送枪”就有了基本的交互逻辑按下按键发出“biu”的一声屏幕显示实时温度并变红松开按键温度锁定并变蓝。这种状态切换给了设备一种“武器”般的操作感。4.3 UI美化与数据可视化进阶基础功能有了我们可以进一步美化背景与图标使用gui.draw_image()加载一张科幻风格的背景图。在温度显示周围画一个准星图标。数据曲线利用unihiker的绘图功能在屏幕下方开辟一个小区域绘制最近一段时间温度变化的折线图。这需要维护一个固定长度的列表来存储历史数据。单位切换在屏幕角落添加一个触摸按钮点击后在摄氏度和华氏度之间切换。计算公式是华氏度 摄氏度 * 9/5 32。阈值报警设置一个高温报警阈值比如50°C当温度超过时屏幕闪烁红色边框或发出连续蜂鸣可以用板载蜂鸣器或播放不同音效。这些美化步骤会让项目从“能用的工具”变成“有趣的玩具”也是学习GUI编程和事件驱动编程的好例子。5. 结构设计与电源管理一个酷炫的“枪”不能只是一堆线材和裸露的电路板。我们需要考虑它的外壳和如何独立供电。5.1 外壳设计与建模对于DIY项目3D打印是最佳的外壳制作方式。设计时需要考虑以下几点固定位为行空板设计准确的卡槽确保屏幕露出按键可被按到。为MLX90614传感器设计一个前端的安装孔确保其红外透镜前方无遮挡注意很多塑料对远红外线是透明的但为了美观和防护可以开一个裸露的小窗。人体工学设计一个握把参考玩具枪或工具枪的造型让握持舒适。扳机位置要自然可以用一个杠杆机构连接外壳上的物理按钮和行空板的A键。散热与扩展行空板运行时会发热需要在主板区域设计通风孔。同时可以为未来的扩展比如增加一个激光指示器用于瞄准预留接口或空间。你可以使用Fusion 360、SolidWorks或免费的Tinkercad进行建模。测量好行空板和传感器模块的精确尺寸是关键第一步。如果不会3D建模也可以使用现成的塑料盒进行改造用热熔胶或螺丝固定内部元件虽然美观度打折扣但速度快。5.2 电池供电与低功耗考量要想真正“无线”必须使用电池。行空板可以通过其底部的锂电池接口连接一块3.7V的锂电池如常见的10400电池。板载的电源管理芯片PMIC会负责充电和升压供电。电池选型容量越大续航越长但重量和体积也越大。对于一个手持设备一块2000mAh-3000mAh的锂电池是比较平衡的选择。功耗优化行空板运行完整的Linux系统和图形界面功耗相对较高。为了延长续航我们可以从软件层面做一些优化屏幕亮度通过unihiker库的API调低屏幕亮度这是最有效的省电方式。息屏策略当一段时间没有操作时自动关闭屏幕显示进入休眠通过晃动设备或按下任意键唤醒。这需要用到板载的加速度计如果有或按键中断。关闭不必要服务如果不需要Wi-Fi和蓝牙可以在脚本中将其关闭。一个简单的息屏功能实现思路import time last_active_time time.time() SCREEN_TIMEOUT 30 # 30秒无操作息屏 def reset_screen_timer(eventNone): global last_active_time last_active_time time.time() # 如果屏幕是暗的则点亮 if not screen_on: wake_up_screen() # 绑定事件当触摸屏幕或按下按键时重置计时器 gui.bind_touch(reset_screen_timer) # 同样可以绑定物理按键事件... def check_screen_timeout(): global screen_on if screen_on and (time.time() - last_active_time SCREEN_TIMEOUT): turn_off_screen() # 调用GUI方法关闭背光 screen_on False gui.after(1000, check_screen_timeout) # 每秒检查一次5.3 装配与调试将所有部件装入外壳是最后一步也是最容易出问题的一步。绝缘处理确保所有电线接头都用热缩管或绝缘胶带包好防止短路。电池一定要固定牢固避免晃动导致接触不良。传感器校准MLX90614是出厂校准的但如果你发现读数与已知温度比如冰水混合物、沸水有系统性偏差可以在代码里加一个偏移量进行软件校准corrected_temp raw_temp offset。干扰排查装壳后如果发现测温不准或跳动大检查传感器窗口是否被灰尘或指纹污染。确保传感器附近没有热源如行空板的主芯片必要时可以用隔热材料做一下隔离。6. 功能扩展与网络应用基础版本完成后我们可以利用行空板的网络能力让它变得更智能。6.1 数据上传与可视化将测温数据上传到云端就可以在手机或电脑上远程查看历史记录和趋势图。这里以使用常见的物联网平台如SIoT、EasyIoT或简单的HTTP服务器为例。首先你需要确保行空板连接上了Wi-Fi。import network import time def connect_wifi(ssid, password): wlan network.WLAN(network.STA_IF) wlan.active(True) if not wlan.isconnected(): print(正在连接网络...) wlan.connect(ssid, password) # 等待连接最多10秒 for i in range(10): if wlan.isconnected(): break time.sleep(1) if wlan.isconnected(): print(网络连接成功:, wlan.ifconfig()) return True else: print(网络连接失败) return False # 在主程序中调用 connect_wifi(你的Wi-Fi名称, 你的密码)连接成功后我们可以定时将温度数据通过HTTP POST请求发送到服务器。import urequests import json def upload_to_server(temperature, sensor_idgun_001): url http://你的服务器地址/api/temperature # 替换为你的API地址 data { device_id: sensor_id, temp_c: temperature, timestamp: time.time() } try: response urequests.post(url, jsondata, timeout5) if response.status_code 200: print(数据上传成功) else: print(上传失败:, response.status_code) response.close() except Exception as e: print(上传请求异常:, e) # 在测温循环中调用 current_temp sensor.obj_temp upload_to_server(current_temp)服务器端可以用Python Flask、Node.js等快速搭建一个接收数据并存入数据库如SQLite或InfluxDB的服务再配合Grafana或简单的网页前端进行可视化展示。6.2 语音播报与更多传感器行空板板载了麦克风和扬声器接口我们可以很方便地添加语音播报功能。使用pyttsx3或edge-tts库在测量完成后用语音读出温度。import pyttsx3 # 初始化语音引擎 engine pyttsx3.init() engine.setProperty(rate, 150) # 语速 def speak_temperature(temp): text f当前温度 {temp:.1f} 摄氏度 engine.say(text) engine.runAndWait() # 在锁定温度后调用 speak_temperature(last_temp)你还可以集成更多传感器比如激光指示器用一个简单的激光头模块连接到另一个GPIO口在按下扳机时同时点亮激光提供一个可见的瞄准点。环境光传感器根据环境光线自动调节屏幕亮度。惯性测量单元IMU检测“枪”的移动姿态实现更有趣的交互比如甩动“枪”切换模式。7. 项目总结与避坑心得回顾整个“测温传送枪”的制作过程它不仅仅是一个简单的传感器应用更是一个涵盖了硬件连接、嵌入式编程、图形界面设计、结构设计和网络通信的综合性项目。下面分享几个我在实践中踩过的坑和总结的经验7.1 电源噪声导致的传感器读数跳动最初当我将行空板和传感器都由同一个移动电源供电时发现温度读数会在小数点后一位频繁跳动。即使对着一个恒温物体也是如此。排查后发现是行空板运行时特别是屏幕点亮、Wi-Fi工作时产生的电源噪声影响了传感器模拟电路的稳定性。解决方案电源隔离为传感器模块单独供电比如使用一块小容量的锂电池或经过LC滤波的独立稳压模块。软件滤波在代码中实现软件滤波算法。最简单的是移动平均滤波即连续读取N次比如10次然后取平均值作为最终输出。这能有效平滑随机干扰。def read_filtered_temp(sensor, n10): readings [] for _ in range(n): readings.append(sensor.obj_temp) time.sleep(0.01) # 短延时 return sum(readings) / n硬件滤波在传感器的电源引脚VCC和GND之间焊接一个10uF-100uF的电解电容和一个0.1uF的陶瓷电容可以很好地滤除高低频噪声。这是解决此类问题的根本硬件措施。7.2 GUI界面卡顿或无响应当在while True循环中频繁更新UI并执行其他阻塞操作如网络请求、复杂计算时界面很容易卡死。解决方案严格遵守事件驱动编程模型。使用gui.after()进行定时任务调度而不是阻塞主循环。将耗时的操作如网络上传放到单独的线程中执行但要注意多线程间数据共享的锁问题。对于行空板这种资源有限的设备网络操作最好使用异步库或确保设置超时。7.3 3D打印外壳的精度问题自己设计的外壳第一次打印出来常常会出现板子塞不进去或者按键按不到的情况。解决方案在设计软件中务必留出“公差”。对于需要紧密配合的卡槽单边留出0.2mm-0.3mm的间隙。对于按键孔要比实际按键尺寸大至少0.5mm。在正式打印前先用廉价材料如PLA打印一个“测试件”只打印关键部分验证尺寸无误后再用最终材料打印整体。7.4 项目代码的模块化与维护随着功能越来越多所有代码都写在一个文件里会变得难以阅读和维护。解决方案将代码模块化。例如sensor_driver.py封装所有与MLX90614通信的代码。gun_gui.py负责创建和管理所有UI组件。network_client.py处理Wi-Fi连接和数据上传。main.py主程序组织各个模块并处理主要逻辑。 这样不仅结构清晰也方便未来替换某个部件比如换用其他测温传感器。这个项目最有价值的地方不在于做出了一个多么精准的测温仪而在于完整地走通了一个创意产品从构思到实现的全流程。它展示了如何用行空板这样易用的开源硬件结合Python强大的生态快速将想法变为可交互、可扩展的实物。你可以在此基础上继续深化比如加入机器学习模型来识别不同材料的发射率并进行补偿或者做成一个网络化的多点温度监测系统。希望我的这些经验能帮你少走弯路更享受创造的乐趣。