本文转载于公众号“技术老小子”整理而成。
IoTClient是一个功能强大的开源库,可以帮助开发者轻松实现与各种工业设备的通信,包括三菱PLC。下面我们将深入探讨如何使用IoTClient与三菱PLC进行通信。
1.引入IoTClient库
首先,我们需要在项目中引入IoTClient库。可以通过NuGet包管理器安装:
Install-Package IoTClient
或者在Visual Studio的NuGet包管理器中搜索"IoTClient"并安装。
以下例子都是用IotClient Tools仿真测试的。
2.初始化MitsubishiClient
要与三菱PLC通信,我们需要使用MitsubishiClient类。以下是初始化客户端的示例:
// 初始化客户端,使用Qna_3E协议,IP地址为"127.0.0.1",端口为6000
MitsubishiClient client = new MitsubishiClient(MitsubishiVersion.Qna_3E, "127.0.0.1", 6000);
3.连接到PLC
建议在进行读写操作之前先打开连接,以提高效率:
client.Open();
if (client.Connected)
{
Console.WriteLine("连接成功!");
}
else
{
Console.WriteLine("连接失败!");
}
4.读取PLC数据
IoTClient提供了多种数据类型的读取方法。以下是一些例子:
读取布尔值
var boolResult = client.ReadBoolean("M100");
if (boolResult.IsSucceed)
{
Console.WriteLine($"M100的值为:{boolResult.Value}");
}
else
{
Console.WriteLine($"读取失败:{boolResult.Err}");
}
读取短整型
var shortResult = client.ReadInt16("D200");
if (shortResult.IsSucceed)
{
Console.WriteLine($"D200的值为:{shortResult.Value}");
}
else
{
Console.WriteLine($"读取失败:{shortResult.Err}");
}
读取整型
var intResult = client.ReadFloat("D210");
if (intResult.IsSucceed)
{
Console.WriteLine($"D210-D211的值为:{intResult.Value}");
}
else
{
Console.WriteLine($"读取失败:{intResult.Err}");
}
读取浮点
var intResult = client.ReadInt32("D210");
if (intResult.IsSucceed)
{
Console.WriteLine($"D210-D211的值为:{intResult.Value}");
}
else
{
Console.WriteLine($"读取失败:{intResult.Err}");
}
5.写入PLC数据
同样,IoTClient也提供了多种数据类型的写入方法:
写入布尔值
var writeBoolResult = client.Write("M100", true);
if (writeBoolResult.IsSucceed)
{
Console.WriteLine("M100写入成功");
}
else
{
Console.WriteLine($"写入失败:{writeBoolResult.Err}");
}
写入短整型
var writeShortResult = client.Write("D200", (short)12345);
if (writeShortResult.IsSucceed)
{
Console.WriteLine("D200写入成功");
}
else
{
Console.WriteLine($"写入失败:{writeShortResult.Err}");
}
写入整型
var writeIntResult = client.Write("D210", 123456789);
if (writeIntResult.IsSucceed)
{
Console.WriteLine("D210-D211写入成功");
}
else
{
Console.WriteLine($"写入失败:{writeIntResult.Err}");
}
6.批量读取
IoTClient还支持批量读取,这可以显著提高效率:
Dictionary<string, DataTypeEnum> addresses = new Dictionary<string, DataTypeEnum>
{
{ "D200", DataTypeEnum.Int16 },
{ "D210", DataTypeEnum.Float }
};
var batchReadResult = client.BatchRead(addresses,0);
if (batchReadResult.IsSucceed)
{
foreach (var item in batchReadResult.Value)
{
Console.WriteLine($"地址:{item.Key},值:{item.Value}");
}
}
else
{
Console.WriteLine($"批量读取失败:{batchReadResult.Err}");
}
简单阅读了一下源代码,发现有些类型在批量读取是会报异常,再就是batchNumber暂时没有用到
不过简单修改一下代码,批量读是没有问题, 以下是读取bool的。
tempVaue = ReadBoolean(item.TypeChar + item.BeginAddress.ToString()).Value;
7.批量写入
同样,批量写入也是支持的:
这个方法还没有具体实现
简单实现一下这个方法
public Result BatchWrite(Dictionary<string, object> addresses, int batchNumber)
{
var result = new Result<Dictionary<string, object>>();
result.Value = new Dictionary<string, object>();
foreach (var item in addresses)
{
var address = item.Key;
var value = item.Value;
// 使用反射将 object 转换回元组
var type = value.GetType();
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(ValueTuple<,>))
{
// 获取元组的元素
var firstItem = type.GetField("Item1").GetValue(value);
var secondItem = type.GetField("Item2").GetValue(value);
switch (secondItem)
{
case DataTypeEnum.Bool:
Write(address, Convert.ToBoolean(firstItem));
break;
case DataTypeEnum.Int16:
Write(address, Convert.ToInt16(firstItem));
break;
case DataTypeEnum.Int32:
Write(address, Convert.ToInt32(firstItem));
break;
case DataTypeEnum.Float:
Write(address, Convert.ToSingle(firstItem));
break;
default:
throw new Exception("Err BatchWrite 未定义类型 -1");
}
}
}
return result.EndTime();
}
Dictionary<string, object> writeValues = new Dictionary<string, object>
{
{ "M100", (true,DataTypeEnum.Bool) },
{ "D200", (12345,DataTypeEnum.Int16) },
{ "D210", (98.34,DataTypeEnum.Float) }
};
var batchWriteResult = client.BatchWrite(writeValues, 10);
if (batchWriteResult.IsSucceed)
{
Console.WriteLine("批量写入成功");
}
else
{
Console.WriteLine($"批量写入失败:{batchWriteResult.Err}");
}
8.错误处理
在进行读写操作时,我们应该始终检查操作是否成功,并适当处理错误:
var result = client.ReadInt16("D200");
if (result.IsSucceed)
{
Console.WriteLine($"读取成功,值为:{result.Value}");
}
else
{
Console.WriteLine($"读取失败,错误信息:{result.Err}");
Console.WriteLine($"请求报文:{result.Requst}");
Console.WriteLine($"响应报文:{result.Response}");
}
9.关闭连接
在完成所有操作后,记得关闭连接:
client.Close();
通过使用IoTClient库,我们可以轻松地实现与三菱PLC的通信,大大简化了工业自动化和物联网应用的开发过程。希望这篇文章能够帮助您更好地理解和使用IoTClient与三菱PLC进行通信。