陳雪嬌,繆文南
(華南理工大學(xué) 廣州學(xué)院, 廣州 510800)
西門子 S7-1200 定位于“低端的離散自動(dòng)化系統(tǒng)和獨(dú)立自動(dòng)化系統(tǒng)中使用的小型控制器模塊”,充分滿足于中小型自動(dòng)化的系統(tǒng)需求。此系列產(chǎn)品的設(shè)計(jì)充分考慮了系統(tǒng)、控制器、人機(jī)界面和軟件的無縫整合和高效協(xié)調(diào)的需求[1-4]。特別是面向小規(guī)模裝置的可編程控制器,具有符合不同用途的通信功能,如:與控制柜內(nèi)的顯示器及變頻器的連接、遠(yuǎn)程監(jiān)控等。
目前,由于西門子公司沒有公開通信協(xié)議,上位機(jī)程序設(shè)計(jì)主要有兩種方式:采用專門的組態(tài)軟件(如 WinCC、組態(tài)王等)開發(fā)或是通過編程語言自行開發(fā)。第1 種方法操作簡單、效率高,對開發(fā)人員的要求相對較低,但成本較高;第 2 種方法相對復(fù)雜,要求開發(fā)者具有較高的編程水平,開發(fā)周期長,但與第1 種方法相比具有靈活、成本低的優(yōu)點(diǎn)[5-7]。本文采用第二種方法。
在進(jìn)行通訊前需要對西門子PLC進(jìn)行配置,本次采用西門子公司生產(chǎn)的S7-1200系列PLC,CPU型號為1212C,集成以太網(wǎng)通訊模塊,在使用第三方程序?qū)LC進(jìn)行讀寫之前,需要對PLC進(jìn)行權(quán)限設(shè)置,允許遠(yuǎn)程連接PLC,以TIA PORTAL V13為例,打開設(shè)備屬性——常規(guī)選項(xiàng)卡——web服務(wù)器——保護(hù)——勾選允許遠(yuǎn)程連接,如圖1所示。
Socket建立在傳輸層協(xié)議(TCP和UDP)之上,由于TCP面向連接,UDP是無連接的,因此,利用Socket進(jìn)行通信,有兩種方式:面向連接的和無連接的[8-9]。在第一種方式下,兩個(gè)通信的應(yīng)用程序之間必須先建立一種虛擬的連接,然后再傳輸數(shù)據(jù)。第二種方式也稱數(shù)據(jù)報(bào)文方式,在此種方式下,傳輸過程中,數(shù)據(jù)有可能丟失,先發(fā)送的數(shù)據(jù)也可能后到,各個(gè)報(bào)文的路徑也不定相同[3]。本文采用面向連接的通信方式,讀數(shù)據(jù)的流程如圖2所示。寫數(shù)據(jù)的流程和讀數(shù)據(jù)的流程是一致的,把圖1中讀數(shù)據(jù)的模塊改為寫數(shù)據(jù)模塊即可。
圖1 PLC設(shè)備的屬性設(shè)置
圖2 讀數(shù)據(jù)流程
通過安裝選裝Ethernet通信單元,加上SOCKET服務(wù),可實(shí)現(xiàn)在以太網(wǎng)下的高速穩(wěn)定的數(shù)據(jù)讀寫功能。而在C#中,System.Net.Sockets命名空間為需要嚴(yán)密控制網(wǎng)絡(luò)訪問的開發(fā)人員提供了Sockets接口的托管實(shí)現(xiàn)。System.Net命名空間中的所有其他網(wǎng)絡(luò)訪問類都建立在該套接字Socket實(shí)現(xiàn)之上,如TCPClient、TCPListener和UDPClient類封裝有關(guān)創(chuàng)建到Internet的TCP和UDP連接的詳細(xì)信息;NetworkStream類則提供用于網(wǎng)絡(luò)訪問的基礎(chǔ)數(shù)據(jù)流等.
定義SOCKET連接及設(shè)置:
mSocket=newSocket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReceiveTimeout, 1000);
mSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.SendTimeout, 1000);
IPEndPoint server = newIPEndPoint(IPAddress.Parse(RemoteIP), RemotePort);
連接:
mSocket.Connect(server);
一般情況下,電腦IP和PLC IP設(shè)置正確后連接都沒有問題,但這一步只表明和PLC的TCP網(wǎng)絡(luò)連接成功,并不代表能對PLC進(jìn)行數(shù)據(jù)讀寫.
在TCP連接正常后,需要對PLC發(fā)送特定的指令才能實(shí)現(xiàn)讀寫功能.
try
{
……
//S7-1200系列PLC以下內(nèi)容和西門子其他類型不同
mSendArray [11]=193;
mSendArray [12]=2;
mSendArray [13]=1;
mSendArray [14]=0;
mSendArray [15]=194;
mSendArray [16]=2;
mSendArray [17]=3;
mSendArray [18]=(byte)(Rack*2*16+Slot); //rack--機(jī)架號,slot--槽號,根據(jù)PLC實(shí)際配置情況設(shè)置,單CPU時(shí)rack默認(rèn)為0,slot默認(rèn)為1
……
mSocket.Send(bSend1, 22, SocketFlags.None);
//收到PLC正確回復(fù)后,可以進(jìn)行數(shù)據(jù)讀寫
if (mSocket.Receive(bReceive, 22, SocketFlags.None) !=22)
{
thrownewException(ErrorCode.WrongNumberReceivedBytes.ToString());
}
}
catch (Exception)
{
return -1;
}
讀數(shù)據(jù)也是采用SOCKET方式進(jìn)行,直接使用PLC地址即可讀取該地址內(nèi)容,地址格式如:M0.0;MB0;MD0;DB1.DBX0.0;DB20.DBD200;T45等.
針對不同的變量類型,需要轉(zhuǎn)換成不同的字節(jié)長度:
privateint VarTypeToByteLength(VarType varType, int varCount=1)
{
switch (varType)
{
caseVarType.Bit:
return varCount; //TODO
caseVarType.Byte:
return (varCount < 1) ? 1 : varCount;
caseVarType.String:
return varCount;
caseVarType.Word:
caseVarType.Timer:
caseVarType.Int:
caseVarType.Counter:
return varCount * 2;
caseVarType.DWord:
caseVarType.DInt:
caseVarType.Real:
return varCount * 4;
default:
return 0;
}
}
寫數(shù)據(jù)也是采用SOCKET方式進(jìn)行,直接使用PLC地址即可讀取該地址內(nèi)容,地址格式和讀數(shù)據(jù)時(shí)相同,需要注意的是寫值時(shí)寫的值類型和該地址的類型必須相同,例:M0.0只能寫入bit類型,MB0只能寫入byte類型。
本文件介紹了在TCP協(xié)議下如何使用C#編程語言對西門子PLC進(jìn)行數(shù)據(jù)讀寫操作,依靠C#編程語言的簡便性及socket服務(wù)的通用性,實(shí)現(xiàn)了對西門子PLC數(shù)據(jù)的讀寫操作,最后需要說明一點(diǎn),C#編程語言自身帶有內(nèi)存回收機(jī)制,在關(guān)閉軟件時(shí),所有資源會(huì)自動(dòng)釋放,但在程序未關(guān)閉時(shí)多次使用socket服務(wù)連接PLC時(shí),在每次連接結(jié)束后需要手動(dòng)釋放資源,否則可能導(dǎo)致無法連接。