1、創(chuàng)建maven工程引入依賴
<!-- https://mvnrepository.com/artifact/com.github.dathlin/HslCommunication -->
<dependency>
<groupId>com.github.dathlin</groupId>
<artifactId>HslCommunication</artifactId>
<version>3.3.1</version>
</dependency>
進行PLC連接需要了解兩個概念:長連接和短連接。為了更好的說明當前的通信情況,我把所有的通信拆分為四個部分,連接,發(fā),收,斷開。
- 短連接:連接,發(fā),收,斷開,連接,發(fā),收,斷開,連接,發(fā),收,斷開,連接,發(fā),收,斷開…無限循環(huán)
- 長連接:連接,發(fā),收,發(fā),收,發(fā),收,發(fā),收,發(fā),收,發(fā),收,發(fā),收,發(fā),收,發(fā),收…斷開
然后我們來看看異常的情況,短連接的異常比較好處理,反正每次請求都是先連接,關(guān)鍵來看長連接的異常
長連接:連接,發(fā),收,發(fā),收…異常,連接,發(fā),收,發(fā),收,異常,連接,連接,連接…收,發(fā),收,發(fā),收,發(fā),收,發(fā),收…斷開
這里第一個異常發(fā)生后,第二次讀寫立即連接上去并且成功,第二個異常觸發(fā)后,一直讀寫失敗,說明就是一直連接不上去。
對于HSL組件來說,不需要重復(fù)連接服務(wù)器或是plc,無論是短連接還是長連接,都只需要一直讀寫就OK了,對讀寫的結(jié)果進行判定,即使發(fā)生異常了,讀寫失敗了,也要一直堅持,網(wǎng)絡(luò)好的時候,讀寫會恢復(fù)成功的。
2、通過代碼進行連接通訊
- 實現(xiàn)短連接
// 實例化對象,指定PLC的ip地址和端口號
MelsecMcNet melsecMc = new MelsecMcNet( "192.168.1.110", 6000 );
// 舉例讀取D100的值
short D100 = melsecMc.ReadInt16( "D100" ).Content;
- 實現(xiàn)長連接
// 實例化對象,指定PLC的ip地址和端口號
MelsecMcNet melsecMc = new MelsecMcNet( "192.168.1.110", 6000 );
// 如果網(wǎng)絡(luò)不太理想,配置了兩個端口,一個有問題,立即切換另一個的話,可以配置如下的代碼
// melsecMc.GetPipeSocket( ).SetMultiPorts( new int[] { 6000, 6001 } );
// 連接對象
OperateResult connect = melsecMc.ConnectServer( );
if (!connect.IsSuccess) //用于判斷是否連接成功,返回true/false
{
Console.WriteLine( "connect failed:" + connect.Message );
return;
}
// 舉例讀取D100的值
short D100 = melsecMc.ReadInt16( "D100" ).Content;
// 實際上所有的讀寫都是返回是否成功的標記的,在實際的開發(fā)中,需要嚴格的判定,怎么判定呢?如下的代碼
OperateResult<short> readD100 = melsecMc.ReadInt16( "D100" );
if (readD100.IsSuccess)
{
// 讀取成功,這時候獲取Content才是正確的值
short value = readD100.Content;
}
else
{
// 讀取失敗,如果仍然堅持去獲取Content的值,就為0
}
// 讀寫是否成功的情況,應(yīng)用于幾乎所有的讀寫代碼,只要看清楚返回的數(shù)據(jù)類型即可
melsecMc.ConnectClose( );
3、基本的讀取示例
MelsecMcNet melsec_net = new MelsecMcNet( "192.168.0.100", 6000 );
melsec_net.SetPersistentConnection( ); // 設(shè)置長連接的操作
// 此處以D寄存器作為示例,此處沒有判斷是否讀寫成功,所以是有風險的,如果通訊失敗,所有的值都不是正確的
short short_D1000 = melsec_net.ReadInt16( "D1000" ).Content; // 讀取D1000的short值
ushort ushort_D1000 = melsec_net.ReadUInt16( "D1000" ).Content; // 讀取D1000的ushort值
int int_D1000 = melsec_net.ReadInt32( "D1000" ).Content; // 讀取D1000-D1001組成的int數(shù)據(jù)
uint uint_D1000 = melsec_net.ReadUInt32( "D1000" ).Content; // 讀取D1000-D1001組成的uint數(shù)據(jù)
float float_D1000 = melsec_net.ReadFloat( "D1000" ).Content; // 讀取D1000-D1001組成的float數(shù)據(jù)
long long_D1000 = melsec_net.ReadInt64( "D1000" ).Content; // 讀取D1000-D1003組成的long數(shù)據(jù)
ulong ulong_D1000 = melsec_net.ReadUInt64( "D1000" ).Content; // 讀取D1000-D1003組成的long數(shù)據(jù)
double double_D1000 = melsec_net.ReadDouble( "D1000" ).Content; // 讀取D1000-D1003組成的double數(shù)據(jù)
string str_D1000 = melsec_net.ReadString( "D1000", 10 ).Content; // 讀取D1000-D1009組成的條碼數(shù)據(jù)
// 讀取數(shù)組
short[] short_D1000_array = melsec_net.ReadInt16( "D1000", 10 ).Content; // 讀取D1000的short值
ushort[] ushort_D1000_array = melsec_net.ReadUInt16( "D1000", 10 ).Content; // 讀取D1000的ushort值
int[] int_D1000_array = melsec_net.ReadInt32( "D1000", 10 ).Content; // 讀取D1000-D1001組成的int數(shù)據(jù)
uint[] uint_D1000_array = melsec_net.ReadUInt32( "D1000", 10 ).Content; // 讀取D1000-D1001組成的uint數(shù)據(jù)
float[] float_D1000_array = melsec_net.ReadFloat( "D1000", 10 ).Content; // 讀取D1000-D1001組成的float數(shù)據(jù)
long[] long_D1000_array = melsec_net.ReadInt64( "D1000", 10 ).Content; // 讀取D1000-D1003組成的long數(shù)據(jù)
ulong[] ulong_D1000_array = melsec_net.ReadUInt64( "D1000", 10 ).Content; // 讀取D1000-D1003組成的long數(shù)據(jù)
double[] double_D1000_array = melsec_net.ReadDouble( "D1000", 10 ).Content; // 讀取D1000-D1003組成的double數(shù)據(jù)
4、具體的詳細讀取demo
常用方法
setNetworkNumber()
:設(shè)置網(wǎng)絡(luò)號ConnectServer()
:把連接由短連接切換為長連接,需要斷開重新連接SetPersistentConnection()
:設(shè)置長連接的操作,不需要斷開重新連接IsSuccess
:判斷是否連接成功read
開頭的方法都為讀取方法,write
開頭的方法都為寫入的方法
public class MelsenMcClent {
private MelsecMcNet clent;
private String ip;
private int port;
/**
* 初始化連接對象
* @author zhengfuping
* @date 2023/1/9 8:07
* @version 1.0
*/
public boolean iniConnet(String ip,int port){
clent = new MelsecMcNet(ip, port);
this.ip = ip;
this.port = port;
clent.setNetworkStationNumber((byte) 0x00);
clent.setSleepTime(10);
OperateResult connet = clent.ConnectServer();
return connet.IsSuccess;
}
/**
* @description: TODO 重試連接
* @author zhengfuping
* @date 2023/1/9 8:07
* @version 1.0
*/
public boolean restartConnet(){
OperateResult connet = clent.ConnectServer();
if(connet != null && connet.IsSuccess){
return true;
}else{
clent = new MelsecMcNet(this.ip, this.port);
clent.setNetworkStationNumber((byte) 0x00);
clent.setSleepTime(10);
connet = clent.ConnectServer();
return connet.IsSuccess;
}
}
/**
* 讀取字符串
* */
public String read(String address,int length){
OperateResultExOne<String> result = clent.ReadString(address,(short)length);
return result.Content.trim();
}
/**
* 讀取32位數(shù)字
* */
public Integer readInt32(String address){
OperateResultExOne<Integer> result = clent.ReadInt32(address);
return result.Content;
}
/**
* 讀取16位數(shù)字
* */
public Short readInt16(String address){
OperateResultExOne<Short> result = clent.ReadInt16(address);
return result.Content;
}
/**
* 讀取浮點數(shù)
* */
public Float readFloat(String address){
OperateResultExOne<Float> result = clent.ReadFloat(address);
return result.Content;
}
/**
* 寫入字符串
* */
public boolean write(String address,String dataVal){
OperateResult result = clent.Write(address, dataVal);
return result.IsSuccess;
}
/**
* 寫入數(shù)字
* */
public boolean write(String address,short dataVal){
OperateResult result = clent.Write(address, dataVal);
return result.IsSuccess;
}
//下面的或者工具類對象可以自己根據(jù)業(yè)務(wù)情況設(shè)置,一般三菱PLC是一個端口只能有一個客戶端去連接
/**
* 創(chuàng)建單例
* */
private static class Interior{
private static MelsenMcClent CLENT = new MelsenMcClent();
public static MelsenMcClent getConnect(String state){
MelsenMcClent writeClent;
if (state.equals("Write")){
writeClent = getWriteClent();
}else if (state.equals("Read")){
writeClent = getReadClent();
}else {
writeClent = null;
}
return writeClent;
}
/**
* 寫入對象
* */
private static MelsenMcClent getWriteClent(){
MelsenMcClent writeClent=Interior.CLENT;
writeClent.iniConnet("192.168.120.158", 4000);
return writeClent;
}
/**讀取對象*/
private static MelsenMcClent getReadClent(){
MelsenMcClent readClent=Interior.CLENT;
readClent.iniConnet("192.168.120.158", 4001);
return readClent;
}
}
/**
* 返回連接工具對象(因為我這邊需要讀取寫入分開,所以設(shè)置為兩個,可以不設(shè)置)
* @param state 讀取/寫入狀態(tài)
* @return MelsenMcClent
*/
public static MelsenMcClent getConnect(String state){
return Interior.getConnect(state);
}
###具體調(diào)用讀取和寫入的代碼如下
因為我本地沒有連接PLC就不粘貼日志的輸出結(jié)果了,可以使用下面的軟件進行配合測試
使用軟件進行測試
1、寫入值:
2、讀取值
剛剛寫入的值
- 軟件名字叫HslCommunication,可以直接他家官網(wǎng)下載,具體頁面如下,選擇好PLC型號,然后輸入IP和端口就可以連接測試了
??一些同學說依賴有問題;我把我的發(fā)百度網(wǎng)盤上了,需要的可以自己拿文章來源:http://www.zghlxwxcb.cn/news/detail-658140.html
鏈接: https://pan.baidu.com/s/1NcpAVuzSqURhWs7wfUhMQg?pwd=rg12
提取碼: rg12文章來源地址http://www.zghlxwxcb.cn/news/detail-658140.html
到了這里,關(guān)于【2023】JAVA和PLC實現(xiàn)通訊讀取寫入數(shù)據(jù),以三菱PLC舉例的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!