python读取S7-1200DB块

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

python读取S7-1200DB块
python读取S7-1200 DB块
读DB区
使⽤的⽅法依旧是read_area
d ef r
e ad_area(sel f, ar ea, d bn um be r, st ar t,size)
area是PLC内各寄存区的代码,具体参考下表
dbnumber是DB块编号,可以在DB块属性中常规选项中查看到,start为寄存区起始地址,size是DB块完整的长度,因为DB块中可以有各种数据类型,所以长度参数⼀定要准确,否则返回数据会出现问题。

要访问DB块,必须取消DB块属性中的优化的块访问选项
针对的是DB块,所有area参数需要使⽤0x84,size参数需要通过DB块内的数据数量和数据类型具体计算出来
因为read_area⽅法返回的是byteArray类型的结果,可以通过get_bool,get_int,get_read,get_dword⽅法直接将byteArray 类型转换成对应的数据类型
⽐如针对get_bool⽅法
d ef g
e t_bool(_byt earray, byte_ind e x, b oo l_in de x)
第⼀个bytearray参数是read_area的返回值,byte_index参数是DB块中变量的偏移量,bool_index参数是位变量的地址。

先来看⼀个简单的例⼦,DB块中有两个变量,⼀个浮点数,⼀个布尔量
main函数中的代码如下
d ef ma in():
s71200 = snap7.client.Client()
c onnect(s71200, '192.168.2.110',0,1) whil e T r ue:tr y:
d at a =s71200.r ea d_ar ea(0x84, 1,0,5)#此处5代表D B块中数据长度,浮点数4个b yte,布尔量⼀个by t e
p ri nt(da ta)
v al ue= get_r ea l(da ta, 0)#此处0是浮点数的
偏移量
v al ue2 =ge t_bo ol(d at a, 4,0)#此处4是布尔量的偏移量
p ri nt(va lu e, v al ue2)
s le ep(5)ex cep t Snap7Exception as e:
c on ne c t(s71200, '192.168.2.110',0,1)if
__name__ =='__ma in__':
m ain()
运⾏后如下
但是这样操作很⿇烦,需要提前计算好DB块中的数据长度,需要将每个数据的偏移量和数据类型都填好,这⾥希望有⼀个简单的⽅法,定义好DB块的数据名称,数据类型,数据偏移量,之后运
⾏程序后,⾃动计算长度,对应数据类型和偏移量,从⽽获取正确的结果。

DB块中的数据名称及数据类型,偏移量如下图
定义DB块数据格式
d b = \"""
D B001 Real 0.0
D B002 Bool 4.0
D B003 Int 6.0
D B004 String 8.0
D B005 Real 264.0
"""
数据格式定义好后,需要从这个数据格式中得到read_area⽅法要的参数,这⾥通过字典是很容易实现的,我们可以定义⼀个字典的列表,列表中每⼀个字典都是⼀个数据,字典的键值可以是name,datatype,bytebit,数据结构如下
[
{'na me':'DB001','d at atype':'Re al', 'b yt ebit': '0.0 '},
{'na me':'DB002','d at atype':'Bo ol', 'b yt ebit': '4.0 '},
{'na me':'DB003','d at atype':'In t','by te bi t':'6.0 '},
{'na me':'DB004','d at atype':'St ring', 'b yt ebit':' 8.0'}
{'na me':'DB005','d at atype':'Re al', 'b yt ebit': '264 '}
]
之后可以通过for⽅法依次取出每⼀个键值,传递到read_area⽅法中。

定义DBRead()函数
这⾥希望DBRead函数中的参数如下代码所⽰:
d ef DB R
e ad(dev,db_num,db_len,db_item s):
dev参数是设备名称,db_num是DB块编号,db_len是DB块中所有数据总长度,db_items是DB块中数据,它的数据结构应该和上图所⽰的字典列表⼀致。

