2. Modbus TCP 电表数据采集
任务目标
通过以太网使用 Modbus TCP 协议连接智能电表,读取电压(寄存器地址 0x0000)、电流(0x0001)、有功功率(0x0002)三个关键电量参数,并验证读取数据的正确性。本案例使用 Modbus 从站模拟器作为电表替代设备,确保无硬件条件下可完整复现。
环境依赖
- Python 3.8+
- 安装依赖:
pip install pymodbus==3.6.9 - Modbus 从站模拟器(如 Modbus Slave、diagslave 或 pymodbus 自带的模拟器),用于模拟电表寄存器数据
完整实现代码
from pymodbus.client import ModbusTcpClient
import time
# 电表 Modbus 寄存器地址映射(以某型号电表为例)
REG_ADDRS = {
"voltage": 0x0000, # 电压 (V),放大10倍存储
"current": 0x0001, # 电流 (A),放大100倍存储
"power": 0x0002 # 有功功率 (W),放大10倍存储
}
# 各参数的数据缩放系数(根据电表说明书设定)
SCALE_FACTORS = {
"voltage": 10.0,
"current": 100.0,
"power": 10.0
}
def read_meter_data(host: str, port: int = 502, unit_id: int = 1, timeout: int = 3):
"""
从 Modbus TCP 电表读取电压、电流、功率数据。
返回: dict,包含三个参数的原始寄存器值和物理值。
"""
client = ModbusTcpClient(host, port=port, timeout=timeout)
if not client.connect():
raise ConnectionError(f"无法连接 Modbus TCP 设备 {host}:{port}")
result = {}
try:
for param, addr in REG_ADDRS.items():
# 读取保持寄存器(功能码 0x03),每个参数占1个寄存器
rr = client.read_holding_registers(address=addr, count=1, slave=unit_id)
if rr.isError():
raise RuntimeError(f"读取 {param} 失败: {rr}")
raw_value = rr.registers[0]
physical_value = raw_value / SCALE_FACTORS[param]
result[param] = {
"raw": raw_value,
"value": round(physical_value, 2)
}
finally:
client.close()
return result
if __name__ == "__main__":
# 从站模拟器地址(根据实际环境修改)
METER_HOST = "127.0.0.1"
METER_PORT = 5020 # 模拟器监听端口
# 连续读取3次,间隔1秒,验证数据稳定性
for i in range(3):
try:
data = read_meter_data(METER_HOST, METER_PORT)
print(f"第 {i+1} 次读取:")
print(f" 电压: {data['voltage']['value']} V (原始值: {data['voltage']['raw']})")
print(f" 电流: {data['current']['value']} A (原始值: {data['current']['raw']})")
print(f" 功率: {data['power']['value']} W (原始值: {data['power']['raw']})")
except Exception as e:
print(f"读取失败: {e}")
time.sleep(1)
运行与验证
- 启动从站模拟器:在本地启动 Modbus TCP 从站模拟器,监听端口 5020,从站地址(Unit ID)设为 1。在模拟器中预设以下寄存器值:
地址 0x0000 = 2200(表示 220.0V)
地址 0x0001 = 500(表示 5.00A)
地址 0x0002 = 11000(表示 1100.0W) - 运行脚本:
python modbus_meter.py - 判定通过条件:程序连续 3 次成功读取数据,且输出值与模拟器预设值一致——电压显示 220.0V、电流显示 5.0A、功率显示 1100.0W。若读取失败或数值偏差超过 0.1,则检查网络连接、寄存器地址或缩放系数配置。
常见问题
- 连接超时:确认模拟器已启动且端口号、IP 地址正确;检查防火墙是否放行 TCP 端口。
- 读取错误(Illegal Data Address):模拟器中未在对应地址设置寄存器值,需在从站配置中添加地址 0x0000~0x0002 的保持寄存器。
- 数值偏差:不同型号电表的寄存器缩放系数可能不同,请以实际电表说明书为准修改
SCALE_FACTORS。