C# 倍福ADS的正确打开方式,使用AdsRemote组件优雅的通过ADS通讯
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通讯相关推荐
- 苹果切换输入法_iPhone输入法的正确打开方式,让你打字更痛快
iPhone输入法的正确打开方式,让你打字更痛快 手机是我们经常会使用到的一个物品,同时我们和手机的互动,目前主要是建立在输入法层面,尽管我们可以通过声音进行控制一些智能化的设备,但是这样的功能并没有 ...
- jquery.ztree 打开父节点_增额终身寿险的正确打开方式
寿险,想必大部分人都理解它的含义:被保人身故或者全残就能获得赔偿的保险,终身寿险自然就是无论何时身故或者全残都会赔偿你的保险.但我们今天要讲的增额终身寿险有点不太一样,它的正确打开方式又是什么呢? 增 ...
- 揭秘超分辨率的正确打开方式
写在前边:图像和视频通常包含着大量的视觉信息,且视觉信息本身具有直观高效的描述能力,所以随着信息技术的高速发展,图像和视频的应用逐渐遍布人类社会的各个领域.近些年来,在计算机图像处理,计算机视觉和机器 ...
- opengl 贴图坐标控制_材质贴图正确打开方式
哈喽,各位观众朋友们好鸭~欢迎来到讲道理画图的地方,我是黄玮宁. 最近呀经常有小伙伴来问我那些不同通道的材质贴图该怎么用,而且频率不是一般的高,所以我觉得有必要来说说这些通道贴图的用法了. 视频版(B ...
- Console控制台的正确打开方式
Console控制台的正确打开方式 console对象提供了访问浏览器调试模式的信息到控制台 -- Console对象|-- assert() 如果第一个参数断言为false,则在控制台输出错误信息| ...
- 任务队列和异步接口的正确打开方式(.NET Core版本)
layout: post title: 任务队列和异步接口的正确打开方式(.NET Core版本) category: dotnet core date: 2019-01-12 tags: dotne ...
- log python_基于Python log 的正确打开方式
保存代码到文件:logger.py import os import logbook from logbook.more import ColorizedStderrHandler import sm ...
- python四舍五入round_四舍五入就用round( )?Python四舍五入的正确打开方式!
四舍五入就用round( )?Python四舍五入的正确打开方式! 2018-09-22 21:40 阅读数 4 <>round( )函数简介 菜鸟教程中介绍到,round() 函数作用就 ...
- 通过机器学习识别“迪士尼在逃公主”,程序员宠女的正确打开方式!
到了庆祝的时候了!我们刚刚送走了圣诞老人.现在正等待新年的钟声敲响.所以我想到建立一个很酷的东西(至少我的七岁小公主会觉得)同时学一点机器学习.所以我们要做一个什么? 我借用的我女儿所有迪士尼公主人偶 ...
最新文章
- JS 中settimeout和setinterval函数的区别
- SVD分解算法及其应用
- C++ Primer 5th笔记(chap 17 标准库特殊设施)匹配与 Regex 迭代器类型
- c# 找出目录下的所有子目录_第9期:Linux下文件系统满的处理
- CentOS 5.5-yum安装配置LNMP
- 不允许使用java方式启动_细品 Java 中启动线程的正确和错误方式
- Safari 版本回退方法
- 读《可复制的领导力》
- 计算机用于数据管理经历了,管理系统中计算机应用--期中测验答案
- python状态码409_HTTP状态码
- [INS-20802] Oracle Net Configuration Assistant failed
- mysql8.0.19解压版_MySQL8.0解压版配置步骤及具体流程
- 我为什么用GO语言来做区块链?
- 富士相机设置传原图_富士XT4 多位摄影师试用体验报告
- Puppet 实验十三 Foreman 基础使用
- 博客制作系 -- 2.4. Git
- LintCode 介绍
- Java生成word 并导出简历
- Android studio底部Logcat模块不见了以及Locat日志中包含了很多无用的错误日志筛选方法
- B站李沐讲论文笔记Transformer
热门文章
- 字节跳动Android实习面试凉凉经,震撼来袭免费下载!
- 【牛客刷题】前端--JS篇(一)
- 电脑如何用HDMI连接电视
- AI跨界,RPA进阶,数字员工会是企业转型的最优解吗?
- 计算机组成原理乘法器组成图,计算机组成原理阵列乘法器课程设计报告
- 用golang重写SS帐号获取脚本
- openpnp摄像头使用
- Vue响应式原理---双向绑定
- Java - StringUtils 中 isNotEmpty 和 isNotBlank 区别
- 高薪聘请2021/2022届本/硕/博数学、物理、统计、计算机、软件等专业 1、量化软件开发工程师(本科211以上)base北上杭深关键词:c++、python、java软件开发