python pymodbus模块详解

python pymodbus模块详解

python pymodbus模块详解

一、详解

pymodbus是一个基于Python的开源库,用于实现Modbus通信协议。Modbus是一种广泛应用于工业自动化领域的串行通信协议,支持主从架构(客户端-服务器模型)。pymodbus库提供了完整的Modbus客户端(主站)和服务器(从站)功能,支持多种传输方式,包括Modbus RTU(串行通信)和Modbus TCP(以太网通信)。


1、 基础概念

Modbus协议定义了一套标准的数据模型和通信规则:

  • 数据模型:使用寄存器存储数据,分为:
    • 线圈(Coils):1位读写寄存器,用于布尔值(如开关状态)。
    • 离散输入(Discrete Inputs):1位只读寄存器。
    • 保持寄存器(Holding Registers):16位读写寄存器,用于整数值(如传感器读数)。
    • 输入寄存器(Input Registers):16位只读寄存器。
  • 地址范围:每个寄存器类型有独立地址空间,范围从0到65535(即 0 ≤ address ≤ 65535 0 \leq \text{address} \leq 65535 0≤address≤65535)。
  • 功能码:Modbus操作使用功能码(Function Code),例如:
    • 读线圈:功能码1。
    • 写单个寄存器:功能码6。
    • 完整列表可参考Modbus标准文档。

pymodmos库实现了这些概念,支持Python 3.6及以上版本,并兼容多种操作系统(Windows、Linux、macOS)。


2、核心功能

pymodbus提供模块化设计,主要组件包括:

  • 客户端(Client):作为主站发起请求,支持同步和异步模式。
    • 支持Modbus TCP和RTU传输。
    • 提供读写API,如read_coilswrite_register
  • 服务器(Server):作为从站响应请求,可模拟设备行为。
    • 支持数据存储上下文(如ModbusServerContext)。
    • 内置线程或异步事件处理。
  • 协议处理
    • 自动处理Modbus PDU(协议数据单元)格式。
    • 支持异常响应(如非法地址时返回错误码)。
  • 扩展性:允许自定义数据处理器和传输层(如通过串口或Socket)。

关键优势:

  • 轻量级:纯Python实现,无需外部依赖。
  • 灵活:支持同步(pymodbus.client)和异步(pymodbus.async)编程。
  • 兼容性:遵循Modbus标准,可与PLC、HMI等工业设备互操作。

3、安装与设置

安装pymodbus简单,通过pip命令即可:

pip install pymodbus 

安装后,导入所需模块:

from pymodbus.client import ModbusTcpClient # TCP客户端from pymodbus.server import StartTcpServer # TCP服务器from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext # 数据存储

环境要求:

  • Python 3.6+。
  • 对于Modbus RTU,需物理串口或虚拟串口工具(如pyserial)。
  • 测试工具推荐:使用Modbus模拟软件(如Modbus Poll)验证通信。

4、使用示例

以下示例展示常见场景,代码基于同步模式(异步模式类似,使用asyncio)。

示例1: Modbus TCP客户端(读取保持寄存器)
作为客户端,连接到服务器并读取数据。

from pymodbus.client import ModbusTcpClient # 连接到服务器(假设IP: 127.0.0.1, 端口: 502) client = ModbusTcpClient('127.0.0.1', port=502) client.connect()# 读取保持寄存器(地址0,数量2个寄存器) result = client.read_holding_registers(address=0, count=2, unit=1)# unit为从站IDifnot result.isError():print("读取成功:", result.registers)# 输出寄存器值列表,如[100, 200]else:print("错误:", result) client.close()# 关闭连接

示例2: Modbus TCP服务器(模拟从站)
创建服务器并存储数据。

from pymodbus.server import StartTcpServer from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext from pymodbus.datastore import ModbusSequentialDataBlock # 初始化数据存储:设置保持寄存器(地址0-9,初始值0) store = ModbusSlaveContext( hr=ModbusSequentialDataBlock(0,[0]*10)# hr表示保持寄存器) context = ModbusServerContext(slaves=store, single=True)# single模式为单从站# 启动服务器(端口502) StartTcpServer(context=context, address=("0.0.0.0",502))

示例3: Modbus RTU通信(使用串口)
适用于串行设备。

from pymodbus.client import ModbusSerialClient # 配置串口(端口COM1, 波特率9600) client = ModbusSerialClient(method='rtu', port='COM1', baudrate=9600) client.connect()# 写单个线圈(地址0,值True) client.write_coil(address=0, value=True, unit=1) client.close()

5、 高级特性

pymodbus支持更复杂场景:

  • 自定义数据处理器:重写ModbusRequestHandler处理特定逻辑。
  • 安全扩展:支持TLS加密(Modbus TCP)或自定义认证。
  • 诊断工具:内置日志记录(import logging),便于调试通信问题。

异步模式:使用AsyncModbusTcpClient结合asyncio,提高并发性能。

import asyncio from pymodbus.client import AsyncModbusTcpClient asyncdefmain(): client = AsyncModbusTcpClient('127.0.0.1', port=502)await client.connect() result =await client.read_holding_registers(0,2)print(result.registers)await client.close() asyncio.run(main())

性能优化建议:

  • 使用连接池管理客户端实例。
  • 批量读写减少请求次数(如read_holding_registerscount参数)。
  • 在资源受限设备上,启用精简模式(禁用不必要功能)。

