简介:这份文档面向智能制造、工业互联网及产线运维方向的从业者与学习者,围绕SMT表面贴片产线的监控管理可视化展开,重点讲解如何借助数字孪生、物联网与数据可视化技术,把传统产线升级为可实时监测、可远程运维的数字化工厂。内容涵盖OEE设备综合效率的三大维度——时间利用率、性能利用率与合格率,并给出计算公式与国内产线70%至80%的典型水平参考,同时结合工厂孪生体的产线与设备建模分析,说明如何实时监控设备状态、查看历史数据并触发异常报警。资源包为1个docx文档,大小约2.62MB,以图文形式呈现印刷机等设备建模、资产模型定义及无代码可配置的产线搭建思路,并引用图扑软件助力武汉联想SMT产线的3D可视化案例,展示全生命周期管理效果。目前已有104人学习,适合希望理解OEE指标、掌握数字孪生落地路径、为智能工厂转型寻找参考方案的读者阅读。
1. SMT 产线监控管理可视化:一份能直接拆开用的产线数据看板方案
车间里最尴尬的场景,不是设备停机,而是停机了半小时,产线主管还在翻三张 Excel 找是哪台贴片机先报的警。SMT 产线监控管理可视化这件事,本质上就是把印刷、贴片、回流焊、AOI 这几段的数据从各自的设备里拽出来,汇到一块屏上,让 OEE、直通率、抛料率、停机时长这些指标实时可见。这份《SMT 产线监控管理可视化.docx》就是围绕这个目标整理的一套方案文档,覆盖数据采集口径、看板布局、指标计算和可视化实现路径。它适合产线信息化工程师、MES 实施人员,以及想用 ECharts 或 Python 做车间级数据看板的开发者。如果你手上正好有 SMT 车间,又不想从零画指标口径,这份东西能省掉不少对齐成本。
2. 先搞清楚数据从哪来:SMT 设备接口与采集口径
2.1 SMT 产线里到底有哪些数据源
SMT 产线的数据不像互联网业务那样天然集中。它散在四五个环节里,每个环节的设备品牌、协议、开放程度都不一样。常见的数据源大致分四类:
第一类是贴片机本身。主流贴片机(无论是日系还是欧系)通常支持 SMEMA 标准接口做板级联机信号,但真正有价值的抛料率、吸嘴真空值、贴装头坐标偏差,往往要通过设备厂商的专用协议或 OPC UA 网关才能拿到。部分设备开放了 CSV 日志导出,但延迟高,不适合做实时看板。
第二类是回流焊。回流焊的温区温度、链速、氮气浓度是核心参数,多数设备通过 Modbus TCP 或串口输出,采集相对成熟。这里的关键是采样频率——温区温度如果 10 秒采一次,做趋势图够用,但做实时报警就偏慢。
第三类是 AOI 和 SPI。这两类设备通常自带数据库,检测结果(良品、不良类型、不良位置)可以直接从它的本地库或通过厂商 API 读取。SPI 的锡膏体积数据对分析印刷质量很有价值,但很多厂没把它接进看板。
第四类是产线级信号。包括轨道有无板、急停状态、工单切换信号,这些一般走 PLC,用 Modbus 或西门子 S7 协议采集。
提示:不要一上来就追求全量采集。先把贴片机的停机原因和 AOI 的直通率接进来,这两个指标对产线主管的决策价值最高,落地也最快。
2.2 采集层怎么选:OPC UA 网关还是直连数据库
选型这件事,我的经验是先看设备有没有 OPC UA 服务端。如果有,优先走 OPC UA,因为它是标准协议,后续换设备、加设备都不用重写采集层。如果没有,再看设备是否开放数据库或日志文件。
常见做法是分两层:边缘层用一台工控机跑采集脚本,通过 Modbus TCP 或串口读 PLC 和设备寄存器;应用层用消息队列(MQTT 或 Kafka)把数据推到后端。这样做的原因是,SMT 车间电磁环境复杂,采集脚本偶尔会断,用消息队列可以缓冲,不至于丢数据。
如果设备只支持文件导出,那就用轮询方式读文件。下面是一个用 Python 读取贴片机导出 CSV 并推送到 MQTT 的最小示例:
import pandas as pd import paho.mqtt.client as mqtt import time import os # 贴片机导出的抛料日志路径,实际部署时改成设备共享目录 LOG_PATH = "/data/smt/mounter_feed_log.csv" MQTT_BROKER = "192.168.1.100" MQTT_TOPIC = "smt/mounter/feed" client = mqtt.Client() client.connect(MQTT_BROKER, 1883, 60) # 记录已处理的行数,避免重复推送 last_row = 0 while True: if os.path.exists(LOG_PATH): df = pd.read_csv(LOG_PATH) if len(df) > last_row: new_rows = df.iloc[last_row:] for _, row in new_rows.iterrows(): payload = { "machine": row["machine_id"], "feeder": row["feeder_no"], "feed_error": row["error_code"], "timestamp": row["time"] } client.publish(MQTT_TOPIC, str(payload)) last_row = len(df) time.sleep(5)这段代码的逻辑很直白:每 5 秒检查一次日志文件,有新行就逐条推送到 MQTT。last_row是断点续传的关键,防止脚本重启后重复推送。MQTT_TOPIC按设备类型分层,方便后端订阅。参数上,time.sleep(5)可以根据设备日志的写入频率调整,如果设备每秒都写,可以降到 1 秒,但要注意文件读取的 IO 开销。
2.3 数据清洗:时间对齐和字段映射
采集上来的数据不能直接进看板。最常见的问题是时间戳不统一——贴片机用的是本地时间,AOI 用的是 UTC,PLC 用的是相对时间。如果不做对齐,看板上的趋势图会出现数据错位。
我一般会在边缘层做一次时间归一化,统一转成 ISO 8601 格式,并打上产线时区。字段映射也要在这一层做,比如把不同设备的error_code映射成统一的停机原因字典。这个字典建议维护在数据库里,而不是硬编码在脚本里,方便后续增删。
3. 指标怎么算:OEE、直通率、抛料率的计算逻辑与看板映射
3.1 OEE 的三个因子在 SMT 场景下的具体口径
OEE(全局设备效率)在教科书里是可用率 × 性能率 × 良品率,但放到 SMT 产线上,每个因子的口径都要重新定义。
可用率方面,SMT 的停机分计划停机和意外停机。计划停机包括换线、保养、计划休息,这些不应该计入 OEE 的损失。意外停机包括缺料、卡板、设备故障。常见做法是从 PLC 读取设备运行信号,结合工单系统里的换线计划,自动区分两类停机。
性能率方面,SMT 的理论产能通常按贴片机的最大贴装速度算,但实际受限于板子复杂度、元件种类。我一般会用「实际贴装点数 / 理论贴装点数」来算,理论值从程序文件里读,实际值从贴片机的计数器读。
良品率方面,SMT 的良品率要看 AOI 的直通率,而不是最终出货良率。因为 AOI 之后还有返修,返修后的良品不能算一次通过。直通率的公式是:一次通过板数 / 总投入板数。
3.2 抛料率的采集与计算
抛料率是 SMT 车间最敏感的指标之一,因为它直接关系到物料成本。抛料率的计算需要两个数据:实际消耗的元件数和理论贴装数。理论贴装数从贴片程序里读,实际消耗数从料枪的计数传感器或贴片机的抛料日志里读。
常见做法是每班次统计一次,按料号汇总。如果要做实时看板,可以按小时滚动计算。下面是一个计算抛料率的 SQL 示例,假设数据已经落在feed_log和placement_log两张表里:
SELECT f.feeder_no, f.material_code, SUM(f.feed_count) AS actual_feed, SUM(p.placement_count) AS theoretical_placement, ROUND( (SUM(f.feed_count) - SUM(p.placement_count)) * 100.0 / SUM(f.feed_count), 2 ) AS feed_loss_rate FROM feed_log f JOIN placement_log p ON f.feeder_no = p.feeder_no AND f.shift_id = p.shift_id WHERE f.shift_id = '2024-06-01-A' GROUP BY f.feeder_no, f.material_code HAVING feed_loss_rate > 0.5 ORDER BY feed_loss_rate DESC;这段 SQL 的核心是feed_loss_rate的计算:实际送料数减去理论贴装数,再除以实际送料数。HAVING子句过滤掉抛料率低于 0.5% 的料号,让看板只显示异常项。参数上,shift_id按班次过滤,如果要做实时看板,可以改成按小时过滤。
3.3 看板布局:从车间大屏到主管手机
看板的布局不是把指标堆上去就行。车间大屏和主管手机看到的应该是不同的东西。大屏挂在车间墙上,看的人站在三米外,所以字体要大、颜色对比要强、刷新频率要高(建议 5 秒一次)。核心指标放 OEE、直通率、当前工单进度、异常停机列表。
主管手机上看的是趋势和对比,比如本周 OEE 对比上周、各线体直通率排名、抛料率 Top 10 料号。刷新频率可以低一些,1 分钟一次就够。
用 ECharts 做看板时,大屏建议用深色主题,因为车间灯光亮,深色背景对比度高。手机端用浅色主题,省电且阅读舒适。下面是一个 ECharts 折线图的配置片段,用于展示 OEE 趋势:
option = { backgroundColor: '#1a1a2e', title: { text: 'OEE 趋势(近 7 天)', textStyle: { color: '#e0e0e0', fontSize: 20 } }, xAxis: { type: 'category', data: ['6-01', '6-02', '6-03', '6-04', '6-05', '6-06', '6-07'], axisLabel: { color: '#a0a0a0', fontSize: 14 } }, yAxis: { type: 'value', min: 50, max: 100, axisLabel: { color: '#a0a0a0', fontSize: 14 } }, series: [{ data: [78.5, 82.1, 79.3, 85.0, 81.2, 76.8, 83.4], type: 'line', smooth: true, lineStyle: { width: 3, color: '#00d4ff' }, areaStyle: { color: 'rgba(0, 212, 255, 0.15)' } }] };配置里min: 50是为了放大 50% 到 100% 之间的波动,如果从 0 开始,趋势线会挤在上面看不出变化。smooth: true让折线更柔和,但如果你需要精确读数,建议关掉。areaStyle的透明度控制在 0.15 左右,太深会盖住网格线。
4. 避坑与排查:SMT 看板落地时最容易翻车的五个地方
4.1 数据延迟导致看板和实际产线不同步
现象:车间大屏显示设备运行中,但实际设备已经停了五分钟。
原因:采集层用的是文件轮询,贴片机日志每 30 秒才写一次,加上脚本 5 秒的轮询间隔,最坏情况下延迟 35 秒。
解决:对实时性要求高的信号(如停机、急停),不要走文件轮询,直接走 PLC 或 OPC UA 订阅。文件轮询只用于抛料日志这类非实时数据。
4.2 时间戳时区不统一导致趋势图错位
现象:AOI 的直通率曲线和贴片机的产量曲线在时间轴上对不上,差了 8 小时。
原因:AOI 设备默认用 UTC 时间,贴片机用本地时间,采集时没有统一转换。
解决:在边缘层强制做时区归一化,所有时间戳转成带时区的 ISO 8601 格式。数据库存储时统一用 UTC,展示时再转回本地时区。
4.3 抛料率算出来是负数
现象:某料号的抛料率显示为 -3.2%。
原因:理论贴装数大于实际送料数,通常是贴片程序里的元件数和实际料枪计数不一致,或者料枪计数器有累积误差。
解决:先检查贴片程序是否更新过但料枪计数没清零。如果确认程序没问题,在计算时加一个GREATEST(0, ...)兜底,避免负数展示。同时排查料枪传感器是否需要校准。
4.4 看板刷新时页面闪烁
现象:大屏每 5 秒刷新一次,整个页面闪一下,看久了眼睛累。
原因:用的是整页刷新,而不是局部数据更新。
解决:用 ECharts 的setOption方法做增量更新,只更新数据部分,不重建图表实例。如果是用前端框架,把数据请求和图表渲染解耦,数据变了只调setOption。
4.5 设备 IP 变动导致采集中断
现象:某天早上发现某台贴片机的数据全断了,采集脚本报连接超时。
原因:车间网络用了 DHCP,设备重启后 IP 变了,采集脚本里写的是固定 IP。
解决:给关键设备配静态 IP 或 DHCP 保留地址。如果做不到,在采集脚本里用设备主机名而不是 IP,并加一个设备发现机制,定期扫描网段更新设备地址。
5. 进阶技巧:用 Python 做实时刷新与异常预警
5.1 用 WebSocket 替代轮询做实时刷新
前面说的 5 秒轮询,在设备多的时候会给后端造成不必要的压力。更优雅的做法是用 WebSocket,后端数据一变就推给前端。Python 这边可以用websockets库起一个轻量服务,前端用原生 WebSocket 接收。
import asyncio import websockets import json import random # 模拟从消息队列或数据库读取实时数据 async def get_realtime_data(): return { "oee": round(random.uniform(75, 90), 1), "throughput": random.randint(800, 1200), "feed_loss_rate": round(random.uniform(0.3, 1.5), 2) } async def handler(websocket): while True: data = await get_realtime_data() await websocket.send(json.dumps(data)) await asyncio.sleep(2) # 每 2 秒推送一次 async def main(): async with websockets.serve(handler, "0.0.0.0", 8765): await asyncio.Future() asyncio.run(main())这段代码起了一个 WebSocket 服务,每 2 秒推送一次模拟数据。实际部署时,get_realtime_data应该从 Redis 或消息队列里读,而不是随机生成。asyncio.sleep(2)控制推送频率,SMT 看板一般 2 到 5 秒足够,太快反而增加前端渲染负担。
5.2 异常预警的阈值怎么定
预警阈值不能拍脑袋。我的习惯是先用历史数据跑一周,算出每个指标的均值和标准差,然后把预警线设在均值加减两倍标准差的位置。比如 OEE 的周均值是 82%,标准差是 4%,那低于 74% 就触发预警。
但 SMT 产线有换线、保养等计划性波动,这些时段的阈值要单独设。常见做法是在工单系统里标记换线时段,预警规则里排除这些时段。
5.3 一个我踩过的坑:预警太多等于没有预警
刚开始做预警时,我把抛料率超过 0.5% 就设成报警,结果一天弹了 200 多条,产线主管直接把通知关了。后来改成只对连续三个小时抛料率超过 1% 的料号报警,并且按料号聚合,一天最多推 5 条。从那以后我每次设预警阈值,都强制走一遍「如果我是主管,这条消息我会不会看」的检查。希望帮到你。
本文还有配套的精品资源,点击获取