赞
踩
一、三菱FX5U 从站设置
1. 打开GX works3 软件
2. 新建项目
3.按向导流程指示设置modbus-tcp从站功能
4.下载模块参数到PLC,并断电重启PLC。
注意:部分PLC会发生模块参数报警,需要PLC做固件升级。
二、PC端设置
1. pip install modbus-tk,struct
2. main.py
- import modbus_tk
- import modbus_tk.defines as cst
- import modbus_tk.modbus_tcp as modbus_tcp
- from shuJuZhuangHuang import WriteDint as wd
- import os
- import tkinter as tk
- import tkinter.font as tkFont
- import tkinter.ttk as ttk
- import csv
- from socket import *
- import sys
- import threading
- import time,random,queue
- import pickle
- import re
- from configparser import ConfigParser
- logger = modbus_tk.utils.create_logger("console")
-
- # 读取配置文件
- cfg = ConfigParser()
- cfg.read('config.ini')
- SERVER= cfg.get('Server','IP')
- PORT= cfg.getint('Server','PORT')
- MACROFILE = cfg.get('File','macroFile')
- MACROCOPY = cfg.get('File','macroCopy')
-
- timeSave = os.path.getmtime(MACROFILE)
-
-
- # 打包函数
- def thread_it(func,*args):
- '''将函数打包进程'''
- # 创建进程
- t = threading.Thread(target=func,args=args)
- # 守护进程
- t.setDaemon(True)
- # 启动
- t.start()
-
-
- class GuiPart():
- def __init__(self):
- self.threadFlg1 = True
- self.caiLiao = 0
- self.jiaGongZongShu = 0
- self.gongJianChanDu = 0
- self.qiShiWeiZhi1 = 0
- self.jieShuWeiZhi1 = 0
- self.qiShiWeiZhi2 = 0
- self.jieShuWeiZhi2 = 0
- self.qiShiWeiZhi3 = 0
- self.jieShuWeiZhi3 = 0
- self.qiShiWeiZhi4 = 0
- self.jieShuWeiZhi4 = 0
- self.tuiHuoCiShu = 0
- self.xieRuFlg = 0 # 写入允许-0 禁止-1
-
- # 连接MODBUS TCP从机
- try:
- master = modbus_tcp.TcpMaster(host=SERVER,port=PORT)
- master.set_timeout(5.0)
- self.master = master
- except modbus_tk.modbus.ModbusError as e:
- logger.error("%s- Code=%d" % (e, e.get_exception_code()))
-
- thread_it(self.readMacro)
- self.guiProcess()
-
-
- # 调整屏幕
- def center_window(self,root,w,h):
- '''
- 窗口居于屏幕中央
- :param root: root
- :param w: 窗口宽度
- :param h: 窗口高度
- :return:
- '''
- # 获取屏幕 宽、高
- ws = root.winfo_screenwidth()
- hs = root.winfo_screenheight()
- # 计算x、y位置
- x = (ws/2) - (w/2)
- y = (hs/2) - (h/2)
- root.geometry('%dx%d+%d+%d' %(w,h,x,y))
-
-
- def send(self):
- try:
- # # 写寄存器起始地址为500的保持寄存器,操作寄存器个数为1
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 500 , output_value=[self.caiLiao]))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 604, output_value=[self.jiaGongZongShu]))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 608, output_value=wd(self.gongJianChanDu)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4606, output_value=wd(self.qiShiWeiZhi1)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4608, output_value=wd(self.jieShuWeiZhi1)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4610, output_value=wd(self.qiShiWeiZhi2)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4612, output_value=wd(self.jieShuWeiZhi2)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4614, output_value=wd(self.qiShiWeiZhi3)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4616, output_value=wd(self.jieShuWeiZhi3)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4618, output_value=wd(self.qiShiWeiZhi4)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4620, output_value=wd(self.jieShuWeiZhi4)))
- logger.info(self.master.execute(1, cst.WRITE_MULTIPLE_REGISTERS, 4622, output_value=[self.tuiHuoCiShu]))
- except modbus_tk.modbus.ModbusError as e:
- logger.error("%s- Code=%d" % (e, e.get_exception_code()))
-
-
- def reset(self):
- print('reset')
- self.threadFlg1 = True
- thread_it(self.readMacro)
-
-
- def readMacro(self):
- global timeSave
-
- while self.threadFlg1:
- time.sleep(0.2)
- # 读取PLC M4606 写入标志
- try:
- self.xieRuFlg = self.master.execute(2, cst.READ_COILS, 9228, 1)[0]
- except modbus_tk.modbus.ModbusError as e:
- logger.error("%s- Code=%d" % (e, e.get_exception_code()))
-
- """
- # print("flg: " )
- self.xieRuFlg = 1
- print(self.xieRuFlg)
- """
-
- # 如果写入标志==0可以写入,否则禁止更新。
- if self.xieRuFlg == 0:
- timeLast = os.path.getmtime(MACROFILE)
- # print(timeLast,' > ',timeSave)
- if timeLast > timeSave:
- # print('time change')
- timeSave = timeLast
- os.system(r'copy %s %s'%(MACROFILE,MACROCOPY))
- f = open (MACROCOPY,'r')
- fileLines = f.readlines()
- f.close()
- # 读取数据
- for item in fileLines:
- patt = r'(\d+)\D+?((-)?\d+\.?\d{0,3})' # 匹配 500 = 34 500=34 500 = 34. 500 =34.5 500 = -34.565 不完全匹配 34.34352345
- m = re.match(patt,item)
- if m:
- shapu = m.group(1)
- data = m.group(2)
- # 读取变量
- if shapu == '500':
- self.caiLiao = int(data)
- elif shapu == '501':
- self.jiaGongZongShu = int(data)
- elif shapu == '502':
- self.gongJianChanDu = int(float (data) * 10000)
- elif shapu == '503':
- self.qiShiWeiZhi1 = int(float (data) * 10000)
- elif shapu == '504':
- self.jieShuWeiZhi1 =int(float (data) * 10000)
- elif shapu == '505':
- self.qiShiWeiZhi2 =int(float (data) * 10000)
- elif shapu == '506':
- self.jieShuWeiZhi2 =int(float (data) * 10000)
- elif shapu == '507':
- self.qiShiWeiZhi3 =int(float (data) * 10000)
- elif shapu == '508':
- self.jieShuWeiZhi3 =int(float (data) * 10000)
- elif shapu == '509':
- self.qiShiWeiZhi4 =int(float (data) * 10000)
- elif shapu == '510':
- self.jieShuWeiZhi4 =int(float (data) * 10000)
- elif shapu == '511':
- self.tuiHuoCiShu = int(data)
- self.send()
- self.l_0_state.configure(bg = 'green')
- self.varState.set("数据已更新!")
-
- else:
- #设置标签为红色
- # print("help")
- self.l_0_state.configure(bg = 'red')
- self.varState.set("设备运行中,禁止写入。设备停止后自动更新数据,请注意!")
-
- self.threadFlg1 = False
-
-
- # 定义Gui界面
- def guiProcess(self):
- '''
- GUI主界面
- :param
- :retuen
- '''
- root=tk.Tk()
- self.root = root
- # 设置窗口位置
- root.title('********* V1')
- self.center_window(root,400,120)
- root.resizable(0,0)# 窗体大小可调整,分别表示x、y方向的可变性
-
- # 设置字体
- ft20 =tkFont.Font(family = 'Fixdsys',size = 20,weight = tkFont.BOLD)
- ft30 =tkFont.Font(family = 'Fixdsys',size = 30,weight = tkFont.BOLD)
- ft40 =tkFont.Font(family = 'Fixdsys',size = 40,weight = tkFont.BOLD)
- ft50 =tkFont.Font(family = 'Fixdsys',size = 50,weight = tkFont.BOLD)
- ft55 =tkFont.Font(family = 'Fixdsys',size = 55,weight = tkFont.BOLD)
- ft80 =tkFont.Font(family = 'Fixdsys',size = 80,weight = tkFont.BOLD)
-
- # 设置标签窗体
- labelFm1= tk.LabelFrame(root)
- labelFm1.pack(padx=5,pady=5,side=tk.TOP,fill=tk.X)
- self.labelFm1 = labelFm1
-
- # labelFm1
- self.varState = tk.StringVar()
- self.varState.set('*'*10)
- l_0_state = tk.Label(labelFm1,textvariable =self.varState )
- l_0_state.grid(row=0,column=0,padx=5,pady=5)
- self.l_0_state = l_0_state
- self.l_0_state.configure(bg = 'green')
-
- button1 = tk.Button(labelFm1,text= "RESET" ,font=ft20)
- button1.grid(row=3,column=0,padx = 5,pady=5)
- self.button1 = button1
-
- # 定义事件响应
- button1.configure(command=self.reset) # 系统复位
-
- root.mainloop()
-
- self.threadFlg1 = False
- print('self.threadFlg1 = ',self.threadFlg1)
-
-
- if __name__=='__main__':
- ui = GuiPart()

