1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > C# 倍福ADS的正确打开方式 使用AdsRemote组件优雅的通过ADS通讯

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

时间:2019-03-21 00:39:13

相关推荐

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

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

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

/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 castingMessageBox.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 bindTextpropertie of theLabelcontrol with default namelabel1. At the PLC side we haveMAIN.countvariable 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.RemoteValueof 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();

}

}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。