2020.11.09更新VD和VW区读写代码
问题描述
网上有很多关于如何用Python读写plc的I、Q、M、DB区的文章和代码,但是如果实践中需要用到V区,那些文章将不太可行。
他们的方法都是使用def read_area(self, area, dbnumber, start, size)和write_area(self, area, dbnumber, start, data):函数读写I\Q\M区不同类型寄存器的值,但是如果我们想读写VB区的值呢?
解决办法
据测试,VB区即为DB寄存器中的B区(就是在DB区以一个字节为单位进行读取),即V区即为DB区
在snap7中的源码关于寄存器的描述:
def db_read(self, db_number, start, size):
"""This is a lean function of Cli_ReadArea() to read PLC DB.
:returns: user buffer.
"""
logger.debug("db_read, db_number:%s, start:%s, size:%s" %
(db_number, start, size))
type_ = snap7.snap7types.wordlen_to_ctypes[snap7.snap7types.S7WLByte]
data = (type_ * size)()
result = (self.library.Cli_DBRead(
self.pointer, db_number, start, size,
byref(data)))
check_error(result, context="client")
return bytearray(data)
@error_wrap
def db_write(self, db_number, start, data):
"""
Writes to a DB object.
:param start: write offset
:param data: bytearray
"""
wordlen = snap7.snap7types.S7WLByte
type_ = snap7.snap7types.wordlen_to_ctypes[wordlen]
size = len(data)
cdata = (type_ * size).from_buffer_copy(data)
logger.debug("db_write db_number:%s start:%s size:%s data:%s" %
(db_number, start, size, data))
return self.library.Cli_DBWrite(self.pointer, db_number, start, size,
byref(cdata))
经过测试,db_number和size这两个参数只能设置为1可行,设置为其他会报错,因此在之后调用的时候,直接把这两个参数赋值1。
因为在写入时,对data的格式有要求,因此写了一个函数把原函数封装了起来:
def read_VB(client, offset):
""" :param client: client
:param offset: int
:returns: str.
"""
vb_data = client.db_read(1, offset, 1)
return vb_data[0]
def write_VB(client, offset, data):
""" :param client: client
:param offset: int
:param data: str
"""
data = int(data)
temp = hex(int(data))[2:]
if data < 0 or data > 255:
print("请输入0-255之间的数")
else:
if data < 16:
temp = "0"+ temp
client.db_write(1, offset, bytes.fromhex(temp))
print("向寄存器VB"+str(offset)+"写入"+str(data)+"成功")
在连接plc之后直接调用即可。
整体代码:
import struct
import time
import snap7
def plc_connect(ip, type, rack=0, slot=1):
"""
连接初始化
:param ip:
:param type::param connection_type: 1 for PG, 2 for OP, 3 to 10 for S7 Basic
:param rack: 通常为0
:param slot: 根据plc安装,一般为0或1
:return:client
"""
client = snap7.client.Client()
client.set_connection_type(type)
client.connect(ip, rack, slot)
return client
def plc_con_close(client):
"""
连接关闭
:param client:
:return:
"""
client.disconnect()
def read_VB(client, offset):
""" :param client: client
:param offset: int
:returns: str.
"""
vb_data = client.db_read(1, offset, 1)
return vb_data[0]
def write_VB(client, offset, data):
""" :param client: client
:param offset: int
:param data: str
"""
data = int(data)
temp = hex(int(data))[2:]
if data < 0 or data > 255:
print("请输入0-255之间的数")
else:
if data < 16:
temp = "0"+ temp
client.db_write(1, offset, bytes.fromhex(temp))
print("向寄存器VB"+str(offset)+"写入"+str(data)+"成功")
if __name__ == "__main__":
client_fd = plc_connect('192.168.2.1', 2)
print("connect success")
write_VB(client_fd, 1, "16")
data = read_VB(client_fd, 1)
print(data)
plc_con_close(client_fd)
运行结果:
def write_VD(client, offset, data):
temp = hex(int(data))
temp = temp[2:].zfill(8)
# print(type(temp))
try:
client.write_area(snap7.snap7types.areas.DB, 1, offset, bytes.fromhex(temp))
print("向寄存器VB"+str(offset)+"写入"+str(data)+"成功")
except Exception as e:
time.sleep(0.003)
write_VD(client, offset, data)
def read_VD(client, offset):
"""This is a lean function of Cli_ReadArea() to read PLC DB.
:param client: client
:param offset
:returns: data int.
"""
try:
v_data = client.read_area(snap7.snap7types.areas.DB, 1, offset, 4)
data = int.from_bytes(v_data, byteorder='big', signed=False)
except Exception as e:
time.sleep(0.003)
data = read_VD(client, offset)
return data
def write_VW(client, offset, data):
temp = hex(int(data))
temp = temp[2:].zfill(4)
# print(type(temp))
try:
client.write_area(snap7.snap7types.areas.DB, 1, offset, bytes.fromhex(temp))
print("向寄存器VB"+str(offset)+"写入"+str(data)+"成功")
except Exception as e:
time.sleep(0.003)
write_VW(client, offset, data)
def read_VW(client, offset):
"""This is a lean function of Cli_ReadArea() to read PLC DB.
:param client: client
:param offset
:returns: data int.
"""
try:
v_data = client.read_area(snap7.snap7types.areas.DB, 1, offset, 2)
data = int.from_bytes(v_data, byteorder='big', signed=False)
except Exception as e:
time.sleep(0.003)
data = read_VW(client, offset)
return data