python pymodbus库使用教程(以Modbus RTU为例)(read

2024-06-04 5754阅读

文档:

https://pymodbus.readthedocs.io/en/latest/

源码:

https://github.com/riptideio/pymodbus/

文章目录

  • Python PyModbus库使用教程:以Modbus RTU为例
    • 介绍
    • 安装PyModbus
    • 配置串行连接
      • 导入必要的模块
      • 创建Modbus客户端实例
      • 建立连接
        • 连接到Modbus设备
        • 读取数据
          • 读取寄存器
          • 关于读取其他寄存器以及查找pymodbus函数源码
          • 写入数据
            • 写入单个寄存器
            • 写入多个寄存器
            • 处理异常
            • 断开连接
            • 高级主题
              • 异步客户端(使用Twisted或Asyncio框架)
              • 自定义消息
              • 日志记录
              • 实例
                • 1. 使用RS485 modbus协议读取温度湿度传感器数据

                  Python PyModbus库使用教程:以Modbus RTU为例

                  介绍

                  Modbus是一种工业领域广泛使用的通信协议,而PyModbus是一个在Python中实现Modbus通信的库。它支持多种Modbus模式,包括RTU(通过串行线路),ASCII和TCP/IP。本教程将重点介绍如何使用PyModbus库进行Modbus RTU通信。

                  安装PyModbus

                  在开始编写代码之前,需要确保已经安装了PyModbus库。可以使用pip命令轻松地安装:

                  pip install pymodbus
                  

                  配置串行连接

                  导入必要的模块

                  首先,需要从pymodbus库中导入必要的模块:

                  from pymodbus.client.sync import ModbusSerialClient as ModbusClient
                  

                  不知道是不是改版了,我用上面导入报错,用下面的可以:

                  from pymodbus.client import ModbusSerialClient as ModbusClient
                  

                  创建Modbus客户端实例

                  接下来,创建一个ModbusClient实例,用于建立与Modbus设备的RTU通信:

                  client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600)
                  

                  在这里,method参数设置为'rtu'以指定通信协议,port参数根据实际连接的串行端口进行设置(例如Linux系统中可能是'/dev/ttyUSB0',Windows中可能是'COM3'),baudrate参数设置传输速率,这些参数应与设备文档或配置相匹配。

                  建立连接

                  连接到Modbus设备

                  在配置好客户端实例后,尝试连接到Modbus设备:

                  if client.connect():
                      print("Modbus RTU Client Connected")
                  else:
                      print("Failed to connect to Modbus RTU Client")
                  

                  读取数据

                  读取寄存器

                  Modbus协议定义了几种类型的寄存器,最常见的是保持寄存器和输入寄存器。以下示例展示了如何读取保持寄存器:

                  response = client.read_holding_registers(address=1, count=10, unit=1)
                  if not response.isError():
                      print("Register Values: ", response.registers)
                  else:
                      print("Failed to read registers")
                  

                  在这个例子中,read_holding_registers方法用于读取地址为1的起始位置、数量为10的连续寄存器。unit参数表示从哪个单元(即设备ID)读取数据。

                  注意:pymodbus某个版本已将unit字段改为slave。使用时即使写错也不会报错,注意查看你的pymodbus文档。

                  关于读取其他寄存器以及查找pymodbus函数源码

                  首先应该先通过厂商文档,看传感器要求用什么功能码去读取寄存器数据,拿到功能码后,转换成响应的函数,比如0x03是“输入寄存器(Input Register)”,0x04是“保持寄存器(Holding Register)”,这在这里可以查到。

                  然后可以到python modbus库中搜源码,我用的虚拟环境,直接在ide里还链接不过去,所以我用fileLocator pro工具直接搜源码,搜到这两个玩意:

                  python pymodbus库使用教程(以Modbus RTU为例)(read 第1张

                  python pymodbus库使用教程(以Modbus RTU为例)(read 第2张

                  接下来就能知道函数该怎么调用了。

                  写入数据

                  写入单个寄存器

                  要向设备的单个寄存器写入数据,可以使用以下代码:

                  write_response = client.write_register(address=1, value=25, unit=1)
                  if not write_response.isError():
                      print("Written successfully")
                  else:
                      print("Failed to write register")
                  

                  这里使用了write_register方法,它接受地址、要写入的值以及目标设备的单元ID。

                  写入多个寄存器

                  如果要写入多个寄存器,可以使用write_registers方法:

                  values = [20, 40, 60, 80, 100]
                  write_response = client.write_registers(address=1, values=values, unit=1)
                  if not write_response.isError():
                      print("Multiple registers written successfully")
                  else:
                      print("Failed to write multiple registers")
                  

                  这里values列表包含了要写入寄存器的值序列。

                  处理异常

                  处理Modbus通信过程中可能出现的异常非常重要,可以使用try-except语句捕获这些异常:

                  from pymodbus.exceptions import ModbusException
                  try:
                      # 尝试执行Modbus操作
                      response = client.read_holding_registers(address=1, count=10, unit=1)
                  except ModbusException as ex:
                      print("An error occurred:", str(ex))
                  

                  断开连接

                  在完成所有Modbus通信后,应该关闭与设备的连接:

                  client.close()
                  print("Modbus RTU Client Connection Closed")
                  

                  调用close()方法将关闭串行端口,并释放相关资源。

                  高级主题

                  异步客户端(使用Twisted或Asyncio框架)

                  除了同步客户端,PyModbus还提供了异步客户端选项,可以使用Twisted或Asyncio框架。异步客户端允许程序在等待响应时执行其他任务,对于需要同时处理多个Modbus请求的应用非常有用。

                  自定义消息

                  有时候,标准的Modbus函数不足以满足特定的需求。PyModbus允许创建自定义消息和事务处理器,使得可以扩展协议以适应特殊用例。

                  日志记录

                  调试和监控Modbus通信过程中,日志记录功能至关重要。PyModbus提供了详细的日志记录机制,可以帮助分析问题所在。

                  实例

                  1. 使用RS485 modbus协议读取温度湿度传感器数据

                  # 请先安装 pymodbus 和 pyserial
                  # pip install pymodbus
                  # pip install pyserial
                  # from pymodbus.client.sync import ModbusSerialClient as ModbusClient   # 报错,说找不到 sync
                  from pymodbus.client import ModbusSerialClient as ModbusClient
                  from pymodbus.exceptions import ModbusException, ConnectionException
                  import logging
                  # 配置日志记录
                  logging.basicConfig()
                  log = logging.getLogger()
                  log.setLevel(logging.DEBUG)
                  # 初始化Modbus串行客户端
                  # client = ModbusClient(method='rtu', port='/dev/ttyUSB0', baudrate=9600, timeout=3)    # [Errno 2] could not open port /dev/ttyUSB0: [Errno 2] No such file or directory: '/dev/ttyUSB0'
                  # client = ModbusClient(method='rtu', port='/dev/ttyTHS1', baudrate=9600, timeout=3)
                  # ttyTHS4 ttyS0 ttyS1 ttyS2 ttyS4
                  # client = ModbusClient(method='rtu', port='/dev/ttyTHS1', baudrate=9600, timeout=3)
                  # client = ModbusClient(method='rtu', port='/dev/ttyTHS0', baudrate=9600, timeout=3, stopbits=1, bytesize=8, parity='N')
                  client = ModbusClient(port='/dev/ttyTHS0', baudrate=9600, timeout=3,
                                        stopbits=1, bytesize=8, parity='N')    # 看文档,method='rtu'貌似没用
                  def read_temperature_and_humidity(client):
                      try:
                          # 读取寄存器地址0和1上的4个字节(两个寄存器)
                          # result = client.read_input_registers(address=0, count=3, unit=1)  # 这个错了,这是读取输入寄存器的)0x04
                          # result = client.read_holding_registers(address=0, count=3, unit=1)  # 这个才是读取输入寄存器的0x03  # unit参数错了,当前pymodbus版本没有这个参数,搞乌龙了,要不是用filelocator搜索函数用法,还真不知道- -
                          result = client.read_holding_registers(
                              address=0, count=2, slave=1)  # 读取输入寄存器的0x03 # 读两个寄存器就ok,卖家说第三个寄存器是预留的,不用读
                          if result.isError():
                              # 处理错误
                              print("读取错误:", result)
                              return None, None
                          # 将读取到的结果转换为温度和湿度
                          registers = result.registers
                          temperature_reg = registers[0]
                          humidity_reg = registers[1]
                          # 检查是否有探头错误
                          if temperature_reg == 0x8000 or humidity_reg == 0x8000:
                              print("探头错误")
                              return None, None
                          # 计算实际的温度和湿度值
                          temperature = temperature_reg * 0.1
                          humidity = humidity_reg * 0.1
                          # 格式化温度和湿度值,保留一位小数
                          temperature = round(temperature, 1)
                          humidity = round(humidity, 1)
                          return temperature, humidity
                      except ModbusException as e:
                          print("Modbus异常:", e)
                          return None, None
                      except Exception as e:
                          # 捕获除ModbusException之外的所有异常
                          print(f"An error occurred: {e}")
                          return None, None
                  def main():
                      try:
                          if client.connect():  # 尝试连接到Modbus服务器/设备
                              temperature, humidity = read_temperature_and_humidity(client)
                              if temperature is not None and humidity is not None:
                                  print(f"温度: {temperature}°C, 湿度: {humidity}%RH")
                              client.close()  # 关闭连接
                          else:
                              print("无法连接到Modbus设备")
                      except ConnectionException as e:
                          print("连接异常:", e)
                  if __name__ == "__main__":
                      main()
                  

                  运行结果:

                  python pymodbus库使用教程(以Modbus RTU为例)(read 第3张


    免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们,邮箱:ciyunidc@ciyunshuju.com。本站只作为美观性配图使用,无任何非法侵犯第三方意图,一切解释权归图片著作权方,本站不承担任何责任。如有恶意碰瓷者,必当奉陪到底严惩不贷!

    目录[+]