4. PLC数据采集基础:PLC选型、Modbus TCP/RTU协议、寄存器映射、数据采集频率设计
各位同学,今天我们来聊聊PLC数据采集。说实话,这是整个重力储能监控系统里最接地气的一环。你想想看,上层平台再花哨,如果底层的PLC数据都拿不准,那一切都是空中楼阁。
我个人习惯把PLC数据采集比作「翻译官」的工作。PLC内部跑的是二进制,上位机要读的是工程值,中间怎么转?靠的就是协议和映射。咱们一步步拆开讲。
4.1 PLC选型:别光看品牌,要看场景
选PLC,我见过太多人犯一个错误:只看品牌,不看IO点数和通信接口。重力储能电站的PLC,核心要求就三条:
- 支持Modbus TCP:这是标配,没有这个接口后面全白搭
- IO点数够用:重力储能一般需要采集电机电流、制动状态、位置传感器、温度等,至少预留20%余量
- 环境适应性:电站现场可能有震动、粉尘,选工业级(-20℃~60℃)
我推荐几个常用型号:西门子S7-1200(性价比高)、汇川AM600(国产替代,Modbus TCP原生支持)、三菱FX5U(稳定但贵)。
4.2 Modbus TCP vs RTU:到底选哪个?
这个问题,我每次培训都会被问到。说白了,就一句话:能走TCP就别走RTU。
为什么?你看这张对比表就明白了:
| 特性 | Modbus TCP | Modbus RTU |
|---|---|---|
| 物理层 | 以太网(RJ45) | RS485/RS232 |
| 传输速率 | 100Mbps | 9.6kbps~115.2kbps |
| 最大节点数 | 几乎无限制 | 32个(RS485) |
| 校验方式 | TCP/IP自带校验 | CRC16 |
| 接线复杂度 | 一根网线 | 双绞线+终端电阻 |
| 适用场景 | 中大型系统、远程监控 | 短距离、低成本 |
嗯,这里要注意:RTU虽然慢,但也不是一无是处。如果现场只有几十米距离,且干扰不大,RTU完全够用。我有个项目在山区,以太网布线成本太高,最后用的RTU+无线数传电台,也跑得很稳。
4.3 寄存器映射:PLC和上位机的「翻译词典」
寄存器映射,说白了就是一张对照表。PLC里哪个地址存了什么数据,上位机必须知道。否则你读回来的0x1234,鬼知道是电流还是温度。
Modbus协议里,寄存器分四类:
- 0x 线圈(Coil):可读写,1位,控制启停
- 1x 离散输入(Discrete Input):只读,1位,读取开关状态
- 3x 输入寄存器(Input Register):只读,16位,读取模拟量
- 4x 保持寄存器(Holding Register):可读写,16位,设置参数
重力储能电站里,最常用的是3x和4x。比如:
// 寄存器映射表示例(重力储能电站)
// 地址范围:40001~40010(保持寄存器)
40001: 电机转速 (RPM) // 数据类型:UINT16
40002: 制动器状态 (0/1) // 数据类型:BOOL(占用1位)
40003: 当前高度 (m) // 数据类型:FLOAT(占用2个寄存器)
40005: 温度 (℃) // 数据类型:INT16
40006: 故障码 // 数据类型:UINT16
4.4 数据采集频率设计:不是越快越好
很多新手上来就问:「老师,采集频率设多少?1秒一次够不够?」
我的回答是:看变量类型。
重力储能电站的变量,按变化速度可以分为三类:
- 快速变化量:电机电流、振动信号。建议100ms~500ms采集一次。
- 中速变化量:温度、压力、高度。建议1s~5s采集一次。
- 慢速变化量:累计发电量、设备运行时长。建议10s~60s采集一次,甚至按分钟。
为什么不能统一设1秒?你想想看,如果PLC有100个寄存器,每秒读一次,网络带宽和PLC的CPU负载都会增加。我见过一个项目,采集频率设了200ms,结果PLC的扫描周期被拖长,导致控制逻辑响应变慢——这就是典型的「采集干扰控制」。
4.5 实战:一个完整的采集流程
好了,理论讲完了,咱们来点实际的。假设你有一台西门子S7-1200 PLC,IP是192.168.1.100,要采集电机转速(40001)和温度(40005)。
用Python写一个简单的Modbus TCP客户端:
from pymodbus.client import ModbusTcpClient
# 连接PLC
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()
# 读取保持寄存器(功能码03)
# 从地址0开始(对应40001),读2个寄存器
result = client.read_holding_registers(0, 2, unit=1)
if not result.isError():
speed = result.registers[0] # 电机转速
temp = result.registers[1] # 温度(原始值)
print(f"转速: {speed} RPM")
print(f"温度: {temp} ℃")
else:
print("读取失败,检查连接")
client.close()
嗯,这里要注意:PLC的寄存器地址和Modbus协议地址差1。比如PLC里标的是40001,那Modbus请求里的地址就是0。这个偏移量,新手最容易搞错。
4.6 本章知识体系
下面这张图,是我自己画的,把本章的核心逻辑串起来了:
这张图我画了好几次才满意。你看,从左到右,从选型到频率设计,每一步都环环相扣。选型错了,后面协议再对也白搭;映射错了,数据就是垃圾;频率设错了,系统稳定性就崩了。
好了,这一章的内容就到这里。记住:PLC数据采集不是技术难题,而是细节活。把每个环节想清楚,做扎实,你的监控系统就成功了一半。