C#读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC

本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作

官方地址:http://www.hslcommunication.cn/ 打赏请认准官网。

nuget地址:https://www.nuget.org/packages/HslCommunication/            

github地址:https://github.com/dathlin/HslCommunication                             如果喜欢可以star或是fork,还可以打赏支持。

联系作者及加群方式(激活码在群里发放):http://www.hslcommunication.cn/Cooperation

在Visual Studio 中的NuGet管理器中可以下载安装,也可以直接在NuGet控制台输入下面的指令安装

1
Install-Package HslCommunication

如果需要教程:Nuget安装教程:http://www.cnblogs.com/dathlin/p/7705014.html

组件的完整信息和其他API介绍参照:http://www.cnblogs.com/dathlin/p/7703805.html   组件的授权协议,更新日志,都在该页面里面。

本文将展示如何配置网络参数及怎样使用代码来访问PLC数据,希望给有需要的人解决一些实际问题。主要对西门子PLC的M,Q,I,DB块的数据读写,亲测有效。

此处使用了网线直接的方式,如果PLC接进了局域网,就可以进行远程读写了^_^

此处使用到了2个命名空间:

1
2
using HslCommunication;
using HslCommunication.Profinet.Siemens;

随便聊聊


当我们一个上位机需要读取100台西门子PLC设备(此处只是举个例子,凡是都是使用Modbus tcp的都是一样的)的时候,你采用服务器主动去请求100台设备的机制对性能来说是个极大的考验,如果开100个线程去轮询100台设备,那么性能损失将是非常大的,更不用说再增加设备,如果搭建Modbus tcp服务器,就可以完美的解决性能问题,因为连接的压力将会平均分摊给每一台PLC,服务器端只要新增一个时间戳就可以知道客户端有没有连接上。

我们在100台PLC里都增加发送Modbus tcp方法,将数据发送到服务器的ip和端口上去,服务器根据站号来区分设备。这样就可以搭建一个高性能总站。 本组件支持快速搭建一个高性能的Modbus tcp总站。

http://www.cnblogs.com/dathlin/p/7782315.html

关于两种模式


本组件所提供的所有客户端类,包括三菱,西门子,欧姆龙,modbus-tcp,以及SimplifyNet都是继承自双模式基类,双模式包含了短连接和长连接,下面就具体介绍下两个模式的区别

短连接:每次读写都是一个单独的请求,请求完毕也就关闭了,如果服务器的端口仅仅支持单连接,那么关闭后这个端口可以被其他连接复用,但是在频繁的网络请求下,容易发生异常,会有其他的请求不成功,尤其是多线程的情况下。

长连接:创建一个公用的连接通道,所有的读写请求都利用这个通道来完成,这样的话,读写性能更快速,即时多线程调用也不会影响,内部有同步机制。如果服务器的端口仅仅支持单连接,那么这个端口就被占用了,比如三菱的端口机制,西门子的Modbus tcp端口机制也是这样的。以下代码默认使用长连接,性能更高,还支持多线程同步。

在短连接的模式下,每次请求都是单独的访问,所以没有重连的困扰,在长连接的模式下,如果本次请求失败了,在下次请求的时候,会自动重新连接服务器,直到请求成功为止。另外,尽量所有的读写都对结果的成功进行判断。

关于日志记录


不管是三菱的数据访问类,还是西门子的,还是Modbus tcp访问类,都有一个LogNet属性用来记录日志,该属性是一个接口类,ILogNet,凡事继承该接口的都可以用来记录日志,该日志会在访问失败时,尤其是因为网络的原因导致访问失败时会进行日志记录(如果你为这个 LogNet 属性配置了真实的日志记录器的话):如果你想使用该记录日志的功能,请参照如下的博客进行实例化:

http://www.cnblogs.com/dathlin/p/7691693.html

举个例子:

1
siemensTcpNet.LogNet = new HslCommunication.LogNet.LogNetSingle( "log.txt" );

关于两种协议


本组件支持的西门子通信有两种协议,一种是S7协议,在PLC侧几乎不需要配置参数,另一个协议Fetch/Write协议,相对比较麻烦一点,如果S7不方便读取的话,可以选择Fetch/Write,相对而言,S7更加方便点。

