发现网上很多关于python通过s7协议控制200smart的代码都失败,我猜应该是版本的问题。自己捣鼓了半天,终于测试成功
from snap7 import util,client
my_plc = client.Client() #建立一个客户端对象
my_plc.set_connection_type(3) #如果是200smart,必须有此段代码。1200,1500可以不写。
my_plc.connect("192.168.11.9",0,1) #连接plc,参数分别为ip ,卡号,槽号。200smart为0和1
state=my_plc.get_connected() #用来判读是否连接成功 返回值为true 和false
# print(state)
#注意,这里的参数有坑,最新的sanp7协议是这样写,后面1代表V区,0代表起始地址,10代表字节数量
#注意,这里0对应VB0,1对应vb1以此类推。
data=my_plc.read_area(client.Areas.DB,1,0,10)
my_data = util.get_byte(data,5)
m=util.get_word(data,0) #相当于vw0
m2=util.get_word(data,2) #相当于vw2
m3=util.get_word(data,4) #相当于vw4
m4=util.get_word(data,6) #相当于vw6
print(m)
print(m2)
print(m3)
print(m4)
my_plc.disconnect() #断开连接
my_plc.destroy() #销毁客户端对象
from HslCommunication import SiemensS7Net
from HslCommunication import SiemensPLCS
#bool read write test
def printReadResult(result):
if result.IsSuccess:
print(result.Connect)
else:
print('failed'+result.Message)
def printWriteReslut(result):
if result.IsSuccess:
print('sucess')
else:
print('failed' + result.Message)
if __name__ == '__main__':
siemens = SiemensS7Net(SiemensPLCS.S200Smart,'192.168.12.10')
# '''连接服务器,也可放在窗口的Load方法中,一般建议使用长连接,速度更快,又是线程安全(下面使用了长连接),如果不连接,直接读取,就是短连接'''
if siemens.ConnectServer().IsSuccess==False:
print('connect failed')
else:
#bool read write test
siemens.WriteBool("M80.6",True)
printWriteReslut(siemens.ReadBool("M80.6"))
#byte read write test
siemens.WriteByte("M100",58)
printWriteReslut(siemens.ReadByte("M100"))
#int16 read write test
siemens.WriteInt16("M102",12358)
printWriteReslut(siemens.ReadInt16("M102"))
data = siemens.ReadByte("V100").Content #读取v100的值
print(data)
# 断开连接
# siemens.ConnectClose()
from snap7 import util, client
my_plc = client.Client() # 建立一个客户端对象
my_plc.set_connection_type(3) # 如果是200smart,必须有此段代码。1200,1500可以不写。
my_plc.connect("192.168.11.9", 0, 1)
class plcData(QThread):
def __init__(self,plc):
super(plcData, self).__init__()
self.plc=plc
def run(self):
self.check_plc_state()
def check_plc_state(self):
short_data=None
QThread.sleep(100)
end_data=None
if short_data==end_data:
print('通讯异常')
self.plc.close()
class PlcThread(QThread):
def __init__(self,plc):
super(PlcThread, self).__init__()
self.plc=plc
def run(self):
while True:
if self.plc.get_connected()==False:
try:
self.plc.connect("192.168.11.9", 0, 1)
except Exception as e:
pass
else:
#读取数据
try:
# da=#
# 区
print('数据读取')
except Exception as e:
pass
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("的学习")
self.resize(500,500)
self.setup_ui()
self.plc = my_plc = client.Client() # 建立一个客户端对象 单独开个线程去处理
self.plc.set_connection_type(3) # 如果是200smart,必须有此段代码。1200,1500可以不写。
self.t = PlcThread()
def setup_ui(self):
self.btn=QPushButton('btn',self)
self.btn.clicked.connect(self.btn_cick)
def btn_click(self):
self.plc.connect("192.168.11.9", 0, 1)
self.plc.get_connected()
#d读取数据,用一个线程
if __name__ == '__main__':
import sys
app=QApplication(sys.argv)
win=Window()
win.show()
sys.exit(app.exec_())
写PLC
写PLC用到的方法为 write_area(area,dbnumber,start,data)
说明如下:area表示往哪个区去写,如:plc.write_area(client.Areas.DB,1,2,bytes)
dbnumber:如果是smart200plc,要填1,1200/1500填0
start 开始的地址,指字节,如上面的2,代表vb2
bytes 代表长度,如果写一个位,就用一个字节
具体分三步:
1,bty_arrays = read_area()或bty_arrays = bytearay(变量类型所占的大小)
2.用snap7.util类来更改字节数组,bool类型用1个字节,word用2个字节等例如
set_bool(_bytearray,byte_index,bit,value)字节数组,字节索引,位索引,要写入的值
3.通过write_area(area,dbnumber,start,data)写入到plc相对应的区
def connect_200smart(ip,plc_mode=3,rack=0,slot=1):
my_plc = client.Client()
my_plc.set_connection_type(plc_mode) #200smart 要设置
my_plc.connect(ip,rack,slot)
return my_plc
plc=connect_200smart("192.168.2.1")
print(plc.get_connected())
bytes=plc.read_area(client.Areas.DB,1,0,10)#说明 smart200 的V区要填写1,0代表VB0
util.set_bool(bytes, 0, 0, 0)
plc.write_area(client.Areas.DB,1,0,bytes) #说明 smart200 的V区要填写1,0代表VB0
util.set_bool(bytes,0,1,0)
plc.write_area(client.Areas.DB,1,1,bytes)
util.set_bool(bytes,0,3,0)
plc.write_area(client.Areas.DB,1,2,bytes)
#用一个字节数组,因为对位操作,一个字节够了
buf=bytearray(1) #第一步,创建一个字节数组
util.set_bool(buf,0,1,0) #第二步,把该字节的第一个位设为TRUE
plc.write_area(client.Areas.DB,1,0,buf) #第三步把更改的字节放到V区,vb0里。
import threading
import time
from PyQt5.Qt import *
from snap7 import client,util
class PlcData():
def __init__(self):
self.db_dd12 :float = None
self.db_d24:float = None
def checkConnectState(self,plc):
self.t = threading.Thread(target=self.run_thread,args=(plc,),daemon=True)
self.t.start()
def run_thread(self,plc):
while True:
start=self.db_d24
time.sleep(1000)
end = self.db_d24
print(f"start={start}--end={end}")
if start==end:
QMessageBox.warning(self,"waringing","通讯异常")
plc.disconnect()
class Window(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("的学习")
self.resize(500,500)
self.setup_ui()
def setup_ui(self):
self.label = QLabel('info',self)
self.label.move(100,50)
self.btn=QPushButton('start',self)
self.btn.move(100,200)
self.btn.clicked.connect(self.btn_click)
self.plc = client.Client()
self.plc.set_connection_type(3)
self.plcdata = PlcData()
def btn_click(self):
try:
self.plc.connect("192.168.2.20",0,1)
self.t=threading.Thread(target=self.getdata)
self.plcdata.checkConnectState(self.plc)
except:
pass
def getdata(self):
while True:
print('11111')
if not self.plc.get_connected():
try:
self.plc.connect('192.168.2.20',0,1)
except Exception as e:
print(e)
else:
#成功直接读数据
try:
bytearray = self.plc.db_read(1, 0, 2)
self.plcdata.db_d24 = util.get_word(bytearray,0)
self.label.setText(str(self.plcdata.db_d24))
except Exception as e:
print(e)
if __name__ == '__main__':
import sys
app=QApplication(sys.argv)
win=Window()
win.show()
sys.exit(app.exec_())