zoukankan      html  css  js  c++  java
  • S7.Net与西门子PLC通讯——纯新手必看

     前言

    本文档适合从未接触过PLC的.NET开发程序员入门查看。(其实看完了之后,PLC开发也就那样)

    PLC通讯入门比较难,需要关注的细节比较多。一边学习一边举一反三多思考,一定要自己创建Demo跟着步骤

    由于项目还未开发完成,准备空抽补充陆续完成这篇博客,更好的设计思路也能给自己加深印象。

    近期公司有一个跟雷达、光电、干扰炮等设备通讯的项目,让我来负责,整个项目只有我一个人且没有PLC开发经验的同事,这对于从未接触过PLC开发的我来说,无疑是一团迷雾,不知从何入手。公司之前也没有PLC开发经验和项目, 头大。。。

    正所谓“没有撤退可言,只有活下来的人才有资格清兵线!”

    开始在网上找各种资料,在此记录一下学习的过程和踩过的坑

    1. 快速锁定有效文章,对于初学来说,先看理论,有些花里胡哨且乱的资料直接关闭

    2. 尽量能找到可以理解的demo,觉得有用但还看不懂的可以先notepad做下笔记

    3. 如果有人在看 WinTcpS7_1K.dll 的,赶紧关闭,并送到回收站快速清理,收费的。1500授权3台电脑(这个家伙广告特别多,涉及各个论坛,还要CSDN下载积分,注意看评论),最主要封装的还很难用

    4. 最后的最后找到 S7NetPlus ,成功实现了PLC的通讯,博客也会总结对 S7NetPlus 的使用

    5. 要有中心思路,不要一会这个,一会看那个

    由于也是初学,如有讲错或不到位的地方还望大佬指教,及时修正!

    先发个视频,这是我在Youtube上找到的一系列视频中的一个,作者通过S7.net的dll控件实现了与西门子S7系列的PLC通信的功能

    链接:https://pan.baidu.com/s/1g3wo4e1HEiuwrzXYD-dSGA
    提取码:lllg

    开发环境准备

    同时由于设备还未采购,没有设备进行测试开发,会安装一个仿真模拟器进行调试。(真心的,谁想到还能仿真模拟设备)

    需要安装的软件包括

    ◦TIA Portal V14

    ◦S7-PLCSIM V14

    ◦NetToPLCsim-S7o-v-1-2-2-0

     

    TIA Portal

     西门子官方管理设备数据块的客户端,每一个项目等同于一个设备型号,可以理解为是我们经常使用的数据块客户端

    S7-PLCSIM

    创建一个仿真的模拟环境,使用TIA Portal进行调用,控制仿真设备的运行停止

    NetToPLCsim

    提供本地服务去连接到仿真设备,和PLCsim之间建立网络通讯

    安装完TIA之后,有两处需要进行设置(重要!)

    1. 选中组态的PLC设备,常规下找到防护与安全,选择允许从远程伙伴使用PUT/GET通信访问

    2. 建立的数据块文件,右键属性,需要取消优化的块访问选项,使用绝对地址

    软件交互使用

    第一步: TIA Portal 新建项目,选择需要通讯的设备型号

     第二步:添加数据块

     第三步:添加数据类型之后,点击编辑,生成偏移量(Offset),后面获取单个数值时需要

     第四步:开始仿真,点击之后会自动打开S7-PLCSIM,根据提示点击“装载”,点“完成”

     第五步:在S7-PLCSIM上点击RUN,运行设备仿真环境

    第六步:设置 NetToPLCsim

      6.1 点击 Add,添加连接到PLCSIM环境

      6.2 NetWork IP Address 手写填为本机(127.0.0.1)

      6.3 Plcsim Ip Address 点击后面两点,选择192.168.0.1 TCP/IP,必须要在仿真环境运行之后才能选择

      6.4 根据不同设备型号设置 Rack / Slot ,我是S7-1200,设置 0 / 1

     第七步:开启服务,这里也很坑! 如果没有按顺序操作,也能Start Server,但是编码时连接不到。最开始不懂仿真设备,在这里研究了好久,Demo硬是连不上

     ok ! 现在就可以开始进行编码了,这里重点介绍从[连接]到[读写]的集中方式和介绍

    创建连接

    以前的历史版本 plc.Open(); 会有一个返回值,可以通过返回值获取 ErrorCode 和 ErrorMessage

    我使用了当前最新版(V0.4.0),没有返回值使用 try-catch 

    using (var plc = new Plc(CpuType.S71200, "127.0.0.1", 0, 1))
        {
                    try
                    {
                        plc.Open();
                    }
                    catch (Exception)
                    {
                        Console.WriteLine($"连接到PLC设备失败:IsConnect={plc.IsConnected},IsAvailable={plc.IsAvailable}");
                        return;
                    }
        }

    读取单个数据项【Read】

    代码中用到三种数据获取方式: DBX、DBW、DBD,深入理解的可以查一下网上资料

    简单理解就是 DBX读取位,比如bool类型;DBW读取字;DBD读取数值

    注释中是对应的 TIA Portal 数据块类型

    #region 单个数据项读取
                    var db1Bool1 = plc.Read("DB1.DBX0.0");
                    Console.WriteLine("DB1.DBX0.0: " + db1Bool1);
    
                    bool db1Bool2 = (bool)plc.Read("DB1.DBX0.1");
                    Console.WriteLine("DB1.DBX0.1: " + db1Bool2);
    
                    // Int
                    int intVariable = (ushort)plc.Read("DB1.DBW2.0");
                    Console.WriteLine("DB1.DBW2.0: " + intVariable);
                    // Real
                    var realVariabl = ((uint)plc.Read("DB1.DBD4.0")).ConvertToFloat();
                    Console.WriteLine("DB1.DBD4.0: " + realVariabl);
                    // DInt
                    var dIntVariable = (uint)plc.Read("DB1.DBD8.0");
                    Console.WriteLine("DB1.DBD8.0: " + dIntVariable);
                    // DWord
                    var dWordVariable = (uint)plc.Read("DB1.DBD12.0");
                    Console.WriteLine("DB1.DBD12.0: " + dWordVariable);
                    // Word
                    var wordVariable = (ushort)plc.Read("DB1.DBW16.0");
                    Console.WriteLine("DB1.DBW16.0: " + wordVariable);
                    #endregion

    另一种方式,通过ReadBytes读取单个数据

                     // 读取int类型
                        byte [] int0 = (byte[])plc.ReadBytes(DataType.DataBlock, 1, 2, 2);
                        byte[] revint0 = int0.Reverse().ToArray();
                        short f5 = BitConverter.ToInt16(revint0, 0);
     
                        Console.WriteLine("DB1.DBD2: " + f5); 

    批量读取数据块【ReadBytes】

     看注释

     #region 批量数据项读取 / 读取整个DB
                    // DataType: 数据类型,DB或Memory等
                    // DB : DataBlock=1,Memory=0
                    // count : 偏移量(offset),设置多少就获取到具体位置的数据
                    // eg: 比如最后一个DBW是16,那么数据类型长度为2,count就需要传18才能获取到
                    var bytes = plc.ReadBytes(DataType.DataBlock, 1, 0, 18);
                    Console.WriteLine(bytes);
    
                    var bool1 = bytes[0].SelectBit(0);
                    Console.WriteLine("DB1.DBX0.0: " + bool1);
                    var bool2 = bytes[0].SelectBit(1);
                    Console.WriteLine("DB1.DBX0.0: " + bool2);
    
                    // Int
                    int intVariable = S7.Net.Types.Int.FromByteArray(bytes.Skip(2).Take(2).ToArray());
                    Console.WriteLine("DB1.DBD2.0: " + intVariable);
                    //  Real
                    Double realVariable = S7.Net.Types.Double.FromByteArray(bytes.Skip(4).Take(4).ToArray());
                    Console.WriteLine("DB1.DBD4.0: " + realVariable);
    
                    // DWord
                    uint dWordVariable = S7.Net.Types.DWord.FromByteArray(bytes.Skip(12).Take(4).ToArray());
                    Console.WriteLine("DB1.DBD12.0: " + dWordVariable);
                    // Word
                    var wordVariable = S7.Net.Types.Word.FromByteArray(bytes.Skip(16).Take(2).ToArray());
                    Console.WriteLine("DB1.DBW16.0: " + wordVariable);
                    #endregion

    读取数据块到类对象【ReadClass】

    创建一个Db1类,数据类型和变量名跟 TAI Portal 数据块里一一对应,这个很简单!

    因为作者已经封装好了,底层实现也是上述原理

    #region 读取数据块(DB)到实体类
         var db1 = new Db1();
         plc.ReadClass(db1, 1, 0);
    #endregion

    多个数据块同时读取 【ReadMultipleVars】

    ReadMultipleVars()方法需要构造一个List作为参数,这里留作业

                    #region 多个数据块(DB)同时读取
    
                    plc.ReadMultipleVars();
                    #endregion

    写入单个数据【Write】

    看完上面的内容,就很容易理解这里

                    // 写入数据
                    plc.Write("DB1.DBX0.1", true);
                    plc.Write("DB1.DBD12.0", 123457);

    我也是第一次接触PLC设备通讯,还有很多没有讲全面,如果有更好的方案或经验欢迎留言一起探讨,感谢!

    后续用到本文未提及的地方再回来补充。

    补充:

    S7.Net 作者的GitHub:github.com/killnine(十个杀九个)

     

  • 相关阅读:
    【郑轻邀请赛 G】密室逃脱
    【郑轻邀请赛 C】DOBRI
    【郑轻邀请赛 F】 Tmk吃汤饭
    【郑轻邀请赛 I】这里是天堂!
    【郑轻邀请赛 B】base64解密
    【郑轻邀请赛 A】tmk射气球
    【郑轻邀请赛 H】 维克兹的进制转换
    解决adb command not found以及sdk环境配置
    adb shell 命令详解,android, adb logcat
    Unexpected exception 'Cannot run program ... error=2, No such file or directory' ... adb'
  • 原文地址:https://www.cnblogs.com/minily/p/13324120.html
Copyright © 2011-2022 走看看