模块----modbus_tk中TCP协议简单应用

2024-05-08 19:18

本文主要是介绍模块----modbus_tk中TCP协议简单应用,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


被告知说会考有关modbus_tk这个模块的东东,我和小伙伴们都惊呆了,很是捉鸡啊~~~

关于这个模块,基本上就是零基础,一步步来。以下都是我的个人见解,若有错误请大胆地指出来吧~~



=====================================================================================================================

第一步  做好基本准备工作

=====================================================================================================================


1.查阅modbus本身相关的资料,弄清楚它大概是什么东东

2.安装modbus_tool,里面有个POLL和SLAVE,尽情去调试吧,有利于弄清楚modbus的结构,还可以测试程序哦~~

楼主当时是没有弄modbus_tool,直接进程序瞎倒腾,后来被高手指点才跑去用modbus_tool,果然豁然开朗




=====================================================================================================================

第二步  安装modbus_tk

=====================================================================================================================


在linux和windows上安装会有点不一样,其实就是windows在前面多了一个步骤。

----------------------------------------------------------------------------------------------------------------

linux:

在官网下载完modbus_tk,解压进去就会发现有个setup.py的文件,直接在此目录下打开终端,运行python setup.py  

就会有个提示help告诉你怎么安装,然后用install的那个参数就行了。


windows:

先下载安装一个Modbus Tools.7z的东东,之后就和在linux的操作一样一样的了。

这个东西是安装python其它模块的一个辅助软件,就是说有了这个东西,它才能去装其它的一些模块

linux 本来就有带Modbus Tools,所以可以直接安装

注:这个Modbus Tools.7z是python里面的一个模块,不是前面说的modbus_tool哦~




=====================================================================================================================

第三步  看示例吧·~

=====================================================================================================================


示例一   前辈的示例 (被我改了一些,原始版的木有了,懒得去再打一次,将就用修改版的吧)

------------------------------------------------------------------------------------------------------------

得把slave先运行,才能用master读取或者修改。

#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: slave.py# ------------------------------------------------------------------------------
# 导入外部模块
# ------------------------------------------------------------------------------import struct
import modbus_tk.defines
import modbus_tk.modbus
import modbus_tk.modbus_tcp
import time
import random# ------------------------------------------------------------------------------
# 主程序
# ------------------------------------------------------------------------------try:server = modbus_tk.modbus_tcp.TcpServer()#注意,若是在linux里面运行,端口就不能不写了,否则就要用root才能跑,其它用户只能用1024以上的端口#这里的端口和地址都是默认的,地址是本地:#原来的程序:server = modbus_tk.modbus_tcp.TcpServer(port=502, address='0.0.0.0', timeout_in_sec=3)server.start()slave_1 = server.add_slave(1)slave_1.add_block('block1', modbus_tk.defines.ANALOG_INPUTS, 0, 2)#给slave_1添加一个模块(模块名,只读,地址,长度)while 1:bb = random.random()aa = struct.unpack('>HH', struct.pack('>f', bb))print 'bb:', bbprint "aa:", aaslave_1.set_values('block1', 0, aa)print '========='time.sleep(3)
except:print '============error==========='
finally:print '=========stop========'server.stop()

