python snap7讀寫西門子s7-1200PLC的數據(PLC的I、Q、M、DB、V區)

KepOPC官方微信公衆號上線:微信公衆號搜索 KepOPC工業互聯 關注即可獲取最新的軟件更新資訊

 

2020年02月17日更新:爲了更加方便快捷地提供西門子S7 Ethernet系列(S7 200smart 、300、400、1200、1500等系列)PLC數據交換到工業雲平臺(WebAPP或移動端APP),作者開發了KepOPC系列PLC驅動之一的S7中間件,具體功能描述及應用介紹參照站內博文 https://blog.csdn.net/weixin_29482793/article/details/104220789

S7中間件支持S7-MQTT&MySQL&OPC
S7中間件運行實時統計和曲線展示

    感興趣的朋友可以訪問www.kepopc.com瞭解,同時歡迎關注作者博客和微信公衆號“KepOPC工業互聯”瞭解更多產品資訊。

2020.02.17本站提供試用下載網盤地址https://pan.baidu.com/s/1ypQEgDtBwa0Gre7UsVqGvA  提取碼:rfvn

S7應用視頻介紹 https://mp.weixin.qq.com/s/2BBhpMKuTC090FPc-r1bfQ

----------------------------------------------------------------------------------------------------------------------------------------

最近要開發基於TCP/IP協議的PC上位機和西門子S7系列PLC的通訊和數據採集,網上搜羅了一圈發現有python snap7這個工具,鑑於此次開發時間有限,就自己研究上手了,期間也碰到很多安裝和連接、讀取數據的問題,網上解決方案有限,現提供一個測試版本,該版本有如下功能:

2018-03-14 更新python s7-1200測試版程序技術特性:   

1、PC直接通過TCP網口連接S7-1200系列PLC;

2、按照PLC導出的點表地址獲取I、Q、M區的地址和類型進行讀取;

3、讀出的值下一步可以通過MYSQL或socket的方式記錄和推送;

4、目前是按照每個點逐個讀取,因此效率較低,後續考慮按塊讀取,那樣效率就很高了,基本上讀一次時間控制在ms級別;

5、擺脫了OPC的束縛,之前都需要從OPC中轉一下,這下PC可以直接通過網絡連接PLC。

(python s7-1200測試版本打包程序)下載地址:https://pan.baidu.com/s/1cRK9vIxW4T1_sVFieUESjA

感謝(蔽月八雲):https://www.jianshu.com/p/5284de40a139 的總結和分析,因爲我也是個PLC小白,python snap7的優勢就在於,一個PLC小白也能很快地利用python和PLC建立通訊,並獲取寄存器的值,這些值爲我們的數據分析提供了數據基礎,基於TCP/IP方式的通訊,是它最大的優勢,期間也用過modbus TCP的方式讀取,但是40001和M區的對應地址關係把我搞的頭暈,相比而言modbus簡單更易操作,python snap7更加專業。

另附 python snap7安裝常見問題和步驟:https://stackoverflow.com/questions/33697263/python-snap7-windows-cant-find-snap7-library

2018年07月31日更新:

感謝每一位關注的朋友,由於最近真的很多人問我python snap7,所以還是覺得應該分享一下微薄的經驗,snap7的read_area方法和Kepserver讀西門子TCP/IP Ethernet驅動的讀取方法是一樣的,我也是利用網絡抓包工具比對着消息體格式才找到功能碼、地址、類型、長度的對應關係,確實還是因爲相關的介紹太少,雖說KepOPC也能更加容易實現這些功能,但是我仍堅信snap7纔是最美解決方案。(下面的文字適合已經連上PLC的朋友):

1、利用def read_area(self, area, dbnumber, start, size)函數讀I\Q\M區不同類型寄存器的值:

            for i in range(0,len(read_list)):
                tag_id = read_list[i]['id']
                tag_type = read_list[i]['type']
                plc_readtime = time.strftime('%Y-%m-%d %H:%M:%S')
                if tag_id[0]=='I' and tag_type=='Boolean'or tag_type=='Bool':
                    result = client.read_area(0x81, 0, int(tag_id[1]), 1)
                    for j in range(0,8):                    
                        if (int(struct.unpack('!B', result)[0]) & pow(2,j)!=0):
                            i_temp_value=1
                        else:
                            i_temp_value=0
                elif tag_id[0]=='Q' and tag_type=='Boolean'or tag_type=='Bool':
                    result = client.read_area(0x82, 0, int(tag_id[1]), 1)
                    q_query_str = ''
                    for j in range(0,8):
                        if (int(struct.unpack('!B', result)[0]) & pow(2,j)!=0):
                            q_temp_value=1
                        else:
                            q_temp_value=0
                elif tag_id[0]=='M':
                    if tag_id[1]!='B' and tag_id[1]!='D'and tag_type=='Boolean'or tag_type=='Bool':
                        m_id_res = re.findall(r'M(\d+)',tag_id)
                        result = client.read_area(0x83, 0, int(m_id_res[0]), 1)
                        for j in range(0,8):
                            if (int(struct.unpack('!B', result)[0]) & pow(2,j)!=0):
                                m_temp_value=1
                            else:
                                m_temp_value=0
                    elif tag_id[1]=='B'and  tag_type=='Byte'or  tag_type=='Boolean':
                        mb_query_str = ''
                        result = client.read_area(0x83, 0, int(tag_id[2:]), 1)
                        read_list[i]['value']=struct.unpack('!B', result)[0]
                    elif tag_id[1]=='D'and tag_type=='DWord':
                        md_query_str = ''
                        result = client.read_area(0x83, 0, int(tag_id[2:]), 4)
                        read_list[i]['value']=struct.unpack('!L', result)[0]
                    else:
                        print "tag_id !=MB\MD\M,or type error!"
                else:
                    pass

以上紅色的文字爲主要讀取代碼,用於按照I/M/Q區+地址+類型的寄存器值的讀取,讀取完需要利用struct.unpack方法轉換成我們要的值。

2、利用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。

2019年12月26日更新:1、新增對S7 200smart的連接;2、新增連接號定義;3、新增V區(V\VB\VW\VD)的讀寫值。

3、SiemensTCPIP測試工具的使用和下載方法:

(1)下載測試工具 SiemensTCPIP.exe

         下載地址:https://pan.baidu.com/s/18JgupJKUcM7qCHNHhes87A

(2)程序運行        

       運行前請將snap7.dll和snap7.lib拷貝到你的操作系統對應的版本的System32或SysWOW64下。

(3)程序運行

備註:  不同PLC的CPU機架號、插槽號和功能碼0x81,0x82,0x83及值類型長度如下表:


                                               


公衆號往期文章回顧:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章