这两个协议除了实例化的类型不一致,读写PLC的代码和连接机制都是一致的,所以FW协议的具体代码就不粘贴了,详细参照下面的Demo项目。

访问测试项目


在上述的github源代码里有个测试项目,HslCommunicationDemo,里面包含了各种客户端的Demo项目,不需要编写任何的代码就可以测试数据的访问了。

下载地址为:HslCommunicationDemo.zip

演示项目


下面的三篇演示了具体如何去访问PLC的数据,我们在访问完成后,通常需要进行处理,以下的示例项目就演示了后台从PLC读取数据后,前台显示并推送给所有在线客户端的功能,客户端并进行图形化显示,具有一定的参考意义,项目地址为:

https://github.com/dathlin/RemoteMonitor

下面的图片示例中的左边程序就是服务器程序,它应该和PLC直接连接并接入局域网,然后把数据推送给客户端显示。注意:一个复杂高级的程序就应该把处理逻辑程序和界面程序分开,比如这里的服务器程序实现数据采集,推送,存储。让客户端程序去实现数据的整理,分析,显示,这样即使客户端程序因为BUG奔溃,服务器端仍然可以正常的工作。

S7协议下的tcp直接通讯,配置简单,一般PLC都支持


测试通过的PLC:1200系列 本人亲测

                          200smart  感谢 無名①终止^^ 的测试

                          300系列  感谢 懂PLC不懂c# 的测试

                          1500系列 感谢 ∮溪风-⊙_⌒ 的测试

报文的格式参考了如下的两篇文章

http://www.itpub.net/thread-2052649-1-1.html

https://wenku.baidu.com/view/d93b88b06394dd88d0d233d4b14e852459fb3912.html

如果你擅长于网络通信和组件开发,可以通过报文格式开发出自己的西门子通信库,我所做的就是基于报文格式进行了二次封装,隐藏了socket通信的细节,还包含了异常处理,提供了简单方便的API来读写数据。提供了整数数据的读写,字符串读写,来丰富各种需求,从事实上来说,只要可以读写字节,相当于任何数据了。

准备:在西门子PLC上配置好IP地址,就只有一个IP地址就够了,然后打开电脑的cmd指令,只要能ping通西门子PLC即可。

还需要在PLC侧配置打开  GET/SET通讯允许:(感谢网友 OLIFE 提供的图片) (如果碰到读取数据时出现长度验证失败的信息,请务必检查下面的勾是否打上)

实例化:

1
2
3
siemensTcpNet = new SiemensS7Net( SiemensPLCS.S1200, "192.168.0.100" ) {
                ConnectTimeOut = 5000
            };

如果你的PLC是其他系列的,就修改上面的枚举值,本组件支持的西门子型号都在里面。

连接服务器,也可以放在窗口的Load方法中,一般建议使用长连接,速度更快,又是线程安全的(调用下面的方法就是使用了长连接,如果不连接直接读取数据,那就是短连接):

1
2
3
4
5
6
7
8
9
OperateResult connect = siemensTcpNet.ConnectServer( );
if (connect.IsSuccess)
{
    MessageBox.Show( "连接成功!" );
}
else
{
    MessageBox.Show( "连接失败!" );
}

断开连接,也就是关闭了长连接,如果再去请求数据,就变成了短连接

1
siemensTcpNet.ConnectClose( );

