對(duì)歐姆龍PLC使用Python程序連接使用方法的研究
0 引言
PLC( 可編程邏輯控制器) 是一種專門為在工業(yè)環(huán)境下應(yīng)用而設(shè)計(jì)的數(shù)字運(yùn)算操作電子系統(tǒng)。在工業(yè)上PLC的使用十分廣泛,其是許多大規(guī)模工作系統(tǒng)包括鋼鐵、石油、化工、電力、建材、機(jī)械制造、汽車、輕紡、交通、環(huán)保、文化娛樂等各行業(yè)中得到廣泛的應(yīng)用的基礎(chǔ)控件。雖然PLC 對(duì)基礎(chǔ)的工業(yè)控制能起到很好的效果,但對(duì)于更加復(fù)雜的應(yīng)用場(chǎng)景,單純使用PLC 進(jìn)行控制難度較大。因此為了實(shí)現(xiàn)較為復(fù)雜的功能,在PLC 的上層,往往需要使用應(yīng)用更加廣泛的編程語(yǔ)言如C++、Python編寫的復(fù)雜程序等進(jìn)行控制,由于PLC 的運(yùn)行與承載程序的上位計(jì)算機(jī)的底層邏輯并不相同,PLC 與上位計(jì)算機(jī)的通信成為工程上的重要課題。在實(shí)際應(yīng)用中不同廠家所提供的PLC 通信方法并不相同,因此需要根據(jù)實(shí)際需求設(shè)計(jì)針對(duì)性的通信程序[1]。
歐姆龍PLC提供Fins協(xié)議作為與其通信的方法,為了搭建計(jì)算機(jī)主機(jī)與PLC 通信的橋梁,當(dāng)計(jì)算機(jī)使用Python語(yǔ)言編寫控制邏輯時(shí),需要專門的Python 通信程序用于與PLC 通信。由于大部分的PLC 設(shè)備都不直接與Python程序直連,而是通過C/C++ 的方式作為中間層的程序,這使得網(wǎng)上公開的使用Python 程序基于Fins 協(xié)議通信歐姆龍PLC 的程序難以尋找且僅有的程序注釋解釋不足,在實(shí)際運(yùn)行過程中容易出現(xiàn)各種問題,自己根據(jù)實(shí)際要求開發(fā)對(duì)應(yīng)的Python 通信程序是必要的[2]。
本文介紹了使用Python 程序與歐姆龍PLC 進(jìn)行通信的基本步驟以及在項(xiàng)目中Python 通信程序的具體構(gòu)建方法,在如今基于Python 程序進(jìn)行Fins 協(xié)議進(jìn)行通信的資料較少的情況下,對(duì)同類型的項(xiàng)目有著借鑒作用。
1 Python程序與歐姆龍PLC通信
在進(jìn)行程序上的通信前首先要建立物理上的連接。此次使用的歐姆龍PLC 型號(hào)為CP1H,其狀態(tài)如圖1 所示。此次選擇的通訊方式是通過網(wǎng)線連接,一端連接計(jì)算機(jī),一端連接PLC,用以傳輸數(shù)據(jù),該P(yáng)LC 還能夠使用USB 連接,此時(shí)可以使用對(duì)應(yīng)的調(diào)試程序?qū)ζ溥M(jìn)行修改,主要用于程序調(diào)試和測(cè)試。
硬件連接后,下一步則是進(jìn)行軟件的連接通訊,F(xiàn)ins協(xié)議屬于數(shù)據(jù)層的協(xié)議,依賴于TCP/IP 協(xié)議,該型號(hào)的PLC 使用TCP 協(xié)議進(jìn)行通訊,這里Fins 協(xié)議將作為TCP協(xié)議的數(shù)據(jù)進(jìn)行傳輸。TCP協(xié)議的可靠性較好,但傳輸數(shù)據(jù)需要經(jīng)過多次確認(rèn),因此在速度上略有損失。同時(shí)Fins 協(xié)議也規(guī)定了自己的返回信息。Fins 協(xié)議的數(shù)據(jù)傳遞邏輯如下。
圖1 CP1H型PLC與連接
1.1 TCP連接
在主機(jī)與PLC 溝通之前,首先要建立TCP 的連接。這一部分可以調(diào)用Socket 包來實(shí)現(xiàn),對(duì)于不同語(yǔ)言來說,需要設(shè)置的結(jié)構(gòu)會(huì)存在一些差別。TCP 協(xié)議共需要經(jīng)過3 次握手,第1 次握手為客戶端向服務(wù)端發(fā)送網(wǎng)絡(luò)包,以此發(fā)起連接,同時(shí)向服務(wù)端告知自己的傳輸能力。第2 次為服務(wù)端向客服端回發(fā),以測(cè)試客戶端的接受能力以及服務(wù)端的發(fā)送能力。第3 次客戶端再次向服務(wù)端發(fā)信,進(jìn)行進(jìn)一步確認(rèn),從而進(jìn)行聯(lián)系。在TCP 層面,之后每次傳遞數(shù)據(jù)都會(huì)收到回復(fù)。
1.2 Fins連接
完成TCP 連接后,接下來依靠TCP 協(xié)議進(jìn)行Fins協(xié)議的連接。對(duì)于Fins 協(xié)議連接也需要進(jìn)行一次請(qǐng)求,這里的請(qǐng)求與TCP 不同,只需要進(jìn)行兩次,一次由主機(jī)向PLC 發(fā)送請(qǐng)求信息,另一次由PLC 發(fā)送確認(rèn)信息,這一過程規(guī)定了Fins 協(xié)議通信中的一些基礎(chǔ)信息,包括節(jié)點(diǎn)地址、節(jié)點(diǎn)網(wǎng)絡(luò)號(hào)等。
1.3 PLC通信
當(dāng)主機(jī)和PLC 完成確認(rèn)后就可以進(jìn)行信息的傳輸工作。對(duì)于Fins 協(xié)議通信,最重要的特點(diǎn)就是所有的數(shù)據(jù)請(qǐng)求都由主機(jī)發(fā)出,PLC 只進(jìn)行被動(dòng)應(yīng)答操作。如對(duì)于讀入操作,由主機(jī)發(fā)送信息,確認(rèn)要進(jìn)行讀取以及讀取的位置,PLC 接受到信號(hào)后按照信號(hào)進(jìn)行操作,之后將數(shù)據(jù)進(jìn)行返回[3],在這種情況下,主機(jī)被稱為發(fā)送方,而PLC 被稱為接收方。在這種框架下,命令只能由發(fā)送方發(fā)出,PLC 會(huì)將數(shù)據(jù)存儲(chǔ)在實(shí)現(xiàn)規(guī)定的地方,讓主機(jī)發(fā)布命令獲取。
2 Fins數(shù)據(jù)幀
Fins 數(shù)據(jù)幀包括Fins header、Fins command 和Fins data3 部分,其中Fins header 用于對(duì)地址目標(biāo)進(jìn)行識(shí)別,F(xiàn)ins command 用于傳遞命令,而Fins data 用于傳輸所需數(shù)據(jù)。在Fins 協(xié)議中,發(fā)送方使用的命令幀和接收方使用的響應(yīng)幀的結(jié)構(gòu)是有所區(qū)別的,其中命令幀的主要結(jié)構(gòu)如下。
2.1 Fins header
該部分共有10個(gè)字節(jié),按順序依次為ICF(Information Control Field),用于顯示框架信息,由4 個(gè)子字段組成,有效信息包括是否使用網(wǎng)關(guān)、該數(shù)據(jù)的具體類型(響應(yīng)或命令)以及是否必須進(jìn)行回應(yīng),該字節(jié)還有5個(gè)保留位,在一些情況下可以指定一些特殊信息;RSV(Reserved),系統(tǒng)保留字;GCT(Gateway count),網(wǎng)關(guān)的允許數(shù)量;DNA(Destination network address)發(fā)送目標(biāo)的網(wǎng)絡(luò)地址,用于指定目標(biāo)的節(jié)點(diǎn)網(wǎng)絡(luò)號(hào);DA1(Destination node number)目標(biāo)節(jié)點(diǎn)地址,此處需要注意的是可以設(shè)置為FF,此時(shí)為廣播編號(hào);DA2(Source unit number)目的單位地址,指定目標(biāo)節(jié)點(diǎn)的單元編號(hào);SNA(Source network address)發(fā)送方的網(wǎng)絡(luò)地址,用于指定發(fā)送方所在的節(jié)點(diǎn)網(wǎng)絡(luò)號(hào),SA1(Source node number)發(fā)送方的節(jié)點(diǎn)地址;SA2(Source Unit address)發(fā)送方的目的單位地址;SID(Service ID)服務(wù)序列號(hào),用于標(biāo)識(shí)生成傳輸過程,響應(yīng)中返回相同數(shù)字來匹配命令和響應(yīng)。以上各單元均占1 個(gè)字節(jié)。
2.2 Fins command
該部分共占兩個(gè)字節(jié),包括MRC 和SRC,分別儲(chǔ)存了1 個(gè)字節(jié)的請(qǐng)求代碼,其中MRC 為主代碼,決定命令類別,SRC 為次要代碼,決定類別下的具體命令。例如當(dāng)MRC 為01 時(shí),類型為I/O 讀寫,此時(shí)當(dāng)SRC為01 時(shí),該命令為讀取I/O。讀取Fins 協(xié)議能夠指定的命令相當(dāng)多,常見的操作包括讀寫I/O 信息、讀寫參數(shù)區(qū)信息、操作模式切換、狀態(tài)讀取、時(shí)間讀取、讀寫故障信息、讀寫文件和強(qiáng)制設(shè)置某些位等。
2.3 Fins data
存放需要傳輸?shù)臄?shù)據(jù),最大2 000 字節(jié),實(shí)際結(jié)構(gòu)受到Fins command部分的約束,即不同命令需要傳輸?shù)臄?shù)據(jù)格式是不同的。例如讀取I/O 區(qū)時(shí),data 區(qū)的結(jié)構(gòu)為一個(gè)字節(jié)的I/O 儲(chǔ)存區(qū)的對(duì)應(yīng)編號(hào)、3 個(gè)字節(jié)的數(shù)據(jù)起始位置和兩個(gè)字節(jié)的讀取數(shù)據(jù)大小。
對(duì)于響應(yīng)幀,其與命令幀的區(qū)別在于Fins data 部分增加了兩個(gè)字節(jié),分別為MRES、SRES,存儲(chǔ)了命令幀的主相應(yīng)和子響應(yīng)代碼,其和實(shí)際的傳輸數(shù)據(jù)合一起組成了FINS 數(shù)據(jù)域,這使得響應(yīng)幀能夠傳輸?shù)膶?shí)際數(shù)據(jù)最大值變?yōu)? 998 個(gè)字節(jié)。
確定了歐姆龍PLC 傳輸數(shù)據(jù)的基本格式后,接下來就是設(shè)計(jì)所需的Python 程序了。本設(shè)計(jì)使用了Python包的socket 進(jìn)行編寫,通過調(diào)用該包的方式,可以避免對(duì)TCP 協(xié)議的頭部進(jìn)行設(shè)計(jì)和模擬,簡(jiǎn)化操作。
3 PLC連接過程的程序設(shè)計(jì)
3.1 對(duì)PLC進(jìn)行初步連通
在對(duì)PLC 進(jìn)行Fins 協(xié)議通信前,首先要確認(rèn)連通了PLC 本身。此時(shí)應(yīng)輸入PLC 的IP 地址,還需要PLC的端口號(hào),歐姆龍PLC 的端口號(hào)默認(rèn)為9 600,基本不會(huì)改變。計(jì)算機(jī)的IP 地址由函數(shù)進(jìn)行獲取,由于不同系統(tǒng)獲取IP 地址的方式不同,需要對(duì)應(yīng)編寫函數(shù),再進(jìn)行匯總,再使用socket 包自帶的TCP 通訊函數(shù)在TCP 層面將主機(jī)與PLC 進(jìn)行連通,測(cè)試成功連接后就可以進(jìn)行下一步驟。
3.2 對(duì)PLC進(jìn)行握手
根據(jù)之前的PLC 溝通過程,對(duì)PLC 進(jìn)行握手是進(jìn)行數(shù)據(jù)傳輸?shù)谋匾襟E。拼接PLC 幀的方式是首先根據(jù)通信幀的具體結(jié)構(gòu)對(duì)得出各個(gè)部分的具體數(shù)據(jù),根據(jù)要求轉(zhuǎn)換為十六進(jìn)制,再轉(zhuǎn)化為字符串,拼接在一起。拼接完數(shù)據(jù)后,再將數(shù)據(jù)發(fā)送出去,等待PLC 的響應(yīng)和對(duì)應(yīng)的連接數(shù)據(jù)傳回。數(shù)據(jù)傳回后,對(duì)其進(jìn)行核對(duì),不為空則成功連接,否則輸出連接失敗。如果數(shù)據(jù)超過一定時(shí)間沒有傳回,同樣輸出連接失敗。
3.3 使用PLC
本項(xiàng)目中,主要通過程序?qū)LC的數(shù)據(jù)區(qū)進(jìn)行操作。一共涉及讀數(shù)據(jù)和寫數(shù)據(jù)兩種操作。在讀數(shù)據(jù)的過程中,需要分別設(shè)計(jì)Fins 幀中的3 部分,其中Fins header由于主要用于輸出連接信息,F(xiàn)ins command 則需要輸出命令的具體內(nèi)容,包括讀命令,讀取的具體區(qū)域,本項(xiàng)目中指DM 區(qū),讀數(shù)據(jù)的具體起始地址以及讀取的長(zhǎng)度,F(xiàn)ins data 則為空。然后將3 段拼接起來進(jìn)行輸出。之后線程開始等待PLC 返回的具體數(shù)值,數(shù)據(jù)返回后,對(duì)命令進(jìn)行解析判斷,當(dāng)格式符合要求時(shí),讀取對(duì)應(yīng)的數(shù)據(jù),并對(duì)其進(jìn)行格式轉(zhuǎn)換。等待需要設(shè)計(jì)1 個(gè)時(shí)限,當(dāng)超過一定時(shí)間數(shù)據(jù)仍為進(jìn)行返回或者沒有返回正確數(shù)據(jù)時(shí),認(rèn)為發(fā)生了未知錯(cuò)誤,程序報(bào)錯(cuò)并退出,并及時(shí)通知主程序。寫數(shù)據(jù)與讀數(shù)據(jù)存在一些區(qū)別,包括Finsdata 將輸出寫入命令,寫入的具體區(qū)域,寫數(shù)據(jù)的具體起始區(qū)域以及寫入長(zhǎng)度,之后還要傳輸經(jīng)過格式轉(zhuǎn)換后的寫入數(shù)據(jù)。當(dāng)命令傳輸后,只需要解析返回幀是否符合要求即可。
3.4 注意事項(xiàng)
除了對(duì)于讀寫數(shù)據(jù)需要設(shè)計(jì)專門的函數(shù)外,由于不同的數(shù)據(jù)類型數(shù)據(jù)結(jié)果區(qū)別很大,且PLC 的數(shù)據(jù)類型與Python 不能簡(jiǎn)單兼容,需要將數(shù)據(jù)分為Bool、UShort、Int、Float 和String 幾類,根據(jù)具體情況分別設(shè)計(jì)讀寫函數(shù),且不同情況下的字符轉(zhuǎn)換方式也需要分別設(shè)計(jì)。對(duì)于Bool 類型的數(shù)據(jù),由于Python 中將Bool和數(shù)字分為兩類,讀取后需要將其轉(zhuǎn)換為對(duì)應(yīng)的數(shù)字,對(duì)于數(shù)字類型,則需要根據(jù)實(shí)際存放的要求轉(zhuǎn)換為對(duì)應(yīng)的十六進(jìn)制數(shù)。對(duì)于Float 類型數(shù)據(jù)需要注意小數(shù)點(diǎn)的位置。對(duì)于String 類型則需要逐一讀取字符,先轉(zhuǎn)換回十進(jìn)制字符,再根據(jù)對(duì)應(yīng)的ASCII 碼值替換成對(duì)應(yīng)的字符。對(duì)于寫操作則按以上進(jìn)行相反的操作。對(duì)于位操作,由于其不需要進(jìn)行類型轉(zhuǎn)換,為了提高讀取寫入速度,需要設(shè)計(jì)專門的寫入讀取函數(shù),以簡(jiǎn)化操作步驟,提高運(yùn)行效率。最后對(duì)于所有操作都需要設(shè)計(jì)1 個(gè)時(shí)鐘計(jì)數(shù),當(dāng)1 個(gè)操作經(jīng)過一定時(shí)間沒有被響應(yīng),則判斷連接出現(xiàn)問題,需要及時(shí)向上層程序進(jìn)行反饋。
在實(shí)際一般的需求通信的程序運(yùn)行過程中,一般需要單獨(dú)開辟1 個(gè)線程負(fù)責(zé)與PLC 的連接通信操作,并將其全程掛起,以達(dá)到實(shí)時(shí)接收發(fā)送數(shù)據(jù)的目的,但這樣可能會(huì)占用大量的內(nèi)存資源。鑒于Fins 協(xié)議可以只從主機(jī)一端開始通信的特點(diǎn),可以設(shè)計(jì)專門的線程函數(shù),在未使用時(shí)將其掛起,當(dāng)需要使用是再進(jìn)行喚醒和調(diào)用,從而提高使用效率,將更多內(nèi)存放松給主機(jī)使用。這種操作的缺點(diǎn)在于,當(dāng)系統(tǒng)需要與PLC 進(jìn)行通信時(shí),才可能得知現(xiàn)在的連接狀態(tài)是否出現(xiàn)問題。如果需要對(duì)連接狀態(tài)進(jìn)行實(shí)時(shí)控制,還是應(yīng)當(dāng)使用連續(xù)的進(jìn)程。
為了保證數(shù)據(jù)進(jìn)行平穩(wěn)傳輸,還需要為線程設(shè)計(jì)1個(gè)鎖對(duì)象,用于鎖定通訊流程,使流程過程中其操作的數(shù)據(jù)不會(huì)被隨意改變且線程不會(huì)被隨意中斷,保證整個(gè)讀取過程的穩(wěn)定性。此外當(dāng)通信的中間環(huán)節(jié)發(fā)生錯(cuò)誤時(shí),需要及時(shí)將信號(hào)發(fā)送給上層程序,之后退出通信。值得注意的是,F(xiàn)ins 協(xié)議中不存在實(shí)際上的退出過程,這意味著實(shí)際上通訊是能夠隨時(shí)中斷的,并不會(huì)影響端口的使用和占用[4]。
由于PLC 存在多個(gè)接口,所以可以在連通的情況下使用另一根導(dǎo)線連接另一個(gè)接口,這樣可以使用另一臺(tái)主機(jī)對(duì)PLC 的實(shí)時(shí)狀態(tài)進(jìn)行監(jiān)測(cè),以在沒有讓PLC實(shí)際運(yùn)行線下設(shè)備的狀態(tài)下進(jìn)行調(diào)試。
在設(shè)計(jì)完成后,需要對(duì)程序設(shè)計(jì)測(cè)試。本次測(cè)試使用CX-Programmer 軟件在另一臺(tái)監(jiān)控主機(jī)上進(jìn)行,在運(yùn)行Python 程序前先查看PLC 的DM 區(qū)的具體數(shù)據(jù),再使用程序進(jìn)行PLC 進(jìn)行讀寫操作,然后再使用軟件查看具體數(shù)據(jù)變化,對(duì)于讀操作則查看是否讀取了對(duì)應(yīng)數(shù)據(jù),對(duì)于寫操作則查看是否寫入正確數(shù)據(jù),結(jié)果完美完成了讀出寫入數(shù)據(jù)的任務(wù),反應(yīng)時(shí)長(zhǎng)達(dá)到使用要求,且當(dāng)人為設(shè)計(jì)了連接錯(cuò)誤后,能較好地將連接錯(cuò)誤反應(yīng)到上層程序。
4 結(jié)束語(yǔ)
本文設(shè)計(jì)了歐姆龍PLC 使用Python 程序基于Fins協(xié)議的進(jìn)行通信的具體步驟,并設(shè)計(jì)了一種基于Python的軟件通信方法,該方法完成了主機(jī)與PLC的連接通信,并完成了讀取數(shù)據(jù)區(qū)數(shù)據(jù)和寫入數(shù)據(jù)的操作,在Python軟件程序與歐姆龍PLC 通過Fins 協(xié)議進(jìn)行通訊的網(wǎng)絡(luò)資料較少的現(xiàn)狀下,具有一定的借鑒作用。由于現(xiàn)存的實(shí)際項(xiàng)目對(duì)于通訊的功能要求不高,不要求通過軟件對(duì)PLC 進(jìn)行實(shí)際控制,本文只研究了讀取和寫入數(shù)據(jù)區(qū)的兩類功能,在今后的研究中,還需要繼續(xù)研究對(duì)PLC 進(jìn)行控制以及讀寫大文件的軟件程序編寫方法,從而提高程序的泛用性和功能性。
參考文獻(xiàn):
[1] 黃燕民,陳宏軒,羅友高,等.基于Python與S7-1500的清洗機(jī)器人運(yùn)動(dòng)控制系統(tǒng)[J].機(jī)電一體化,2022,28(Z2):79-84.
[2] 王奚,王新月,李航,等.面向PLC產(chǎn)品的自動(dòng)化測(cè)試系統(tǒng)平臺(tái)設(shè)計(jì)與實(shí)現(xiàn)[J].自動(dòng)化儀表,2022,43(5):8-11+19.
[3] 韓志三.基于Python的豐煒系列PLC與PC串行通信的實(shí)現(xiàn)[J].硅谷,2013,6(22):59-60+15.
[4] 周任杰,劉宇,張子立,等.基于Python的龍骨成型機(jī)通信方案設(shè)計(jì)[J].計(jì)算機(jī)應(yīng)用與軟件,2019,36(06):93-96+135.
(本文來源于《電子產(chǎn)品世界》雜志2023年8月期)
評(píng)論