#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: master.py# ------------------------------------------------------------------------------
# 导入外部模块
# ------------------------------------------------------------------------------import modbus_tk
import modbus_tk.defines
import modbus_tk.modbus
import modbus_tk.modbus_tcp
import struct
import time# ------------------------------------------------------------------------------
# 主程序
# ------------------------------------------------------------------------------try:while 1:master = modbus_tk.modbus_tcp.TcpMaster()#('0.0.0.0', 502)   (master ip 地址,端口)#注意用linux的童鞋们,端口小于1024得用root才能跑起来哦~#为这个问题楼主曾经也折腾了一阵,后来才发现居然是这个原因·····#这里有个问题就是原来我是用'0.0.0.0'这个地址的。#但是它应该不能算一个ip地址了,这个是代表现有的ip地址均可的意思,有种通配符的感觉#在slave中可以用它,但是在master中不行,一定要给它指明一个具体的地址,看来它也有选择困难症master.set_timeout(3)  #timeout表示若超过3秒没有连接上slave就会自动断开#set_timeout(3)不知是何意----重新把timeout时间设置成3秒,在生成master那里就可以进行初始化定义的,若没有自定义就会用默认值aa = master.execute(1, modbus_tk.defines.ANALOG_INPUTS, 0, 2)#(slave id,只读,block地址,长度:即字节乘个数)print 'aa:', aa, 'size', len(aa)bb = struct.unpack('>f', struct.pack('>HH', aa[0], aa[1]))#在slave中,是先打包成'>f'在以'>HH'解包的,在master中刚好相反#struct.unpack里解出来的是一个元组,可以用bb, = 或者输出bb[0]print 'bb:', bb[0]time.sleep(3)
except Exception as e:print '=========error========='print e
finally:print '=======stop======='

查看端口是否已经开放               (用root权限)
/etc/init.d/iptables status
/sbin/iptables -I INPUT -p tcp --dport 5023 -j ACCEPT   # 开启5023端口
/etc/rc.d/init.d/iptables save #保存配置
/etc/rc.d/init.d/iptables restart #重启服务 



示例二   官网的示例       很坑爹····好多错误····不知道怎么会放在官网上的·····果断也被我改了
---------------------------------------------------------------------------------------------------------------------

#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: server_example.py# ------------------------------------------------------------------------------
# 导入外部模块
# ------------------------------------------------------------------------------import modbus_tk
import modbus_tk.modbus_tcp as modbus_tcp
import modbus_tk.defines as mdef
import threading
import sys# ------------------------------------------------------------------------------
# 主程序
# ------------------------------------------------------------------------------logger = modbus_tk.utils.create_logger(name='console', record_format='%(message)s')if __name__ == '__main__':try:logger.info("running...")logger.info("enter 'quit' for closing the server")server = modbus_tcp.TcpServer(port=1152)server.start()#sever.start()可以在加了slave和模块以后,也可以不加直接裸奔~#creates a slave with id 0slave1 = server.add_slave(1)#add 2 blocks of holding registersslave1.add_block('a', mdef.HOLDING_REGISTERS, 0, 100)  #address 0, length 100slave1.add_block('b', mdef.HOLDING_REGISTERS, 200, 20) #address 200, length 20#create another slave with id 5slave5 = server.add_slave(5)slave5.add_block('c', mdef.COILS, 0, 100)slave5.add_block('d', mdef.HOLDING_REGISTERS, 0, 100)#set the values of registers at address 0slave1.set_values('a', 0, range(100))while True:cmd = sys.stdin.readline()if cmd.find('quit')==0:#当输入的只有quit,程序就会退出sys.stdout.write('bye-bye\r\n')sys.exit(0)finally:server.stop()

#!/usr/bin/python
# -*- coding: utf-8 -*-
# filename: master_example.py# ------------------------------------------------------------------------------
# 导入外部模块
# ------------------------------------------------------------------------------
import modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcp# ------------------------------------------------------------------------------
# 主程序
# ------------------------------------------------------------------------------
if __name__ == '__main__':try:#Connect to the slavemaster = modbus_tcp.TcpMaster(port=1152)print master.execute(1, cst.READ_HOLDING_REGISTERS, 10, 3)master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 200, output_value=xrange(12))print master.execute(1, cst.READ_HOLDING_REGISTERS, 10, 3)except modbus_tk.modbus.ModbusError, e:print "Modbus error", e.get_exception_code()except Exception, e2:print "Error", str(e2)


示例三   modbus_tk文件中本身自带的example
---------------------------------------------------------------------------------------------------------------------

slave

