219 lines
7.1 KiB
Markdown
219 lines
7.1 KiB
Markdown
# 【CSDN】制造业数据孤岛怎么破?——基于 SCADA 的多协议设备接入实战笔记
|
||
|
||
> **来源母版**:`2026-04-20_master_上位机-多品牌协议整合.md`
|
||
> **改写平台**:CSDN / 博客园
|
||
|
||
---
|
||
|
||
## 标签
|
||
|
||
```
|
||
工业协议 | SCADA | Modbus | 西门子S7 | OPC_UA | EtherNet/IP
|
||
设备数据采集 | 制造业数字化 | OEE
|
||
```
|
||
|
||
---
|
||
|
||
## 正文
|
||
|
||
---
|
||
|
||
## 制造业数据孤岛怎么破?——基于 SCADA 的多协议设备接入实战笔记
|
||
|
||
### 背景:工厂里最贵的浪费,是设备"语言不通"
|
||
|
||
在工厂做 MES 系统集成的人,几乎都会遇到一个共同问题:**设备层采集做不下去,系统层逻辑再漂亮也没用。**
|
||
|
||
西门子 PLC 用 S7 协议,施耐德变频器用 Modbus,ABB 机器人用 EtherNet/IP,国产设备各有各的私有协议。一条产线上可能同时存在五六个品牌,**每多一个品牌,就要多一套驱动的开发工作量。**
|
||
|
||
本文记录一次真实的工厂上位机改造项目中,设备层通讯接入的全流程实践。
|
||
|
||
---
|
||
|
||
### 一、项目概况
|
||
|
||
| 项目要素 | 内容 |
|
||
|---------|------|
|
||
| 设备规模 | 120+ 节点 |
|
||
| 品牌构成 | 西门子 S7-1200/1500、施耐德 Modbus TCP、ABB EtherNet/IP、汇川伺服等 |
|
||
| 行业 | 3C 电子制造 |
|
||
| 通讯调试周期 | 2 周 |
|
||
| 上位系统 | SCADA + OEE + 生产追溯 |
|
||
| 数据指标 | OEE 提升 42%,能耗下降 15% |
|
||
|
||
---
|
||
|
||
### 二、协议层架构设计
|
||
|
||
#### 2.1 常见工业协议对比
|
||
|
||
| 协议 | 典型品牌 | 传输层 | 数据模型 | 开发难度 |
|
||
|------|---------|--------|---------|---------|
|
||
| 西门子 S7 (ISO-on-TCP) | 西门子全系列 | TCP 102 | Pdu 结构 | 中等,需处理连接管理 |
|
||
| Modbus TCP | 施耐德、ABB、汇川 | TCP 502 | 寄存器寻址 | 较低,格式简单 |
|
||
| OPC UA | 主流厂商 | TCP 4840 | 信息模型 | 较高,配置复杂但通用性强 |
|
||
| EtherNet/IP | 罗克韦尔 | TCP 44818 | CIP 报文 | 中等,文档质量一般 |
|
||
| Profinet | 西门子 | 实时以太网 | IO 数据 | 高,实时性要求严 |
|
||
|
||
#### 2.2 分层接入架构
|
||
|
||
我们采用的架构是**协议网关 + 统一数据中台 + SCADA 应用层**:
|
||
|
||
```
|
||
[设备层] 西门子 S7 / 施耐德 Modbus / ABB EtherNet/IP / 汇川
|
||
↓
|
||
[协议网关层] 各协议驱动模块 → 统一 JSON 数据格式
|
||
↓
|
||
[数据中台层] 实时数据库 + 历史存储 + 数据翻译
|
||
↓
|
||
[SCADA 应用层] Dashboard / OEE 计算 / 告警策略 / 趋势分析
|
||
```
|
||
|
||
**为什么这样分层?**
|
||
|
||
核心思路是**把协议差异消解在网关层**,上层应用不需要关心底下跑的是什么协议。设备换了品牌,只需要换驱动模块,上层逻辑不用动。
|
||
|
||
#### 2.3 西门子 S7 驱动要点
|
||
|
||
```python
|
||
# S7 协议连接示例(Python snap7)
|
||
import snap7
|
||
from snap7.util import get_int, get_real
|
||
|
||
client = snap7.client.Client()
|
||
client.connect('192.168.1.10', 0, 1) # IP, rack, slot
|
||
|
||
# 读取 DB1.DBD0 (Real 类型,4字节)
|
||
db_number = 1
|
||
start = 0
|
||
amount = 4
|
||
data = client.db_read(db_number, start, amount)
|
||
value = get_real(data, 0) # 浮点数
|
||
|
||
# 读取 DB1.DBW2 (Int 类型,2字节)
|
||
data = client.db_read(db_number, 2, 2)
|
||
value = get_int(data, 0) # 整数
|
||
```
|
||
|
||
**踩坑记录**:
|
||
- 西门子 S7 需要注意 **rack 和 slot** 参数,错误会导致连接建立不上
|
||
- S7-1200 默认不允许 PUT/GET 访问,需要在 TIA Portal 里手动开启
|
||
- 大量数据点读取时建议用 `BSEND/BRECV` 批量方式,减少通讯开销
|
||
|
||
#### 2.4 施耐德 Modbus TCP 驱动要点
|
||
|
||
```python
|
||
# Modbus TCP 读取示例
|
||
from pymodbus.client import ModbusTcpClient
|
||
|
||
client = ModbusTcpClient('192.168.1.20', port=502)
|
||
|
||
# 读取保持寄存器 0-9 (Holding Registers, 地址偏移 0)
|
||
result = client.read_holding_registers(0, 10, unit=1)
|
||
registers = result.registers # List[int]
|
||
|
||
# 解析浮点数(Modbus 浮点数格式需要注意字节顺序)
|
||
high = registers[0]
|
||
low = registers[1]
|
||
value = struct.unpack('>f', struct.pack('>HH', high, low))[0]
|
||
```
|
||
|
||
**踩坑记录**:
|
||
- Modbus 寄存器地址有三种模式(0x, 4x, 3x),需要和设备厂家确认
|
||
- 施耐德 PLC 有时默认开启 Modbus RTU over TCP,需要注意切换
|
||
- 某些设备对请求间隔有要求,轮询间隔不能太短
|
||
|
||
#### 2.5 数据建模:从设备数据到 OEE
|
||
|
||
原始设备数据需要经过翻译才能成为 OEE 计算因子:
|
||
|
||
```python
|
||
# 设备状态映射
|
||
STATUS_MAP = {
|
||
0: 'running', # 运行中
|
||
1: 'idle', # 待机
|
||
2: 'setup', # 换型
|
||
3: 'maintenance', # 维护
|
||
4: 'fault' # 故障
|
||
}
|
||
|
||
# OEE 计算
|
||
def calc_oee(availability, performance, quality):
|
||
"""
|
||
OEE = 可用率 × 表现率 × 质量率
|
||
典型目标:85%+
|
||
"""
|
||
return availability * performance * quality
|
||
|
||
# 示例
|
||
availability = 0.92 # 可用率 92%(故障停机少)
|
||
performance = 0.88 # 表现率 88%(速度损失少)
|
||
quality = 0.97 # 质量率 97%(不良品少)
|
||
|
||
oee = calc_oee(availability, performance, quality)
|
||
print(f"OEE: {oee:.2%}") # 输出: OEE: 78.43%
|
||
```
|
||
|
||
---
|
||
|
||
### 三、2 周交付是怎么做到的
|
||
|
||
很多工厂觉得设备接入是个无底洞,其实是因为没有系统化的方法。
|
||
|
||
**第一周:协议层跑通**
|
||
|
||
- Day 1–2:现场勘察,梳理设备清单和通讯参数
|
||
- Day 3–4:完成西门子 S7 驱动调试,建立基准数据
|
||
- Day 5:完成施耐德 Modbus 驱动,与 S7 数据统一建模
|
||
|
||
**第二周:数据层和应用层打通**
|
||
|
||
- Day 8–9:ABB EtherNet/IP 接入,与已有数据模型对接
|
||
- Day 10–11:OEE 计算逻辑上线,Dashboard 首版发布
|
||
- Day 12–13:告警策略配置,微信/邮件推送测试
|
||
- Day 14:联调测试,移交文档
|
||
|
||
**关键不是加班,是每层有验收节点,发现问题当天解决,不把问题留到下周。**
|
||
|
||
---
|
||
|
||
### 四、交付数据
|
||
|
||
| 指标 | 改造前 | 改造后 |
|
||
|------|--------|--------|
|
||
| 设备数据采集率 | 约 35% | 95%+ |
|
||
| OEE | 基准值 | 提升 42% |
|
||
| 综合能耗 | 基准值 | 下降 15% |
|
||
| 故障响应时间 | 人工巡检,平均 >25min | < 300ms 自动告警 |
|
||
| 停线时间 | 基准值 | 减少 40% |
|
||
|
||
---
|
||
|
||
### 五、经验总结
|
||
|
||
1. **协议层是基础**:协议跑通了,后面的数据建模、OEE 计算、告警策略都是顺水推舟;协议跑不通,上面全是白搭。
|
||
|
||
2. **分层架构减少维护成本**:设备品牌更换只需要换驱动层,应用层不用动。我们这个项目后来客户换了 ABB 机器人型号,只花了两天重新配置驱动,应用层零改动。
|
||
|
||
3. **数据建模要提前**:设备数据点少则几十个,多则几百个,提前定义好数据字典和翻译规则,交付时少返工。
|
||
|
||
4. **告警要分级**:把所有告警都设成最高级等于没设告警。分级推送(微信 / 短信 / 邮件)让不同角色收到不同级别的告警。
|
||
|
||
---
|
||
|
||
### 六、代码仓库
|
||
|
||
本文相关协议驱动和数据建模代码已脱敏整理,有兴趣的朋友可以联系作者了解。
|
||
|
||
---
|
||
|
||
**作者**:上海橙轩智能(Orpaon)
|
||
**官网**:[www.orpaon.com](https://www.orpaon.com)
|
||
**本文数据来源**:官网项目案例(已脱敏)
|
||
|
||
---
|
||
|
||
## 评论区引导
|
||
|
||
> 你的工厂用的是哪个品牌的 PLC?协议接入遇到过什么坑?欢迎评论区说说。
|