我的编程空间,编程开发者的网络收藏夹
学习永远不晚

python使用pymodbus库进行modbus tcp通信

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

python使用pymodbus库进行modbus tcp通信

使用python解决工业通信问题是一个非常好的选择,python具有丰富的生态,可以轻松解决工业通信的各种问题。本篇主要介绍使用pymodbus库进行modbus tcp仿真,实现pc端读取plc或工业设备modbus变量。

安装pymodbus:

pip install -U pymodbus

1 创建modbus tcp server

这里我们先创建一个虚拟的modbus设备,如果你手里有一个plc或者工业设备,可以直接跳过本节。

modbus_server.py

''' * @Author: liuzhao  * @Last Modified time: 2022-10-05 09:56:13 '''from pymodbus.server.sync import (    StartTcpServer,)from pymodbus.datastore import (    ModbusSequentialDataBlock,    ModbusServerContext,    ModbusSlaveContext,)from pymodbus.version import versiondatablock = ModbusSequentialDataBlock.create()context = ModbusSlaveContext(    di=datablock,    co=datablock,    hr=datablock,    ir=datablock,    )single = True# Build data storagestore = ModbusServerContext(slaves=context, single=single)if __name__ == '__main__':address = ("0.0.0.0", 503)StartTcpServer(    context=store,  # Data storage    address=address,  # listen address  allow_reuse_address=True,  # allow the reuse of an address)

直接运行该脚本,就可以在本机的503端口创建一台modbus设备了,具体实现暂不深追,我们学习的重点是客户端对modbus变量的读写。

2 读写modbus变量

modbus变量类型以及地址

Object typeAccessSizeAddress
CoilRead-write1 bit00001 – 09999
Discrete inputRead-only1 bit10001 – 19999
Input registerRead-only16 bits30001 – 39999
Holding registerRead-write16 bits40001 – 49999

coil是线圈,Discrete input是数字量输入,Input register是模拟量输入,Holding register是保持寄存器。一般地址范围是0-65535 [wiki]

2.1 读取常规变量

读写线圈 | 读取输入变量 | 读写保持寄存器

from pymodbus.client.sync import ModbusTcpClientfrom pymodbus.bit_read_message import ReadCoilsResponsefrom pymodbus.register_read_message import ReadInputRegistersResponsefrom pymodbus.exceptions import ConnectionException      # 连接失败,用于异常处理host = '127.0.0.1'port = 503client = ModbusTcpClient(host,port)# 写入线圈client.write_coil(1, True)client.write_coil(2, False)client.write_coil(3, True)# 读取线圈    注意对于离散量的读取,第二个参数cout是有坑的,必须为8的倍数个result:ReadCoilsResponse = client.read_coils(address=1,cout=8)     # 从地址1开始读,读取8个线圈,一次读8的倍数个线圈,不设置为8的倍数可能会出现问题print(result.isError())# 不建议使用print(result.getBit(7))            # 这里的参数address不是plc里的地址,而是python列表的address,print('read_coils ')# 建议使用print(result.bits)        # 打印读取结果,一共8位# 读取其中的位print(                       result.bits[0],    result.bits[1],    result.bits[2]    )         # 相当于result.getBit(0)# 读取数字输入result = client.read_discrete_inputs(address=10001,count=8)    # 从10001开始读,读取8位print(result.bits)# 读取模拟输入寄存器input_register_result:ReadInputRegistersResponse = client.read_input_registers(1,count=8)# print(f'is_error:{input_register_result.isError()}')print('read_input_registers ')print(input_register_result.registers)   print(input_register_result.getRegister(0))   # 读写保持寄存器client.write_register(address=40001,value=100)result:ReadInputRegistersResponse = client.read_holding_registers(address=40001,count=1)print('read_holding_registers ')print(result.registers)# 关闭连接client.close()

2.2 读取复杂变量

字符串、浮点数、负数等
这里需要注意modbus设备的存储结构是低位低字节还是低位高字节,也就是设备内存的字节、字的排列顺序。

  根据不同的设备,对照下表调整正确的组合方式。
