1、创建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连接需要了解两个概念:长连接和短连接。为了更好的说明当前的通信情况,我把所有的通信拆分为四个部分,连接,发,收,断开。
- 短连接:连接,发,收,断开,连接,发,收,断开,连接,发,收,断开,连接,发,收,断开…无限循环
- 长连接:连接,发,收,发,收,发,收,发,收,发,收,发,收,发,收,发,收,发,收…断开
然后我们来看看异常的情况,短连接的异常比较好处理,反正每次请求都是先连接,关键来看长连接的异常
长连接:连接,发,收,发,收…异常,连接,发,收,发,收,异常,连接,连接,连接…收,发,收,发,收,发,收,发,收…断开
这里第一个异常发生后,第二次读写立即连接上去并且成功,第二个异常触发后,一直读写失败,说明就是一直连接不上去。
对于HSL组件来说,不需要重复连接服务器或是plc,无论是短连接还是长连接,都只需要一直读写就OK了,对读写的结果进行判定,即使发生异常了,读写失败了,也要一直坚持,网络好的时候,读写会恢复成功的。
2、通过代码进行连接通讯
- 实现短连接
// 实例化对象,指定PLC的ip地址和端口号
MelsecMcNet melsecMc = new MelsecMcNet( "192.168.1.110", 6000 );
// 举例读取D100的值
short D100 = melsecMc.ReadInt16( "D100" ).Content;
- 实现长连接
// 实例化对象,指定PLC的ip地址和端口号
MelsecMcNet melsecMc = new MelsecMcNet( "192.168.1.110", 6000 );
// 如果网络不太理想,配置了两个端口,一个有问题,立即切换另一个的话,可以配置如下的代码
// 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;
// 实际上所有的读写都是返回是否成功的标记的,在实际的开发中,需要严格的判定,怎么判定呢?如下的代码
OperateResult<short> readD100 = melsecMc.ReadInt16( "D100" );
if (readD100.IsSuccess)
{
// 读取成功,这时候获取Content才是正确的值
short value = readD100.Content;
}
else
{
// 读取失败,如果仍然坚持去获取Content的值,就为0
}
// 读写是否成功的情况,应用于几乎所有的读写代码,只要看清楚返回的数据类型即可
melsecMc.ConnectClose( );
3、基本的读取示例
MelsecMcNet melsec_net = new MelsecMcNet( "192.168.0.100", 6000 );
melsec_net.SetPersistentConnection( ); // 设置长连接的操作
// 此处以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数据
uint uint_D1000 = melsec_net.ReadUInt32( "D1000" ).Content; // 读取D1000-D1001组成的uint数据
float float_D1000 = melsec_net.ReadFloat( "D1000" ).Content; // 读取D1000-D1001组成的float数据
long long_D1000 = melsec_net.ReadInt64( "D1000" ).Content; // 读取D1000-D1003组成的long数据
ulong ulong_D1000 = melsec_net.ReadUInt64( "D1000" ).Content; // 读取D1000-D1003组成的long数据
double double_D1000 = melsec_net.ReadDouble( "D1000" ).Content; // 读取D1000-D1003组成的double数据
string str_D1000 = melsec_net.ReadString( "D1000", 10 ).Content; // 读取D1000-D1009组成的条码数据
// 读取数组
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数据
uint[] uint_D1000_array = melsec_net.ReadUInt32( "D1000", 10 ).Content; // 读取D1000-D1001组成的uint数据
float[] float_D1000_array = melsec_net.ReadFloat( "D1000", 10 ).Content; // 读取D1000-D1001组成的float数据
long[] long_D1000_array = melsec_net.ReadInt64( "D1000", 10 ).Content; // 读取D1000-D1003组成的long数据
ulong[] ulong_D1000_array = melsec_net.ReadUInt64( "D1000", 10 ).Content; // 读取D1000-D1003组成的long数据
double[] double_D1000_array = melsec_net.ReadDouble( "D1000", 10 ).Content; // 读取D1000-D1003组成的double数据
4、具体的详细读取demo
常用方法
setNetworkNumber()
:设置网络号ConnectServer()
:把连接由短连接切换为长连接,需要断开重新连接SetPersistentConnection()
:设置长连接的操作,不需要断开重新连接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位数字
* */
public Integer readInt32(String address){
OperateResultExOne<Integer> result = clent.ReadInt32(address);
return result.Content;
}
/**
* 读取16位数字
* */
public Short readInt16(String address){
OperateResultExOne<Short> result = clent.ReadInt16(address);
return result.Content;
}
/**
* 读取浮点数
* */
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;
}
/**
* 写入数字
* */
public boolean write(String address,short dataVal){
OperateResult result = clent.Write(address, dataVal);
return result.IsSuccess;
}
//下面的或者工具类对象可以自己根据业务情况设置,一般三菱PLC是一个端口只能有一个客户端去连接
/**
* 创建单例
* */
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;
}
}
/**
* 返回连接工具对象(因为我这边需要读取写入分开,所以设置为两个,可以不设置)
* @param state 读取/写入状态
* @return MelsenMcClent
*/
public static MelsenMcClent getConnect(String state){
return Interior.getConnect(state);
}
###具体调用读取和写入的代码如下
因为我本地没有连接PLC就不粘贴日志的输出结果了,可以使用下面的软件进行配合测试
使用软件进行测试
1、写入值:
2、读取值
刚刚写入的值
- 软件名字叫HslCommunication,可以直接他家官网下载,具体页面如下,选择好PLC型号,然后输入IP和端口就可以连接测试了
🔗一些同学说依赖有问题;我把我的发百度网盘上了,需要的可以自己拿文章来源:https://www.toymoban.com/news/detail-658140.html
链接: https://pan.baidu.com/s/1NcpAVuzSqURhWs7wfUhMQg?pwd=rg12
提取码: rg12文章来源地址https://www.toymoban.com/news/detail-658140.html
到了这里,关于【2023】JAVA和PLC实现通讯读取写入数据,以三菱PLC举例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!