⾸先通过read_area获取DB块中的数据,代码如下
d ata = plc.read_ar ea(0x84,db_n um,0,d b_len):
通过for循环以此取出db_items中的字典,通过键判断数据类型和偏移量,之后调⽤对应的get⽅法,代码如下
f or it em in db_ite ms:
value =N one
#取出数据的偏移量
offset = int(i te m['b yt ebi t'].s pl it('.')[0])
#通过键da t at ype获取数据类型,调⽤不同的ge t⽅法
if item['datatype']=='Rea l':
v al ue= get_r ea l(da ta,offset) i f i t em['d at atype']=='Bo ol':
b it=i nt(i te m['b yt ebi t'].s pl it('.')[1])
v al ue= get_b oo l(da ta,offset,bit)
if item['datatype']=='Int':
v al ue= get_i nt(d at a,offs et) i f i t em['d at atype']=='St ri ng':
v al ue= get_s tr in g(da ta, o ff se t)
完整DBRead函数的代码如下
d ef DB R
e ad(dev,db_num,db_len,db_i tem s):
d ata = dev.r
e ad_area(0x84,db_n um,0,d b_len)
o bj = DBObjec t() f or item i n db_items:
value =N one
offset = int(i te m['b yt ebi t'].s pl it('.')[0])
if item['datatype']=='Rea l':
v al ue= get_r ea l(da ta,offset) i f i t em['d at atype']=='Bo ol':
b it=i nt(i te m['b yt ebi t'].s pl it('.')[1])
v al ue= get_b oo l(da ta,offset,bit)
if item['datatype']=='Int':
v al ue= get_i nt(d at a,offs et) i f i t em['d at atype']=='St ri ng':
v al ue= get_s tr in g(da ta, o ff se t)
ob j.__set attr__(item['nam e'], va lu e)r eturn obj
DBRead函数中还需要知道db_len的值,所以还需要定义⼀个函数去获得DB块中数据的总长度
定义get_db_len()函数
通过下图
可以看出,数据的总长度其实就是最后⼀个数据的偏移量的数值
加上⾃⽣所占的数据长度,如图五个数据的总长度应该是264 + 4 = 268,所以get_db_len()函数只要找到偏移量最⼤的数,在获得这个偏移量对⽤的数据类型所占的内存长度,相加后就可以得到
整个数据长度。

