3、数据采集协议:Modbus RTU/TCP协议详解、IEC 61850/104规约、MQTT在物联网中的应用

说到储能监控,数据采集协议就是整个系统的“神经末梢”。没有它,你连电池电压都读不到,更别提什么运维了。今天咱们就把这几个主流协议掰开揉碎,聊聊我在实际项目中是怎么选型和落地的。

核心观点:没有最好的协议,只有最合适的场景。Modbus是“万金油”,IEC 61850是“高富帅”,MQTT是“互联网原住民”。

3.1 Modbus RTU/TCP:储能行业的“普通话”

Modbus这玩意儿,说实话,老归老,但真管用。我最早接触它是在2015年做光伏电站的时候,那时候BMS(电池管理系统)厂家清一色都支持Modbus。你想想看,一个1979年诞生的协议,到现在还在用,说明什么?说明它足够简单、足够稳定。

3.1.1 Modbus RTU vs Modbus TCP

特性 Modbus RTU Modbus TCP
物理层 RS-232/RS-485 以太网
传输速率 9.6kbps ~ 115.2kbps 10/100/1000Mbps
最大节点数 32(RS-485) 理论上无限制
传输距离 1200米(RS-485) 100米(网线)
数据格式 二进制(含CRC校验) 二进制(TCP/IP封装)
典型场景 就地采集、短距离 站内通信、远程监控

我个人习惯是:柜内设备用RTU,跨机柜用TCP。为什么?因为RS-485抗干扰能力强,在机柜这种电磁环境复杂的地方反而比网线靠谱。我曾经在一个项目中,网线走线不规范,结果通信老是丢包,换成RS-485后问题迎刃而解。

3.1.2 数据模型与寄存器

Modbus的数据模型其实就四种:线圈、离散输入、保持寄存器、输入寄存器。在储能场景中,我们最常用的是保持寄存器输入寄存器

  • 保持寄存器(03功能码):可读可写,用来设置参数。比如PCS的功率指令、BMS的均衡开关。
  • 输入寄存器(04功能码):只读,用来采集数据。比如电池电压、SOC、温度。
避坑指南:我曾经遇到过BMS厂家把SOC放在保持寄存器里,结果运维人员误写导致数据异常。所以我的建议是:只读数据统一用输入寄存器,可写参数用保持寄存器,别混着用。

3.1.3 代码示例:Python读取Modbus数据

这里给一个我常用的Python示例,用pymodbus库读取BMS数据:

from pymodbus.client import ModbusTcpClient

# 连接BMS(假设IP为192.168.1.100,端口502)
client = ModbusTcpClient('192.168.1.100', port=502)
client.connect()

# 读取保持寄存器,起始地址0,读取10个寄存器
result = client.read_holding_registers(0, 10, unit=1)

if not result.isError():
    # 假设寄存器0-1存储电压值(高16位+低16位)
    voltage = (result.registers[0] << 16) | result.registers[1]
    voltage = voltage / 1000.0  # 转换为实际值
    print(f"当前电压: {voltage}V")
    
    # 寄存器2存储SOC(百分比)
    soc = result.registers[2] / 10.0
    print(f"当前SOC: {soc}%")

client.close()

嗯,这里要注意:Modbus地址是从0开始的,但很多厂家文档里写的是“地址1”,实际上是协议地址0。这个坑我踩过不止一次。

3.2 IEC 61850/104:电力系统的“贵族协议”

IEC 61850,说白了就是电力行业的“高级货”。它不像Modbus那样简单粗暴,而是有一套完整的建模体系。在大型储能电站(尤其是并网型)中,调度端要求必须用61850。

3.2.1 为什么需要IEC 61850?

你想想看,一个储能电站可能有几十台PCS、几百个电池簇,如果用Modbus,你得定义一大堆寄存器地址表,而且不同厂家的定义还不一样。但61850不一样,它用逻辑节点(LN)来标准化设备模型。

  • MMXU:测量单元(电压、电流、功率)
  • ZBAT:电池系统(SOC、SOH、温度)
  • ZPCS:储能变流器(功率指令、运行状态)

每个逻辑节点都有标准的数据对象(DO),比如MMXU.PhV表示相电压。这样一来,不同厂家的设备就能“说同一种语言”。

