C# IoTClient与三菱PLC通讯详解
Mr.oki
撰写于 2024年 08月 22 日

本文转载于公众号“技术老小子”整理而成。
IoTClient是一个功能强大的开源库,可以帮助开发者轻松实现与各种工业设备的通信,包括三菱PLC。下面我们将深入探讨如何使用IoTClient与三菱PLC进行通信。

1.引入IoTClient库

首先,我们需要在项目中引入IoTClient库。可以通过NuGet包管理器安装:

Install-Package IoTClient

或者在Visual Studio的NuGet包管理器中搜索"IoTClient"并安装。
1.png
以下例子都是用IotClient Tools仿真测试的。
2.png

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}");
}

3.png

读取短整型

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}");
}

4.png

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;

5.png

7.批量写入

同样,批量写入也是支持的:

这个方法还没有具体实现
6.png
简单实现一下这个方法

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进行通信。

C# IoTClient与三菱PLC通讯详解

本文转载于公众号“技术老小子”整理而成。
IoTClient是一个功能强大的开源库,可以帮助开发者轻松实现与各种工业设备的通信,包括三菱PLC。下面我们将深入探讨如何使用IoTClient与三菱PLC进行通信。

1.引入IoTClient库

首先,我们需要在项目中引入IoTClient库。可以通过NuGet包管理器安装:

Install-Package IoTClient

或者在Visual Studio的NuGet包管理器中搜索"IoTClient"并安装。
1.png
以下例子都是用IotClient Tools仿真测试的。
2.png

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}");
}

3.png

读取短整型

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}");
}

4.png

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;

5.png

7.批量写入

同样,批量写入也是支持的:

这个方法还没有具体实现
6.png
简单实现一下这个方法

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进行通信。

赞 (1)

猜您想看

评论区(2条评论)

我要评论


小小云
LV1
  

想问一下博主,博主用的是Winform还是Wpf呀

Mr.oki
博主
   小小云

都可以用的,看你使用习惯。我比较喜欢用winform,但实际工作中用的也不多。

回复 0