d ef g
e t_db_len(db_items,bytebit,d atatype):
db_items和DBRead函数中的⼀致,bytebit和datatype是
db_items中字典的两个键名,通过
o ffset_str,dataty pe =[(x[b yt eb it])f or x in db_ite ms], [x[datatype] f or x in db_items]
获得偏移量和数据类型的列表,结果应该如下
o ffset_str = ['0.0','4.0','6.0','8.0','264.0'],da t at yp e= [Real,Bool,Int,S tr in g,Real]
因为获取的offset值均为字符串,所有没法正确获取最⼤值,需
要将字符串列表转换为整数的列表,代码如下
f or x i n of fs et_s tr:
o ffset_int.app en d(in t(x.split('.')[0]))
之后通过index⽅法获得offset中最⼤值的索引值,通过此索引值获得datatype列表中的数据类型,代码如下
i dx =offset_int.i nd ex(m ax(offset_int)) #结果=4
为了得到不同数据类型占⽤内存的长度,需要先定义⼀个字典,可以通过不同的数据类型取出对应的内存长度,如下o ffsets ={ "Bo ol":2,"In t": 2,"Rea l":4,"DI nt":6,"Strin g":256}
之后便可获得DB块中数据总长度,如下
d b_len = (max(offs et_i nt))+ in t(o ff s
e ts[d at at ype[id x]]) #结果=264+4=268
完整的get_db_len()函数如下
d ef g
e t_db_len(db_items,bytebit,d atatype):
o ffset_int = []
o ffset_str,dat at yp e =[(x[byte bit]) f or x in db_i t e ms],[x[datatype]fo r x i n db_ite ms] f or x in offs e t_str:
offset_in t.append(int(x.s pli t('.')[0]))
i dx = offset_int.index(max(of fse t_in t)) #结果=4
d b_len = (max(offset_int)) + i nt(o ff s
e ts[d ata type [idx]]) #结果=264+4=268
r et ur n db_l en
⾄此,两个函数全部定义完了,接下来需要在主函数中构造
db_items列表
主函数
通过如下的代码构造db_items列表
i temlist = filter(la mb da a: a!='',db.s pl it('\n'))
s pace=''
i tems = [
{ "n am e":x.s pli t(sp ac e)[0],
"da ta type":x.s plit(sp ace)[1],
"by te bit":x.sp li t(spac e)[2]
} for x i n itemlist
]
通过上⾯的两个函数获得DB块中的数据
d b_len = get_db_l
e n(it em s,'by tebi t', 'd at atype')
D B_obj = DBRead(s71200, 1,db_len,items)
p rint(DB_obj.DB001, DB_o bj.D B002, DB_obj.DB003,DB_o b j.DB004, DB_ob j.D B005)
s leep(5)
最终结果如下
完整代码
f rom time imp or t sleep im po rt sn ap7fr om snap7.snap7exc e ptions im port Sn ap7Except io n f rom sn ap7.ut il im po r t* d b = \"""
D B001 Real 0.0
D B002 Bool 4.0
D B003 Int 6.0
D B004 String 8.0
D B005 Real 264.0
"""o ff se ts ={ "B o ol":2,"I nt":2,"Re al":4,"D In t":6,"S t ring":256}cla ss D BO bj ec t(ob je ct):
p as sd ef c on ne ct(de vi ce, ip, r ack, sl ot):
w hi le T ru e:# c he ck con nection
if device.get_connecte d():b re ak
tr y: # attempt co nn ec ti on
d ev ic e.c on n
e ct(i p, rac k,slot) ex c
e pt:p ass
sleep(5)d ef DB Re ad(d ev,db_num,db_len,db_i tem s):
d ata = dev.r
e ad_area(0x84,db_n um,0,d b_len)
o bj = DBObjec t() f or item i n db_items:
value =N one
offset = int(i te m['b yt ebi t'].s pl it('.')[0])
if item['datatype']=='Rea l':
v al ue= get_r ea l(da ta,offset) i f i t em['d at atype']=='Bo ol':
b it=i nt(i te m['b yt ebi t'].s pl it('.')[1])
v al ue= get_b oo l(da ta,offset,bit)
if item['datatype']=='Int':
v al ue= get_i nt(d at a,offs et) i f i t em['d at atype']=='St ri ng':
v al ue= get_s tr in g(da ta, o ff se t,256)
obj.__set attr__(item['nam e'], va lu e)r etur n ob j d ef ge t_db_le n(db_i te ms,b yteb it,d at at yp e):
o ffset_int = []
o ffset_str,dat at yp e =[(x[byte bit]) f or x in db_i t e ms],[x[datatype]fo r x i n db_ite ms] f or x in offs e t_str: offset_in t.append(int(x.s pli t('.')[0]))
i dx = offset_int.index(max(of fse t_in t)) #结果=4
d b_len = (max(offset_int)) + i nt(o ff s
e ts[d ata type [idx]]) #结果=264+4=268
r et ur n db_l en d ef m ai n():
s71200 = snap7.client.Client()
c onnect(s71200, '192.168.2.111',0,1) whil e T r ue:tr y:
i te ml i st =fi lt er(l am bda a: a!='', d b.s p lit('\n'))
s pa ce= ' '
i te ms= [
{ "n am e": x.spl it (space)[0], "d a ta ty pe": x.s plit(s p
a ce)[1],"by te bit": x.s pl it(spa ce)
[2]
} fo r x i n itemli st
]
d b_l
e n =ge t_db_l en(i tems, 'by te bi t','d a t atype')
D B_ob j =DB Re ad(s71200, 1,db_len, it ems)
p ri nt(DB_o bj.D B001, DB_o bj.DB002, DB_obj.
D B003, DB_obj.DB004, D B_ob j.DB005)
s le ep(5)ex cep t Snap7Exception as e:
c on ne c t(s71200, '192.168.2.111',0,1)if
__name__ =='__ma in__':
m ain()。

相关文档
最新文档