Word OrderByte orderWord1Word2
BigBig0x12340x5678
BigLittle0x34120x7856
LittleBig0x56780x1234
LittleLittle0x78560x3412
# 复杂数据类型from collections import OrderedDictimport loggingfrom pymodbus.client.sync import ModbusTcpClient as ModbusClientfrom pymodbus.constants import Endianfrom pymodbus.payload import BinaryPayloadBuilder, BinaryPayloadDecoderORDER_DICT = {"<": "LITTLE", ">": "BIG"}def run_binary_payload_client(host:str,port:int):      for word_endian, byte_endian in (        (Endian.Big, Endian.Big),        (Endian.Big, Endian.Little),        (Endian.Little, Endian.Big),        (Endian.Little, Endian.Little),    ):        print("-" * 60)        print(f"Word Order: {ORDER_DICT[word_endian]}")        print(f"Byte Order: {ORDER_DICT[byte_endian]}")        print()            builder = BinaryPayloadBuilder(            wordorder=word_endian,            byteorder=byte_endian,        )# 写入的变量        my_string = "abcd-efgh123345765432"        builder.add_string(my_string)        builder.add_bits([0, 1, 0, 1, 1, 0, 1, 0])        builder.add_8bit_int(-0x12)        builder.add_8bit_uint(0x12)        builder.add_16bit_int(-0x5678)        builder.add_16bit_uint(0x1234)        builder.add_32bit_int(-0x1234)        builder.add_32bit_uint(0x12345678)        builder.add_16bit_float(12.34)        builder.add_16bit_float(-12.34)        builder.add_32bit_float(22.34)        builder.add_32bit_float(-22.34)        builder.add_64bit_int(-0xDEADBEEF)        builder.add_64bit_uint(0x12345678DEADBEEF)        builder.add_64bit_uint(0x12345678DEADBEEF)        builder.add_64bit_float(123.45)        builder.add_64bit_float(-123.45)        registers = builder.to_registers()        print("Writing Registers:")        print(registers)        print("\n")        payload = builder.build()        address = 40001          # 从40001开始写入        # We can write registers        client.write_registers(address, registers, unit=1)    # 写入          # 读取复杂变量        print("Reading Registers:")        address = 40001        count = len(payload)        print(f"payload_len {count}")        result = client.read_holding_registers(address, count, slave=1)        print(result.registers)        print("\n")        decoder = BinaryPayloadDecoder.fromRegisters(            result.registers, byteorder=byte_endian, wordorder=word_endian        )        # Make sure word/byte order is consistent between BinaryPayloadBuilder and BinaryPayloadDecoder        assert (            decoder._byteorder == builder._byteorder  # pylint: disable=protected-access        )  # nosec        assert (            decoder._wordorder == builder._wordorder  # pylint: disable=protected-access        )  # nosec        decoded = OrderedDict(            [                ("string", decoder.decode_string(len(my_string))),                ("bits", decoder.decode_bits()),                ("8int", decoder.decode_8bit_int()),                ("8uint", decoder.decode_8bit_uint()),                ("16int", decoder.decode_16bit_int()),                ("16uint", decoder.decode_16bit_uint()),                ("32int", decoder.decode_32bit_int()),                ("32uint", decoder.decode_32bit_uint()),                ("16float", decoder.decode_16bit_float()),                ("16float2", decoder.decode_16bit_float()),                ("32float", decoder.decode_32bit_float()),                ("32float2", decoder.decode_32bit_float()),                ("64int", decoder.decode_64bit_int()),                ("64uint", decoder.decode_64bit_uint()),                ("ignore", decoder.skip_bytes(8)),                ("64float", decoder.decode_64bit_float()),                ("64float2", decoder.decode_64bit_float()),            ]        )        print("Decoded Data")        for name, value in iter(decoded.items()):            print(                "%s\t" % name,  # pylint: disable=consider-using-f-string                hex(value) if isinstance(value, int) else value,            )        print("\n")# 关闭连接    client.close()if __name__ == "__main__":    run_binary_payload_client("127.0.0.1", 503)    

相关资料

modbus tcp 通信协议
2、modbus tcp 通信协议2
3、pymodbus官方文档
4、pymodbus仓库

欢迎转载

来源地址:https://blog.csdn.net/brandon_l/article/details/127169641

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

python使用pymodbus库进行modbus tcp通信

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

使用TCP协议在Go语言中进行网络通信