注意:IEC 61850的学习曲线比较陡。我刚开始接触时,光理解SCL(变电站配置描述语言)就花了两周。如果你只是做中小型储能项目,建议先用Modbus,别一上来就上61850。

3.2.2 IEC 104:远动通信的“老大哥”

IEC 104是IEC 60870-5-104的简称,主要用于远动通信。在储能场景中,它通常用来把数据上传到调度中心。

我记得有一次做电网侧储能项目,调度端要求用104协议上传遥测、遥信数据。当时我查了标准文档,发现104的ASDU(应用服务数据单元)结构其实挺清晰的:

类型标识 含义 示例
1 单点遥信 断路器状态(合/分)
3 双点遥信 刀闸状态(合/分/中间)
9 归一化遥测 电压、电流(标幺值)
13 浮点遥测 功率、频率(实际值)

说白了,104就是一套“打包上传”的规则。你只要把数据按照标准格式封装好,调度端就能解析。但要注意:104的地址分配需要和调度端提前确认,否则数据对不上。

3.3 MQTT:物联网时代的“新宠”

MQTT这几年在储能行业越来越火,尤其是分布式储能户用储能场景。为什么?因为它轻量、支持发布/订阅模式,而且能穿透防火墙。

3.3.1 MQTT的核心机制

MQTT有三个角色:发布者订阅者代理(Broker)。在储能系统中,通常是这样用的:

  • BMS/PCS作为发布者:定时上报电压、SOC、温度等数据
  • 监控平台作为订阅者:接收数据并存储、展示
  • 云端Broker:负责消息路由(比如EMQX、Mosquitto)

我个人习惯用EMQX作为Broker,因为它支持集群部署,而且有Web管理界面,调试起来很方便。

3.3.2 主题设计

主题(Topic)是MQTT的核心。我建议用分层结构来设计:

储能电站ID/设备类型/设备ID/数据点
示例:station_001/bms/bms_01/voltage
      station_001/pcs/pcs_01/power

为什么要这样设计?因为订阅者可以灵活订阅。比如运维人员想监控所有BMS的电压,只需要订阅station_001/bms/+/voltage,用+通配符匹配所有设备ID。

避坑指南:我曾经在一个项目中,主题设计得太扁平(比如直接用bms/voltage),结果设备多了之后,订阅者收到大量无关消息,导致性能下降。所以主题一定要分层,而且每层含义要清晰。

3.3.3 代码示例:MQTT发布数据

用Python的paho-mqtt库发布BMS数据:

import paho.mqtt.client as mqtt
import json
import time

# 创建客户端
client = mqtt.Client()
client.connect("broker.emqx.io", 1883, 60)

# 模拟BMS数据
while True:
    data = {
        "voltage": 48.5,
        "soc": 85.2,
        "temperature": 25.3
    }
    
    # 发布到主题
    client.publish("station_001/bms/bms_01/data", 
                   json.dumps(data), 
                   qos=1)  # QoS=1确保至少一次送达
    
    time.sleep(5)  # 每5秒上报一次

嗯,这里要注意QoS(服务质量)的选择。QoS=0可能丢消息,QoS=2性能开销大。我一般用QoS=1,既保证可靠性,又不会太慢。

3.4 协议选型建议

说了这么多,到底怎么选?我总结了一张图,你可以参考:

储能数据采集协议选型决策树 储能系统类型? 大型并网(>10MW) IEC 61850(调度通信) IEC 104(远动上传) 中小型分布式(<10MW) Modbus RTU(柜内设备) Modbus TCP(站内通信) 户用/边缘场景 MQTT(云端通信) 注:实际项目中可能多种协议混合使用,比如Modbus采集 + MQTT上传

说白了,选型就三个原则:

  1. 看规模:大型电站必须上61850/104,中小型用Modbus就够了
  2. 看距离:就地通信用RTU,远程通信用TCP或MQTT
  3. 看生态:如果设备厂家都支持Modbus,就别强行上61850
我的建议:刚开始做储能监控时,先用Modbus把数据采上来,跑通流程。等系统稳定了,再考虑升级到61850或MQTT。别一上来就追求“高大上”,稳定才是第一位的。

好了,这一章的内容就到这里。数据采集协议这块,说白了就是“因地制宜”。你只要理解了每种协议的特点和适用场景,选型就不会出错。下一章咱们聊聊数据存储和时序数据库,那又是另一个有意思的话题了。


专注资料整理