6、注意事项

  • 协议限制
    • Modbus RTU要求严格时序(如3.5字符间隔)。
    • 地址溢出:确保地址在有效范围(如超出65535会报错)。
  • 常见问题
    • 连接超时:检查网络或串口配置。
    • 数据不一致:验证字节序(pymodbus默认大端序)。
    • 性能瓶颈:在高频通信中,优先使用异步模式。
  • 资源
    • 官方文档:pymodbus GitHub
    • 社区支持:通过GitHub Issues获取帮助。

错误处理:pymodbus可能抛出异常(如ModbusIOException),需捕获处理:

try: result = client.read_coils(0,1)except Exception as e:print("通信错误:", e)

二、代码示例

1、modbusTCP client

from time import sleep from pymodbus.client import ModbusTcpClient client = ModbusTcpClient('127.0.0.1') client.connect()whileTrue: res = client.read_holding_registers(slave=1,address=0,count=10)print(res.registers) sleep(0.5)
在这里插入图片描述

2、modbusRTU client

from time import sleep from pymodbus.client import ModbusSerialClient client = ModbusSerialClient(method='rtu', port='COM1', baudrate=9600, timeout=1) connection = client.connect()whileTrue: res = client.read_holding_registers(slave=1,address=0,count=10)print(res.registers) sleep(0.5)
在这里插入图片描述
在这里插入图片描述

Read more

【C++】现代C++的新特性constexpr,及其在C++14、C++17、C++20中的进化

【C++】现代C++的新特性constexpr,及其在C++14、C++17、C++20中的进化

各位读者大佬好,我是落羽!一个坚持不断学习进步的学生。 如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步! 也欢迎关注我的blog主页:落羽的落羽 文章目录 * 一、从C++11引入 * 1. 常量表达式和constexpr关键字的概念 * 2. constexpr修饰函数 * 二、constexpr在C++14中的进化 * 三、constexpr在C++17中的进化 * 四、constexpr在C++20中的进化 一、从C++11引入 1. 常量表达式和constexpr关键字的概念 现代C++,从C++11开始,引入了常量表达式和constexpr关键字的概念,并且在之后的C++标准中不断更新 常量表达式是指,值不会改变并且在编译过程中就能得到计算结果的表达式。用字面量、常量表达式初始化的const对象都是常量表达式。但是用变量初始化的const对象不是常量表达式。 constint a =1;//a是常量表达式constint b = a +1;//b是常量表达式int c

By Ne0inhk

从GetDiagnostics到C++全栈诊断:开发者必备的排障与调试工具集

文章目录 * 从GetDiagnostics到C++全栈诊断:开发者必备的排障与调试工具集 * 一、GetDiagnostics:通用诊断信息采集的“瑞士军刀” * 1. 什么是GetDiagnostics? * 2. 主流场景下的GetDiagnostics用法 * 场景1:PowerShell中的诊断数据采集(最常用) * 场景2:SQL中的执行诊断(错误处理必备) * 场景3:.NET/SCOM中的诊断规则查询 * 3. GetDiagnostics使用核心要点 * 二、C++开发全流程必备工具集 * 1. 编译/语法检查工具:提前拦截基础错误 * (1)GCC/Clang:自带警告与诊断能力 * (2)CMake:构建过程诊断 * 2. 调试工具:定位运行时逻辑错误 * (1)GDB:跨平台命令行调试器 * (2)LLDB:Clang配套调试器(macOS/Linux优先) * (3)Visual

By Ne0inhk
【Linux系统】C/C++的调试器gdb/cgdb,从入门到精通

【Linux系统】C/C++的调试器gdb/cgdb,从入门到精通

各位读者大佬好,我是落羽!一个坚持不断学习进步的学生。 如果您觉得我的文章还不错,欢迎多多互三分享交流,一起学习进步! 也欢迎关注我的blog主页:落羽的落羽 文章目录 * 一、调试前的预备知识 * 二、gdb/cgdb的使用 * 1. 启动,查看代码 * 2. 基础调试命令 * 3. 监视变量相关命令 * 4. 设置条件断点 一、调试前的预备知识 程序发布的方式有两种,debug模式和release模式。 * debug模式:生成的可执行程序中会包含程序的调试信息,便于程序员进行调试代码。 * release模式:会剥离或不生成这些调试信息。这使得文件更小,但也意味着调试器几乎无法工作,release版本程序无法进行调试。 Linux的gcc/g++,按照我们之前的写法gcc -o $@ $^,默认生成的是release版本的程序,是无法进行调试的。要在命令后加-g选项,指定以debug方式发布,debug模式下的程序我们才能进行调试。 gcc -o $@ $^ -g 二、gdb/cgdb的使用

By Ne0inhk
纸上谈“型”不如运行识“真”:深入 C++ RTTI 与多态的底层真相!

纸上谈“型”不如运行识“真”:深入 C++ RTTI 与多态的底层真相!

文章目录 * 本篇摘要 * RTTI(Run-Time Type Information,运行时类型信息) 介绍 * RTTI 的核心组成 * 1. `typeid` 运算符 * 2. `dynamic_cast` 运算符 * RTTI 如何工作?(底层原理) * ① 编译器为多态类型做了什么? * ② 当我们调用对应接口,RTTI底层是如何实现呢? * **`场景 1:typeid(obj)`** * 场景 2:dynamic_cast<Derived*> ( p ) * `std::type_info` 类简介 * RTTI 的开销与争议 * 优点: * 缺点: * 何时使用 RTTI? * 禁用 RTTI操作 * 为什么非多态类型不支持 RTTI? * 总结

By Ne0inhk