目前编程网上已经有很多关于Golang的文章了,自己在初次阅读这些文章中,也见识到了很多学习思路;那么本文《使用TCP协议在Go语言中进行网络通信》,也希望能帮助到大家,如果阅读完后真的对你学习Golang有帮助,欢迎动动手指,评论留言并分
使用TCP协议在Go语言中进行网络通信
2024-04-04

利用TCP进行通信出现丢包如何解决

这篇文章给大家介绍利用TCP进行通信出现丢包如何解决,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。如果通信中发现缺少数据或者丢包,那么,最大的可能在于程序发送的过程或者接收的过程出现问题。例如服务器给客户端发大量数据,
2023-05-31

Android进程间使用Intent进行通信

Android进程间通信(IPC,Inter-ProcessCommunication)底层采用的是Binder机制,具体到应用层有网友根据安卓四大组件将进程间通信方式分为对应的四种方式Activity,Broadcast,ContentProvider,Service
2023-02-28

Android怎么使用GRPC进行通信

这篇文章主要介绍“Android怎么使用GRPC进行通信”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Android怎么使用GRPC进行通信”文章能帮助大家解决问题。引言Android作为一个开发平
2023-07-05

Android进程间如何使用Intent进行通信

这篇文章主要介绍“Android进程间如何使用Intent进行通信”,在日常操作中,相信很多人在Android进程间如何使用Intent进行通信问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Android进程
2023-07-05

如何使用 Golang 协程进行通信?

在 go 中使用协程进行通信,通道是一种基本机制,用于在协程之间发送和接收数据。通过使用发送(使用 Golang 协程进行通信在 Go 语言中,协程提供了并发编程的一种轻量级且高效的方式。它们允许在单个线程上下文中同时执行多个任务,从而提
如何使用 Golang 协程进行通信?
2024-05-21

如何使用Python中的socket编程进行数据通信

标题:Python中的socket编程及代码示例引言:在现代互联网时代,数据通信无处不在。而Python中的socket编程提供了一种简单而有效的方式来实现网络上的数据传输。本文将介绍如何使用Python的socket模块来进行数据通信,并
2023-10-22

Android使用GRPC进行通信过程解析

这篇文章主要给大家介绍了在Android上使用grpc的方法教程,文中通过示例代码给大家详细介绍了在android上使用grpc的方法以及可能遇到的种种问题的解决方法,对大家具有一定的参考学习价值,需要的朋友们下面来一起看看吧
2023-02-28

Blazor 组件之间使用 EventCallback 进行通信

Blazor 应用程序是相互交互的多个 Blazor 组件的集合,我们可以在其他父组件中使用子组件。在实际的应用程序中,将数据或事件信息从一个组件传递到另一组件是一种十分常见的场景。

如何使用Python中的进程间通信

如何使用Python中的进程间通信进程间通信(IPC,Inter-Process Communication)是计算机科学中一个重要的概念,它允许不同的进程在同一个计算机系统中进行数据交换和共享资源。在Python中,有多种方式可以实现进程
2023-10-22

如何使用Golang与RabbitMQ进行高效通信?

要使用Golang与RabbitMQ进行高效通信,可以按照以下步骤进行操作:1. 安装RabbitMQ:首先需要安装RabbitMQ消息队列服务器。可以从RabbitMQ官方网站下载并安装RabbitMQ,或者通过包管理器安装。2. 安装R
2023-10-08

golang函数如何使用管道进行通信

在 go 中,管道是用于 goroutine 之间通信的 fifo 队列。创建一个管道:使用 make(chan t) 函数,其中 t 是管道中数据类型。发送数据:使用 ch Go 中使用管道进行函数通信在 Go 中,管道是一种轻量级的通
golang函数如何使用管道进行通信
2024-04-30

使用 python 进行微信好友分析

使用 python 进行微信好友分析1. 使用到的库① wxpy:初始化微信机器人② openpyxl:保存微信好友数据为Excel表格③ pyecharts:生成可视化的地图④ wordcloud、matplotlib、jieba:生成词
2023-01-31

Python项目实战:使用多线程进行TCP端口扫描

前言今天为大家一个利用Python扫描开放主机的TCP端口,首先你要查看其中的开放的端口,创建一个TCP全连接扫描器,一般使用socket来创建连接器的,测试当前主机和端口是否开放,直接使用socket连接导入第三方库
2023-06-02

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录