C# 倍福ADS的正确打开方式,使用AdsRemote组件优雅的通过ADS通讯,支持WPF窗体控件的绑定机制,做上位机页面很方便,大大节省了开发时间。

倍福的官方文档给的例子我就不多说了,今天介绍一种更改优雅的使用ADS组件进行通讯的方式,非常符合高级语言的编程风格,在也不用到处readany,writeany了。

https://github.com/nikvoronin/AdsRemote

AdsRemote:Beckhoff的TwinCAT.Ads API库的高级接口可以节省大量的开发时间。您不需要网络线程或句柄。只需声明一个C#变量,并通过变量属性将其绑定到PLC var。就这样。

我最喜欢的使用方式是变量变化后自动通知,类似观察者模式,不用傻傻的死等结果的反馈。Adsremote组件内部会使用一个线程来对取变量,当值发生变化时,调用ValueChanged事件。

PLC instance

First you have to create an instance of PLC object. This one wiil be like a factory that produces linked variables.

PLC plc = new PLC("5.2.100.109.1.1");

When device connected or disconnected

plc.DeviceReady += Plc_DeviceReady;
plc.DeviceLost += Plc_DeviceLost;[...]private void Plc_DeviceReady(object sender, AdsDevice e)
{Log("READY [" + e.Address.Port.ToString() + "]");
}

How to create and link variables

Create a copy of your PLC's variable then use it like an ordinary variable We use PLC object that produces linked variables. After that variables will autoupdating their state and value.

//定义变量就这么简单,很容易做其他抽象。直接复杂的结构体类型

Var<short>  main_count = plc.Var<short> ("MAIN.count");
Var<ushort> main_state = plc.Var<ushort>("MAIN.state");
Var<short>  g_Version  = plc.Var<ushort>(".VERSION");Var<ushort> frm0       = plc.Var<ushort>("Inputs.Frm0InputToggle", 27907);
Var<ushort> devState   = plc.Var<ushort>(0xF030, 0x5FE, 27907);long framesTotal += frm0 / 2; // automatic type casting
MessageBox.Show(frm0);        // cast into the string type without call of the ToString()

From now you can subscribe on value changing.

main_count.ValueChanged +=delegate{counterStatusLabel.Text = main_count;};

or

main_count.ValueChanged +=delegate (object src, Var v){ushort val = (ushort)v.GetValue();framesTotal += val / 2;counterStatusLabel.Text = val.ToString();};

Write-back to the PLC

Use "RemoteValue" propertie to write a new value to the PLC runtime.

main_count.RemoteValue = 123;

WinForms data binding

For example we will bind Text propertie of the Label control with default name label1. At the PLC side we have MAIN.count variable that contains value of counter that we should show.

Var<short> main_count = plc.Var<short>("MAIN.count");Binding b = new Binding("Text", main_count, "RemoteValue");
b.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
b.DataSourceUpdateMode = DataSourceUpdateMode.Never;label1.DataBindings.Add(b);

If we have to convert given value we define a format converter

Var<short> main_count = plc.Var<short>("MAIN.count");Binding b2 = new Binding("ForeColor", main_count, "RemoteValue");
b2.ControlUpdateMode = ControlUpdateMode.OnPropertyChanged;
b2.DataSourceUpdateMode = DataSourceUpdateMode.Never;
b2.Format += (s, ea) =>
{ea.Value =  (short)ea.Value < 0 ? Color.Blue : Color.Red;
};
label1.DataBindings.Add(b2);

WPF data bindings

In WPF you must use properties instead of variables.

PLC plc;
public Var<ushort> frm0 { get; set; }private void Window_Loaded(object sender, RoutedEventArgs e)
{plc = new PLC("5.2.100.109.1.1");frm0 = plc.Var<ushort>("Inputs.Frm0InputToggle", Port: 27907);DataContext = this;
}

And explicitly specifying the field .RemoteValue of the remote variable

<Grid><Label x:Name="label" Content="{Binding frm0.RemoteValue}" />
</Grid>

Create variables with help of attributes

