C#遇上WINCC

Posted dotNet工控上位机

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C#遇上WINCC相关的知识,希望对你有一定的参考价值。

前言

在工控领域中,WinCC仍然占有很大的市场份额。很多时候我们说学习C#开发上位机可以取代传统的组态软件,两者就像冤家一样,然而,即使是冤家,也会有联合的时候。比如,当我们的项目已经采用WINCC并已经落地,如果我们学会C#,能做哪些事情呢?今天跟大家分享一下如何使用C#/.NET联合西门子WinCC实现数据通信。

环境搭建

众所周知,WinCC作为西门子家族的一款组态软件,主要是用来和PLC(主要是西门子PLC)通信,因此我们选择的硬件就是一款西门子S7-1200 PLC。软件方面,使用的是WinCC V7.4(其他版本待测试),以及宇宙第一IDE——VS 2019。

这里注意一下:测试时当安装好WinCC V7.4,通过添加驱动和S7-1200 PLC通信时,怎么都连接不上,最后发现应该是WINCC的S7-1200 PLC的驱动有点BUG,缺少一些组件,通过安装TIA博图之后,最终解决。

如果想通过C#联合WINCC访问到PLC里的变量,前提是WINCC项目已经开发好,并且处于运行状态,操作步骤如下:

2、创建一个画面,拖入4个显示控件,分别绑定这4个变量,通过博图将4个变量的值分别设置为50.5、60.5、70.5、80.5,如下图所示:

C#遇上WINCC

3、运行WINCC画面,如下图所示:

C#遇上WINCC

访问WINCC变量

1、首先创建一个新的Windows窗体应用,再从WINCC安装目录中找到两个dll,分别是CCHMIRuntime.dll和CCHMITags.dll,位置默认处于C:\Program Files (x86)\Common Files\Siemens\Bin,将这两个dll复制到debug根目录下并手动添加引用:

C#遇上WINCC

2、Windows窗体界面设计,下图所示:

C#遇上WINCC

3、编写读取变量代码,如下图所示:


        //创建通信对象
        CCHMIRUNTIME.HMIRuntime hmi = new CCHMIRUNTIME.HMIRuntime();
        //创建计时器
        Stopwatch sw = new Stopwatch();
        /// <summary>
        /// 读取变量
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Read_Click(object sender, EventArgs e)
        {
            //开始计时
            sw.Restart();
            //读取变量
            object data1 = hmi.Tags["data1"].Read();
            object data2 = hmi.Tags["data2"].Read();
            object data3 = hmi.Tags["data3"].Read();
            object data4 = hmi.Tags["data4"].Read();
            //显示变量
            this.txt_data1R.Text = data1?.ToString();
            this.txt_data2R.Text = data2?.ToString();
            this.txt_data3R.Text = data3?.ToString();
            this.txt_data4R.Text = data4?.ToString();
            //显示耗时
            this.lbl_Time.Text = sw.ElapsedMilliseconds.ToString() + "ms";
        }

4、编写写入变量代码,如下图所示:

        /// <summary>
        /// 写入变量
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Write_Click(object sender, EventArgs e)
        { 
            //开始计时
            sw.Restart();
            //写入变量
            try
            {
                hmi.Tags["data1"].Write(Convert.ToSingle(this.txt_data1W.Text));
                hmi.Tags["data2"].Write(Convert.ToSingle(this.txt_data2W.Text));
                hmi.Tags["data3"].Write(Convert.ToSingle(this.txt_data3W.Text));
                hmi.Tags["data4"].Write(Convert.ToSingle(this.txt_data4W.Text));
            }
            catch (Exception)
            {
                MessageBox.Show("写入失败");
                return;
            }
            //显示耗时
            this.lbl_Time.Text = sw.ElapsedMilliseconds.ToString() + "ms";
        }

5、读取测试结果如下图所示:

C#遇上WINCC

6、写入测试结果如下图所示:

C#遇上WINCC

访问WINCC控件

1、重新新建一个窗体,窗体内容和布局与之前一致,如下所示:

C#遇上WINCC