3. shuJuZhuangHuang.py 作为数据转换模块使用
- import struct
-
- def ReadFloat(*args,reverse=False):
- for n,m in args:
- n,m = '%04x'%n,'%04x'%m
- if reverse:
- v = n + m
- else:
- v = m + n
- y_bytes = bytes.fromhex(v)
- y = struct.unpack('!f',y_bytes)[0]
- y = round(y,6)
- return y
-
- def WriteFloat(value,reverse=False):
- y_bytes = struct.pack('!f',value)
- # y_hex = bytes.hex(y_bytes)
- y_hex = ''.join(['%02x' % i for i in y_bytes])
- n,m = y_hex[:-4],y_hex[-4:]
- n,m = int(n,16),int(m,16)
- if reverse:
- v = [n,m]
- else:
- v = [m,n]
- return v
-
- def ReadDint(*args,reverse=False):
- for n,m in args:
- n,m = '%04x'%n,'%04x'%m
- if reverse:
- v = n + m
- else:
- v = m + n
- y_bytes = bytes.fromhex(v)
- y = struct.unpack('!i',y_bytes)[0]
- return y
-
- def WriteDint(value,reverse=False):
- y_bytes = struct.pack('!i',value)
- # y_hex = bytes.hex(y_bytes)
- y_hex = ''.join(['%02x' % i for i in y_bytes])
- n,m = y_hex[:-4],y_hex[-4:]
- n,m = int(n,16),int(m,16)
- if reverse:
- v = [n,m]
- else:
- v = [m,n]
- return v
-
- if __name__ == "__main__":
- print(ReadFloat((15729,16458)))
- print(WriteFloat(3.16))
- print(ReadDint((1734,6970)))
- print(WriteDint(456787654))