You can create special class with several variables then mark those ones as remote PLC variables. Remember, all variables must declare a type. Otherwise you'll get NULL.

Public fields only!

public class PRG_Main
{[LinkedTo("MAIN.count", As: typeof(short), Port: (int)AmsPort3.PlcRuntime1)]public Var count;[LinkedTo("MAIN.state", Port: (int)AmsPort3.PlcRuntime1)]public Var<ushort> state;[LinkedTo("Inputs.Frm0InputToggle", Port: 27907)]public Var<ushort> frm0_1;[LinkedTo(IGrp: 0xF030, IOffs: 0x5F4, Port: 27907)]public Var<ushort> frm0;
}

or more concisely for the PLC's Runtime #1

public class PRG_Main
{[LinkedTo("MAIN.count")]public Var<short> count;[LinkedTo("MAIN.state")]public Var<ushort> state;
}

Again in WPF-project you should use properties

public class PRG_Main
{[LinkedTo("MAIN.count")]public Var<short> count { get; set; }[LinkedTo("MAIN.state")]public Var<ushort> state { get; set; }
}

It's time to create instance of our class.

If you don't need of special class constructor just write:

PRG_Main Main = plc.Class<PRG_Main>();

otherwise for cunstructor with parameter list or something else we use it in this maner

Main = new PRG_Main(param1, param2, ...);
plc.Class(Main);

在看看倍福TwinCAT.Ads组件的例子

using TwinCAT.Ads;

/// <summary>
        /// 读、写PLC变量
        /// </summary>
        static void ReadAndWrite()
        {
            //Create a new instance of class TcAdsClient
            TcAdsClient tcClient = new TcAdsClient();
            AdsStream dataStream = new AdsStream(8);
            AdsBinaryReader binReader = new AdsBinaryReader(dataStream);

int iHandle = 0;
            double iValue = 0;
            AdsBinaryWriter binWriter = new AdsBinaryWriter(dataStream);//共用一个变量,要控制Position
            int iHandle2 = 0;

try
            {
                //tcClient.Connect("5.49.89.132.1.1", 851);//远程连接,具体的设备
                tcClient.Connect(851);//本地测试
                //Get the handle of the SPS variable "PLCVar"
                iHandle = tcClient.CreateVariableHandle("GVL_Remote.SensorMM");
                iHandle2 = tcClient.CreateVariableHandle("GVL_Remote.Score");
                while (iValue <= 999)
                {
                    //Use the handle to read PLCVar
                    dataStream.Position = 0;
                    tcClient.Read(iHandle, dataStream);
                    iValue = binReader.ReadDouble();
                    Console.WriteLine($"Current Distance = {iValue} at time {DateTime.Now}");
                    //write
                    double newValue = iValue * 3;
                    dataStream.Position = 0;
                    binWriter.Write(newValue);
                    tcClient.Write(iHandle2, dataStream);
                    Console.WriteLine($"new value = {newValue} at time {DateTime.Now}");
                    System.Threading.Thread.Sleep(1000);
                }
                Console.WriteLine("Exit");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                Console.ReadKey();
            }
            finally
            {
                tcClient.Dispose();
            }
        }

