本文是利用snap7进行对plc1200进行读写,所用语言是python3,windows7下,plc具体型号为S7-1212DC/DC/DC
win+R打开运行串口,输入cmd,确定后,输入下面的命令:(需要提前安装python 和 pip)
使用python的pip命令安装即可:pip install python-snap7
截图是我已经安装过了,如果有问题,请检查python安装是够正确,是否增加python的路径到环境变量中。
snap7相关内容可以查看链接https://blog.csdn.net/Paul22101574/article/details/81583198。
不做深入探究,请继续向下看。
******************************************************************************************
windows安装报错:
Traceback (most recent call last):
File "Y:\Lonnox\Projekte\Bibliothek\Python und SPS\S7-1200 Test.py", line 6, in
plc = snap7.client.Client()
File "C:\Python34\lib\site-packages\snap7\client.py", line 30, in __init__
self.library = load_library()
File "C:\Python34\lib\site-packages\snap7\common.py", line 54, in load_library
return Snap7Library(lib_location).cdll
File "C:\Python34\lib\site-packages\snap7\common.py", line 46, in __init__
raise Snap7Exception(msg)
snap7.snap7exceptions.Snap7Exception: can't find snap7 library. If installed, try running ldconfig
解决方法:将dll lib文件拷入python安装文件夹。资源处有。
******************************************************************************************
在ubantu14.04中linux系统安装及配置
系统自带python2,同样的pip install python-snap7,安装snap7库成功。
下面配置系统的ip地址:
1.确保ubantu关闭了防火墙
启用
sudo ufw enable
sudo ufw default deny
作用:开启了防火墙并随系统启动同时关闭所有外部对本机的访问(本机访问外部正常)。
关闭
sudo ufw disable
查看防火墙状态
sudo ufw status
2.配置eth0或者eth1 的静态ip地址
$gedit /etc/network/interfaces
# interfaces eth0 for snap7 connect plc
auto eth0
iface eth0 inet static
address 192.168.0.100
netmask 255.255.255.0
gateway 192.168.0.1
保存,重启。
ifconfig就可以看见修改了。
使用博图软件对PLC属性进行设置
(1)打开plc,更改IP地址:(注意这一步不是必须的,我自己链接的时候使用默认192.168.0.1总是出现连接超时或者失败,修改了IP就好了,修改为192.168.1.11)。
(3)数据读写可以对输入(I)、输出(Q)、M区甚至是T区(时钟)区读写,但是实际操作中,我对I区读写没有任何反应,对M区和Q区测试可以,所以建议使用全局DB数据块进行读写,然后PLC程序稍加修改就行。例如,原来的I0.1可以使用M10.1的数字使用==指令判别,==1接通,逻辑差不多,就是需要把I区的开关转换成M区。
好了,废话到此。建立全局数据块DB_1,这里的DB号为1.
取消优化的块访问,默认块访问是优化的
好了,看下DB块中的数据吧。
我这里只用了这几个,重要的是看数据块的偏移量,这里是后面要用到的地址。
暂停,请打开网址,端好小板凳,认真观看 http://www.ad.siemens.com.cn/service/elearning/Course/455.html
这三个视频。如果想怎加记忆,每个视屏同名的会有强化记忆的小程序。
PLC的部分到此结束,请给PLC接上24V电源,用网线把电脑和PLC连接,把刚才修改plc的项目导入plc中。如果连不上,可以手动修改电脑的ip为192.168.1.0,和之前设置的plc需要在同一个子网下面。
下面打开python的shell,确认是否能够连接和读写。
输入下面的命令
>>> import snap7
>>> plc=snap7.client.Client()
>>> plc.connect('192.168.1.11',0,1)
这里需要注意的是ip和你设置的Plc的ip一致,connect的参数,0,1位一般为默认参数,是指代plc的网口插槽位置的。断开连接直接调用plc.disconnect()就可以断开连接了。
下面介绍两个最最重要的函数:也就基本上只使用到这些:
read_area(area,dbnumber,start,size)
write(area,dbnumber,start,data)
首先介绍第一个参数,我们读写,主要的区别就是地址不同,plc自带地址分类,如下:
0x81是输入区,0x82输出区,0x84是db块。
第二个参数是dbnumber,输入输出区域默认为0,db块就是块的序号,我这里是数据块_1,其实就是1号,所以写1.
下面两个参数,start和size,对于I0.3起始地址为0,对应size为3
对于M3.4,对应的就是M(0x83),起始地址是3,对应bit位是4,
用write_area(self, area, dbnumber, start, data):函数写I\Q\M区不同类型寄存器的值:
过程与read_area相逆,根据地址和数据类型,把值填到函数的data中。
举个写的例子:client.write_area(0x82, 0,0,struct.pack('B',24)) 意思是向PLC的开关量输出口D0.3和D0.4值写1,24的二进制是00011000。
这里需要提醒下,因为读写获得的都是16进制的数字,需要把相对应的解码和编码到10进制方便读写。
>>> plc.write_area(0x84,1,0,struct.pack('B',1))
>>> data=plc.read_area(0x84,1,0,8)
>>> print(data)
bytearray(b'\x01\x00\x00\x00\x00\x00\x00\x00')
这是对db块的M1.0写1,读写例子,。读取时候为了减少多次读取,我是用了一次性读取了8位。
这里给出我记录的某一博文的例子,有错误不管,哈哈哈
---------------------------------------------------------------老子是分割线--------------------------------------------------------------------------
通过读写PLC的M10.1、MW201来具体看看如何读写PLC。
import struct
import time
import snap7
def plc_connect(ip, rack=0, slot=1):
"""
连接初始化
:param ip:
:param rack: 通常为0
:param slot: 根据plc安装,一般为0或1
:return:
"""
client = snap7.client.Client()
client.connect(ip, rack, slot)
return client
def plc_con_close(client):
"""
连接关闭
:param client:
:return:
"""
client.disconnect()
def test_mk10_1(client):
"""
测试M10.1
:return:
"""
area = snap7.snap7types.areas.MK
dbnumber = 0
amount = 1
start = 10
print(u'初始值')
mk_data = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!c', mk_data))
print(u'置1')
client.write_area(area, dbnumber, start, b'')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!c', mk_cur))
def test_mk_w201(client):
"""
测试MW201,数据类型为word
:param client:
:return:
"""
area = snap7.snap7types.areas.MK
dbnumber = 0
amount = 2
start = 201
print(u'初始值')
mk_data = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_data))
print(u'置12')
client.write_area(area, dbnumber, start, b'')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_cur))
time.sleep(3)
print(u'置3')
client.write_area(area, dbnumber, start, b'')
print(u'当前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!h', mk_cur))
if __name__ == "__main__":
client_fd = plc_connect('192.168.0.1')
test_mk10_1(client_fd)
test_mk10_1(client_fd)
plc_con_close(client_fd)
从代码可见,MW201,根据M确定area为MK,根据W确定数据amount为2Btye,根据201确定start为201,读出来的数据根据数据长度用struct进行unpack,写数据对应strcut的pack。
这里给出PLC变量类型和大小,这样对应确定读写的amount。
---------------------------------------------------------------老子是分割线--------------------------------------------------------------------------
下面是我读写i0.1的例子,可是却没有成功,原因未知。
>>> plc.write_area(0x81,0,0,struct.pack('B',1))
>>> data=plc.read_area(0x81,0,0,1)
>>> print(data)
bytearray(b'\x00')
>>> data=plc.read_area(0x81,0,0,8)
>>> print(data)
bytearray(b'\x00\x00\x00\x00\x00\x00\x00\x00')
下面这个同样的,不过使用了转码,以供转码的示范
>>> plc.write_area(0x81,0,0,struct.pack('B',1))
>>> data=plc.read_area(0x81,0,0,1)
>>> print(struct.unpack('!B',data)[0])
0
>>> data=plc.read_area(0x81,0,0,0)
特别提醒,对于DB块M的读写时,当是多个字时,低地址的字节其实在写入时候位于数字的高字节段,也就是高位,高地址的字节反而位于数字的低位数段。所谓的大端模式和小端模式,请自行百度。知道就行。
写数据都是8位一次写入,如果写入MW类型或者Real等更大数据,需要8位分割,我的实现是每次进行位与操作,然后通过移位8位获得高位。
在提供几篇不错的博客::
https://blog.csdn.net/xiaoxianerqq/article/details/81661010
https://blog.csdn.net/weixin_29482793/article/details/79555836
第二个博客博主做了个软件,如果大家只是玩一下,可以看看,但是源码没有开放,可以用QT也完成该界面操作。