下面就演示一些简单的数据操作,省去了对结果是否成功的验证,所有的读写结果都是OperateResult类型及派生类型,都有一个IsSuccess属性来判断成功与否

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// 读取操作,这里的M100可以替换成I100,Q100,DB20.100效果时一样的
bool M100_7 = siemensTcpNet.ReadBool( "M100.7" ).Content;  // 读取M100.7是否通断,注意M100.0等同于M100
byte byte_M100 = siemensTcpNet.ReadByte( "M100" ).Content; // 读取M100的值
short short_M100 = siemensTcpNet.ReadInt16( "M100" ).Content; // 读取M100-M101组成的字
ushort ushort_M100 = siemensTcpNet.ReadUInt16( "M100" ).Content; // 读取M100-M101组成的无符号的值
int int_M100 = siemensTcpNet.ReadInt32( "M100" ).Content;         // 读取M100-M103组成的有符号的数据
uint uint_M100 = siemensTcpNet.ReadUInt32( "M100" ).Content;      // 读取M100-M103组成的无符号的值
float float_M100 = siemensTcpNet.ReadFloat( "M100" ).Content;   // 读取M100-M103组成的单精度值
long long_M100 = siemensTcpNet.ReadInt64( "M100" ).Content;      // 读取M100-M107组成的大数据值
ulong ulong_M100 = siemensTcpNet.ReadUInt64( "M100" ).Content;   // 读取M100-M107组成的无符号大数据
double double_M100 = siemensTcpNet.ReadDouble( "M100" ).Content; // 读取M100-M107组成的双精度值
string str_M100 = siemensTcpNet.ReadString( "M100", 10 ).Content;// 读取M100-M109组成的ASCII字符串数据
// 写入操作,这里的M100可以替换成I100,Q100,DB20.100效果时一样的
siemensTcpNet.Write( "M100.7"true );                // 写位,注意M100.0等同于M100
siemensTcpNet.Write( "M100", (byte)0x33 );            // 写单个字节
siemensTcpNet.Write( "M100", (short)12345 );          // 写双字节有符号
siemensTcpNet.Write( "M100", (ushort)45678 );         // 写双字节无符号
siemensTcpNet.Write( "M100", 123456789 );             // 写双字有符号
siemensTcpNet.Write( "M100", (uint)3456789123 );      // 写双字无符号
siemensTcpNet.Write( "M100", 123.456f );              // 写单精度
siemensTcpNet.Write( "M100", 1234556434534545L );     // 写大整数有符号
siemensTcpNet.Write( "M100", 523434234234343UL );     // 写大整数无符号
siemensTcpNet.Write( "M100", 123.456d );              // 写双精度
siemensTcpNet.Write( "M100""K123456789" );// 写ASCII字符串

下面说明复杂的数据操作,以及批量化的数据操作,例如读取M100-M109

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
OperateResult<byte[]> read = siemensTcpNet.Read( "M100", 10 );
{
    if(read.IsSuccess)
    {
        byte m100 = read.Content[0];
        byte m101 = read.Content[1];
        byte m102 = read.Content[2];
        byte m103 = read.Content[3];
        byte m104 = read.Content[4];
        byte m105 = read.Content[5];
        byte m106 = read.Content[6];
        byte m107 = read.Content[7];
        byte m108 = read.Content[8];
        byte m109 = read.Content[9];
    }
    else
    {
        // 发生了异常
    }
}

这样就把所有的字节数据都提取上来了,如果数据比较复杂,还可以根据实际情况处理。当然也支持批量的写入数据信息

如果想实现自定义的数据类型,需要继承一个接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
public class UserType : HslCommunication.IDataTransfer
{
    #region IDataTransfer
    private HslCommunication.Core.IByteTransform ByteTransform = new HslCommunication.Core.ReverseBytesTransform( );
    public ushort ReadCount => 20;
    public void ParseSource( byte[] Content )
    {
        int count = ByteTransform.TransInt32( Content, 0 );
        float temp = ByteTransform.TransSingle( Content, 4 );
        short name1 = ByteTransform.TransInt16( Content, 8 );
        string barcode = Encoding.ASCII.GetString( Content, 10, 10 );
    }
    public byte[] ToSource( )
    {
        byte[] buffer = new byte[20];
        ByteTransform.TransByte( count ).CopyTo( buffer, 0 );
        ByteTransform.TransByte( temp ).CopyTo( buffer, 4 );
        ByteTransform.TransByte( name1 ).CopyTo( buffer, 8 );
        Encoding.ASCII.GetBytes( barcode ).CopyTo( buffer, 10 );
        return buffer;
    }
    #endregion
    #region Public Data
    public int count { getset; }
    public float temp { getset; }
    public short name1 { getset; }
    public string barcode { getset; }
    #endregion
}

  这样我们就是可以实现特殊数据的读写了