C# 倍福ADS的正确打开方式,使用AdsRemote组件优雅的通过ADS通讯相关推荐

  1. 苹果切换输入法_iPhone输入法的正确打开方式,让你打字更痛快

    iPhone输入法的正确打开方式,让你打字更痛快 手机是我们经常会使用到的一个物品,同时我们和手机的互动,目前主要是建立在输入法层面,尽管我们可以通过声音进行控制一些智能化的设备,但是这样的功能并没有 ...

  2. jquery.ztree 打开父节点_增额终身寿险的正确打开方式

    寿险,想必大部分人都理解它的含义:被保人身故或者全残就能获得赔偿的保险,终身寿险自然就是无论何时身故或者全残都会赔偿你的保险.但我们今天要讲的增额终身寿险有点不太一样,它的正确打开方式又是什么呢? 增 ...

  3. 揭秘超分辨率的正确打开方式

    写在前边:图像和视频通常包含着大量的视觉信息,且视觉信息本身具有直观高效的描述能力,所以随着信息技术的高速发展,图像和视频的应用逐渐遍布人类社会的各个领域.近些年来,在计算机图像处理,计算机视觉和机器 ...

  4. opengl 贴图坐标控制_材质贴图正确打开方式

    哈喽,各位观众朋友们好鸭~欢迎来到讲道理画图的地方,我是黄玮宁. 最近呀经常有小伙伴来问我那些不同通道的材质贴图该怎么用,而且频率不是一般的高,所以我觉得有必要来说说这些通道贴图的用法了. 视频版(B ...

  5. Console控制台的正确打开方式

    Console控制台的正确打开方式 console对象提供了访问浏览器调试模式的信息到控制台 -- Console对象|-- assert() 如果第一个参数断言为false,则在控制台输出错误信息| ...

  6. 任务队列和异步接口的正确打开方式(.NET Core版本)

    layout: post title: 任务队列和异步接口的正确打开方式(.NET Core版本) category: dotnet core date: 2019-01-12 tags: dotne ...

  7. log python_基于Python log 的正确打开方式

    保存代码到文件:logger.py import os import logbook from logbook.more import ColorizedStderrHandler import sm ...

  8. python四舍五入round_四舍五入就用round( )?Python四舍五入的正确打开方式!

    四舍五入就用round( )?Python四舍五入的正确打开方式! 2018-09-22 21:40 阅读数 4 <>round( )函数简介 菜鸟教程中介绍到,round() 函数作用就 ...

  9. 通过机器学习识别“迪士尼在逃公主”,程序员宠女的正确打开方式!

    到了庆祝的时候了!我们刚刚送走了圣诞老人.现在正等待新年的钟声敲响.所以我想到建立一个很酷的东西(至少我的七岁小公主会觉得)同时学一点机器学习.所以我们要做一个什么? 我借用的我女儿所有迪士尼公主人偶 ...

最新文章

  1. JS 中settimeout和setinterval函数的区别
  2. SVD分解算法及其应用
  3. C++ Primer 5th笔记(chap 17 标准库特殊设施)匹配与 Regex 迭代器类型
  4. c# 找出目录下的所有子目录_第9期:Linux下文件系统满的处理
  5. CentOS 5.5-yum安装配置LNMP
  6. 不允许使用java方式启动_细品 Java 中启动线程的正确和错误方式
  7. Safari 版本回退方法
  8. 读《可复制的领导力》
  9. 计算机用于数据管理经历了,管理系统中计算机应用--期中测验答案
  10. python状态码409_HTTP状态码
  11. [INS-20802] Oracle Net Configuration Assistant failed
  12. mysql8.0.19解压版_MySQL8.0解压版配置步骤及具体流程
  13. 我为什么用GO语言来做区块链?
  14. 富士相机设置传原图_富士XT4 多位摄影师试用体验报告
  15. Puppet 实验十三 Foreman 基础使用
  16. 博客制作系 -- 2.4. Git
  17. LintCode 介绍
  18. Java生成word 并导出简历
  19. Android studio底部Logcat模块不见了以及Locat日志中包含了很多无用的错误日志筛选方法
  20. B站李沐讲论文笔记Transformer

热门文章

  1. 字节跳动Android实习面试凉凉经,震撼来袭免费下载!
  2. 【牛客刷题】前端--JS篇(一)
  3. 电脑如何用HDMI连接电视
  4. AI跨界,RPA进阶,数字员工会是企业转型的最优解吗?
  5. 计算机组成原理乘法器组成图,计算机组成原理阵列乘法器课程设计报告
  6. 用golang重写SS帐号获取脚本
  7. openpnp摄像头使用
  8. Vue响应式原理---双向绑定
  9. Java - StringUtils 中 isNotEmpty 和 isNotBlank 区别
  10. 高薪聘请2021/2022届本/硕/博数学、物理、统计、计算机、软件等专业 1、量化软件开发工程师(本科211以上)base北上杭深关键词:c++、python、java软件开发