4. 添加配置文件 config.ini
- ;config.ini
-
- [Server]
- IP=192.168.3.39
- PORT=502
-
- [File]
- macroFile=c:\\macro\\macro.txt
- macroCopy=macro.txt
5.添加macro.txt文本
- 500 = 2
- 501 = 3
- 502 = 40.03
- 503 = 5.5
- 504 = 6.6
- 505 = 7.8
- 506 = 8.8
- 507 = 9.6
- 508 = 8.7
- 509 = 7.7
- 510 = 6.7
- 511 = 3
6.添加指令定义
- #modbus exception codes
- ILLEGAL_FUNCTION = 1
- ILLEGAL_DATA_ADDRESS = 2
- ILLEGAL_DATA_VALUE = 3
- SLAVE_DEVICE_FAILURE = 4
- COMMAND_ACKNOWLEDGE = 5
- SLAVE_DEVICE_BUSY = 6
- MEMORY_PARITY_ERROR = 8
-
- #supported modbus functions
- RAW = 0
- READ_COILS = 1
- READ_DISCRETE_INPUTS = 2
- READ_HOLDING_REGISTERS = 3
- READ_INPUT_REGISTERS = 4
- WRITE_SINGLE_COIL = 5
- WRITE_SINGLE_REGISTER = 6
- READ_EXCEPTION_STATUS = 7
- DIAGNOSTIC = 8
- REPORT_SLAVE_ID = 17
- WRITE_MULTIPLE_COILS = 15
- WRITE_MULTIPLE_REGISTERS = 16
- READ_FILE_RECORD = 20
- READ_WRITE_MULTIPLE_REGISTERS = 23
- DEVICE_INFO = 43
-
- #supported block types
- COILS = 1
- DISCRETE_INPUTS = 2
- HOLDING_REGISTERS = 3
- ANALOG_INPUTS = 4

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。