2、编写读取控件属性代码,如下所示:

        //创建通信对象
        CCHMIRUNTIME.HMIRuntime hmi = new CCHMIRUNTIME.HMIRuntime();
        //创建计时器
        Stopwatch sw = new Stopwatch();
        /// <summary>
        /// 读取变量
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_Read_Click(object sender, EventArgs e)
        {
            //开始计时
            sw.Restart();
            try
            {
                //读取变量
                dynamic data1 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件1"];
                dynamic data2 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件2"];
                dynamic data3 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件3"];
                dynamic data4 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件4"];
                //显示变量
                this.txt_data1R.Text = data1.CurrentValue.ToString();
                this.txt_data2R.Text = data2.CurrentValue.ToString();
                this.txt_data3R.Text = data3.CurrentValue.ToString();
                this.txt_data4R.Text = data4.CurrentValue.ToString();
            }
            catch (Exception)
            {
                MessageBox.Show("读取失败");
                return;
            }
            //显示耗时
            this.lbl_Time.Text = sw.ElapsedMilliseconds.ToString() + "ms";
        }

3、编写写入控件属性代码,如下所示:


      /// <summary>
      /// 写入变量
      /// </summary>
      /// <param name="sender"></param>
      /// <param name="e"></param>
      private void btn_Write_Click(object sender, EventArgs e)
      {
          //开始计时
          sw.Restart();

          //写入变量
          try
          {
              dynamic data1 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件1"];
              dynamic data2 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件2"];
              dynamic data3 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件3"];
              dynamic data4 = hmi.Screens["NewPdl1"].ScreenItems[".NET 控件4"];
              
              data1.CurrentValue = Convert.ToSingle(this.txt_data1W.Text);
              data2.CurrentValue = Convert.ToSingle(this.txt_data2W.Text);
              data3.CurrentValue = Convert.ToSingle(this.txt_data3W.Text);
              data4.CurrentValue = Convert.ToSingle(this.txt_data4W.Text);

          }
          catch (Exception)
          {
              MessageBox.Show("写入失败");
              return;
          }

          //显示耗时
          this.lbl_Time.Text = sw.ElapsedMilliseconds.ToString() + "ms";
      }

4、读取结果如下所示:

C#遇上WINCC

5、写入结果如下所示:

C#遇上WINCC

这里值得注意的是,通过访问控件实现的写入并没有真正写入PLC,所以这种方式仅限于读取数据,但可以通过这种方式来设置控件的其他属性,比如样式、背景、文本等。

整体总结

本文主要以学习研究为主,针对C#与WINCC之间的数据通信做了较为详尽的描述,相信对于很多电气工程师,尤其是以西门子PLC为主的电气工程师来说,会有很大帮助。

如果大家对本文的内容或者C#上位机开发感兴趣,我们安排了一次免费集训课,需要的小伙伴可以扫描下方二维码,免费参加直播课。

【集训营课程目录】

1、C#小白入门开发技巧与经验分享

(1)小白如何开始OOP学习

(2)C#编程中快速突破技巧

(3)C#编程中常见错误分析

(4)一道题测试你是否入门

2、C#小白快速蜕变开发高手解密

(1)写好程序必知六大原则

(2)程序开始前的分析技巧

(3)优雅代码编写重要步骤

(4)一个案例帮你蜕变大神

3、C#联合WINCC实现数据实时通信

(1)无硬件搭建西门子PLC仿真

(2)WINCC与西门子PLC通信测试

(3)C#访问WINCC变量实现读写

(4)C#访问WINCC控件实现读写

大家如果对上面的课程内容或者上位机感兴趣,赶紧扫码参加吧,3天全免费,如果无法参加直播课,可以提供完整录播。

名额仅限前200名,先到先得。

以上是关于C#遇上WINCC的主要内容,如果未能解决你的问题,请参考以下文章

C#开发WinCC语音报警插件

C#与WinCC通讯之西门子S7-1200数据读取详解

C# 最有用的(自定义)代码片段是啥? [关闭]

c#代码片段快速构建代码

此 Canon SDK C++ 代码片段的等效 C# 代码是啥?

是否可以动态编译和执行 C# 代码片段?