这台树莓派5,我在工位上跑得好好的。跑YOLOv5推理、刷Ubuntu、连屏调参,手感丝滑。结果真把它装进车间设备柜,连续踩了一整天的坑。重启、掉帧、断连、掉系统,每一步都卡得人头疼。
这篇文章就把我在车间里被卡住的六件事完整写一遍。供电、散热、系统选型、模型部署、远程运维、掉电恢复,每件事我都会把排查过程、原理分析和最终的解决配置贴出来。不管你是打算把树莓派5搬进产线做视觉质检,还是只是想在一个恶劣环境里稳定跑AI推理,这篇都值得从头到尾看一遍。尤其是“自训YOLOv5模型部署”和“Ubuntu安装”这两块,是我实际折腾了两轮才顺手的路线,网上说法很多,实操细节我一次性给全。
1. 供电不稳是第一道坎:车间老旧线路下的反复重启
1.1 故障现象与第一轮误判
设备装好,系统起来,摄像头画面正常,YOLOv5开始推理。大约跑了十分钟,板子突然重启。我第一反应是系统问题,检查内核日志,发现根本没有正常关机记录——不是软重启,是硬件级掉电复位。
说实话,第一次遇到这种情况,我整整浪费了一个下午在错误的方向上。刷系统、换镜像、关掉一些服务,全都没用。问题还是一样:负载一上来就重启。
后来换了个思路,直接怀疑供电。树莓派5和前几代不太一样,它对电源质量敏感得多。官方要求5V/5A的电源,但“功率够”和“电压稳”是两码事。车间里的老插座,旁边还接着电焊机和大功率电机,这些设备一启动,电网电压会瞬时跌落。手机用的PD快充头在这种环境里根本顶不住。
1.2 用数据定位欠压故障
判断欠压,最直接的办法看系统自己的状态记录。树莓派启动后执行:
vcgencmd get_throttled返回一个十六进制值,按位表示发生过的故障状态。0x1表示发生过欠压,0x2表示当前正在欠压,0x4表示CPU频率曾被限制,0x8表示当前正在降频。我读到的值,几乎每周都有欠压标志,满载推理时用电表直接测板端USB-C口的电压,已经跌到4.6V左右,远低于稳定工作需要的5V±5%范围。
这里的原理也很好理解。树莓派5在高负载时瞬时电流能冲到3-5A,经过USB线、连接器和电路板走线,每一段都会产生压降。算笔账:一条1米长的普通USB-C线,双线电阻约0.1Ω,在5A电流下就有0.5V的压降。电源输出5.1V,到板端只剩4.6V,正好卡在欠压阈值附近。负载一抖,直接复位。
1.3 电源选型与线材计算
换掉PD快充头,换成工业级明纬电源,输出5V/5A,带接线端子。线材也换了,截面积更粗的20AWG USB线,长度控制在0.5米以内。接线端子方案在车间更实用,直接压接到电源端,不用频繁插拔USB头。
替换之后,我用以下命令连续监控半小时:
watch -n 5 vcgencmd get_throttled vcgencmd measure_volts coreget_throttled返回值全程为0,核心电压稳定在0.9V左右(这是PMIC给核心供电的电压,不是输入电压),设备再没重启过。这里有个经验:别迷信“65W快充”这类参数,快充头设计目标是给手机充电,瞬态响应未必适合树莓派这种动态负载。车间环境里,源端稳定比额定功率更重要。
2. 散热跟不上:性能被温度“锁”住的教训
2.1 高温降频带来的帧率雪崩
供电问题解决之后,系统稳定运行了,但我很快发现另一个问题——推理速度越跑越慢。刚启动时YOLOv5推理大约每秒8帧,跑了二十分钟后掉到每秒3帧。我还以为模型转换出了问题,结果一看CPU温度:92°C。
树莓派5用的Cortex-A76核心在高负载下发热量不可小看。芯片内部有温度保护机制,超过85°C就会主动降频,把主频从2.4GHz一步步压下来。性能不是你感觉慢,而是处理器自己砍自己的频率。
温度监控命令:
vcgencmd measure_temp cat /sys/class/thermal/thermal_zone0/temp当时整个设备装在一个密闭的配电柜里,柜内没有通风,加上车间本身环境温度就不低,原装散热器根本压不住。
2.2 车间粉尘环境下的散热方案取舍
先说结论:靠原装被动散热器在车间密闭柜里跑AI负载,不现实。
我最终用的是组合方案:板子装进带大面积散热鳍片的金属外壳,CPU位置涂好导热硅脂,外壳顶部再加一个5V温控风扇向外排风。风扇不直接吹板子,而是把密闭柜内的热空气排出,形成对流。这样做的好处是灰尘不会直接吹进板卡内部,散热效率也比纯被动式高很多。
实测数据供参考:开放环境下原装散热器能把满载温度压在70°C左右;换金属壳加顶排风扇之后,即使在密闭柜内,满载温度也稳定在65-70°C之间,降频再也没有触发过。
这里有一个细节值得注意:树莓派5的风扇接口支持PWM调速。不要一直全速转,吵且吸灰,用系统自带的fancontrol配置温度曲线就好。
2.3 温度监控与性能校准
设备装完后,不要直接上线。先做一个20分钟的满载压测,同时记录温度和帧率。我写了个简单循环,每10秒记录一次:
while true; do date >> /tmp/thermal.log; vcgencmd measure_temp >> /tmp/thermal.log; vcgencmd get_throttled >> /tmp/thermal.log; sleep 10; done跑完看温度曲线是否平稳,有没有降频标志。这一步特别重要,因为车间的环境温度跟你工位上是两回事。我见过不少项目,在空调房里调好了,一进车间就歇菜,绝大部分都是散热和供电这两件“小事”。
3. 系统选型来回折腾:Ubuntu才是YOLOv5的最佳搭档
3.1 先装了树莓派OS,为什么又换
第一次刷系统,我理所当然选了Raspberry Pi OS,毕竟是官方正统,对树莓派5的支持最及时。但在实际部署YOLOv5的过程中,我越来越别扭。
最痛的一点是软件生态。现在大量AI部署工具、容器镜像、ONNX Runtime的预编译wheel,都是优先服务Ubuntu。树莓派OS虽然基于Debian,但不少依赖包和文档教程对不上号,遇到问题搜解决方案,十有八九是Ubuntu的路径。为了省这几分钟装机时间,后面多花了两天查兼容性问题,不划算。
3.2 Ubuntu 24.04的配置差异
换到Ubuntu 24.04 LTS之后,整个过程顺滑太多。下载Raspberry Pi Imager,选择Ubuntu 24.04 LTS预装镜像直接写卡。开机后默认用户和密码是ubuntu/ubuntu,系统会强制让你改密码。
有几个配置差异需要特别留意:
树莓派OS的配置文件在/boot/config.txt,Ubuntu下变成了/boot/firmware/config.txt。启用I2C、SPI或者摄像头CSI口,修改的位置不一样。
默认没有预装raspi-config工具,需要自己装:
sudo apt install raspi-configGPIO权限问题要处理。Ubuntu下默认用户ubuntu没有直接操作GPIO的权限,需要把用户加入gpio组:
sudo usermod -aG gpio ubuntu之后重启,Python直接import RPi.GPIO或者使用libgpiod就不会报权限错误。
3.3 什么情况下应该老实留在树莓派OS
虽然我最后选了Ubuntu,但必须说清楚边界。如果你这个项目主要跑PLC通信、Modbus、大量底层GPIO控制,或者依赖wiringPi这类老牌库,树莓派OS会更省心。官方源的库更全,内核和固件匹配度更高,一些底层的DMA接口在Ubuntu下可能需要折腾。
我的最终划分是:以视觉检测和Python生态为核心的项目,无脑选Ubuntu;以电子控制、传感器采集为核心的项目,留在树莓派OS。两者没有高下之分,只是侧重点不一样。
4. 把自训YOLOv5模型搬进树莓派5:导出、转换、部署
4.1 模型导出:从PyTorch到ONNX
在PC上用YOLOv5训练好的模型是best.pt,格式是PyTorch权重。直接放到树莓派上跑PyTorch也可以,但内存占用高、速度慢。我实际测试时,PyTorch跑640×640输入大概只有5 FPS,树莓派5的4GB/8GB内存版本都会有些吃紧。
更合理的路线是先导出ONNX,然后用推理框架加载。YOLOv5自带导出脚本,关键参数如下:
python export.py --weights best.pt --img 320 --batch 1 --include onnx --opset 12 --simplify这里我把输入尺寸从默认的640改成了320,后面会细说原因。opset指定为12,兼容性和算子支持比较稳。加上--simplify做图优化,能去掉一些冗余算子。
导出完成后,在树莓派上安装ONNX Runtime:
pip install onnxruntime注意,树莓派5是arm64架构,pip会自动安装对应架构的wheel,不用自己编译。
4.2 ONNX Runtime与NCNN的实测对比
为了找到最合适在树莓派5上跑的方式,我把PyTorch、ONNX Runtime和NCNN都试了一遍。结果整理成表格:
| 推理方案 | 输入尺寸 | 实测帧率 | 内存占用 | 备注 |
|---|---|---|---|---|
| PyTorch FP32 | 640×640 | 约5 FPS | 较高 | 部署简单,性能最低 |
| ONNX Runtime | 640×640 | 约8 FPS | 中等 | 导出后直用,最省事 |
| NCNN CPU | 640×640 | 约10-11 FPS | 较低 | 需要额外转换步骤 |
| ONNX Runtime | 320×320 | 约16-18 FPS | 中等 | 检测精度需验证 |
数据来源是我自己的8GB树莓派5实测,散热状态良好时测得,供参考。不同模型、不同温度环境下会有浮动。
ONNX Runtime的优点是省心,导出即用;NCNN速度确实更快,但需要把ONNX再转成NCNN格式:
onnx2ncnn best.onnx best.param best.bin转换过程会提示一些不支持的算子,但YOLOv5比较友好,基本都能转。NCNN的CPU推理在ARM架构上有针对性的优化,内存也小,特别适合嵌入式。
4.3 推理脚本与输入尺寸的取舍
不管用哪个框架,推理脚本的核心逻辑都一样:图像预处理时做letterbox缩放,保持宽高比并填充到指定尺寸,推理后对输出做NMS非极大值抑制,过滤重复框。我以ONNX Runtime为例贴一个最小可运行的推理骨架:
import cv2 import numpy as np import onnxruntime as ort session = ort.InferenceSession("best.onnx", providers=["CPUExecutionProvider"]) input_name = session.get_inputs()[0].name input_shape = session.get_inputs()[0].shape # [1,3,320,320] 或 [1,3,640,640] def letterbox(img, size=320): h, w = img.shape[:2] scale = min(size / w, size / h) nw, nh = int(w * scale), int(h * scale) resized = cv2.resize(img, (nw, nh)) canvas = np.full((size, size, 3), 114, dtype=np.uint8) canvas[(size - nh) // 2:(size - nh) // 2 + nh, (size - nw) // 2:(size - nw) // 2 + nw] = resized return canvas frame = cv2.imread("test.jpg") inp = letterbox(frame, 320).transpose(2, 0, 1)[None].astype(np.float32) / 255.0 output = session.run(None, {input_name: inp})[0] # 后处理:根据模型输出格式做NMS输入尺寸的选择是这个环节最重要的取舍。640×640和320×320,帧率相差一倍多。如果检测目标在画面中占比较大、不需要太高的分辨率,320完全够用。我做了几百张测试图对比,漏检率只上升了一个百分点左右,但帧率从8FPS提升到16FPS以上,对实时性要求高的场景非常关键。
至于FP16量化或者INT8量化,我在这个项目上没有一上来就做。FP16在树莓派5的CPU上不一定有加速效果,反而可能在部分算子引入精度损失;INT8需要准备校准数据集,且YOLOv5这类检测模型量化后的精度抖动比较大,不是首版就该碰的东西。
5. 没有显示器的车间:远程运维与网络排障
5.1 配网与第一次无头启动
车间设备柜旁边没有显示器,我也没有给树莓派5配屏幕。无头部署的关键是第一次启动就能拿到设备地址。
用Raspberry Pi Imager烧录时,在设置界面直接预填Wi-Fi的SSID和密码,开启SSH服务,设置好用户名和密码。Ubuntu的镜像预装的是cloud-init机制,同样可以在烧录时注入用户数据和网络配置。
如果是树莓派OS,传统方法是烧录完成后在boot分区放一个名为ssh的空文件,再放一个userconf.txt文件来设置默认用户密码。Ubuntu镜像支持更完整的user-data,可以把时区、升级策略、SSH公钥都写进去。
5.2 Wi-Fi不稳的排查链路
第一次部署用的是Wi-Fi连接,结果问题不断。典型症状:SSH刚连上没问题,过十几分钟就断,必须重启网络服务才能恢复。
排查过程是这样的:
先看无线网卡的省电模式:
iwconfig wlan0输出里如果看到Power Management: on,那基本可以确定是罪魁祸首之一。Wi-Fi省电模式在有数据流量时会频繁切换收发状态,树莓派和很多家用路由器配合不好,表现就是间歇性断连。
关闭它:
sudo iw dev wlan0 set power_save off同时检查路由器设置。车间里那台民用路由器2.4GHz频段干扰非常严重,周围还有蓝牙、微波炉、各种工控设备。我直接把板子切到5GHz频段,断连问题明显减少。
但说实话,Wi-Fi在车间里终归不是长久之计。金属机柜对无线信号衰减很厉害,门一关信号直接掉一半。最终我把树莓派5的Wi-Fi当作调试通道,主要的网络路径换成了有线网线。树莓派5自带千兆以太网口,稳定性和带宽都远好于无线。
5.3 PoE供电与远程管理的组合方案
这里必须提一下树莓派5的PoE HAT。官方出了支持802.3af的PoE HAT,通过一根网线同时实现供电和网络,对车间部署来说简直是量身定做的方案。
一根网线,既解决了我前面说的供电不稳问题——PoE供电模块有标准的电压输出和过流保护,不像变压器直接插墙上那样受电网波动影响——又解决了网络稳定问题。配一台PoE交换机,板子接线非常简单。
远程管理配置方面,几个细节值得记下来:
给设备分配固定IP,在路由器里做DHCP保留,避免IP变化导致运维找不到设备。
启用SSH密钥登录,同时禁止密码登录,车间环境虽然相对封闭,但安全习惯不能省。
电脑上浏览器的web终端、代码仓库的自动部署钩子,都可以配合使用。我自己的流程是本地git推送代码,板子上通过systemd服务定时拉取更新并重启进程,基本不用摸到设备本体。
还有一个兜底方案:树莓派5的GPIO串口可以接USB转串口模块,万一网络彻底断了,通过串口还是能进系统排查。
6. 突然断电和SD卡损坏:可靠性问题的最后一道坎
6.1 SD卡为何成为软肋
第六个坑,也是车间项目最容易翻车的地方——异常断电。车间里设备启停频繁,总开关被拉闸的情况时有发生。树莓派5用SD卡启动时,一次突然断电就可能让文件系统损坏,症状是重启后系统进不去,或者在启动过程中挂载分区失败,SD卡变成只读。
SD卡本身的硬件特性决定它对掉电很敏感。控制器内部的FTL映射表和缓存没有完整的掉电保护,写操作正在执行时断电,轻则数据丢失,重则整个分区表损坏。在工位上你可能一年都遇不到一次异常断电,在车间里可能是每周一次。
6.2 NVMe SSD + 只读挂载的组合
我用两步把这个问题的风险降到最低。
第一步,把系统从SD卡迁移到NVMe SSD。树莓派5正式支持NVMe启动,通过PCIe接口接一块M.2 HAT和NVMe固态盘,系统镜像写入SSD,从SSD引导。SSD同样依赖缓存的写入,理论上也会损坏,但有断电保护机制的固态盘比SD卡可靠得多。实测同样异常断电十次的情况下,SD卡出现文件系统错误的概率远高于NVMe盘。
需要注意的是,NVMe SSD的功耗比SD卡高,供电方案必须同步升级。我用的5V/5A工业电源完全能带起来,但没有冗余余量的电源方案在接入SSD后容易踩第1章的坑。
第二步,软件层面把写入降到最低。针对只读挂载需求,把一些频繁写入的目录放到内存,比如日志:
sudo systemctl edit systemd-journald配置Storage=volatile后,系统日志只写入内存tmpfs,减少SSD的写擦除次数。还有Python运行时的字节码缓存文件,在systemd服务环境里设PYTHONDONTWRITEBYTECODE=1,也能减少垃圾写入。
外置根文件系统如果觉得必要,还可以用overlay模式把系统分区做成只读,把可写层放在内存或另一个分区。这个配置稍微复杂一些,适合要求系统长期运行不产生任何写操作的场景。
6.3 开机自启与硬件看门狗
系统稳定之后,还要保证程序本身可靠运行。我用systemd把YOLOv5推理程序做成服务,配置开机自启,程序崩溃自动重启:
[Unit] Description=YOLOv5 Detector After=network-online.target Wants=network-online.target [Service] User=ubuntu WorkingDirectory=/home/ubuntu/deploy ExecStart=/home/ubuntu/deploy/venv/bin/python /home/ubuntu/deploy/run.py Restart=always RestartSec=5 Environment=PYTHONDONTWRITEBYTECODE=1 [Install] WantedBy=multi-user.target写成/etc/systemd/system/ai-detector.service后:
sudo systemctl daemon-reload sudo systemctl enable ai-detector sudo systemctl start ai-detector这里加了After=network-online.target,确保网络就绪后再启动程序,避免程序起来后因为依赖的MQTT或数据库连接失败退出。
硬件看门狗也不可少。树莓派5有硬件看门狗模块,启用后如果系统或者核心进程卡死,看门狗会自动重启板子。在Ubuntu下启用systemd的看门狗:
sudo sed -i 's/#RuntimeWatchdogSec=0/RuntimeWatchdogSec=10/' /etc/systemd/system.conf重启后执行wdctl可以看到/dev/watchdog设备。有了硬件看门狗,遇到程序死循环、内存泄漏这类故障,系统会在10秒内自动复位,不用人工去车间重启设备。
这一套组合跑下来,我的设备在车间连续运行了几个月,没有再因为掉电和SD卡问题返工。回想整个过程,六件事没有一件是“高深技术”,全是基础环境问题。但恰恰是这些基础问题,决定了一个开发板项目能不能真正在车间里站住脚。每次有人问我树莓派5能不能上产线,我都会说:能,前提是你把供电、散热、系统、存储和自恢复这五件事先想清楚,第六件事才是把模型跑起来。