snap7读写西门子plc1200步骤(python) PLC通讯
本文是利用snap7進行對plc1200進行讀寫,所用語言是python3,windows7下,plc具體型號為S7-1212DC/DC/DC??
注意在ubuntu安裝的時候,先安裝python3-pip在進行pip3 install,否則默認使用python2環(huán)境。
1.snap7安裝
?win+R打開運行串口,輸入cmd,確定后,輸入下面的命令:(需要提前安裝python 和 pip)
使用python的pip命令安裝即可:pip install python-snap7
截圖是我已經(jīng)安裝過了,如果有問題,請檢查python安裝是夠正確,是否增加python的路徑到環(huán)境變量中。
snap7相關(guān)內(nèi)容可以查看鏈接https://blog.csdn.net/Paul22101574/article/details/81583198。
不做深入探究,請繼續(xù)向下看。
******************************************************************************************
windows安裝報錯:
Traceback (most recent call last):File "Y:\Lonnox\Projekte\Bibliothek\Python und SPS\S7-1200 Test.py", line 6, in <module>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_libraryreturn Snap7Library(lib_location).cdllFile "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安裝文件夾。資源處有。
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
2021.3.1更新
如果在linux出現(xiàn)同樣的報錯,解決方法如下:
https://www.cnblogs.com/yinsedeyinse/p/13657904.html
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*
******************************************************************************************
在ubantu14.04中l(wèi)inux系統(tǒng)安裝及配置
系統(tǒng)自帶python2,同樣的pip install python-snap7,安裝snap7庫成功。
下面配置系統(tǒng)的ip地址:
1.確保ubantu關(guān)閉了防火墻
?啟用
sudo ufw enablesudo ufw default deny 作用:開啟了防火墻并隨系統(tǒng)啟動同時關(guān)閉所有外部對本機的訪問(本機訪問外部正常)。關(guān)閉
sudo ufw disable
?查看防火墻狀態(tài)
sudo ufw status2.配置eth0或者eth1 的靜態(tài)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就可以看見修改了。
?
?
?
2.設(shè)置西門子PLC
使用博圖軟件對PLC屬性進行設(shè)置
(1)打開plc,更改IP地址:(注意這一步不是必須的,我自己鏈接的時候使用默認192.168.0.1總是出現(xiàn)連接超時或者失敗,修改了IP就好了,修改為192.168.1.11)。
(2)打開保護,修改為無保護,默認無保護。
(3)數(shù)據(jù)讀寫可以對輸入(I)、輸出(Q)、M區(qū)甚至是T區(qū)(時鐘)區(qū)讀寫,但是實際操作中,我對I區(qū)讀寫沒有任何反應(yīng),對M區(qū)和Q區(qū)測試可以,所以建議使用全局DB數(shù)據(jù)塊進行讀寫,然后PLC程序稍加修改就行。例如,原來的I0.1可以使用M10.1的數(shù)字使用==指令判別,==1接通,邏輯差不多,就是需要把I區(qū)的開關(guān)轉(zhuǎn)換成M區(qū)。
好了,廢話到此。建立全局數(shù)據(jù)塊DB_1,這里的DB號為1.
點到項目樹的DB1右擊打開屬性列表,保護為無保護。
取消優(yōu)化的塊訪問,默認塊訪問是優(yōu)化的
好了,看下DB塊中的數(shù)據(jù)吧。
我這里只用了這幾個,重要的是看數(shù)據(jù)塊的偏移量,這里是后面要用到的地址。
暫停,請打開網(wǎng)址,端好小板凳,認真觀看??http://www.ad.siemens.com.cn/service/elearning/Course/455.html
這三個視頻。如果想怎加記憶,每個視屏同名的會有強化記憶的小程序。
PLC的部分到此結(jié)束,請給PLC接上24V電源,用網(wǎng)線把電腦和PLC連接,把剛才修改plc的項目導(dǎo)入plc中。如果連不上,可以手動修改電腦的ip為192.168.1.0,和之前設(shè)置的plc需要在同一個子網(wǎng)下面。
下面打開python的shell,確認是否能夠連接和讀寫。
輸入下面的命令
>>> import snap7 >>> plc=snap7.client.Client() >>> plc.connect('192.168.1.11',0,1)這里需要注意的是ip和你設(shè)置的Plc的ip一致,connect的參數(shù),0,1位一般為默認參數(shù),是指代plc的網(wǎng)口插槽位置的。斷開連接直接調(diào)用plc.disconnect()就可以斷開連接了。
下面介紹兩個最最重要的函數(shù):也就基本上只使用到這些:
read_area(area,dbnumber,start,size)write(area,dbnumber,start,data)首先介紹第一個參數(shù),我們讀寫,主要的區(qū)別就是地址不同,plc自帶地址分類,如下:
0x81是輸入?yún)^(qū),0x82輸出區(qū),0x84是db塊。
第二個參數(shù)是dbnumber,輸入輸出區(qū)域默認為0,db塊就是塊的序號,我這里是數(shù)據(jù)塊_1,其實就是1號,所以寫1.
下面兩個參數(shù),start和size,對于I0.3起始地址為0,對應(yīng)size為3
對于M3.4,對應(yīng)的就是M(0x83),起始地址是3,對應(yīng)bit位是4,
用write_area(self, area, dbnumber, start, data):函數(shù)寫I\Q\M區(qū)不同類型寄存器的值:
??????過程與read_area相逆,根據(jù)地址和數(shù)據(jù)類型,把值填到函數(shù)的data中。
??????舉個寫的例子:client.write_area(0x82, 0,0,struct.pack('B',24)) 意思是向PLC的開關(guān)量輸出口D0.3和D0.4值寫1,24的二進制是00011000。
這里需要提醒下,因為讀寫獲得的都是16進制的數(shù)字,需要把相對應(yīng)的解碼和編碼到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: 根據(jù)plc安裝,一般為0或1
:return:
"""
client = snap7.client.Client()
client.connect(ip, rack, slot)
return client
def plc_con_close(client):
"""
連接關(guān)閉
: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'當(dāng)前值')
mk_cur = client.read_area(area, dbnumber, start, amount)
print(struct.unpack('!c', mk_cur))
def test_mk_w201(client):
"""
測試MW201,數(shù)據(jù)類型為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'當(dāng)前值')
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'當(dāng)前值')
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,根據(jù)M確定area為MK,根據(jù)W確定數(shù)據(jù)amount為2Btye,根據(jù)201確定start為201,讀出來的數(shù)據(jù)根據(jù)數(shù)據(jù)長度用struct進行unpack,寫數(shù)據(jù)對應(yīng)strcut的pack。
這里給出PLC變量類型和大小,這樣對應(yīng)確定讀寫的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')下面這個同樣的,不過使用了轉(zhuǎn)碼,以供轉(zhuǎn)碼的示范
>>> 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的讀寫時,當(dāng)是多個字時,低地址的字節(jié)其實在寫入時候位于數(shù)字的高字節(jié)段,也就是高位,高地址的字節(jié)反而位于數(shù)字的低位數(shù)段。所謂的大端模式和小端模式,請自行百度。知道就行。
寫數(shù)據(jù)都是8位一次寫入,如果寫入MW類型或者Real等更大數(shù)據(jù),需要8位分割,我的實現(xiàn)是每次進行位與操作,然后通過移位8位獲得高位。
?
在提供幾篇不錯的博客::
https://blog.csdn.net/xiaoxianerqq/article/details/81661010
https://blog.csdn.net/weixin_29482793/article/details/79555836
第二個博客博主做了個軟件,如果大家只是玩一下,可以看看,但是源碼沒有開放,可以用QT也完成該界面操作。
***************************************************************************更新 2020.12.15 WJ*************************************************************
如上文所示,存在字節(jié)大小端問題,所以每次讀寫的時候需要去編解碼,轉(zhuǎn)換,很費事。
偶然嘗試用可變字節(jié)數(shù)組bytearray獲得新的方法
import snap7 plc=snap7.client.Client() plc.connect('192.168.1.11',0,1)#DB1中偏移2位置寫入兩個字節(jié) plc.write_area(0x84,1,2,b'\x12\x34')##DB1中偏移6位置寫入四個字節(jié) plc..write_area(0x84,1,6,b'\x12\x34\x56\x78')#讀取 first=plc.read_area(0x84,1,2,2) second=plc.read_area(0x84,1,6,4)#這里可以打印出來不過都會視為字符串等 #我需要將其轉(zhuǎn)換成整數(shù) data1=int.from_bytes(first,'big') #需要注意這里會視為無符號的整形數(shù)據(jù) #如果存在符號,可以使用減法去計算超過你最大正整數(shù)時的復(fù)數(shù)數(shù)據(jù)#例如data2=int.from_bytes(second,'big')-0xFFFFFFFF-1?
?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的snap7读写西门子plc1200步骤(python) PLC通讯的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java邮件系统(java邮件收发系统源
- 下一篇: python基础之序列类型的方法——列表