1
2
3
4
5
6
7
OperateResult<UserType> read = siemensTcpNet.ReadCustomer<UserType>( "M100" );
if (read.IsSuccess)
{
    UserType value = read.Content;
}
// write value
siemensTcpNet.WriteCustomer( "M100"new UserType( ) );

  

支持M,I,Q,DB,T,C数据的读写操作

究极数据的读取:

此处提供一个核心的报文读取机制,你可以自己传入自己的报文,然后接收服务器的报文,再自己解析操作,可以根据报文格式实现任意的操作,当然,前提是需要报文支持。假设我要实现写入M100,为0x3B,那么最终的报文为

03 00 00 24 02 F0 80 32 01 00 00 00 01 00 0E 00 05 05 01 12 0A 10 02 00 01 00 00 83 00 03 20 00 04 00 08 3B

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
private void userButton23_Click_1(object sender, EventArgs e)
{
    byte[] buffer = HslCommunication.BasicFramework.SoftBasic.HexStringToBytes(
        "03 00 00 24 02 F0 80 32 01 00 00 00 01 00 0E 00 05 05 01 12 0A 10 02 00 01 00 00 83 00 03 20 00 04 00 08 3B");
    OperateResult<byte[]> operate = siemensTcpNet.ReadFromServerCore(buffer);
    if (operate.IsSuccess)
    {
        // 显示服务器返回的报文
        TextBoxAppendStringLine(HslCommunication.BasicFramework.SoftBasic.ByteToHexString(operate.Content));
    }
    else
    {
        // 显示网络错误
        MessageBox.Show(operate.ToMessageShowString());
    }
}

更详细的信息,可以参照源代码里面的测试项目。

如果使用Fetch/Write协议进行读写操作,PLC端的配置不一致,实例化的类不一致,其他都是一样的,不再赘述了,就重点说明下PLC网络模块的配置


环境:此处使用了STEP 7V5.5 sp4编程软件作为示例,在添加以太网模块(6GK7 343-1EX30-0E0 CP343-1)到组态中时,可以设置IP地址及子网掩码, 此处测试使用,所以不使用路由器,如果您的西门子需要连接到内网中的话,需要配置路由器。目前只支持M,I,Q数据的读写。 然后点击新建,创建一个Ethernet(1)网络。以太网参数配置如下图:

将以太网的模块添加到机架中以后,现在打开网络组态 ,打开后点击组态上的PLC模块。会出现如下界面,在箭头出进行双击操作,可以弹出对话框,并进行一系列操作:

按照上面一套操作下来,创建了一个读取的端口,端口号为2000,后面有用,需要记住, 按照上述的步骤再创建一个写入的端口,只有最后一步不一致,如下:

配置完之后的效果图如下,新建了两个端口,一个用于读取数据,一个用于写入数据。 <strong>注意:设置完成后一定要写入到PLC才算真的完成。</strong>

如上图所示,上图配置错误,应该配置一个同时支持读写的操作的端口

实例化的类的时候

1
private SiemensFetchWriteNet siemensFWNet = null;

  

1
2
3
4
5
6
siemensFWNet = new SiemensFetchWriteNet( )
            {
                IpAddress = "192.168.0.100",
                Port = 2000,
                ConnectTimeOut = 5000,
            };

  

创作不易,感谢打赏

微信:        支付宝:

转载于:https://www.cnblogs.com/Gxiaopan/p/11479119.html