#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""Modbus TestKit: Implementation of Modbus protocol in python(C)2009 - Luc Jean - luc.jean@gmail.com(C)2009 - Apidev - http://www.apidev.frThis is distributed under GNU LGPL license, see license.txt
"""import sys#add logging capability
import logging
import threadingimport modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus as modbus
import modbus_tk.modbus_tcp as modbus_tcplogger = modbus_tk.utils.create_logger(name="console", record_format="%(message)s")if __name__ == "__main__":try:#Create the serverserver = modbus_tcp.TcpServer(port=1500)logger.info("running...")logger.info("enter 'quit' for closing the server")server.start()slave_1 = server.add_slave(1)slave_1.add_block('0', cst.COILS, 0, 100)slave_1.set_values('0', 0, range(100))#range(100)为0-99的列表while True:cmd = sys.stdin.readline()#这里是进入程序以后,读取每次输入的命令:以回车来判断命令是否输入完毕args = cmd.split(' ')if cmd.find('quit')==0:#当输入的只有quit,程序就会退出sys.stdout.write('bye-bye\r\n')breakelif args[0]=='add_slave':slave_id = int(args[1])#slave id只能为int?是的server.add_slave(slave_id)sys.stdout.write('done: slave %d added\r\n' % (slave_id))#write到哪里去了?屏幕输出去了~~elif args[0]=='add_block':slave_id = int(args[1])name = args[2]block_type = int(args[3])starting_address = int(args[4])length = int(args[5])slave = server.get_slave(slave_id)slave.add_block(name, block_type, starting_address, length)sys.stdout.write('done: block %s added\r\n' % (name))elif args[0]=='set_values':slave_id = int(args[1])name = args[2]#这个name是slave_id对应的block的名字address = int(args[3])values = []#这里的values只可少设不可多设,否则就报错退出程序for v in args[4:]:#value只能是int,就算是其他数字类型也报错#囧 好奇怪,明明平时int(0.1)也是可以的values.append(int(v))slave = server.get_slave(slave_id)slave.set_values(name, address, values)values = slave.get_values(name, address, len(values))sys.stdout.write('done: values written: %s\r\n' % (str(values)))elif args[0]=='get_values':slave_id = int(args[1])name = args[2]address = int(args[3])length = int(args[4])slave = server.get_slave(slave_id)values = slave.get_values(name, address, length)sys.stdout.write('done: values read: %s\r\n' % (str(values)))else:sys.stdout.write("unknown command %s\r\n" % (args[0]))finally:server.stop()

master

#!/usr/bin/env python
# -*- coding: utf_8 -*-
"""Modbus TestKit: Implementation of Modbus protocol in python(C)2009 - Luc Jean - luc.jean@gmail.com(C)2009 - Apidev - http://www.apidev.frThis is distributed under GNU LGPL license, see license.txt
"""import sys#add logging capability
import loggingimport modbus_tk
import modbus_tk.defines as cst
import modbus_tk.modbus_tcp as modbus_tcplogger = modbus_tk.utils.create_logger("console")if __name__ == "__main__":try:#Connect to the slavemaster = modbus_tcp.TcpMaster(port=1500)master.set_timeout(5.0)logger.info("connected")#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 100, 100))#(slave id,Modbus数据模型,block地址,长度:即字节乘个数)#同一个slave下,不同block的Modbus数据模型可以是不一样的##################################################################################################
#下面的例子都需要自己在slave里面添加slave(需要改下面的id)或block才能实现#-------------------------------------------------------------------------------------------------print cst.COILS                              #1-----1位读写print cst.READ_COILS                         #1-----1位只读print cst.WRITE_SINGLE_COIL                  #5-----1位只写print cst.WRITE_MULTIPLE_COILS               #15----1位写logger.info(master.execute(1, cst.READ_COILS, 0, 10))#一位:所以个数是10,字节是1     若给非0值,均会以1存入   默认值是(0,0,0,0,0,0,0,0,0,0)#只写的,这里会输出modbus的可识别的格式'>HH',即有两个元素的元组:a = logger.info(master.execute(1, cst.WRITE_SINGLE_COIL, 7, output_value=0))#将slave的地址7的value改成1。logger.info(master.execute(1, cst.READ_COILS, 0, 10))#logger.info(master.execute(1, cst.WRITE_MULTIPLE_COILS, 5, output_value=xrange(12)))print 'a =', a # a=None#-------------------------------------------------------------------------------------------------print cst.DISCRETE_INPUTS                    #2-----1位只读print cst.READ_DISCRETE_INPUTS               #2-----1位只读#logger.info(master.execute(1, cst.READ_DISCRETE_INPUTS, 0, 8))#一位:所以个数是8,字节是1     若给非0值,均会以1存入    默认值是(0,0,0,0,0,0,0,0)#-------------------------------------------------------------------------------------------------print cst.HOLDING_REGISTERS           #3-----16位读写print cst.READ_HOLDING_REGISTERS      #3-----16位只读print cst.WRITE_SINGLE_REGISTER       #6-----16位写print cst.WRITE_MULTIPLE_REGISTERS    #16----16位写#这里读取的是之前的信息#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 3))#16位:所以个数是3,字节是16     若给负值,会出错         默认值是(0,0,0)#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 100))#logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 0, output_value=[50, 1, 1, 1, 1, 1, 1, 1]))#从地址0开始,后面8为全是1#logger.info(master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 5, output_value=xrange(12)))#从地址5开始,后面12位是xrange(12)#这里读取的是改变后的信息#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 3))#logger.info(master.execute(1, cst.READ_HOLDING_REGISTERS, 0, 100))#logger.info(master.execute(1, cst.WRITE_SINGLE_REGISTER, 5, output_value=1))#-------------------------------------------------------------------------------------------------print cst.ANALOG_INPUTS               #4-----16位只读print cst.READ_INPUT_REGISTERS        #4-----16位只读#logger.info(master.execute(1, cst.READ_INPUT_REGISTERS, 10, 12))#16位:所以个数是3,字节是16     若给负值,会出错         默认值是(0,0,0,0,0,0,0,0,0,0,0,0)##################################################################################################except modbus_tk.modbus.ModbusError, e:logger.error("%s- Code=%d" % (e, e.get_exception_code()))


更多资料   后来才发现原来modbus_tk文件中自带的doc文件夹下面有源代码的   囧   看那个应该会很不错



=====================================================================================================================
第四步  小总结
=====================================================================================================================
1.在linux上运行除了要注意端口,还要注意的就是防火墙的问题,我是直接把防火墙给关了的。


2.modbus本身可以传输16位无符号整数,如果要传输浮点数或者是32位无符号整数就要进行打包,具体看struct模块。


3.server和master的功能码对应表
===================================================================
对于server(slave):


  modbus_tk.defines.COILS:               1位读写                  1
  modbus_tk.defines.DISCRETE_INPUTS:     1位只读                  2
  modbus_tk.defines.HOLDING_REGISTERS:   16位读写                 3
  modbus_tk.defines.ANALOG_INPUTS:       16位只读                 4
===================================================================
对于master(要于server对应起来):


  modbus_tk.defines.COILS:                       1-----1位读写
  modbus_tk.defines.READ_COILS                   1-----1位只读
  modbus_tk.defines.WRITE_SINGLE_COIL            5-----1位只写,一个个写的,更稳定,但效率低
  modbus_tk.defines.WRITE_MULTIPLE_COILS         15----1位只写,多个一起写,稳定性一般,效率高
-------------------------------------------------------------------
  modbus_tk.defines.DISCRETE_INPUTS:             2-----1位只读
  modbus_tk.defines.READ_DISCRETE_INPUTS         2-----1位只读
 
-------------------------------------------------------------------
  modbus_tk.defines.HOLDING_REGISTERS:           3-----16位读写
  modbus_tk.defines.READ_HOLDING_REGISTERS       3-----16位只读
  modbus_tk.defines.WRITE_SINGLE_REGISTER        6-----16位写,一个个写的,更稳定,但效率低
  modbus_tk.defines.WRITE_MULTIPLE_REGISTERS     16----16位写,多个一起写,稳定性一般,效率高
-------------------------------------------------------------------
  modbus_tk.defines.ANALOG_INPUTS:               4-----16位只读
  modbus_tk.defines.READ_INPUT_REGISTERS         4-----16位只读


===================================================================


这篇关于模块----modbus_tk中TCP协议简单应用的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/971204

相关文章

在Ubuntu上部署SpringBoot应用的操作步骤

《在Ubuntu上部署SpringBoot应用的操作步骤》随着云计算和容器化技术的普及,Linux服务器已成为部署Web应用程序的主流平台之一,Java作为一种跨平台的编程语言,具有广泛的应用场景,本... 目录一、部署准备二、安装 Java 环境1. 安装 JDK2. 验证 Java 安装三、安装 mys

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

基于Qt开发一个简单的OFD阅读器

《基于Qt开发一个简单的OFD阅读器》这篇文章主要为大家详细介绍了如何使用Qt框架开发一个功能强大且性能优异的OFD阅读器,文中的示例代码讲解详细,有需要的小伙伴可以参考一下... 目录摘要引言一、OFD文件格式解析二、文档结构解析三、页面渲染四、用户交互五、性能优化六、示例代码七、未来发展方向八、结论摘要

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一

java中VO PO DTO POJO BO DO对象的应用场景及使用方式

《java中VOPODTOPOJOBODO对象的应用场景及使用方式》文章介绍了Java开发中常用的几种对象类型及其应用场景,包括VO、PO、DTO、POJO、BO和DO等,并通过示例说明了它... 目录Java中VO PO DTO POJO BO DO对象的应用VO (View Object) - 视图对象

Go信号处理如何优雅地关闭你的应用

《Go信号处理如何优雅地关闭你的应用》Go中的优雅关闭机制使得在应用程序接收到终止信号时,能够进行平滑的资源清理,通过使用context来管理goroutine的生命周期,结合signal... 目录1. 什么是信号处理?2. 如何优雅地关闭 Go 应用?3. 代码实现3.1 基本的信号捕获和优雅关闭3.2

Java如何接收并解析HL7协议数据

《Java如何接收并解析HL7协议数据》文章主要介绍了HL7协议及其在医疗行业中的应用,详细描述了如何配置环境、接收和解析数据,以及与前端进行交互的实现方法,文章还分享了使用7Edit工具进行调试的经... 目录一、前言二、正文1、环境配置2、数据接收:HL7Monitor3、数据解析:HL7Busines

正则表达式高级应用与性能优化记录

《正则表达式高级应用与性能优化记录》本文介绍了正则表达式的高级应用和性能优化技巧,包括文本拆分、合并、XML/HTML解析、数据分析、以及性能优化方法,通过这些技巧,可以更高效地利用正则表达式进行复杂... 目录第6章:正则表达式的高级应用6.1 模式匹配与文本处理6.1.1 文本拆分6.1.2 文本合并6

python中的与时间相关的模块应用场景分析

《python中的与时间相关的模块应用场景分析》本文介绍了Python中与时间相关的几个重要模块:`time`、`datetime`、`calendar`、`timeit`、`pytz`和`dateu... 目录1. time 模块2. datetime 模块3. calendar 模块4. timeit

Python模块导入的几种方法实现

《Python模块导入的几种方法实现》本文主要介绍了Python模块导入的几种方法实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学... 目录一、什么是模块?二、模块导入的基本方法1. 使用import整个模块2.使用from ... i