C#读写西门子PLC数据相关推荐

  1. s7 200 java_java android 读写西门子PLC数据,包含S7协议和Fetch/Write协议,s7支持200smart,300PLC,1200PLC,1500PLC...

    本文将使用一个gitHub开源的组件技术来读写西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 gi ...

  2. C#读写三菱PLC和西门子PLC数据 使用TCP/IP 协议

    本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...

  3. C#读写三菱PLC数据 使用TCP/IP 协议

    本文将使用一个Github开源的组件库技术来读写三菱PLC和西门子plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能 ...

  4. Softing dataFEED OPC Suite将西门子PLC数据存储到Oracle数据库中

    一 背景 现代工业产品不仅生产批量大,而且过程自动化程度高,这对于用户追溯产品设计与制造过程中产生的数据而言,无疑是个新的挑战.与此同时,制造商们对产品制造过程中产生的大量工艺数据也愈发重视,并不断寻 ...

  5. C#读写西门子PLC中英文字符串数据的学习笔记

    最近由于需要对西门子PLC进行字符串类型数据的读写,才专门了解了一下西门子PLC字符串类型的数据的使用及存储形式.在PLC中: 一.String数据类型包含总字符数和当前字符数. String 类型提 ...

  6. plc tcp ip通讯怎么只能连一个客户端_如何远程读取西门子PLC数据?

    随着工业的发展,PLC联网进行远程监控.远程运维的需求越来越多,通常是通过PLC的通信口外接一个联网模块来实现.很多企业自动化产品与非标自动化产品安装现场地处偏僻,没有网络怎么办?随着本地通信控制的局 ...

  7. thymealf如何实现传单个变量给html_如何远程读取西门子PLC数据?

    随着工业的发展,PLC联网进行远程监控.远程运维的需求越来越多,通常是通过PLC的通信口外接一个联网模块来实现.很多企业自动化产品与非标自动化产品安装现场地处偏僻,没有网络怎么办?随着本地通信控制的局 ...

  8. .net通过S7.net读写西门子PLC中,字符串,bool,整数,小数及byte型

    注:.net中通过TCP/IP方式通过S7.net.dll动态库,连接到西门子PLC,西门子程序中许勾选优化块,程序读取需要 db块号+偏移量 一.使用VS项目,在项目中添加S7.net动态库 代码中 ...

  9. python三菱_python 读写三菱PLC数据,使用以太网读写Q系列,L系列,Fx系列的PLC数据...

    本文将使用一个gitHub开源的组件技术来读写三菱的plc数据,使用的是基于以太网的TCP/IP实现,不需要额外的组件,读取操作只要放到后台线程就不会卡死线程,本组件支持超级方便的高性能读写操作 里面 ...

  10. netlink怎么读_在VB中访问NETLINK并读写S7300 PLC数据

    (无锡市北辰自动化技术有限公司 张鹏 2007-10-16) 一.概述 Hilscher NETLINK用于将西门子MPI协议转换为以太网TCP/IP协议,并提供公开的无需授权的驱动函数库. NETL ...

最新文章

  1. python set集合
  2. 替换字符串指定位置字符 php,PHP substr_replace 替换字符串指定位置字符
  3. 数值数据表示的三要素
  4. 用CRT查找内存泄漏
  5. 一、使用两台Centos7系统搭建Hadoop-3.1.4完全分布式集群
  6. VisualStudio解决方案配置Debug和Release选项
  7. edX Devstack 汉化(i18n)
  8. CCF202104-1 灰度直方图
  9. 20150702 问题随记
  10. Oracle PLSQL工具登陆界面:连接库选项没有本地数据库名可选 解决方法
  11. 开源jeecms,jeebbs学习笔记4——从jo_user表看持久层设计
  12. POJ2031Building a Space Station
  13. 【无标题】win7系统怎么配置adb环境变量
  14. 台式计算机 按键盘字母键 没反应6,电脑键盘数字键失灵-键盘字母上面数字键有的失灵不能用怎么?键盘字母上面数字键有的失灵 爱问知识人...
  15. 正常邮件被误判为垃圾邮件
  16. 分享830个蜘蛛IP段(分析1G日志得)
  17. 网络共享查看其他计算机取消密码,Win7局域网访问需要密码 win7取消共享密码的方法...
  18. Win10系统的SurfacePro4的触摸笔如何使用
  19. 企业应如何制定多云世界的反脆弱身份?
  20. matlab对于图像压缩,Matlab的图像压缩技术

热门文章

  1. json数据循环左侧三级导航菜单
  2. 遇到问题---hosts不起作用问题的解决方法
  3. 联通微服务怎么还款_重磅!中国联通推出微信签约代扣新功能
  4. Java复习第二弹!
  5. PostgreSQL创建、连接企业型地理数据库
  6. 易语言精益模块json_精易模块|精易模块下载 v3.46 官方免费版_最火软件站
  7. 【逆向JS】调用网易云音乐搜歌功能并爬取评论Python/Java
  8. vue axios封装 类方法
  9. Pandas 安装到Pycharm
  10. Android-EditText属性大全